做辅助的基础知识

  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]
    004082EF  |.  2BFD          SUB EDI,EBP
    004082F1  |.  3BC7          CMP EAX,EDI
    004082F3  |.  73 02         JNB SHORT start.004082F7
    004082F5  |.  8BF8          MOV EDI,EAX
    004082F7  |>  3BF3          CMP ESI,EBX
    004082F9  |.  75 1F         JNZ SHORT start.0040831A
    004082FB  |.  6A FF         PUSH -1
    004082FD  |.  03FD          ADD EDI,EBP
    004082FF  |.  57            PUSH EDI
    00408300  |.  8BCE          MOV ECX,ESI
    00408302  |.  E8 99E6FFFF   CALL start.004069A0
    00408307  |.  55            PUSH EBP
    00408308  |.  6A 00         PUSH 0
    0040830A  |.  8BCE          MOV ECX,ESI
    0040830C  |.  E8 8FE6FFFF   CALL start.004069A0
    00408311  |.  5F            POP EDI
    00408312  |.  8BC6          MOV EAX,ESI
    00408314  |.  5E            POP ESI
    00408315  |.  5D            POP EBP
    00408316  |.  5B            POP EBX     
    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 eax
    push edx
    call 00401000

    //上CALL有2个参数,通过PUSH看出来的,这2个参数的值假设分别是
    push 1
    push 2

    那我们在代码注入器如何来写汇编的呢?

    具体是:
    push 1
    push 2
    call 00401000

    然后按下 注入远程代码 就能看效果了。

    无参数CALL直接写call 00401000即可。

  9. 能达到CALL效果,但游戏出错怎么办?

    用代码注入器测试能达到CALL效果,但游戏出错了,这如何解决?

    这通常是由于有参数的CALL,有个堆栈不平衡导致的,

    那如何恢复堆栈平衡呢?

    举例 有参数CALL:
    push 1
    push 2
    call 00401000

    这个CALL有2个参数,代码注入器能达到效果,但会出错,

    这时候要加上堆栈平衡汇编语句

    具体是:
    push 1
    push 2
    call 00401000
    add esp,8

    1个参数是4字节,2个参数是8字节,所以是add esp,8

    这样就不会达到CALL效果同时游戏出错了。

  10. 游戏数据分析“汇编”很重要吗?

    汇编看得懂就行,例如:mov eax,ebx 是什么意思?
                                                mov eax,[00401000] 是什么意思?

    你能看懂就OK了。

  11. 什么是内存挂,什么是变态挂,什么是脱机挂?

    内存挂就是获取游戏里面的CALL数据,主要以调用游戏数据为主。

    变态挂就是修改游戏里面的数据,例如:像单机游戏一样修改数据,或者修改汇编,达到游戏本没的功能。主要以修改游戏数据以及汇编为主。

    脱机挂就是向服务器发送封包数据,可以不用开客户端也能挂机。主要以封包数据为主。

  12. 发送封包的函数都有哪些?OD如何下断?

    send
    sendto
    WSASend
    WSASendTo

    这四个是常用的发送封包函数,OD里获取CALL数据的时候相当有用。


    OD下断点就是:

    bp send
    bp sendto
    bp WSASend
    bp 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死码,
    方便快速获取游戏更新后的相关数据。

    =======================


你可能感兴趣的:(E语言,OD,CE相关)