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

汉化工具 HookDx

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

[汉化工具] HookDx

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

HookDx

本帖最后由 shane007 于 2021-2-13 22:23 编辑
7 [. r; e$ U1 R2 L( G
8 l4 y4 n; H2 Y# vDirrectxHook 工具
* Z: U) U* p3 t" i
. X8 M$ G" S; B2 a2 U3 l标 题: 【原创】高手莫入 在游戏中显示自己的文字和图形的方法
) X# Q1 k# N- j8 P作 者: runjin: y$ C% R% m, |
时 间: 2009-04-03,23:44% Z2 x3 l5 l  ], p
链 接: http://bbs.pediy.com/showthread.php?t=85368; w2 x) t$ w3 c2 o0 l, k

8 O0 f. _  j: p4 d: d7 O& U9 aHook Directx:在游戏中显示自己的文字和图形的方法
/ ?- y& c2 L+ Z$ u% V
9 |# ]6 F8 Y$ g# d* F这个方法出自我大概两年前的一个项目,现在经整理后贴出来和大家分享一下,利用该方法可以在一般的directx游戏里面绘制文本甚至图形对象.
/ m- _- F0 a# Z其实思路上非常简单,大致是这样的:要在directx中绘制文字和各种图形对象,只要获得一个类型为LPDIRECT3DDEVICE9的设备对象指针.怎样获得这个指针呢?我的方法是首先hook掉Direct3DCreate9以获得类型为LPDIRECT3D9的Direct3D对象的接口指针,这个Direct3D对象有一个成员函数为 IDirect3D9::CreateDevice,设备对象指针就是在这个函数里面创建的.所以,只要根据Direct3D对象接口指针找到Direct3D对象的虚函数表,再根据虚函数表确定IDirect3D9::CreateDevice的内存地址,就可以hook这个函数,从而获得类型为LPDIRECT3DDEVICE9的设备对象指针,然后就可以随意绘制文字或者图形了., j4 ?: X( f  k- M1 m; m
还有一个要hook的地方,即IDirect3DDevice9::Present,这个函数用于交换当前后备缓存区,刷新窗口.要使得我们自己绘制的东西一直显示在屏幕上,比较好的处理方法是hook掉IDirect3DDevice9::Present,在程序真正调用这个函数前插入我们自己的绘制代码.只要根据设备对象指针找到设备对象的虚函数表,根据虚函数表找到IDirect3DDevice9::Present在内存中的地址就可以hook了.下面是对hook directx的详细说明.3 L' V/ t8 i5 {1 [: V' W
首先是找到Direct3DCreate9的内存地址,然后把入口的5个字节修改为跳转指令.
2 K. m9 _& f! x3 _    pC=GetProcAddress(GetModuleHandle("d3d9.dll"),"Direct3DCreate9");//获得内存地址9 F* L/ u' G) ^. k
    DWORD oldpro=0;$ R9 r, X- ]% F, w
    memcpy(d3dcen5bytes,pC,5);; s6 _/ a" r+ f1 G. I3 y
    VirtualProtect(pC,5,PAGE_EXECUTE_READWRITE,&oldpro);
) |1 u% n$ d% V& K    *(BYTE*)pC=0xe9;//0xe9在汇编中是跳转指令操作码: h! s$ D3 r7 b) t% m
    *(DWORD*)((BYTE*)pC+1)=(DWORD)hookedDirect3DCreate9-(DWORD)pC-5;//目标地址-原地址-5. s' L" f6 L2 V' K
! N: Y0 c) B4 \# i& Y+ T

