设为首页收藏本站官方微博

汉化工具 HookDx

[复制链接]
查看: 2957|回复: 3
打印 上一主题 下一主题

[汉化工具] HookDx

跳转到指定楼层
楼主
发表于 2010-2-10 11:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

HookDx

本帖最后由 shane007 于 2021-2-13 22:23 编辑 # ~4 \. K2 T! `

/ Y5 r3 A9 h$ R# N1 C. i( Q; ]' {DirrectxHook 工具
+ `, B1 Z2 k$ M" t
- d. B+ O) H" R8 D标 题: 【原创】高手莫入 在游戏中显示自己的文字和图形的方法; ]& I+ f, L! \) ]: N
作 者: runjin7 T  Y7 W) Z1 {& D- z3 m$ ]
时 间: 2009-04-03,23:44& \8 x8 T% y( f# S0 @( O' b
链 接: http://bbs.pediy.com/showthread.php?t=85368
# u" Q2 B; N0 s
6 X" J: k" T- rHook Directx:在游戏中显示自己的文字和图形的方法/ W7 s1 W( v, F5 g! u, m

! O( L2 j8 ^: a8 y# ?! D' z9 A这个方法出自我大概两年前的一个项目,现在经整理后贴出来和大家分享一下,利用该方法可以在一般的directx游戏里面绘制文本甚至图形对象.7 Z3 @; S2 a' `
其实思路上非常简单,大致是这样的:要在directx中绘制文字和各种图形对象,只要获得一个类型为LPDIRECT3DDEVICE9的设备对象指针.怎样获得这个指针呢?我的方法是首先hook掉Direct3DCreate9以获得类型为LPDIRECT3D9的Direct3D对象的接口指针,这个Direct3D对象有一个成员函数为 IDirect3D9::CreateDevice,设备对象指针就是在这个函数里面创建的.所以,只要根据Direct3D对象接口指针找到Direct3D对象的虚函数表,再根据虚函数表确定IDirect3D9::CreateDevice的内存地址,就可以hook这个函数,从而获得类型为LPDIRECT3DDEVICE9的设备对象指针,然后就可以随意绘制文字或者图形了.; P( s9 X. R; N: j) e$ Y( w
还有一个要hook的地方,即IDirect3DDevice9::Present,这个函数用于交换当前后备缓存区,刷新窗口.要使得我们自己绘制的东西一直显示在屏幕上,比较好的处理方法是hook掉IDirect3DDevice9::Present,在程序真正调用这个函数前插入我们自己的绘制代码.只要根据设备对象指针找到设备对象的虚函数表,根据虚函数表找到IDirect3DDevice9::Present在内存中的地址就可以hook了.下面是对hook directx的详细说明.4 ~$ X! B4 z$ @  R' A7 q* P
首先是找到Direct3DCreate9的内存地址,然后把入口的5个字节修改为跳转指令.
& W/ k6 Q+ U5 X+ l0 {    pC=GetProcAddress(GetModuleHandle("d3d9.dll"),"Direct3DCreate9");//获得内存地址9 L1 r& }8 W/ u' ~
    DWORD oldpro=0;
; s- R! l9 j/ `! O    memcpy(d3dcen5bytes,pC,5);
- x& I  U( _4 A* o- x/ H& k    VirtualProtect(pC,5,PAGE_EXECUTE_READWRITE,&oldpro);
  P/ `0 W  s8 M& Q    *(BYTE*)pC=0xe9;//0xe9在汇编中是跳转指令操作码" T0 u/ P, c+ j9 I/ ?
    *(DWORD*)((BYTE*)pC+1)=(DWORD)hookedDirect3DCreate9-(DWORD)pC-5;//目标地址-原地址-56 n) a/ I- x1 l. E, q
2 [( t: \3 ~/ e$ j6 @* n

. @$ o, ]- H3 i9 L, c. f这样,在程序运行到Direct3DCreate9时就会跳转到hookedDirect3DCreate9,在这个函数中,首先是还原Direct3DCreate9入口的5个字节,然后调用真正的Direct3DCreate9,如果函数调用成功,就会返回类型为LPDIRECT3D9的Direct3D对象指针,这正是我们所需要的,得到这个指针后,就可以根据Direct3D对象的虚函数表确定IDirect3D9::CreateDevice的内存地址,然后就可以把这个函数入口的5个字节修改成为跳转指令,跳到我们自己的函数中去. 有个地方值得注意的是,在directx的虚函数中把this指针作为第一个形参入栈了.例如说sdk中IDirect3D9::CreateDevice的函数说明是这样:
& u) i+ q  `6 \# w1 {HRESULT CreateDevice(- G3 A( m. j* q! y# S7 e7 }* m
  UINT Adapter,
9 F1 c7 _; i; v7 b" l1 t0 Z) X  D3DDEVTYPE DeviceType,4 a( j; [% @) O4 \2 I" l! Z
  HWND hFocusWindow,
7 ^, l0 P! C. |" U  DWORD BehaviorFlags,
3 U; ^6 t# l& z, F  D3DPRESENT_PARAMETERS * pPresentationParameters,
/ u, B1 e" {9 z; w  IDirect3DDevice9 ** ppReturnedDeviceInterface( |5 \- X* e) f* p
);" R! `: [2 H# ~: Z
" z" K+ ^2 B; ?7 N6 g

0 G( V& s7 R" e* ^5 r而为了程序跳转到我们的代码执行完后保持栈的平衡,hookedDirect3DCreat9函数声明应该是这样:
% h/ ^6 X% Z" y$ H1 W5 N* XHRESULT _stdcall hookedCreateDevice(8 B, C7 ?' ~9 {! ~5 N
                                  LPDIRECT3D9 pDx9,
: h4 x5 X, t; I/ U/ @                                  UINT Adapter,
: b$ w$ y1 T' i                                  D3DDEVTYPE DeviceType,& a* K* R6 M6 `8 c) U; w
                                  HWND hFocusWindow,
; A7 A' S9 c9 E. L6 @# D                                  DWORD BehaviorFlags,
6 K) k# L4 k& p8 t" ~) v' F7 ]1 P0 Z                                  D3DPRESENT_PARAMETERS * pPresentationParameters,
% Q& N) g- U: g: q                                  IDirect3DDevice9 ** ppReturnedDeviceInterface
" W* U. z7 i! j7 w! ^, U; B0 e% M" n5 T
                                  );
3 m9 S7 O5 g6 v( ]; i5 Y/ E0 f3 W! E0 ~+ d
其中的LPDIRECT3D9 pDx9就是this指针.
' i) O( x) G/ z. Y) s
1 S: P( Z9 L( hhookedDirect3DCreate9的关键代码如下:# e/ Z. }. a6 d5 ]" U9 S
pCdev=(void*)*(DWORD*)(*(DWORD*)m_pD3D+0x40);//获得IDirect3D9::CreateDevice的地址指针
7 H/ h5 d5 S9 i$ N( i
$ c. Q! ?1 S3 H8 Y        DWORD oldpro=0;7 `. H, G: @& g- O+ ]- b: m0 i
        memcpy(devcen5bytes,pCdev,5);//保存IDirect3D9::CreateDevice入口5个字节$ J$ P% X6 P5 ~4 c/ J4 E5 K
        VirtualProtect(pCdev,5,PAGE_EXECUTE_READWRITE,&oldpro);  `% s$ e0 S8 r! t# F
        *(BYTE*)pCdev=0xe9;% k) ~, k" q8 w% U# _
        *(DWORD*)((BYTE*)pCdev+1)=(DWORD)hookedCreateDevice-(DWORD)pCdev-5;4 |" _6 B! F( p+ v' J6 j9 @

& w& }5 f7 V! ^1 |在hookedCreateDevice中,首先还原原来的CreateDevice函数入口的5个字节,然后调用原来的函数, IDirect3D9::CreateDevice的最后一个参数是一个二重指针,如果函数调用成功,这个二重指针所指向的指针就是我们所需要的设备对象指针,由此找到设备对象的虚函数表,然后确定IDirect3DDevice9::Present的内存地址,然后又可以改掉入口的5个字节为跳转指令. hookedCreateDevice的关键代码如下:/ ^+ K/ j/ ]! N( {( G
pPre=(void*)*(DWORD*)(*(DWORD*)m_pDevice+0x44);//获得IDirect3DDevice9::Present的地址指针' `# F  ~! b1 z
        memcpy(pren5bytes,pPre,5);//保存IDirect3DDevice9::Present入口的5个字节
" r- A% E4 j# O9 k        DWORD oldpro=0;
. T9 ~; C! u9 P5 ^        VirtualProtect(pPre,5,PAGE_EXECUTE_READWRITE,&oldpro);% }; a% G. S1 w; [% S2 A8 a3 x
        *(BYTE*)pPre=0xe9;0 i* C4 @, G. e. J
        *(DWORD*)((BYTE*)pPre+1)=(DWORD)hookedPresent-(DWORD)pPre-5;7 ]0 V( s% ~$ Z2 o4 c9 w' d
8 Y& X! U# T0 R* A' d+ J) o6 A
实际上这几个函数的hook都是同样的道理,现在,当程序运行到IDirect3DDevice9::Present后又会跳转到hookedPresent,而我们自己的绘制代码就是放在hookedPresent里面.在执行完自己的绘制代码后再调用原来的IDirect3DDevice9::Present.我的hookedPresent的关键代码如下:
- t% E7 Z: `) }" X7 Q- e+ p2 Y0 [char strdraw[]="The drawing in directx game\nAuthor:RunJin\nEmail:[email protected]";* l5 e; Z1 d' {. p, w' Y
            DrawMyText(pDxdevice,strdraw,sizeof strdraw-1);//绘制文本3 N5 S2 `1 c* b" w' b! @0 e: k8 x
            //在这里写入您的其它绘图代码. j7 k8 ?# g4 i% A

' o0 w: \  }1 |5 H; ]2 \. t4 k3 L1 d# \( Y! w- B. V. o; h! h: E
再来看看其中的DrawMyText,这个函数是我的绘制文本的函数:
, {! S! w/ Y2 R! M! j# ]  H+ T0 z% {BOOL _stdcall DrawMyText(LPDIRECT3DDEVICE9 pDxdevice,TCHAR* strText ,int nbuf)0 i! m- h  M2 }: N. |: f5 g; |
{
0 {7 B' I! R. X4 O# y
* x2 z3 b: x+ v5 T7 _/ R" L1 Q  `" w    if(m_pD3D && pDxdevice){7 Z. O- F2 t/ f( o4 \
, E; j6 K+ k# d' E4 m
        RECT myrect;
) k9 `" y9 f' p4 s* K" G1 L        myrect.top=150;  //文本块的y坐标
) A& c5 a; W5 ?5 U. X4 F, A        myrect.left=0; //文本块的左坐标0 @& ]% ^5 l) V# b9 Y5 P9 Z! U
        myrect.right=500+myrect.left;
5 a  S- |  V3 x: L8 `! e        myrect.bottom=100+myrect.top;( ~! [' M3 p+ y* N2 V6 y5 B1 y
        pDxdevice->BeginScene();//开始绘制8 G/ P+ D/ S+ o8 \/ g

+ L) }' ^; R" G. G" h# `8 [5 K        D3DXFONT_DESCA lf;1 z) \; y' y  U4 Q
        ZeroMemory(&lf, sizeof(D3DXFONT_DESCA));0 ^* X# ~% m6 F9 r
        lf.Height = 24; //字体高度
% t8 }8 [6 h) y! w' m% e$ d        lf.Width = 12; // 字体宽度
6 r: I: M5 e+ ]1 ?        lf.Weight = 100; # |5 i5 a6 i" u* g
        lf.Italic = false;. h7 w" I! q# P* `: U1 ~' m
        lf.CharSet = DEFAULT_CHARSET;! h& O6 k$ C6 {5 g! Z5 }1 e7 L
        strcpy(lf.FaceName, "Times New Roman"); // 字型
5 p+ t5 v5 X# R2 Q+ g: f  @        ID3DXFont* font=NULL;
& C! x+ ]5 \/ ~0 k) L3 ?        if(D3D_OK!=D3DXCreateFontIndirect(pDxdevice, &lf, &font)) //创建字体对象
* q+ A/ Y" k7 D  f            return false;3 @3 G4 d. {! L* k# [

* E3 e0 l/ a* f4 c$ S! w        font->DrawText(2 z8 ?6 o8 V6 o4 R, }
            NULL,
9 R$ g* R1 h" Q9 D1 R5 ?& k# U            strText, // 要绘制的文本
3 k4 g+ B7 U5 U            nbuf, 6 K1 @- \6 @( W2 C& c
            &myrect, 2 L/ R1 G* S5 ~) l) N' d
            DT_TOP | DT_LEFT, // 字符居左显示
1 Q- d2 j3 k$ x: f9 b  ?            D3DCOLOR_ARGB(255,255,255,0));
7 ^& \5 K9 o7 `/ s/ z: R' y  [
2 k2 f. \* q. O( |' J' e% I  k        pDxdevice->EndScene();//结束绘制
. Z9 h! D. K2 V" l6 E        font->Release();//释放对象8 u2 B; H" Y( d* }( N# b
    }4 j8 U* c# T* b1 J
    return true;
  ^9 H. y8 i) q: x& x}' W5 q: I( z; O& y$ h
) P% i1 @. W% ]( r0 X
效果图:
$ M6 u/ `7 g  S  O7 R
& z* q# W5 P8 }% w5 ?: H0 n* W; m* V
0 e( P1 `" t- }  G- V9 P. i5 d0 C, x
  4 b: o1 B0 u, X

3 v) Q. {" O- V4 ]; u% c, A% w! v( g% [; Q. s
后记: 代码是以前写的,因此文章就按照着代码来讲.然而现在看来,把函数入口点的5个字节改成跳转指令这种hook方法并不是那么好,其实可以直接改掉虚函数表中的函数指针,这样更加的安全保险.; P/ s0 m9 x' \

" a9 S! {& a, F5 r8 o
( m; X. ?0 `; ^, @/ z" H$ J  g! p

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
发表于 2010-2-11 01:06 | 只看该作者
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
% N( W4 w. u9 C8 |. _1 u0 H8 C% d
& C# T7 C4 T) J# c# V0 i发一篇希望有帮助
回复 支持 反对

使用道具 举报

板凳
 楼主| 发表于 2010-2-11 07:51 | 只看该作者
引用第1楼byp100于2010-02-11 01:06发表的  :4 X" k& ?- S1 x! x. X
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
- W$ }" P8 @6 A( n' ^$ d$ ?1 ?* M" W' X" {2 V% \, y4 w% O5 w
发一篇希望有帮助
4 `- E- M; H8 ]; i1 p
收到,多谢了,这篇文章我也早就找到过。
3 B- |5 K' t6 \& v( p! s* ?目前就是要研究如何把汉化和hook dx结合起来。
回复 支持 反对

使用道具 举报

地板
 楼主| 发表于 2021-2-13 22:22 | 只看该作者
顶上来
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

冒险解谜游戏中文网 ChinaAVG

官方微博官方微信号小黑屋 微信玩家群  

(C) ChinaAVG 2004 - 2019 All Right Reserved. Powered by Discuz! X3.2
辽ICP备11008827号 | 桂公网安备 45010702000051号

冒险,与你同在。 冒险解谜游戏中文网ChinaAVG诞生于2004年9月9日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

快速回复 返回顶部 返回列表