首页
社区
课程
招聘
Hook显卡厂商驱动(draw whatever you want)
发表于: 2014-12-21 02:16 54174

Hook显卡厂商驱动(draw whatever you want)

2014-12-21 02:16
54174

作者:hhstudy
博客: http://hi.baidu.com/hhstudy
转载请在文章开头注明出处

本文要点:
介绍一种从显卡驱动入手的构造D3DHook的方法,DX9,DX9EX,DX10,DX11均试用,无需重启进程,注入即可使用。

以DX9为例。

前置知识:
1. API Hook的基础知识
2. DX绘图知识
3. 关于DX Hook 有很多种方法,传统的方法请自行查找资料。
4. Windows Display Driver 的基础知识

首先Vender驱动导出了一个叫做OpenAdapter的函数。
原型

typedef HRESULT APIENTRY _OpenAdapter(D3DDDIARG_OPENADAPTER 
typedef struct _D3DDDIARG_OPENADAPTER
{
    HANDLE                         hAdapter;           // in/out:  Runtime handle/out: Driver handle
    UINT                           Interface;          // in:  Interface version
    UINT                           Version;            // in:  Runtime version
    CONST D3DDDI_ADAPTERCALLBACKS* pAdapterCallbacks;  // in:  Pointer to runtime callbacks
    D3DDDI_ADAPTERFUNCS*           pAdapterFuncs;      // out: Driver function table
    UINT                           DriverVersion;      // out: D3D UMD interface version the
                                                       //      driver was compiled with. Use
                                                       //      D3D_UMD_INTERFACE_VERSION.
} D3DDDIARG_OPENADAPTER;
typedef struct _D3DDDI_ADAPTERFUNCS
{
    PFND3DDDI_GETCAPS                       pfnGetCaps;
    PFND3DDDI_CREATEDEVICE                  pfnCreateDevice;
    PFND3DDDI_CLOSEADAPTER                  pfnCloseAdapter;
} D3DDDI_ADAPTERFUNCS;
BOOL DetourOpenAdapter()
{
OpenAdapter = (_OpenAdapter *)GetProcAddress(GetModuleHandleA("nvd3dum.dll"), "OpenAdapter");
if (OpenAdapter == NULL)
{
OpenAdapter = (_OpenAdapter *)GetProcAddress(GetModuleHandleA("aticfx32.dll"), "OpenAdapter");
}

if (OpenAdapter)
{
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((void **)&OpenAdapter, WarpOpenAdapter);
DetourTransactionCommit();
}

return OpenAdapter != NULL;
}
HRESULT APIENTRY WarpOpenAdapter(D3DDDIARG_OPENADAPTER *pAdapterData)
{
    HRESULT ret = OpenAdapter(pAdapterData);
    if (ret == S_OK && pAdapterData->pAdapterFuncs->pfnCreateDevice)
    {
        DdiCreateDevice = pAdapterData->pAdapterFuncs->pfnCreateDevice;
        pAdapterData->pAdapterFuncs->pfnCreateDevice = WarpDdiCreateDevice;
    }
    return ret;
} 
HRESULT APIENTRY WarpDdiCreateDevice(
    HANDLE hAdapter,
    D3DDDIARG_CREATEDEVICE *pDeviceData)
{
    // DdiCreateDevice must not be NULL if this path hit
    HRESULT ret = DdiCreateDevice(hAdapter, pDeviceData);
    if (pDeviceData->pDeviceFuncs->pfnPresent && gDetourFuncTable.DdiPresent.isAttatched == FALSE)
    {
        DdiPresent = pDeviceData->pDeviceFuncs->pfnPresent;
        ULONG_PTR realTramponLine = DetourDDiPresent();
        gDetourFuncTable.DdiPresent.isAttatched = TRUE;
        gDetourFuncTable.DdiPresent.preFuncPtr = DdiPresent;
        gDetourFuncTable.DdiPresent.TrampoLinePtr = (PFND3DDDI_PRESENT)realTramponLine;
        gDetourFuncTable.DdiPresent.warpFuncPtr = WarpDdiPresent;
    }
    if (pDeviceData->pDeviceFuncs->pfnPresent1 && gDetourFuncTable.DdiPresent1.isAttatched == FALSE)
    {
        DdiPresent1 = pDeviceData->pDeviceFuncs->pfnPresent1;
        ULONG_PTR realTramponLine = DetourDDiPresent1();
        gDetourFuncTable.DdiPresent1.isAttatched = TRUE;
        gDetourFuncTable.DdiPresent1.preFuncPtr = DdiPresent1;
        gDetourFuncTable.DdiPresent1.TrampoLinePtr = (PFND3DDDI_PRESENT1)realTramponLine;
        gDetourFuncTable.DdiPresent1.warpFuncPtr = WarpDdiPresent1;
    }
    DdiLock = pDeviceData->pDeviceFuncs->pfnLock;
    DdiCreateResource = pDeviceData->pDeviceFuncs->pfnCreateResource;
    DdiCreateResource2 = pDeviceData->pDeviceFuncs->pfnCreateResource2;
    DdiUnlock = pDeviceData->pDeviceFuncs->pfnUnlock;
    DdiBlt = pDeviceData->pDeviceFuncs->pfnBlt;

    return ret;
}

typedef struct _D3DDDIARG_CREATEDEVICE
{
    HANDLE                          hDevice;                // in:  Runtime handle/out: Driver handle
    UINT                            Interface;              // in:  Interface version
    UINT                            Version;                // in:  Runtime Version
    CONST D3DDDI_DEVICECALLBACKS*   pCallbacks;             // in:  Pointer to runtime callbacks
    VOID*                           pCommandBuffer;         // in:  Pointer to the first command buffer to use.
    UINT                            CommandBufferSize;      // in:  Size of the first command buffer to use.
    D3DDDI_ALLOCATIONLIST*          pAllocationList;        // out: Pointer to the first allocation list to use.
    UINT                            AllocationListSize;     // in:  Size of the allocation list that will be available
                                                            //      when the first command buffer is submitted.
    D3DDDI_PATCHLOCATIONLIST*       pPatchLocationList;     // out: Pointer to the first patch location list to use.
    UINT                            PatchLocationListSize;  // in:  Size of the patch location list that will be available
                                                            //      when the first command buffer is submitted.
    D3DDDI_DEVICEFUNCS*             pDeviceFuncs;           // out: Driver function table
    D3DDDI_CREATEDEVICEFLAGS        Flags;                  // in:  Flags
#if (D3D_UMD_INTERFACE_VERSION >= D3D_UMD_INTERFACE_VERSION_WIN7)
    D3DGPU_VIRTUAL_ADDRESS          CommandBuffer;          // out: GPU Virtual address to the command buffer to use. _ADVSCH_
#endif // D3D_UMD_INTERFACE_VERSION
} D3DDDIARG_CREATEDEVICE;
PFND3DDDI_CREATEDEVICE DdiCreateDevice = NULL;
PFND3DDDI_PRESENT DdiPresent = NULL;
PFND3DDDI_PRESENT1 DdiPresent1= NULL;
PFND3DDDI_LOCK DdiLock = NULL;
PFND3DDDI_CREATERESOURCE DdiCreateResource = NULL;
PFND3DDDI_CREATERESOURCE2 DdiCreateResource2 = NULL;
PFND3DDDI_UNLOCK DdiUnlock = NULL;
PFND3DDDI_BLT DdiBlt = NULL;
HRESULT APIENTRY WarpDdiCreateDevice(
    HANDLE hAdapter,
    D3DDDIARG_CREATEDEVICE *pDeviceData)
{
    // DdiCreateDevice must not be NULL if this path hit
    HRESULT ret = DdiCreateDevice(hAdapter, pDeviceData);
    if (pDeviceData->pDeviceFuncs->pfnPresent && gDetourFuncTable.DdiPresent.isAttatched == FALSE)
    {
        DdiPresent = pDeviceData->pDeviceFuncs->pfnPresent;
        ULONG_PTR realTramponLine = DetourDDiPresent();
        gDetourFuncTable.DdiPresent.isAttatched = TRUE;
        gDetourFuncTable.DdiPresent.preFuncPtr = DdiPresent;
        gDetourFuncTable.DdiPresent.TrampoLinePtr = (PFND3DDDI_PRESENT)realTramponLine;
        gDetourFuncTable.DdiPresent.warpFuncPtr = WarpDdiPresent;
    }
    if (pDeviceData->pDeviceFuncs->pfnPresent1 && gDetourFuncTable.DdiPresent1.isAttatched == FALSE)
    {
        DdiPresent1 = pDeviceData->pDeviceFuncs->pfnPresent1;
        ULONG_PTR realTramponLine = DetourDDiPresent1();
        gDetourFuncTable.DdiPresent1.isAttatched = TRUE;
        gDetourFuncTable.DdiPresent1.preFuncPtr = DdiPresent1;
        gDetourFuncTable.DdiPresent1.TrampoLinePtr = (PFND3DDDI_PRESENT1)realTramponLine;
        gDetourFuncTable.DdiPresent1.warpFuncPtr = WarpDdiPresent1;
    }
    DdiLock = pDeviceData->pDeviceFuncs->pfnLock;
    DdiCreateResource = pDeviceData->pDeviceFuncs->pfnCreateResource;
    DdiCreateResource2 = pDeviceData->pDeviceFuncs->pfnCreateResource2;
    DdiUnlock = pDeviceData->pDeviceFuncs->pfnUnlock;
    DdiBlt = pDeviceData->pDeviceFuncs->pfnBlt;

    return ret;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 4
支持
分享
最新回复 (44)
雪    币: 219
活跃值: (783)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
2
我是来学习的
2014-12-21 02:19
0
雪    币: 376
活跃值: (92)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
楼主不错啊,都注释那么详细,好多人发都只是丢一段代码出来新手都看不懂
2014-12-21 07:28
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
学习下d3dhook
2014-12-21 09:11
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
5
显卡种类太多了xxxx.dll!OpenAdapter的hook方法不好。比较科学的方式是读注册表读出DLL名称,然后走起~

DDIHook有个小问题就是有些东西跟操作系统版本太贴了~好处是没几个人关注这个hook点~

PS:
好文章顶了~
2014-12-21 09:37
0
雪    币: 124
活跃值: (469)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
围观和学习的。。。。
2014-12-21 10:12
0
雪    币: 144
活跃值: (335)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
mark谢谢分享
2014-12-21 12:46
0
雪    币: 65
活跃值: (452)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
8
恩,感谢V大提醒。
DDIHook需要处理WDDM1.0-WDDM1.3 就能兼容目前所有的微软还支持的OS了。
等下一代Windows出来再处理WDDM2.0就好了。
2014-12-21 15:01
0
雪    币: 78
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
最好来个小应用实例。。比如透视这类的
2014-12-22 11:37
0
雪    币: 277
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
好文章,支持一下!
2014-12-22 12:29
0
雪    币: 69
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
看着很不错的呢!
2014-12-22 16:30
0
雪    币: 1283
活跃值: (46)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
额,支持学习,以前一直是通过找D3D的接口函数进行挂钩的
2014-12-22 16:48
0
雪    币: 293
活跃值: (239)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
mark
2014-12-24 22:36
0
雪    币: 231
活跃值: (2631)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
14
mark
2014-12-25 01:30
0
雪    币: 267
活跃值: (794)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
可否把ATI驱动*.sys上载?
2014-12-25 01:49
0
雪    币: 45
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
great project!
2014-12-25 03:35
0
雪    币: 135
活跃值: (106)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
17
貌似需要nt6以上才能支持吧
2014-12-25 06:09
0
雪    币: 11096
活跃值: (17617)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
楼主辛苦了,

虽然我看不懂,但总有人看得懂的
2014-12-25 15:32
0
雪    币: 65
活跃值: (452)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
19
是的,XP上UMD Driver在 R0, 已经放弃, WDDM 1.0 以后才支持.
2014-12-25 22:51
0
雪    币: 188
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
学习楼主大牛。
2014-12-26 12:32
0
雪    币: 135
活跃值: (106)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
21
我之前也听说过这个, 虽然nt6之后有了个这样的东西,但是既然在R3层,你可以改,游戏也可以查,只能说可以虐虐那些还没查的游戏。
2014-12-27 03:04
0
雪    币: 272
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
即将加入TP猥琐检测豪华大餐
2014-12-27 05:26
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
23
早检测了~只是权重比例小于D3D~呵呵~
2014-12-27 11:47
0
雪    币: 65
活跃值: (452)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
24
更正一个错误
原帖贴的是BltToRTWDDM1_1 这个适合WIN7,大同小异。
HRESULT BltToRTWDDM1_3(HANDLE hDevice, HANDLE hRes, CONST D3DDDIARG_PRESENT1 *pPresent1, RECT rc)
{
        D3DDDIARG_BLT bltData;
        RECT srcRC;
        RECT destRC;
        HRESULT ret = S_OK;

        memset(&bltData, 0, sizeof(bltData));
        memset(&srcRC, 0, sizeof(srcRC));
        memset(&destRC, 0, sizeof(destRC));

        srcRC = destRC = rc;
        bltData.hDstResource = pPresent1->phSrcResources[0].hResource;
        bltData.DstSubResourceIndex = pPresent1->phSrcResources[0].SubResourceIndex;
        bltData.hSrcResource = hRes;
        bltData.SrcSubResourceIndex = 0;
        bltData.SrcRect = srcRC;
        bltData.DstRect = destRC;
        bltData.Flags.SrcColorKey = 1;
        bltData.ColorKey = 0;
        return DdiBlt(hDevice, &bltData);
}
2014-12-28 10:58
0
雪    币: 201
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
mark
2014-12-28 18:55
0
游客
登录 | 注册 方可回帖
返回
//