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

汉化工具 HookDx

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

[汉化工具] HookDx

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

HookDx

本帖最后由 shane007 于 2021-2-13 22:23 编辑
3 n& N9 u/ V$ o7 r4 _
5 K2 R! k6 I, S5 U% {& l& zDirrectxHook 工具
9 v; I- W. _+ F9 p0 {4 M* e% K5 }+ ]* H  g3 v
标 题: 【原创】高手莫入 在游戏中显示自己的文字和图形的方法. }. D' z6 t3 `' j8 g, o) _! B* A
作 者: runjin
9 M( y6 C- S& P& Q5 G3 {时 间: 2009-04-03,23:446 r# }4 R1 ?9 ^% u) ]/ g; D: r
链 接: http://bbs.pediy.com/showthread.php?t=85368
9 K% C# H  u. B# t1 z2 U" ?7 o& k) Q9 }
Hook Directx:在游戏中显示自己的文字和图形的方法
( j  y' S! m! U0 a
6 G" }) h* T" G6 Q0 \+ J3 u这个方法出自我大概两年前的一个项目,现在经整理后贴出来和大家分享一下,利用该方法可以在一般的directx游戏里面绘制文本甚至图形对象.9 q) L' g4 K9 E1 |
其实思路上非常简单,大致是这样的:要在directx中绘制文字和各种图形对象,只要获得一个类型为LPDIRECT3DDEVICE9的设备对象指针.怎样获得这个指针呢?我的方法是首先hook掉Direct3DCreate9以获得类型为LPDIRECT3D9的Direct3D对象的接口指针,这个Direct3D对象有一个成员函数为 IDirect3D9::CreateDevice,设备对象指针就是在这个函数里面创建的.所以,只要根据Direct3D对象接口指针找到Direct3D对象的虚函数表,再根据虚函数表确定IDirect3D9::CreateDevice的内存地址,就可以hook这个函数,从而获得类型为LPDIRECT3DDEVICE9的设备对象指针,然后就可以随意绘制文字或者图形了.2 k6 s/ w8 f, W, A0 X7 e
还有一个要hook的地方,即IDirect3DDevice9::Present,这个函数用于交换当前后备缓存区,刷新窗口.要使得我们自己绘制的东西一直显示在屏幕上,比较好的处理方法是hook掉IDirect3DDevice9::Present,在程序真正调用这个函数前插入我们自己的绘制代码.只要根据设备对象指针找到设备对象的虚函数表,根据虚函数表找到IDirect3DDevice9::Present在内存中的地址就可以hook了.下面是对hook directx的详细说明.! z8 F" t9 o- G4 }
首先是找到Direct3DCreate9的内存地址,然后把入口的5个字节修改为跳转指令." a! P) f6 a5 d) n6 f! Y9 }. h
    pC=GetProcAddress(GetModuleHandle("d3d9.dll"),"Direct3DCreate9");//获得内存地址
1 G+ B3 \: c3 z' S, w( U    DWORD oldpro=0;$ P9 C5 _( O# N: z) i2 U2 f
    memcpy(d3dcen5bytes,pC,5);& y  N5 G9 A. t5 z8 R# ^2 I
    VirtualProtect(pC,5,PAGE_EXECUTE_READWRITE,&oldpro);
/ ?, w0 p+ G5 S6 T0 C% h# R. j    *(BYTE*)pC=0xe9;//0xe9在汇编中是跳转指令操作码! R+ K4 }* r$ _0 A" b% D
    *(DWORD*)((BYTE*)pC+1)=(DWORD)hookedDirect3DCreate9-(DWORD)pC-5;//目标地址-原地址-5
, V: Y3 q/ t1 t
' [+ e) `: \: k% U: O" M; F6 n+ d! x2 Q
' A1 i( n) W; B+ D; q2 V" U5 p这样,在程序运行到Direct3DCreate9时就会跳转到hookedDirect3DCreate9,在这个函数中,首先是还原Direct3DCreate9入口的5个字节,然后调用真正的Direct3DCreate9,如果函数调用成功,就会返回类型为LPDIRECT3D9的Direct3D对象指针,这正是我们所需要的,得到这个指针后,就可以根据Direct3D对象的虚函数表确定IDirect3D9::CreateDevice的内存地址,然后就可以把这个函数入口的5个字节修改成为跳转指令,跳到我们自己的函数中去. 有个地方值得注意的是,在directx的虚函数中把this指针作为第一个形参入栈了.例如说sdk中IDirect3D9::CreateDevice的函数说明是这样:
# R' c' ^6 j  T; P6 bHRESULT CreateDevice(
/ f& u! w" e( m5 f4 Y# H/ E  UINT Adapter,
6 e4 A4 p6 O5 P8 h) \# [  D3DDEVTYPE DeviceType,
% P: [) ^3 ?% `  {8 J5 ~; l- X  HWND hFocusWindow,: J5 s( L" D8 U$ h
  DWORD BehaviorFlags,' p# w1 |! G) t8 Z1 c+ s
  D3DPRESENT_PARAMETERS * pPresentationParameters,, V6 I# l& ^4 \8 w' l
  IDirect3DDevice9 ** ppReturnedDeviceInterface
! l4 @9 J+ J- Q+ U8 E);
% B5 |9 y6 k- a- V
1 ]- k' M" |( f  v4 c4 [
! _! d: d. |: `# F4 I6 ^而为了程序跳转到我们的代码执行完后保持栈的平衡,hookedDirect3DCreat9函数声明应该是这样:
! |, z6 q% z) \: e! \. Q+ yHRESULT _stdcall hookedCreateDevice(/ A9 |+ }6 \. B" O4 O; {0 g
                                  LPDIRECT3D9 pDx9,8 R: M* E0 P( d7 A* H) X
                                  UINT Adapter,
