lannyboy
lannyboy

Reputation: 843

ASM: code cave termination

This is actually disassembled Windows 7 D3D9.dll DrawIndexedPrimitive method.

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

Say, I replace 58EBB6DB (3 bytes) and 58EBB6DE (3 bytes) with my jump code cave. This will replace the 6 bytes code (jump to my code cave function address for 5 bytes and nopping the 6th byte).

Then, I put back the replaced original 6 bytes code in my code cave function. "MOV DWORD PTR SS:[EBP-10],ESP" and "MOV EDI,DWORD PTR SS:[EBP+8]". Then my code cave starts to do my stuffs...

I have a If-Then-Else in my code cave.

Assuming
1) When the result is true, my code cave returns to 58EBB6E1 address.
2) When the result is false, this DrawIndexedPrimitive method will be terminated at my code cave coding.

I don't have issue with the first one when my code cave return to the next instruction line at 58EBB6E1 address. But when I terminated it, the game crashed.

This is how I terminated the method.

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)

Upvotes: 1

Views: 1997

Answers (1)

Iridium
Iridium

Reputation: 23721

I'm not really sure why you're putting your jump so far into the method, and then having to worry about replicating the original method code into your target code, and restoring the stack changes already made by the original method. Perhaps you can enlighten us?

The means to easily intercept method calls is already there in the form of the mov edi, edi - a 2-byte NOP intended for hot-patching by allowing you to atomically replace it with a short jump to a long jump you place in the 5 empty bytes immediately prior to the method. See: hot patching

Explicitly - if you look at the bytes before the method, there should be (at least) 5 nop instructions. The patch should be performed as follows:

  1. Write a 5 byte long-jump to your patch code in the 5 bytes preceeding the method being patched.
  2. Write a 2 byte short jump to the jump written in step 1 at the start of the method (replacing mov edi, edi). This will simply be 0xEB 0xF9.
  3. Based on the processing in your patch you can either:
    • Continue the method by jumping to 58EBB6B3 (i.e. skipping the short jump of the patch).
    • Skip the method by executing a ret 0x1c

Upvotes: 1

Related Questions