D3D9 HOOK [透视原理]

最近研究了下FPS游戏透视方法,市面上透视大概分为两种,一种是方框透视 就是在游戏角色模型上画一个框,另外一种就是Z缓冲区透视,这种透视原理是对指定模型(一般是人物模型)禁用Z缓冲进行深度测试,当然这两种都可以是基于D3D的,第一种方块透视也可以是不用D3D绘制方块,找到人物坐标 直接转换坐标为投影视图坐标,再用GDI绘制到屏幕上,也可以

今天我想说的是D3D Z缓冲透视,你需要一些DX基础知识,可以百度下  很多资料、下面代码以D3D9为例


首先Hook Dx,Hook Dx 有不同的方法,网上也应该能找到许多现成的代码,我就说下我常用的。

Hook Dx函数之前 我们要找到函数所在类的指针,然后再通过保存指针的内存地址+偏移定位到成员函数内存地址 ,其他的就和Hook普通函数一样。


Dx程序在调用Dx绘图之前要调用 Direct3DCreate9 获得D3D接口指针IDirect3D9, 通过IDirect3D9对象函数CreateDevice创建设备 获得设备指针、


下面代码演示如何获得这几个指针:

void OnHookInit()//CreateDevice  
{  
//这里只是hookDirect3DCreate9  
    pC=GetProcAddress(GetModuleHandle("d3d9.dll"),"Direct3DCreate9");//获得内存地址  
    DWORD oldpro=0;  
    memcpy(d3dcen5bytes,pC,5);  
    VirtualProtect(pC,5,PAGE_EXECUTE_READWRITE,&oldpro);  
    *(BYTE*)pC=0xe9;//0xe9在汇编中是跳转指令操作码  
    *(DWORD*)((BYTE*)pC+1)=(DWORD)hookedDirect3DCreate9-(DWORD)pC-5;//目标地址-原地址-5  
}  
  
  
  ---------------------------------------------------------------  
  
//当运行到Direct3DCreate9时跳转到这里  
IDirect3D9 * _stdcall hookedDirect3DCreate9(  
    UINT SDKVersion  
    )  
{  
    __asm pushad  
    memcpy(pC,d3dcen5bytes,5);//首先还原入口的5个字节  
    m_pD3D=Direct3DCreate9(SDKVersion);  
    if(m_pD3D){//如果成功  
        pCdev=(void*)*(DWORD*)(*(DWORD*)m_pD3D+0x40);//获得IDirect3D9::CreateDevice的地址指针  
  
        DWORD oldpro=0;  
        memcpy(devcen5bytes,pCdev,5);//保存IDirect3D9::CreateDevice入口5个字节  
        VirtualProtect(pCdev,5,PAGE_EXECUTE_READWRITE,&oldpro);  
        *(BYTE*)pCdev=0xe9;  
        *(DWORD*)((BYTE*)pCdev+1)=(DWORD)hookedCreateDevice-(DWORD)pCdev-5;  
  
    }  
    __asm popad  
        return m_pD3D;  
}  
  
//当运行到IDirect3D9::CreateDevice的时候跳转到这里  
HRESULT _stdcall hookedCreateDevice(  
                                  LPDIRECT3D9 pDx9,  
                                  UINT Adapter,  
                                  D3DDEVTYPE DeviceType,  
                                  HWND hFocusWindow,  
                                  DWORD BehaviorFlags,  
                                  D3DPRESENT_PARAMETERS * pPresentationParameters,  
                                  IDirect3DDevice9 ** ppReturnedDeviceInterface  
  
                                  )  
{  
    __asm pushad  
  
  
        memcpy(pCdev,devcen5bytes,5);//先还原入口的5个字节  
  
  
    HRESULT ret=pDx9->CreateDevice( //创建设备  
        Adapter,  
        DeviceType,  
        hFocusWindow,  
        BehaviorFlags,  
        pPresentationParameters,  
        ppReturnedDeviceInterface);  
    //x*4=68  
  
      
    if (ret==D3D_OK)  
       {  
        //如果创建设备成功  
        //执行你的HOOK D3D设备对象成员函数代码  
        //以从缓存区顶点渲染函数为例  
  
       LPDIRECT3DDEVICE9 m_pDevice=*ppReturnedDeviceInterface;  
  
       DWORD oldpro2=0;  
        VirtualProtect(Dp,5,PAGE_EXECUTE_READWRITE,&oldpro2);  
        *(BYTE*)Dp=0xe9;  
        *(DWORD*)((BYTE*)Dp+1)=(DWORD)hookDrawIndexedPrimitive-(DWORD)Dp-5;  
  
               
         }  
  
    __asm popad  
    return ret;  
}  
  
//顶点缓存绘制hook函数  
HRESULT _stdcall hookDrawIndexedPrimitive(LPDIRECT3DDEVICE9 Device_Interface, D3DPRIMITIVETYPE Type, INT BaseIndex,UINT MinIndex, UINT NumVertices, UINT AAAAAAAA, UINT PrimitiveCount)   
      
{  
    __asm pushad  
  
    //----------------------------  
    LPDIRECT3DVERTEXBUFFER9 Stream_Data;  
    UINT Stride = 0;  
    UINT iOffsetInBytes =0;  
  
    if (Device_Interface->GetStreamSource(0,&Stream_Data,&iOffsetInBytes,&Stride) == D3D_OK)          
        Stream_Data->Release();  
  
            if (Stride==32)  
            {  
  
                Device_Interface->SetRenderState(D3DRS_ZENABLE,false);   
  
            }  
      
  
    //-----------------------------  
    if(pC && pCdev && Dp)  
        memcpy(Dp,Dp5bytes,5);//先还原IDirect3DDevice9::DrawIndexedPrimitive入口的5字节  
  
    HRESULT retdata= Device_Interface->DrawIndexedPrimitive(Type,BaseIndex,MinIndex,NumVertices,AAAAAAAA,PrimitiveCount);  
  
    if(pC && pCdev && Dp){  
        //DWORD oldpro=0;  
        //VirtualProtect(pPre,5,PAGE_EXECUTE_READWRITE,&oldpro);  
        //调用完IDirect3DDevice9::DrawIndexedPrimitive后再hook一次  
        *(BYTE*)Dp=0xe9;  
        *(DWORD*)((BYTE*)Dp+1)=(DWORD)hookDrawIndexedPrimitive-(DWORD)Dp-5;  
    }  
  
    __asm popad  
        return retdata;  
}  

基本上的D3D Hook流程就完成了 ,对于上面的Hook代码需要的Dx程序 创建D3D设备之前钩住。还有种方法 是直接查找特征 获取指针。



何定位对象下的成员函数地址:

1.打开d3d9.h头文件

2.找到对象指针定义位置




3.下面从第一个对象成员函数开始数 直到DrawIndexedPrimitive函数的定义 函数位置是第83个函数 [ 函数顺序个数-1 * 4 = 函数内存地址]





DrawIndexedPrimitive是 (83-1)*4 = 328 16进制 0x148

然后Hook这个地址就行了。




本文代码测试环境 xp win7 32位 虚幻引擎系列游戏、







  • 7
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值