如何从中间函数钩子获取类指针

时间:2014-04-25 19:00:41

标签: c++ assembly x86 directx-9

我创建了一个示例中间函数钩子。但是当我取消引用一个指针时遇到了崩溃。 让我说我挂到中间 公开:virtual long __stdcall CD3DBase:DrawIndexedPrimitive(enum _D3DPRIMITIVETYPE, int, unsigned int, unsigned int, unsigned int, unsigned int)

位于d3d9.dll中。以下是CD3DBase:DrawIndexedPrimitive的开始汇编代码:

.text:10029760                 mov     edi, edi
.text:10029762                 push    ebp 
.text:10029763                 mov     ebp, esp 
.text:10029765                 push    0FFFFFFFFh 
.text:10029767                 push    offset loc_1014A0AC 
.text:1002976C                 mov     eax, large fs:0 
.text:10029772                 push    eax 
.text:10029773                 sub     esp, 28h 
.text:10029776                 push    ebx  

钩子从.text:10029765 push 0FFFFFFFFh开始 我只是改变它来跳转到我的功能。跳转语句像往常一样只有5个字节,0xE9(JMP) [Offset] 在我的函数中,我尝试获取类指针,因为我想用它来调用calss中的其他函数。下面是我的代码

LPDIRECT3DDEVICE9  g_deviceInterface; 
__declspec(naked) void WINAPI MyDipFunc()  
{ 

    //Here I get this pointer. As I know the this pointer is in EBP + 0x08 
    __asm mov EAX, DWORD PTR SS:[EBP + 0x08]  
    __asm mov  DWORD PTR DS:[g_deviceInterface], EAX  

    //Replace code.  
    __asm PUSH 0xFFFFFFFF  //2 
    __asm PUSH 0x67F3A0AC  //7 
    __asm MOV EAX,DWORD PTR FS:[0] //12 
    __asm PUSH EAX //13 
    __asm SUB ESP,0x28 //16 
}  

结果是在调用原始函数时遇到MyDipFunc但是当我执行g_deviceInterface->GetStreamSource(....)时它崩溃了。

注意:我知道类指针将通过被调用者CD3DBase:DrawIndexedPrimitive的第一个参数,即[EBP+8]

如果有人做错了,有人可以提出建议吗?

谢谢,

已编辑:有关我的问题的更清晰

我的假设是g_deviceInterface可能没有正确设置,因为类指针可能不在[EBP+0x08]中。我不知道如何获得应该存储在由CD3DBase:DrawIndexedPrimitive的调用者管理的堆栈中的某个位置的类指针。

已编辑2:我的完整挂钩功能

LPDIRECT3DDEVICE9  g_deviceInterface = NULL; 
__declspec(naked) void WINAPI MyDipFunc()  
{ 

    //Here I get this pointer. As I know the this pointer is in EBP + 0x08 
    __asm mov EAX, DWORD PTR SS:[EBP + 0x08]  
    __asm mov  DWORD PTR DS:[g_deviceInterface], EAX  

    //Replace code.  
    __asm PUSH 0xFFFFFFFF  //2 
    __asm PUSH 0x67F3A0AC  //7 
    __asm MOV EAX,DWORD PTR FS:[0] //12 
    __asm PUSH EAX //13 
    __asm SUB ESP,0x28 //16 

    if(g_deviceInterface != NULL)
    {
         LPDIRECT3DVERTEXBUFFER9 StreamData;
         UINT OffsetInBytes;
         UINT Stride;
         if(g_deviceInterface->GetStreamSource(0,&StreamData,&OffsetInBytes,&Stride) == D3D_OK) //Crash at this line
         {
              if(StreamData != NULL)
                   StreamData->Release();
         }
    }

    __asm jmp [DIPJmpBack] //Jump back to caller, DIPJmpBack contain address to jump
}

0 个答案:

没有答案