8 Q% s/ K* ]" {* E, x这样,在程序运行到Direct3DCreate9时就会跳转到hookedDirect3DCreate9,在这个函数中,首先是还原Direct3DCreate9入口的5个字节,然后调用真正的Direct3DCreate9,如果函数调用成功,就会返回类型为LPDIRECT3D9的Direct3D对象指针,这正是我们所需要的,得到这个指针后,就可以根据Direct3D对象的虚函数表确定IDirect3D9::CreateDevice的内存地址,然后就可以把这个函数入口的5个字节修改成为跳转指令,跳到我们自己的函数中去. 有个地方值得注意的是,在directx的虚函数中把this指针作为第一个形参入栈了.例如说sdk中IDirect3D9::CreateDevice的函数说明是这样:
  F( f+ s( j& xHRESULT CreateDevice(
/ {) f6 m( G7 F' B0 N; |- s  UINT Adapter,
" ?9 y! u- ~$ X' j  D3DDEVTYPE DeviceType,( l2 N& v: A" u
  HWND hFocusWindow,
; o/ \/ Z" y) s0 E  DWORD BehaviorFlags,
( u9 p) G1 E9 ~  D3DPRESENT_PARAMETERS * pPresentationParameters,
# i1 m: @; @2 U- w# Z- c) l5 K  IDirect3DDevice9 ** ppReturnedDeviceInterface  G  c. h7 I4 C
);+ Z( t' z" Y% m/ |
* I9 Y0 f# I3 U8 t7 K/ u

. i5 K8 U' Y2 Z9 R( h) e/ r' l+ K- V而为了程序跳转到我们的代码执行完后保持栈的平衡,hookedDirect3DCreat9函数声明应该是这样:
, {! j. r6 x  o" [9 RHRESULT _stdcall hookedCreateDevice(/ T3 W4 t3 G# ^) a
                                  LPDIRECT3D9 pDx9,* W( x* v  ^' a* J* O/ q
                                  UINT Adapter,
$ h# V1 A/ e5 m# x* y% i& M                                  D3DDEVTYPE DeviceType,
9 K1 c6 b9 Y  I0 }& M/ v/ F0 b( i                                  HWND hFocusWindow,0 i, p, ]6 F) D6 H% s4 n
                                  DWORD BehaviorFlags,, U) }0 l/ m  E0 K8 O/ j7 M
                                  D3DPRESENT_PARAMETERS * pPresentationParameters,; F0 s" `/ T. \
                                  IDirect3DDevice9 ** ppReturnedDeviceInterface* ^* J& T+ E9 _5 x2 k$ B4 L9 w

) Z! m7 q/ z9 R5 A- v2 w                                  );
" e% x5 }. u; r$ W4 z! ?" b- u; x+ F- T; H; r* C( A3 ~& q1 Q) g
其中的LPDIRECT3D9 pDx9就是this指针.! Q8 m" [1 `( ?. ]0 m' U
) V) l0 h1 S0 _) n  Z' \0 K/ a
hookedDirect3DCreate9的关键代码如下:
! J0 S$ v5 H/ U' _3 c- Q, JpCdev=(void*)*(DWORD*)(*(DWORD*)m_pD3D+0x40);//获得IDirect3D9::CreateDevice的地址指针
$ F& W  E) C/ j5 a# Q# _  T2 x( P4 a# }
        DWORD oldpro=0;
: E- V  p2 A6 z- ]' l: L6 F        memcpy(devcen5bytes,pCdev,5);//保存IDirect3D9::CreateDevice入口5个字节
$ S) S4 {% j. N- N& Q: W        VirtualProtect(pCdev,5,PAGE_EXECUTE_READWRITE,&oldpro);* n) V3 J+ ]" m& ]" f  B
        *(BYTE*)pCdev=0xe9;