0 h" v2 J8 |9 f; ?: y! L2 M0 `                                  D3DDEVTYPE DeviceType,
$ F$ t4 K$ k9 V1 K! `                                  HWND hFocusWindow,* A- D* e$ C) \% Y& ^3 b
                                  DWORD BehaviorFlags,
8 Z. Q2 ?1 n/ c% \) f0 S2 t0 n7 D                                  D3DPRESENT_PARAMETERS * pPresentationParameters,
" _( o, D; y4 @) [+ \* O                                  IDirect3DDevice9 ** ppReturnedDeviceInterface
2 B& z" p5 q: O7 S8 {3 }0 R9 f' x6 q: `/ S0 p
                                  );) S; @" C. e0 d3 j0 a$ V* m; p
7 _5 y0 w0 J8 @
其中的LPDIRECT3D9 pDx9就是this指针.2 M3 r3 L3 V* G- d

/ ]3 @8 Y6 u# x: ]8 K5 khookedDirect3DCreate9的关键代码如下:
2 u4 L. |! E# F' X2 _- |. OpCdev=(void*)*(DWORD*)(*(DWORD*)m_pD3D+0x40);//获得IDirect3D9::CreateDevice的地址指针6 {7 ^+ S+ y2 g1 u/ [% _6 Z
+ o9 Q# f6 J0 a  ^
        DWORD oldpro=0;% ?7 e  u% s4 x* u4 E1 y! ^# u
        memcpy(devcen5bytes,pCdev,5);//保存IDirect3D9::CreateDevice入口5个字节; P1 u5 r% S1 K+ |) r3 _4 e/ R3 l% s
        VirtualProtect(pCdev,5,PAGE_EXECUTE_READWRITE,&oldpro);
