?? 逆向分析.txt
字號:
標 題: 【原創】第一次嘗試逆向分析,這是一個游戲里的部分函數.用來實現用戶結構體不停的變換防止外掛.
作 者: ericzw
時 間: 2007-12-14,23:06
鏈 接: http://bbs.pediy.com/showthread.php?t=56577
:00436100 56 push esi ;esi入棧,因為esi要保存到后面要使用
:00436101 8BF1 mov esi, ecx ;esi=ecx
:00436103 8B4E08 mov ecx, dword ptr [esi+08];ecx=內存esi+08處
:00436106 85C9 test ecx, ecx ;測試ecx
:00436108 7419 je 00436123 ;為0則跳轉到00436123處
:0043610A E821FCFEFF call 00425D30 ;調用425d30處函數
:0043610F 8B4E08 mov ecx, dword ptr [esi+08];ecx=esi+8
:00436112 85C9 test ecx, ecx ;測試ecx
:00436114 7406 je 0043611C ;為0跳轉
:00436116 8B01 mov eax, dword ptr [ecx] ;ecx=內存ecx的值
:00436118 6A01 push 00000001 ;壓棧(傳一個參數)
:0043611A FF10 call dword ptr [eax] ;調用函數,函數地址在內存eax處
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00436114(C)
|
:0043611C C7460800000000 mov [esi+08], 00000000 ;內存esi+08=0
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00436108(C)
|
:00436123 8B0D34E09000 mov ecx, dword ptr [0090E034];ecx=內存90e034的值
:00436129 5E pop esi ;esi出棧
:0043612A E931371F00 jmp 00629860 ;跳轉到629860
:0043612F 90 nop
* Referenced by a CALL at Address:
|:00435435
|
:00436130 6AFF push FFFFFFFF ;FFFFFFFF入棧
:00436132 684B758200 push 0082754B ;入棧
:00436137 64A100000000 mov eax, dword ptr fs:[00000000];eax=SEH鏈指針(NT_TIB結構第一項指向的EXCEPTION_REGISRATION結構的Prev(下一個結構的地址)
:0043613D 50 push eax ;SEH地址入棧
:0043613E 64892500000000 mov dword ptr fs:[00000000], esp;設置函數的當前的SEH鏈,鏈地址是82754b
:00436145 51 push ecx ;ecx入棧
:00436146 56 push esi ;esi入棧
:00436147 8BF1 mov esi, ecx ;esi=ecx
:00436149 57 push edi ;edi入棧
:0043614A 68440B0000 push 00000B44 ;b44入棧
:0043614F 8B4608 mov eax, dword ptr [esi+08] ;eax=esi+08
:00436152 8B781C mov edi, dword ptr [eax+1C] ;edi=eax+1c
:00436155 E816702B00 call 006ED170 ;函數006ed170
:0043615A 83C404 add esp, 00000004 ;丟棄一個堆棧值
:0043615D 89442408 mov dword ptr [esp+08], eax ;esp+8=eax
:00436161 85C0 test eax, eax ;測試eax是否為0
:00436163 C744241400000000 mov [esp+14], 00000000 ;esp+14=0
:0043616B 740A je 00436177 ;根據上面eax的測試結果來跳轉
:0043616D 57 push edi ;edi入棧
:0043616E 8BC8 mov ecx, eax ;ecx=eax
:00436170 E8FB700200 call 0045D270 ;函數45d270
:00436175 EB02 jmp 00436179 ;跳轉到436179
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0043616B(C)
|
:00436177 33C0 xor eax, eax ;根據上面的eax為0跳轉到這 eax再次清0(其實這句可要可不要,因為eax已經是0了,可見程序員寫的代碼
還是有點重復)
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00436175(U)
|
:00436179 894624 mov dword ptr [esi+24], eax ;關鍵地方:(這就是血的基址說明有以下2點 : 1.當eax為0時,就表示用戶正在登錄游戲,或者在選擇人物
的時候. 用戶的數據結構體當時還沒有取到所以為0 2.就是用戶已經正常登錄了,用來不停的更新用戶數據,比如當前血量、藍值等.esi為基址再加上偏移24就查找到了內存某一塊地方x, 其實x就是一個結構 定義了人物的各種屬性 結構+偏移25ch就得到了當前用戶結構,如:當前多少血量,反過來想的話就是用程序到此處去取結構體的地址,結構體的地址再加偏移就是具體的用戶值
)
:0043617C 5F pop edi ;edi出棧
:0043617D 85C0 test eax, eax ;再次測試eax是否為0
:0043617F C7442410FFFFFFFF mov [esp+10], FFFFFFFF ;esp+10=ffffffff
:00436187 5E pop esi ;esi出棧
:00436188 7525 jne 004361AF ;如果eax不為0就跳轉,如果eax為0就從下面去創建用戶信息,,不為0就不需要創建了直接跳到4361af處
:0043618A 68AC030000 push 000003AC ;入棧
* Possible StringData Ref from Data Obj ->"CECGameRun::CreateHostPlayer"
|
:0043618F 6820648C00 push 008C6420 ;入棧
:00436194 6A02 push 00000002 ;入棧
:00436196 E8A5A90000 call 00440B40 ;函數
:0043619B 83C40C add esp, 0000000C ;丟棄一個4字節棧
:0043619E 32C0 xor al, al ;al=0 ,這個值是用作這個函數的返回值,值上級函數查詢使用
:004361A0 8B4C2404 mov ecx, dword ptr [esp+04] ;ecx=esp+4
:004361A4 64890D00000000 mov dword ptr fs:[00000000], ecx;撒消SEH鏈
:004361AB 83C410 add esp, 00000010 ;還給堆棧4個字
:004361AE C3 ret ;函數返回
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00436188(C)
|
:004361AF 8B4C2404 mov ecx, dword ptr [esp+04] ;這里是用戶已經登錄的返回
:004361B3 B001 mov al, 01 ;al=1,這個值是用作這個函數的返回值,值上級函數查詢使用
:004361B5 64890D00000000 mov dword ptr fs:[00000000], ecx;撒消SEH鏈
:004361BC 83C410 add esp, 00000010 ;還給堆棧4個字
:004361BF C3 ret ;函數返回
下面代碼實現讀取用戶當前血量,重啟游戲后還是能再次讀取到。
代碼:
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
include hook.inc
includelib hook.lib
IDD_DIALOG1 equ 101
IDC_EDIT1 equ 1000
IDC_EDIT2 equ 1001
IDC_EDIT3 equ 1002
IDC_EDIT4 equ 1003
IDC_BUTTON1 equ 1004
IDC_STATIC equ -1
IDT_TIME equ 1
ELE_RAW EQU 02E0A424h
ELE_HP EQU 06E68270H
ELE_MP EQU 025CH
ELE_MAXHP EQU 06E68288H
ELE_MAXMP EQU 06E68284H
.data?
hInstance dword ?
hProcess dword ?;打開的進程
stMsg MSG <?>;消息結構
dwRaw dword ?
dwHp dword ?
dwMp dword ?
dwMaxHp dword ?
dwMaxMp dword ?
.data
szErr byte '游戲并沒有啟動,請先啟動游戲!',0
szErr2 byte '權限不夠,打開進程失敗!',0
szTitle byte 'QElementClient Window',0
.code
_DiaProc proc uses ebx esi edi hWnd,uMsg,wParam,lParam
local @ProcessId
mov eax,uMsg
.if eax==WM_COMMAND
mov eax,wParam
.if ax==IDC_BUTTON1
invoke _msg
.endif
.elseif eax==WM_TIMER
invoke ReadProcessMemory,hProcess,ELE_RAW,addr dwRaw,4,NULL
add dwRaw,ELE_MP
invoke ReadProcessMemory,hProcess,dwRaw,addr dwMp,4,NULL
invoke SetDlgItemInt,hWnd,IDC_EDIT1,dwMp,FALSE
.elseif eax==WM_CLOSE
invoke UninstallHook
invoke DestroyWindow,hWnd
invoke PostQuitMessage,-1
.elseif eax==WM_INITDIALOG
invoke SetTimer,hWnd,IDT_TIME,1000,NULL
invoke FindWindow,addr szTitle,NULL
mov ebx,eax
invoke GetWindowThreadProcessId,ebx,addr @ProcessId
invoke OpenProcess,PROCESS_VM_OPERATION OR PROCESS_VM_READ OR PROCESS_VM_WRITE OR PROCESS_CREATE_THREAD,NULL,@ProcessId
.if eax
mov hProcess,eax
.else
invoke MessageBox,NULL,addr szErr2,0,MB_OK
.endif
invoke InstallHook,hWnd
.else
mov eax,FALSE
RET
.endif
mov eax,TRUE
RET
_DiaProc endp
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke FindWindow,addr szTitle,NULL
.if eax
invoke CreateDialogParam,hInstance,IDD_DIALOG1,eax,addr _DiaProc,NULL
invoke ShowWindow,eax,SW_SHOW
.while TRUE
invoke GetMessage,addr stMsg,NULL,0,0
.break .if !eax
invoke TranslateMessage,addr stMsg
invoke DispatchMessage,addr stMsg
.endw
.else
invoke MessageBox,NULL,addr szErr,0,MB_OK
.endif
invoke ExitProcess,-1
end start
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -