-
-----=========-----
-------==========================================----------
----------=====_masta_的 Win95 汇编教程 part 2 修正版 1=====-----------
-------==========================================----------
( I called this revision 1 because it contains new sourcecode without errors
_masta_ found when going through it again - fungus )
--==介绍==--
Hi,
Part0 和 part1 相对比较成功,我也很高兴发表 part 2了。
实际上我很想做一些关于 GUI 的东西,可是最近我很忙,所以现在只能让你们
看到这些没有 GUI 代码的东西。不管怎样,这也是一个很有趣的东西。
从这篇教程开始我不再会解释一些诸如 MessageBox 之类简单的东东了,
这在头两篇都是解释的非常详细的。我想这也不会给你带来什么不便,如果你看过
头两篇的话。
--==我们需要什么?==--
1. 文本编辑器
2. TASM 5.0 和库文件等等。
3. Windows API 参考手册 (WIN32.HLP)
4. 星际争霸(StarCraft) (ONLY for testing purposes!;]) (Sendfree:MyGod,他要做什么?)
5. 一些脑细胞 ;)
6. 一些基本的汇编知识 (前面两课)
7. Numega Softice 3.xx (并不是必需的) (Sendfree: 这么暴力的工具也用!做什么?!
你的周围有没有Cracker 啊,向他们要一个。)
--==这次我们要做什么?==--
哪一个游戏迷不想有下面的这些东西呢?
more lives
more money
more energy
more gas (sendfree: gas 是星际中的一种资源(就是钞票),下面的 mineral 也是)
more ...
我说的就是游戏修改器(Trainer),这在C64-/Amiga-/PC-DOS-times 是非常常见的,
但是现在却越来越少了,真让人怀念那段美好的岁月。
所以这次拿星际开刀(当然我也知道已经有好些修改器了!
理由:-这个游戏眼下非常流行
-我是在玩这个游戏的时候得到写这篇教程的灵感 :)
--==LET'S GO==--
开始工作之前先仔细考虑一下。
游戏修改器的定义:-一个小程序,可以改变游戏的部分内存数据,例如
这样可以得到更多的 money ...
一般说来,在windows 中一个程序不能读写其他程序的内存空间。幸运的是
我们最亲爱的朋友 Billy 作了一些本来用于 debug 的函数,我们可以用这些
东东达到我们目的。
它们就是:OpenProcess, WriteProcessMemory 和 ReadProcessMemory.
通过这组函数我们就可以读写其他程序的内存空间。
最基本的,我们的程序就像一个除错器(debugger),存取其他程序的内存
并改变它。
--==结构==--
1. 介绍 (用 MessageBox 显示)
2. 得到要修改的程序的 Process_ID
(找到 Starcraft 的主窗口; 然后再找到进程号)
3. 打开进程
4. 改变值
5. 关闭进程, 结束 (成功)
--==重要的 API 函数==--
我们可以用 FindWindowA 得到主窗口的句柄,然后得到窗口类的名字("SWarrClass")和
窗口的名字("Starcraft")。这些东西可以从 Softice (TASK->HWND)中获取。
(sendfree:没有用过 softice 的朋友可以一支雪糕贿赂Cracker 们,然后取点经。)
由窗口句柄(windowshandle)可以得到相应的进程,再用 GetWindowThreadProcessId得到
进程ID(PID).
现在我们可以通过 PID->OpenProcess 的帮助抓住进程内存空间的句柄。
现在一切都变得容易了,我们通过 WriteProcessMemory函数操作程序的句柄就像
通常的文件操作一样操作程序的内存。
最后也是很重要的,调用 CloseHandle 关闭进程的句柄。这在 Win95 中不是真的很重要的,但是谁会
相信一个来自 Redmont(sendfree:雷蒙得,MS的总部)的软件呢 ;-)?
最后一个函数就是 ExitProcess.
--==内存地址==--
我们能够很轻松的通过 debugger搜索显示在屏幕上的十进制数相应的十六进制数
来得到minerals 的地址,在我的系统里是这样的:
Minerals = 04EFE08h
Gas = 04EFE38h
--==THE SOURCE==--
代码并不长,而且结构也不是很好,但是不管怎样,应该是很容易看懂的...
;This is a slightly edited source to my tutorial (Part 2)
;I did a mistake while searching the informations for the memory locations
;not taking care, that starcraft uses different locations ...
;Only change is that the million-value is written 2 times
;and 8 bytes instead of 4
; Set some params for the assembler
.386P
Locals
jumps
.Model Flat ,StdCall
PROCESS_VM_WRITE equ 020h ; Flags for the write-access
PROCESS_VM_OPERATION equ 008h ; to the process
mb_ok equ 0
minerals_pos equ 04efe08h
gas_pos equ 04efe38h
; declaration of used API-functions
extrn MessageBoxA : PROC ; Show a Messagebox
extrn FindWindowA : PROC ; Find Window with the name
extrn GetWindowThreadProcessId :Proc; Find PID with the HWND
extrn OpenProcess : PROC ; Procedure to access the process
extrn WriteProcessMemory: PROC ; Write into memory of the running
; program
extrn CloseHandle : PROC ; Close the handle again
; Cleanup, after use ;)
extrn ExitProcess : PROC ; Procedure to exit the program
; here begins our Data
.Data
caption db "_masta_'s essay on Win32-ASM-Coding, part 2",0
;Captionstring, 0-terminated
text db "Hi, here we are at part 2",13,10
db "This tut will describe you how to make",13,10
db "Win32-ASM Trainer",0
; Introtext , 0-terminated
err_cap db "ERROR",0 ; Caption for Errormessages
notrun db "Sorry, Starcraft is not running",0 ; Error if SC isn't running
no_write db "Mmmhhhh, a problem, by writing",13,10
db "to Starcrafts memory",13,10,0
readycap db "Ready",0 ; Caption for "ready"
readytxt db "Ok, now you have 1000000 Minerals and Gas",0
; Text for "ready"
million dd 1000000 ; How much do you want??? ;]
dd 1000000
wnd_name db "Starcraft",0 ; Name of the Starcraft-window
cls_name db "SWarClass",0 ; Class of the Starcraft-window
pid_sc dd ? ; Here we save the PID ...
p_hand dd ? ; and here the handle to the
; process
; And here we start with our code
.Code
Main:
push mb_ok
push offset caption
push offset text
push 0
call MessageBoxA ;Startmessage
is_SC_RUN:
push offset wnd_name
push offset cls_name
call FindWindowA ; Find Window handle with Windowclass and
; -name
cmp eax,0 ; if 0, window is not existing
jz SC_isnt_run_end; --> Starcraft is not launched
push offset pid_sc ; Where to save the PID ?
push eax ; PUSH Windowhandle
call GetWindowThreadProcessId ; Determine PID with Windowhandle
open_the_process:
push pid_sc ; PUSH PID
push 0 ; only used when
; building new
; processes
push PROCESS_VM_WRITE OR PROCESS_VM_OPERATION ; activate write-access
call OpenProcess ; Get handle of Starcraft
mov p_hand,eax ; Save handle to p_hand
change_Minerals:
push 0 ; Can be zero mostly
push 8 ; Write 8 Bytes (2 Dwords)
push offset million ; How much ? (1 Million)
push minerals_pos ; 1st Memoryaddress
push p_hand ; Handle to the process
call WriteProcessMemory; write minerals
cmp eax,0
jz error_on_write ; If any error while writing (eax=0) -> end
change_gas: ; the same again for gas, but this time
; the memory address of the gas is PUSHed
push 0
push 8
push offset million
push gas_pos
push p_hand
call WriteProcessMemory
cmp eax,0
jz error_on_write
Trainer_ready:
push mb_ok
push offset readycap
push offset readytxt
push 0
call MessageBoxA ; Everything OK
close_the_PID_Handle:
push p_hand
Call CloseHandle ; CloseHandle
jmp end_ ; Go to End
error_on_write:
push mb_ok
push offset err_cap
push offset no_write
push 0
call MessageBoxA ; Mmmhhh, Error while writing
jmp close_the_PID_Handle ; Close handle before quit
SC_isnt_run_end:
push mb_ok
push offset err_cap
push offset notrun
push 0
call MessageBoxA ; nothing there to train =(
end_:
CALL ExitProcess ; Exit program
End Main ; End of Code Determination
of Jump-point (Main)
;--------------------------==END OF SOURCE==----------------------------
;--------------------------------START---------------------------make.bat
@echo off
echo assembling your trainer
tasm32 /mx /m3 /z /q w95asm_2
tlink32 -x /Tpe /aa /c w95asm_2,w95asm_2,, import32.lib
del *.obj
del *.map
;---------------------------------END----------------------------make.bat
--==FINAL WORDS==--
OK, as I told you before this was a little tutorial, but I think very
interesting anyway. I guess there is not much to optimize (sorry fungus),
maybe the routine for writing into memory (use of a procedure).
I hope my mailbox (masta_t@usa.net) is flodded soon (CRITICS ARE WELCOME)
and you are all here next time. I promise the next one will be about GUI,
because many people told me to do so.
BTW, I am trying to build an IRC channel (EFNET) on this (#win32asm) and
finally there is a project-page 'HTTP://win32asm.cjb.net'!
If anyone is interested, any contribution to this subject is very welcome,
we are waiting for it ...
I really hope there are enough people, who spend their time on this
subject and who are willing to give their knowledge to others, too.
--==WISE WORDS==--
------===========================================================-------
-----=====A hardcoded serial is as common as a 25-year-old virgin=====------
------===========================================================-------
-----=========-----
-