: z" r# V, Q8 n& Z* f6 b4 @        *(BYTE*)pCdev=0xe9;
; C+ l3 N* \, J        *(DWORD*)((BYTE*)pCdev+1)=(DWORD)hookedCreateDevice-(DWORD)pCdev-5;
2 B6 i. O- t6 M7 m+ G- i8 v' j( [8 N2 u7 f, }/ z
在hookedCreateDevice中,首先还原原来的CreateDevice函数入口的5个字节,然后调用原来的函数, IDirect3D9::CreateDevice的最后一个参数是一个二重指针,如果函数调用成功,这个二重指针所指向的指针就是我们所需要的设备对象指针,由此找到设备对象的虚函数表,然后确定IDirect3DDevice9::Present的内存地址,然后又可以改掉入口的5个字节为跳转指令. hookedCreateDevice的关键代码如下:
% {( E0 A8 {* r7 Z, GpPre=(void*)*(DWORD*)(*(DWORD*)m_pDevice+0x44);//获得IDirect3DDevice9::Present的地址指针! O+ L; X! X3 W) u6 u
        memcpy(pren5bytes,pPre,5);//保存IDirect3DDevice9::Present入口的5个字节
/ {5 P% L, O' u' A/ g        DWORD oldpro=0;. @+ V5 Q  i2 y  c
        VirtualProtect(pPre,5,PAGE_EXECUTE_READWRITE,&oldpro);9 H, m4 ^0 i! ~) ^
        *(BYTE*)pPre=0xe9;! R$ ]* b( o; ?7 N  J. @) x( F
        *(DWORD*)((BYTE*)pPre+1)=(DWORD)hookedPresent-(DWORD)pPre-5;8 [  M% q) p5 ~+ N( u* `
9 Q4 J. l' R% ?3 f+ |/ {2 d
实际上这几个函数的hook都是同样的道理,现在,当程序运行到IDirect3DDevice9::Present后又会跳转到hookedPresent,而我们自己的绘制代码就是放在hookedPresent里面.在执行完自己的绘制代码后再调用原来的IDirect3DDevice9::Present.我的hookedPresent的关键代码如下:
: J% A* U! E. {( [char strdraw[]="The drawing in directx game\nAuthor:RunJin\nEmail:[email protected]";
, |- h/ |' s: l, B+ j            DrawMyText(pDxdevice,strdraw,sizeof strdraw-1);//绘制文本
2 E- t& x0 J5 L* E1 x, o            //在这里写入您的其它绘图代码* R# b! U" H2 r& a) x$ q& ~
. m6 a0 b, r& k% @0 M
. g! s5 m$ j) V: ^' k
再来看看其中的DrawMyText,这个函数是我的绘制文本的函数:8 ~8 J" ^4 |+ ]) q* U6 ~3 w8 g( x
BOOL _stdcall DrawMyText(LPDIRECT3DDEVICE9 pDxdevice,TCHAR* strText ,int nbuf)9 ~9 M9 O" m+ _# a: R
{! g) A. b5 D) b8 ~% @

$ c" X* W5 [3 L- l& n% i    if(m_pD3D && pDxdevice){
* m0 `: I% ]+ H- y5 v
: [- x2 J4 z+ |        RECT myrect;
3 c5 }, ^. k6 \        myrect.top=150;  //文本块的y坐标& l0 m' M. M9 {
        myrect.left=0; //文本块的左坐标
* W6 f1 g6 g# }3 u        myrect.right=500+myrect.left;! r( G# O* ^) W6 C
        myrect.bottom=100+myrect.top;
9 b7 n; E' Z  N* W, x( R  K0 K1 X        pDxdevice->BeginScene();//开始绘制: Z- `* Y% t4 G- y' |
4 r# g( h* t& P* i
        D3DXFONT_DESCA lf;4 E" R! N6 k% q/ b6 A
        ZeroMemory(&lf, sizeof(D3DXFONT_DESCA));8 a( ^" R+ e/ o- R4 w# F) d/ I5 Q
        lf.Height = 24; //字体高度3 ]6 f+ A  Q" R3 ^: a6 T
        lf.Width = 12; // 字体宽度- e2 K, U9 ]$ Z% t. t
        lf.Weight = 100;
  e# _" ^9 V% _! ^        lf.Italic = false;3 l, l" ~: k5 n- ?" ]6 I/ f
        lf.CharSet = DEFAULT_CHARSET;
7 ]( D. l/ q+ U- l- y        strcpy(lf.FaceName, "Times New Roman"); // 字型+ [, W2 x# O3 ]0 c: f6 E
        ID3DXFont* font=NULL;; q3 W4 i% q2 d+ r
        if(D3D_OK!=D3DXCreateFontIndirect(pDxdevice, &lf, &font)) //创建字体对象
) @1 s& g3 P' `  F5 [            return false;
" x% D& G7 u. z5 W/ A: `7 _3 |; s/ g- s2 a( [5 N
        font->DrawText(9 s' X' v: Y, B% j+ o
            NULL,
$ X$ v5 d" k8 @            strText, // 要绘制的文本
: B. c; G2 a2 ?            nbuf,
1 V+ g: y1 D% f, c            &myrect, 3 h! {4 e- Z: D6 h4 Z
            DT_TOP | DT_LEFT, // 字符居左显示
$ e1 z. J6 ]1 P5 {! u- ?* f9 a) e+ T            D3DCOLOR_ARGB(255,255,255,0)); . _0 m  E& S; k! C# Q# A% \2 E

3 I8 g2 C2 S( y) U& X& D        pDxdevice->EndScene();//结束绘制
- a; y% P. S+ B  }& y' N        font->Release();//释放对象7 Z6 @! H. k  C& V' n. q, p$ U
    }
- I7 `  V) s; T5 [) ]. v4 z* E) E    return true;
. m" P/ {, r$ ^# e}" b1 V8 }( b5 y% X

& E) E! a* i# h4 h* Z- v3 E效果图:- _- J% T0 R! g5 {* o* y
. O, t% u! h0 k
+ P4 o; n& g0 w' [5 V7 d. ]- I
3 b5 q$ a  b6 w4 a/ \
  - W+ d- l* B) X8 g& @1 ^$ b) K  ]

/ N2 m5 w- A, P; T! D$ u/ t1 Q& H, L" }6 U6 Y$ g: c. `
后记: 代码是以前写的,因此文章就按照着代码来讲.然而现在看来,把函数入口点的5个字节改成跳转指令这种hook方法并不是那么好,其实可以直接改掉虚函数表中的函数指针,这样更加的安全保险.
2 X4 a$ \* J9 R  J. R! T9 P
3 o+ R$ W7 Q! [0 m! V& @  q
5 H' z+ i# E  ^& I9 H7 y9 Y5 w: c

本帖子中包含更多资源

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

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

使用道具 举报

沙发
发表于 2010-2-11 01:06 | 只看该作者
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx  d- N$ }. g: s

& ]5 _6 Q) k/ a( R4 r; {& _% ^! p发一篇希望有帮助
回复 支持 反对

使用道具 举报

板凳
 楼主| 发表于 2010-2-11 07:51 | 只看该作者
引用第1楼byp100于2010-02-11 01:06发表的  :
( ^4 E7 L8 v5 b; Chttp://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
$ x/ X1 X( J6 G- C1 n; }: _* b$ `
4 r) N3 r! Y8 Z) Q) n发一篇希望有帮助
4 }, K- |) B! q
收到,多谢了,这篇文章我也早就找到过。
3 b5 l3 F& P5 o目前就是要研究如何把汉化和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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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