D3D9 HOOK [透视原理]

来源:互联网 发布:启明星软件金融 编辑:程序博客网 时间:2024/05/18 02:25
最近研究了下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位 虚幻引擎系列游戏、







原创粉丝点击