ASM:代码洞穴终止

时间:2012-07-30 08:34:43

标签: assembly x86 direct3d

这实际上是反汇编的Windows 7 D3D9.dll DrawIndexedPrimitive方法。

CPU Disasm
Address   Hex dump          Command                                  Comments
58EBB6B1   .  8BFF          MOV EDI,EDI
58EBB6B3  /.  55            PUSH EBP
58EBB6B4  |.  8BEC          MOV EBP,ESP
58EBB6B6  |.  6A FF         PUSH -1
58EBB6B8  |.  68 28BE0259   PUSH 5902BE28                            ; Entry point
58EBB6BD  |.  64:A1 0000000 MOV EAX,DWORD PTR FS:[0]
58EBB6C3  |.  50            PUSH EAX
58EBB6C4  |.  83EC 20       SUB ESP,20
58EBB6C7  |.  53            PUSH EBX
58EBB6C8  |.  56            PUSH ESI
58EBB6C9  |.  57            PUSH EDI
58EBB6CA  |.  A1 50920359   MOV EAX,DWORD PTR DS:[59039250]
58EBB6CF  |.  33C5          XOR EAX,EBP
58EBB6D1  |.  50            PUSH EAX
58EBB6D2  |.  8D45 F4       LEA EAX,[EBP-0C]
58EBB6D5  |.  64:A3 0000000 MOV DWORD PTR FS:[0],EAX
58EBB6DB  |.  8965 F0       MOV DWORD PTR SS:[EBP-10],ESP
58EBB6DE  |.  8B7D 08       MOV EDI,DWORD PTR SS:[EBP+8]
58EBB6E1  |.  33DB          XOR EBX,EBX
58EBB6E3  |.  3BFB          CMP EDI,EBX
58EBB6E5  |.- 0F84 BA030000 JE 58EBBAA5
58EBB6EB  |.  8D77 04       LEA ESI,[EDI+4]
58EBB6EE  |.  8975 EC       MOV DWORD PTR SS:[EBP-14],ESI
58EBB6F1  |>  8975 D4       MOV DWORD PTR SS:[EBP-2C],ESI
58EBB6F4  |.  895D D8       MOV DWORD PTR SS:[EBP-28],EBX
58EBB6F7  |.  395E 18       CMP DWORD PTR DS:[ESI+18],EBX
58EBB6FA  |.- 0F85 66DE0500 JNE 58F19566
58EBB700  |>  F647 2C 02    TEST BYTE PTR DS:[EDI+2C],02
58EBB704  |.  895D FC       MOV DWORD PTR SS:[EBP-4],EBX
58EBB707  |.- 0F85 65DE0500 JNE 58F19572
58EBB70D  |.  818F 0C2A0000 OR DWORD PTR DS:[EDI+2A0C],40000000
58EBB717  |.  F647 2C 08    TEST BYTE PTR DS:[EDI+2C],08
58EBB71B  |.  C645 FC 01    MOV BYTE PTR SS:[EBP-4],1
58EBB71F  |.- 0F85 54030000 JNE 58EBBA79
58EBB725  |>  8B8F F02C0000 MOV ECX,DWORD PTR DS:[EDI+2CF0]
58EBB72B  |.  8B55 10       MOV EDX,DWORD PTR SS:[EBP+10]
58EBB72E  |.  8DB7 3C2B0000 LEA ESI,[EDI+2B3C]
58EBB734  |.  8951 14       MOV DWORD PTR DS:[ECX+14],EDX
58EBB737  |.  399E 70010000 CMP DWORD PTR DS:[ESI+170],EBX
58EBB73D  |.- 0F85 54DE0500 JNE 58F19597
58EBB743  |>  F787 0C2A0000 TEST DWORD PTR DS:[EDI+2A0C],00000200
58EBB74D  |.- 0F85 AE020000 JNE 58EBBA01
58EBB753  |>  8B4D 20       MOV ECX,DWORD PTR SS:[EBP+20]
58EBB756  |.  8B55 1C       MOV EDX,DWORD PTR SS:[EBP+1C]
58EBB759  |.  8B45 18       MOV EAX,DWORD PTR SS:[EBP+18]
58EBB75C  |.  51            PUSH ECX
58EBB75D  |.  8B4D 14       MOV ECX,DWORD PTR SS:[EBP+14]
58EBB760  |.  52            PUSH EDX
58EBB761  |.  8B55 10       MOV EDX,DWORD PTR SS:[EBP+10]
58EBB764  |.  50            PUSH EAX
58EBB765  |.  8B45 0C       MOV EAX,DWORD PTR SS:[EBP+0C]
58EBB768  |.  51            PUSH ECX
58EBB769  |.  8B8F 0C2D0000 MOV ECX,DWORD PTR DS:[EDI+2D0C]
58EBB76F  |.  52            PUSH EDX
58EBB770  |.  50            PUSH EAX
58EBB771  |.  57            PUSH EDI
58EBB772  |.  FFD1          CALL ECX
58EBB774  |.  8B45 EC       MOV EAX,DWORD PTR SS:[EBP-14]
58EBB777  |.  81A7 0C2A0000 AND DWORD PTR DS:[EDI+2A0C],BFFFFFFF
58EBB781  |.  83C4 1C       ADD ESP,1C
58EBB784  |.  3958 18       CMP DWORD PTR DS:[EAX+18],EBX
58EBB787  |.- 0F85 6ADF0500 JNE 58F196F7
58EBB78D  |>  33C0          XOR EAX,EAX
58EBB78F  |.  8B4D F4       MOV ECX,DWORD PTR SS:[EBP-0C]
58EBB792  |.  64:890D 00000 MOV DWORD PTR FS:[0],ECX
58EBB799  |.  59            POP ECX
58EBB79A  |.  5F            POP EDI
58EBB79B  |.  5E            POP ESI
58EBB79C  |.  5B            POP EBX
58EBB79D  |.  8BE5          MOV ESP,EBP
58EBB79F  |.  5D            POP EBP
58EBB7A0  \.  C2 1C00       RETN 1C

