本程序在WinXP/SP2、ra2之1.006英文版(有中国超牛机器人的那个)运行通过且稳定无误。;---------------------------------------------------------------------------------------- ;用打补丁的方法改游戏,必需先跟踪游戏程序,找到金钱储存地址,然后直接改代码或打内存补丁 ;---------------------------------------------------------------------------------------- .586 .model flat ,stdcall option casemap :none
include windows.inc
include kernel32.inc
include user32.inc
include psapi.inc
includelib kernel32.lib
includelib user32.lib
includelib psapi.lib
ADD_DATA equ 0830FFCh
ADD_CODE1 equ 0494A81h
ADD_CODE2 equ 049466Bh.code
_GetProcessHandle proc ;comment *在调试时用这段代码取得游戏进程的句柄为好
LOCAL info:PROCESSENTRY32
LOCAL handle :HANDLE
invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0 ;进程快照
mov handle ,eax
mov info.dwSize,sizeof PROCESSENTRY32
invoke Process32First,handle ,addr info
.repeat
mov eax ,@F
invoke lstrcmpi,addr info.szExeFile,eax ;比较是否为我们要找的进程名,不区分大小写
.if !eax
invoke CloseHandle,handle
;invoke MessageBox,NULL,addr info.szExeFile,NULL,MB_OK
invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE ,info.th32ProcessID
jmp EXIT
.endif
invoke Process32Next,handle ,addr info
.until !eax
invoke CloseHandle,handle
xor eax ,eax
EXIT:
ret
@@:
db "Game.exe" ,0; *通常情况下也可以用下面的方法取得游戏进程的句柄,但要注意…… ; LOCAL ProcessId ; invoke GetForegroundWindow ;你必须确保当前窗口为游戏界面窗口,这样才能正确取得游戏进程ID ; lea edx,ProcessId ; invoke GetWindowThreadProcessId,eax,edx ; invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,ProcessId
; ret
_GetProcessHandle endp ;----------------------------------------------------------------------- ;之所以这么做,是为了给出别人一个未作弊的假象,如果用补丁代码直接改钱数, ;显示的钱数不会变,很容易被人发现你作弊了 ;-----------------------------------------------------------------------
_WriteProcessData proc uses esi hProcess
LOCAL DATA,IsRun,add2data
mov esi ,2000 ;要锁定的金钱数,别太多,多了是会招贼来偷的:)
mov DATA,esi
.repeat
.if esi >=5h ;每五循环锁定一次
invoke ReadProcessMemory,hProcess,ADD_DATA,addr add2data,sizeof add2data,NULL
add add2data,228h;游戏中真正的保存金钱数的地址
invoke WriteProcessMemory,hProcess,add2data,addr DATA,sizeof DATA,NULL ;写入钱数
xor esi ,esi ;循环次数清0
.endif
invoke Sleep,1000 ;定时一秒
inc esi ;循环次数加一
invoke GetExitCodeProcess,hProcess,addr IsRun ;游戏程序还在运行吗?
invoke GetAsyncKeyState,VK_SUBTRACT ;按了“-”键吗?
.until eax || IsRun!=STILL_ACTIVE ;如果游戏退出或按了“-”键则结束循环
ret
_WriteProcessData endp ;--------------------- ;写入补丁代码,共两处 ;---------------------
_WritePathCode proc hProcess
jmp @F
WRITE_CODE1_START: ;补丁代码一,含义见下面
db 0A3h,0FCh,0Fh,83h,00h,0FFh,52h,18h,33h,0C9h,0E9h,0E0h,0FBh,0FFh,0FFh
WRITE_CODE1_END equ this byte ;00494A81 A3 FC0F8300 mov dword ptr [00830FFC], eax ;补丁一源码 ;00494A86 FF52 18 call dword ptr [edx+18] ;00494A89 33C9 xor ecx, ecx ;00494A8B ^ E9 E0FBFFFF jmp 00494670
WRITE_CODE2_START: ;补丁代码二,含义见下面
db 0E9h,11h,04h,00h,00h
WRITE_CODE2_END equ this byte ;0049466B E9 11040000 jmp 00494A81 ;补丁二源码
@@:
mov eax ,WRITE_CODE1_START
invoke WriteProcessMemory,hProcess,ADD_CODE1,eax ,WRITE_CODE1_END-WRITE_CODE1_START,NULL ;写入补丁一
mov eax ,WRITE_CODE2_START
invoke WriteProcessMemory,hProcess,ADD_CODE2,eax ,WRITE_CODE2_END-WRITE_CODE2_START,NULL ;写入补丁二
ret
_WritePathCode endp ;------------------------------------------------------------------------ ;把本程序拷入游戏文件夹,运行本程序,游戏被启动,本程序在后台运行,无界面 ;本程序运行后启动“ra2.exe”,再由“ra2.exe”启动游戏程序,之后“ra2.exe” ;无用了,停掉它以节约内存。 ;------------------------------------------------------------------------
_StartGame proc
LOCAL StartInfo:STARTUPINFO
LOCAL PI:PROCESS_INFORMATION
LOCAL GamehProcess
invoke RtlZeroMemory,addr StartInfo,sizeof STARTUPINFO
mov StartInfo.cb,sizeof STARTUPINFO
mov ecx ,GAME_NAME
xor edx ,edx
invoke CreateProcess,edx ,ecx ,edx ,edx ,edx ,edx ,edx ,edx ,addr StartInfo,addr PI ;启动游戏
.repeat
invoke Sleep,100 ;等10秒,游戏程序应该启动了吧?
invoke _GetProcessHandle
.until eax
mov GamehProcess,eax
invoke _WritePathCode,eax ;打补丁
invoke Sleep,9000
invoke TerminateProcess,PI.hProcess,0h ;没用了,停掉它
invoke CloseHandle,PI.hProcess ;释放内存
mov eax ,GamehProcess
ret
GAME_NAME:
db "ra2.exe" ,0
_StartGame endp
start:
MAIN proc
LOCAL msg:MSG
LOCAL hProcess,MutexName
invoke _StartGame ;启动游戏
mov hProcess,eax
mov eax ,"2ar"
mov MutexName,eax
invoke CreateMutex,NULL,TRUE ,addr MutexName
invoke GetLastError
.if eax !=ERROR_ALREADY_EXISTS ;只让本程序的一个实例运行
invoke RegisterHotKey,NULL,VK_MULTIPLY,0h,VK_MULTIPLY ;注册热键“*”
invoke RegisterHotKey,NULL,'X',MOD_CONTROL OR MOD_ALT,'X' ;注册热键“Ctrl+Alt+X”
.while 1
invoke GetMessage,addr msg,NULL,NULL,NULL ;等待消息
.if msg.message==WM_HOTKEY ;热键消息
.break .if msg.wParam=='X' ;按了热键“Ctrl+Alt+X”则退出本程序
.if msg.wParam==VK_MULTIPLY ;按了热键“*”
invoke MessageBeep,MB_OK ;发声提示游戏者,按键收到,该做的本程序都做过了
invoke SetCursorPos,9h,9h ;把鼠标置于屏幕左上角,提醒游戏者,第一遍搜索时特别有用
invoke GetCurrentProcess
invoke EmptyWorkingSet,eax ;减少自己的内存占用量,不和游戏争内存
invoke _WriteProcessData,hProcess;去锁定它!
.break .if eax ==0 ;如果你没按“-”键,那一定是游戏退出了,咱也退出吧
.endif
.endif
.endw
invoke UnregisterHotKey,NULL,VK_MULTIPLY ;以下为退出前的清理工作
invoke UnregisterHotKey,NULL,'X'
invoke CloseHandle,hProcess
invoke ExitProcess,NULL
.endif
ret
MAIN endp end start
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)