7 W, O4 i( P( T+ a/ t# S3 ?        *(DWORD*)((BYTE*)pCdev+1)=(DWORD)hookedCreateDevice-(DWORD)pCdev-5;
$ V$ v/ v5 X( o
, d) `0 b7 t2 l) }  I8 C在hookedCreateDevice中,首先还原原来的CreateDevice函数入口的5个字节,然后调用原来的函数, IDirect3D9::CreateDevice的最后一个参数是一个二重指针,如果函数调用成功,这个二重指针所指向的指针就是我们所需要的设备对象指针,由此找到设备对象的虚函数表,然后确定IDirect3DDevice9::Present的内存地址,然后又可以改掉入口的5个字节为跳转指令. hookedCreateDevice的关键代码如下:% `/ p( L% o+ [& ?+ d+ v. U
pPre=(void*)*(DWORD*)(*(DWORD*)m_pDevice+0x44);//获得IDirect3DDevice9::Present的地址指针
8 p, W- }( h: v' Q        memcpy(pren5bytes,pPre,5);//保存IDirect3DDevice9::Present入口的5个字节! ~- e& x2 Q% h. g+ o5 T( T7 R
        DWORD oldpro=0;5 z& e- H, }( m; F" U1 g0 k* s3 x$ h
        VirtualProtect(pPre,5,PAGE_EXECUTE_READWRITE,&oldpro);
( A% _  M; m& }4 V1 h  O        *(BYTE*)pPre=0xe9;$ C# R  {2 P# m
        *(DWORD*)((BYTE*)pPre+1)=(DWORD)hookedPresent-(DWORD)pPre-5;
! L5 ^0 y# r& M5 l$ k( j* ~( X* Z$ Z7 o8 C1 {/ D/ o% k; H( o
实际上这几个函数的hook都是同样的道理,现在,当程序运行到IDirect3DDevice9::Present后又会跳转到hookedPresent,而我们自己的绘制代码就是放在hookedPresent里面.在执行完自己的绘制代码后再调用原来的IDirect3DDevice9::Present.我的hookedPresent的关键代码如下:
; z' r; g5 c: ], F9 W& W) v* ]" j8 pchar strdraw[]="The drawing in directx game\nAuthor:RunJin\nEmail:[email protected]";
4 T/ o/ c5 v9 ^4 d# w" x            DrawMyText(pDxdevice,strdraw,sizeof strdraw-1);//绘制文本0 q2 h; _1 B" J
            //在这里写入您的其它绘图代码( H7 q4 Z0 I; D8 L, K( R6 |

0 D) N% R( g% m- Z9 S. v% n: \
0 b4 c7 S0 d# z  w8 D! h  ?. t& U再来看看其中的DrawMyText,这个函数是我的绘制文本的函数:7 t$ v& c; c4 i6 D, D
BOOL _stdcall DrawMyText(LPDIRECT3DDEVICE9 pDxdevice,TCHAR* strText ,int nbuf)0 r1 j) m$ {* c( o5 a
{
9 P$ t* N0 a' C7 y* c$ u& d
  {1 ^! U5 @, ^    if(m_pD3D && pDxdevice){- D' E: T0 T# {8 o
' j1 j6 {/ b/ |- O. i  h  F
        RECT myrect;/ Z, w  X1 _3 u+ t& t4 h& M. ~/ p
        myrect.top=150;  //文本块的y坐标& {' f" m. `9 d9 m: d7 ~( y
        myrect.left=0; //文本块的左坐标, M6 {: v4 G4 g$ ?+ ?! d
        myrect.right=500+myrect.left;
, J3 R' y+ f( w: t        myrect.bottom=100+myrect.top;
, _( E! Y5 x, a        pDxdevice->BeginScene();//开始绘制
& r# Y& M' T* ?$ x1 [$ E6 l( {7 I! m$ M9 c% k/ [8 i
        D3DXFONT_DESCA lf;& M) L& K" p' S+ h' C2 Q
        ZeroMemory(&lf, sizeof(D3DXFONT_DESCA));
, A! P3 B1 Y" V! u) R* O        lf.Height = 24; //字体高度# e0 M2 \1 B. v- _, p+ i
        lf.Width = 12; // 字体宽度
6 c& ?2 E& @7 X- k8 L2 _( Q0 o1 v        lf.Weight = 100;
' ?; _0 c+ H4 Z, i" M  |% h        lf.Italic = false;
% E7 ]! x* i, o* j8 M        lf.CharSet = DEFAULT_CHARSET;+ B4 J1 E1 H6 L- R2 c" U
        strcpy(lf.FaceName, "Times New Roman"); // 字型
! D+ Y$ _. j. g% w' [        ID3DXFont* font=NULL;/ d$ X- d+ n( f: Y
        if(D3D_OK!=D3DXCreateFontIndirect(pDxdevice, &lf, &font)) //创建字体对象
% j* m6 k' @: \: `: m6 I% ~9 @; G0 q/ P            return false;7 w& V7 I1 d& Y1 t
/ u& l( D' ?9 g0 y0 G( r
        font->DrawText(9 W0 v# x+ O( ]* y8 H
            NULL,
: U1 H* G( j4 R, o$ q$ b9 T            strText, // 要绘制的文本  Z+ E9 c: j+ R5 n' k2 L. H, P
            nbuf,
- g6 p, ]5 u8 f& P8 I$ Q1 t) A            &myrect,
) }* L2 ^  Q0 j  [: @  W) l            DT_TOP | DT_LEFT, // 字符居左显示
3 J% i# n2 L8 N/ _) I6 b! R            D3DCOLOR_ARGB(255,255,255,0)); ( q1 k& I8 _2 x
* t! \4 J, h' j+ H
        pDxdevice->EndScene();//结束绘制- f$ g5 h3 Q% ~: ~: d: v
        font->Release();//释放对象
" z) n0 g  Y) [$ e- U    }, F( ~$ M6 V1 N
    return true;
4 ^* _" ^# H0 i6 h$ a. K( N' R- p}) z" C5 ^' z; }/ }& W6 p8 N
1 O+ d0 `- `1 _
效果图:; U6 ^" ~% e% _; T* r* y4 n1 k

( B+ I) _; ?9 n; \6 a) T& S) G3 W2 k
6 c" t, R6 _) q. E8 P
  
% {7 f3 S# ~& E% o9 A0 o& @/ j8 U: X8 E/ _2 E0 B

1 ~- k9 Z: S* k; H6 Q7 w% R后记: 代码是以前写的,因此文章就按照着代码来讲.然而现在看来,把函数入口点的5个字节改成跳转指令这种hook方法并不是那么好,其实可以直接改掉虚函数表中的函数指针,这样更加的安全保险.
0 d  W. K3 m* E  X4 z
6 m6 ?. y. C- D2 z# }! ?
6 d+ g3 F& M3 X" R

本帖子中包含更多资源

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

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

使用道具 举报

沙发
发表于 2010-2-11 01:06 | 只看该作者
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx) c% a: w" Y0 r* V  m+ Q
1 B( I" R) m4 `/ L, r$ L* \& G
发一篇希望有帮助
回复 支持 反对

使用道具 举报

板凳
 楼主| 发表于 2010-2-11 07:51 | 只看该作者
引用第1楼byp100于2010-02-11 01:06发表的  :
8 O- L. {9 _# vhttp://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
  @2 S% f1 W$ ?" W
) M7 J1 I/ [: j( F# T/ Z) a发一篇希望有帮助

1 f1 I4 F  |8 A. Q, J3 e收到,多谢了,这篇文章我也早就找到过。
5 R. B0 s: J# j7 m目前就是要研究如何把汉化和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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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