说,我用跳转代码洞替换58EBB6DB(3字节)和58EBB6DE(3字节)。这将替换6字节代码(跳转到我的代码洞穴函数地址5个字节并且删除第6个字节)。

然后,我在我的代码洞穴函数中放回了替换的原始6字节代码。 “MOV DWORD PTR SS:[EBP-10],ESP”和“MOV EDI,DWORD PTR SS:[EBP + 8]”。然后我的代码洞穴开始做我的东西......

我的代码洞里有一个If-Then-Else。

假设
1)当结果为真时,我的代码洞穴返回到58EBB6E1地址 2)当结果为false时,此DrawIndexedPrimitive方法将在我的代码洞穴编码处终止。

当我的代码洞穴返回到58EBB6E1地址的下一条指令行时,我没有第一个问题。但当我终止它时,游戏就崩溃了。

这是我终止该方法的方法。

TERMINATE:
        POPAD     // clear the previous PUSHAD
        POPFD     // clear the previous PUSHFD

            // restore what DrawIndexedPrimitive method called...
        POP EDI
        POP ESI
        POP EBX
        MOV ESP,EBP
        POP EBP
        RETN 1C    //CD3DBase::DrawIndexedPrimitive(enum  _D3DPRIMITIVETYPE, int, unsigned int, unsigned int, unsigned int, unsigned int)

1 个答案:

答案 0 :(得分:1)

我不确定为什么你将跳转到目前为止的方法,然后不得不担心将原始方法代码复制到目标代码中,并恢复原始方法已经进行的堆栈更改。也许你可以启发我们?

轻松拦截方法调用的方法已经以mov edi, edi的形式出现了 - 一个2字节的NOP用于热补丁,允许你用短暂的跳转来原子地替换它来跳远你放在方法之前的5个空字节中。请参阅:hot patching

明确地 - 如果你在方法之前查看字节,那么应该有(至少)5 nop条指令。补丁应按如下方式执行:

  1. 在补丁方法之前的5个字节中写一个5字节的长跳转到补丁码。
  2. 将2字节短跳转写入方法开头的步骤1中写入的跳转(替换mov edi, edi)。这只是0xEB 0xF9
  3. 根据补丁中的处理,您可以:
    • 通过跳转到58EBB6B3继续该方法(即跳过补丁的短跳)。
    • 执行ret 0x1c
    • 跳过该方法