- 原创 [基础1] 什么是基址?
- 象一棵苹果树,树有根,树上也有苹果,某个苹果对应某个偏移,而树根就是基址,通过基址往上找就能找到某个苹果而找到的这个苹果,相对于有个偏移。通过基址+偏移就能确定是哪个苹果。例如:基址=00401000
- 偏移是20,代表1号苹果,那OD里:dd [00401000]+20 就能找到这个1号苹果。dd命令 是以内存地址的方式查看数据。
- 原创 [基础2] 为什么要找基址?
- 因为游戏退出基址不会变化,只有游戏更新后才会变化,而要是用找到的内存地址,例如:血的内存地址,游戏退出是会变化的,不方便我们编写辅助调用。
- 原创 [基础3] 用什么工具适合找基址和偏移?
- Ollydbg(简称OD)Cheat Engine(简称CE)强烈推荐这两款游戏数据分析高手都必备的工具。
- 原创 [基础4] 偏移最多有多少级?
- 最少偏移就是一个基址代表一个数据,例如:dd 00401000 就是血数量最多偏移可以是无穷大,分析过最多的是20多偏移。例如:dd
- [00401000]+20 20就是一级偏移 而类推:
- dd [[00401000]+20]+30 30就是二级偏移
- 原创 [基础5] 什么是CALL?
- CALL就是相当于易语言里的子程序,相当于C++里面的函数。每个CALL都有用途,很多独立的功能都可以封装在CALL里,这样调用这个CALL也就调用了对应封装的功能。
- CALL有“参数”,也有“返回值”“参数”可以是没有,也可以是多个。“返回值”一般通过EAX寄存器返回。
- 原创 [基础6] 如何识别CALL有多少个参数?
- 实战举例说明:
- 这个CALL:
- 0042FC9F > $ E8 ECCF0000 CALL start.0043CC90 //内存地址是0043CC90
- 进入CALL里面,OD里是用enter回车键进入:
- 0043CC90 /$ 55 PUSH EBP
- 0043CC91 |. 8BEC MOV EBP,ESP
- 0043CC93 |. 83EC 10 SUB ESP,10
- 0043CC96 |. A1 10F84500 MOV EAX,DWORD PTR DS:[45F810]
- 0043CC9B |. 8365 F8 00 AND DWORD PTR SS:[EBP-8],0
- 0043CC9F |. 8365 FC 00 AND DWORD PTR SS:[EBP-4],0
- 0043CCA3 |. 53 PUSH EBX
- 0043CCA4 |. 57 PUSH EDI
- 0043CCA5 |. BF 4EE640BB MOV EDI,BB40E64E
- 0043CCAA |. 3BC7 CMP EAX,EDI
- 0043CCAC |. BB 0000FFFF MOV EBX,FFFF0000
- 0043CCB1 |. 74 0D JE SHORT start.0043CCC0
- 0043CCB3 |. 85C3 TEST EBX,EAX
- 0043CCB5 |. 74 09 JE SHORT start.0043CCC0
- 0043CCB7 |. F7D0 NOT EAX
- 0043CCB9 |. A3 14F84500 MOV DWORD PTR DS:[45F814],EAX
- 0043CCBE |. EB 60 JMP SHORT start.0043CD20
- 0043CCC0 |> 56 PUSH ESI
- 0043CCC1 |. 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
- 0043CCC4 |. 50 PUSH EAX ; /pFileTime
- 0043CCC5 |. FF15 74C14400 CALL DWORD PTR DS:[<&KERNEL32.GetSystemT>; \\GetSystemTimeAsFileTime
- 0043CCCB |. 8B75 FC MOV ESI,DWORD PTR SS:[EBP-4]
- 0043CCCE |. 3375 F8 XOR ESI,DWORD PTR SS:[EBP-8]
- 0043CCD1 |. FF15 70C24400 CALL DWORD PTR DS:[<&KERNEL32.GetCurrent>; [GetCurrentProcessId
- 0043CCD7 |. 33F0 XOR ESI,EAX
- 0043CCD9 |. FF15 7CC24400 CALL DWORD PTR DS:[<&KERNEL32.GetCurrent>; [GetCurrentThreadId
- 0043CCDF |. 33F0 XOR ESI,EAX
- 0043CCE1 |. FF15 B4C14400 CALL DWORD PTR DS:[<&KERNEL32.GetTickCou>; [GetTickCount
- 0043CCE7 |. 33F0 XOR ESI,EAX
- 0043CCE9 |. 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10]
- 0043CCEC |. 50 PUSH EAX ; /pPerformanceCount
- 0043CCED |. FF15 70C14400 CALL DWORD PTR DS:[<&KERNEL32.QueryPerfo>; \\QueryPerformanceCounter
- 0043CCF3 |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
- 0043CCF6 |. 3345 F0 XOR EAX,DWORD PTR SS:[EBP-10]
- 0043CCF9 |. 33F0 XOR ESI,EAX
- 0043CCFB |. 3BF7 CMP ESI,EDI
- 0043CCFD |. 75 07 JNZ SHORT start.0043CD06
- 0043CCFF |. BE 4FE640BB MOV ESI,BB40E64F
- 0043CD04 |. EB 0B JMP SHORT start.0043CD11
- 0043CD06 |> 85F3 TEST EBX,ESI
- 0043CD08 |. 75 07 JNZ SHORT start.0043CD11
- 0043CD0A |. 8BC6 MOV EAX,ESI
- 0043CD0C |. C1E0 10 SHL EAX,10
- 0043CD0F |. 0BF0 OR ESI,EAX
- 0043CD11 |> 8935 10F84500 MOV DWORD PTR DS:[45F810],ESI
- 0043CD17 |. F7D6 NOT ESI
- 0043CD19 |. 8935 14F84500 MOV DWORD PTR DS:[45F814],ESI
- 0043CD1F |. 5E POP ESI
- 0043CD20 |> 5F POP EDI
- 0043CD21 |. 5B POP EBX
- 0043CD22 |. C9 LEAVE
- 0043CD23 \\. C3 RETN //注意看这个retn返回命令,直接retn返回说明该CALL没参数。
- =================================================
- 再举例 说明有参数的识别:
- 0040C0B6 |. 6A FF PUSH -1 //参数
- 0040C0B8 |. 53 PUSH EBX //参数
- 0040C0B9 |. 50 PUSH EAX //参数 可以看这里有多少个push 代表有多少个参数。是在CALL的前面
- 0040C0BA |. 8D8C24 D00000>LEA ECX,DWORD PTR SS:[ESP+D0]
- 0040C0C1 |. C68424 180100>MOV BYTE PTR SS:[ESP+118],4
- 0040C0C9 |. E8 02C2FFFF CALL start.004082D0 //这个CALL,进入里面
- 得到:
- 004082D0 /$ 53 PUSH EBX
- 004082D1 |. 8B5C24 08 MOV EBX,DWORD PTR SS:[ESP+8]
- 004082D5 |. 55 PUSH EBP
- 004082D6 |. 8B6C24 10 MOV EBP,DWORD PTR SS:[ESP+10]
- 004082DA |. 396B 14 CMP DWORD PTR DS:[EBX+14],EBP
- 004082DD |. 56 PUSH ESI
- 004082DE |. 57 PUSH EDI
- 004082DF |. 8BF1 MOV ESI,ECX
- 004082E1 |. 73 05 JNB SHORT start.004082E8
- 004082E3 |. E8 ACE70300 CALL start.00446A94
- 004082E8 |> 8B7B 14 MOV EDI,DWORD PTR DS:[EBX+14]
- 004082EB |. 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C]
- 00408317 |. C2 0C00 RETN 0C //看这里 是返回 0c 是16机制,转成10进制 12/4=3个参数 为什么要除以4,因为1个push 占用4个字节 3个push就是3*4=12字节
- 原创 [基础7] 如何调试CALL可能对应的功能?
- 当你在找某个CALL数据的时候,例如:吃药CALL,吃药CALL相关的CALL你可以通过 :1.无参数CALL,可以直接OD里,右键-二进制-用NOP填充
- 该CALL,填充后,回游戏看是否能吃药,能的话,说明与吃药CALL不想干。2.有参数CALL,可以直接修改CALL,OD里按空格键修改反汇编,修改为add
- esp,4 4代表1个参数,如果是三个参数的话,就修改为:add
- esp,0c 这样使堆栈平衡了,游戏才不会出错,然后也是回游戏看是否能吃药,能的话,说明也是与吃药CALL不想干的CALL。
- 原创 [基础8] 知道了有参数CALL的参数数据,如何调试CALL效果?
- 可以通过“代码注入器”这个工具来调试CALL效果,举例 有参数CALL:push eaxpush edxcall
- 00401000//上CALL有2个参数,通过PUSH看出来的,这2个参数的值假设分别是push 1push
- 2那我们在代码注入器如何来写汇编的呢?具体是:push 1push 2call 00401000然后按下 注入远程代码
- 就能看效果了。无参数CALL直接写call 00401000即可。
- 原创 [基础9] 能达到CALL效果,但游戏出错怎么办?
- 用代码注入器测试能达到CALL效果,但游戏出错了,这如何解决?这通常是由于有参数的CALL,有个堆栈不平衡导致的,那如何恢复堆栈平衡呢?举例
- 有参数CALL:push 1push 2call
- 00401000这个CALL有2个参数,代码注入器能达到效果,但会出错,这时候要加上堆栈平衡汇编语句具体是:push 1push 2call
- 00401000add esp,81个参数是4字节,2个参数是8字节,所以是add esp,8这样就不会达到CALL效果同时游戏出错了。
- 原创 [基础10] 游戏数据分析“汇编”很重要吗?
- 汇编看得懂就行,例如:mov eax,ebx 是什么意思?
-
- mov eax,[00401000] 是什么意思?你能看懂就OK了。
- 原创 [基础11] 什么是内存挂,什么是变态挂,什么是脱机挂?
- 内存挂就是获取游戏里面的CALL数据,主要以调用游戏数据为主。变态挂就是修改游戏里面的数据,例如:像单机游戏一样修改数据,或者修改汇编,达到游戏本没的功能。主要以修改游戏数据以及汇编为主。脱机挂就是向服务器发送封包数据,可以不用开客户端也能挂机。主要以封包数据为主。
- 原创 [基础12] 发送封包的函数都有哪些?OD如何下断?
- sendsendtoWSASendWSASendTo这四个是常用的发送封包函数,OD里获取CALL数据的时候相当有用。OD下断点就是:bp sendbp
- sendtobp WSASendbp WSASendTo不同的游戏可能用了不同的发送封包函数,在实际的实践当中,可以灵活运用。列出2个最常用函数原型:int
- send( __in SOCKET
- s, //封包ID __in const char
- *buf, //封包数据 __in int len,
- //封包大小 __in int flags
- //标志位);====================int WSASend( __in SOCKET
- s, //封包ID __in LPWSABUF
- lpBuffers, //封包数据 __in DWORD
- dwBufferCount, //封包数量 __out LPDWORD
- lpNumberOfBytesSent, //封包大小 __in DWORD dwFlags,
- //标志位 __in LPWSAOVERLAPPED
- lpOverlapped, //指向WSAOVERLAPPED结构指针 __in
- LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
- //完成例程的指针);以上了解了解就ok。
- 原创 [基础13] 什么是OD死码,如何设立?为什么要设立?
- =======================什么是OD死码?OD死码指的就是OD反汇编中游戏更新后也不变的汇编。=======================如何设立?规则:最多8条汇编,因为OD里ctrl+s搜的时候最多只能8条哪些汇编不能用于OD死码:call
- 内存地址
- jz/jnz/je(等跳转语句) 内存地址
-
- mov eax,[ecx+0abc] 偏移abc比较大的不可以。
-
- mov eax,[esp+30]
- 汇编里有ESP堆栈寄存器的不可以,后面跟的偏移+30会变化=======================为什么要设立?因为游戏更新基址,较大的偏移会变化,为了方便,所以设立OD死码,方便快速获取游戏更新后的相关数据。=======================
|