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

汉化工具 HookDx

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

[汉化工具] HookDx

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

HookDx

本帖最后由 shane007 于 2021-2-13 22:23 编辑
+ k' n7 G5 @6 q1 S7 T5 u* w, J0 S( O9 ^4 _
DirrectxHook 工具+ H& k) x9 H+ G/ _. w

" D5 c& Q& J- ?8 a. a$ z标 题: 【原创】高手莫入 在游戏中显示自己的文字和图形的方法
4 d( |+ @6 b& _9 `, _3 [- w作 者: runjin
6 v6 Y$ R5 [! N+ }时 间: 2009-04-03,23:44, }( i& n# w9 q+ D! x$ @/ z
链 接: http://bbs.pediy.com/showthread.php?t=85368/ h7 n. }( w+ s/ W* X! V

+ ^! u; p" g" t7 p# bHook Directx:在游戏中显示自己的文字和图形的方法8 y9 d( R9 C2 T

5 |, }' J+ {) g8 X; \) u. O这个方法出自我大概两年前的一个项目,现在经整理后贴出来和大家分享一下,利用该方法可以在一般的directx游戏里面绘制文本甚至图形对象.$ n( J4 p, g7 ]7 G% }+ @" t
其实思路上非常简单,大致是这样的:要在directx中绘制文字和各种图形对象,只要获得一个类型为LPDIRECT3DDEVICE9的设备对象指针.怎样获得这个指针呢?我的方法是首先hook掉Direct3DCreate9以获得类型为LPDIRECT3D9的Direct3D对象的接口指针,这个Direct3D对象有一个成员函数为 IDirect3D9::CreateDevice,设备对象指针就是在这个函数里面创建的.所以,只要根据Direct3D对象接口指针找到Direct3D对象的虚函数表,再根据虚函数表确定IDirect3D9::CreateDevice的内存地址,就可以hook这个函数,从而获得类型为LPDIRECT3DDEVICE9的设备对象指针,然后就可以随意绘制文字或者图形了.
3 `3 N3 @! p$ A% W# T: M2 o! D还有一个要hook的地方,即IDirect3DDevice9::Present,这个函数用于交换当前后备缓存区,刷新窗口.要使得我们自己绘制的东西一直显示在屏幕上,比较好的处理方法是hook掉IDirect3DDevice9::Present,在程序真正调用这个函数前插入我们自己的绘制代码.只要根据设备对象指针找到设备对象的虚函数表,根据虚函数表找到IDirect3DDevice9::Present在内存中的地址就可以hook了.下面是对hook directx的详细说明.: _8 l3 Z1 ?! M3 w
首先是找到Direct3DCreate9的内存地址,然后把入口的5个字节修改为跳转指令.5 Z- ]0 w& @1 F% H6 k# N4 @
    pC=GetProcAddress(GetModuleHandle("d3d9.dll"),"Direct3DCreate9");//获得内存地址
/ p+ N- L, [/ u. d    DWORD oldpro=0;
/ X/ L/ G4 _* |    memcpy(d3dcen5bytes,pC,5);
; ^1 v' p6 o# X$ H    VirtualProtect(pC,5,PAGE_EXECUTE_READWRITE,&oldpro);
/ f& {4 B; [8 [7 ~    *(BYTE*)pC=0xe9;//0xe9在汇编中是跳转指令操作码
' ~8 |% a4 a, i* F( ^    *(DWORD*)((BYTE*)pC+1)=(DWORD)hookedDirect3DCreate9-(DWORD)pC-5;//目标地址-原地址-5  {" A8 X0 ]% B0 W

5 c3 J2 Q$ B9 `) i7 O* c1 y7 g2 I/ F) D
2 j& t+ e  E7 I2 ~这样,在程序运行到Direct3DCreate9时就会跳转到hookedDirect3DCreate9,在这个函数中,首先是还原Direct3DCreate9入口的5个字节,然后调用真正的Direct3DCreate9,如果函数调用成功,就会返回类型为LPDIRECT3D9的Direct3D对象指针,这正是我们所需要的,得到这个指针后,就可以根据Direct3D对象的虚函数表确定IDirect3D9::CreateDevice的内存地址,然后就可以把这个函数入口的5个字节修改成为跳转指令,跳到我们自己的函数中去. 有个地方值得注意的是,在directx的虚函数中把this指针作为第一个形参入栈了.例如说sdk中IDirect3D9::CreateDevice的函数说明是这样:* s" G  F6 \- v7 y1 e$ M
HRESULT CreateDevice(
& w7 P: w( ?: ^: v& K( u1 V  UINT Adapter,: E4 i7 |/ c! U1 H0 y
  D3DDEVTYPE DeviceType,7 k' L9 Q+ M! J4 d: y: t
  HWND hFocusWindow,) y; Z3 L: C# N, |) F
  DWORD BehaviorFlags,
9 N/ w" n$ P/ D4 k. S. X  D3DPRESENT_PARAMETERS * pPresentationParameters,1 X; |0 ?0 R" }' y9 e; f
  IDirect3DDevice9 ** ppReturnedDeviceInterface/ m( N# b6 s- I. i% r/ [7 e) q2 d
);
" h3 P+ J- `( W$ R7 r  p, L' _' i8 f  {
! d1 z" Q) H: o* i+ Q
而为了程序跳转到我们的代码执行完后保持栈的平衡,hookedDirect3DCreat9函数声明应该是这样:/ J, p& Q/ `7 |2 g* s  C, i4 K5 M, z, x
HRESULT _stdcall hookedCreateDevice(  _7 @+ u2 Y+ @& D0 t' ?' R2 B* t
                                  LPDIRECT3D9 pDx9,. [8 M2 h" a; a; x2 Z$ e8 d2 x- Q) G7 Q
                                  UINT Adapter,+ J9 E; w" }5 S# Y- e$ l/ E
                                  D3DDEVTYPE DeviceType,
% n( l; N0 a6 ?, J                                  HWND hFocusWindow,2 k4 h3 g( g5 b7 a
                                  DWORD BehaviorFlags,) d; R: x6 y1 A! ]. B4 o8 F
                                  D3DPRESENT_PARAMETERS * pPresentationParameters,
  m+ w' ]5 }3 u                                  IDirect3DDevice9 ** ppReturnedDeviceInterface
$ Q/ p( I4 D! Y! j
; B& @0 I* u& J" G6 T$ l( V                                  );" u. K5 v# x- |. [; H- _' z* S3 W6 c

' I9 g0 q1 |9 n3 D" y其中的LPDIRECT3D9 pDx9就是this指针.( h3 u& B7 f! o4 S' l4 r
0 U& b$ n. c" B- P) S* v
hookedDirect3DCreate9的关键代码如下:- }0 w' \$ c7 _2 z+ ]' g3 |" B7 U/ k! J: _
pCdev=(void*)*(DWORD*)(*(DWORD*)m_pD3D+0x40);//获得IDirect3D9::CreateDevice的地址指针. j4 b3 s1 p5 _

4 |# [2 j' ~4 n4 ^: q( F        DWORD oldpro=0;
- ~3 X1 R8 L4 _% p( J; Y) B6 W        memcpy(devcen5bytes,pCdev,5);//保存IDirect3D9::CreateDevice入口5个字节- {: v5 _/ _  G
        VirtualProtect(pCdev,5,PAGE_EXECUTE_READWRITE,&oldpro);( ^- _/ V& o/ |% |+ k4 P& A: C- a1 O
        *(BYTE*)pCdev=0xe9;; S$ @/ H0 `& s6 ^! J9 b
        *(DWORD*)((BYTE*)pCdev+1)=(DWORD)hookedCreateDevice-(DWORD)pCdev-5;0 b7 }2 c) `5 a* V8 u4 |

* ?" e, D0 v6 x在hookedCreateDevice中,首先还原原来的CreateDevice函数入口的5个字节,然后调用原来的函数, IDirect3D9::CreateDevice的最后一个参数是一个二重指针,如果函数调用成功,这个二重指针所指向的指针就是我们所需要的设备对象指针,由此找到设备对象的虚函数表,然后确定IDirect3DDevice9::Present的内存地址,然后又可以改掉入口的5个字节为跳转指令. hookedCreateDevice的关键代码如下:
+ N  b# e) {5 m# \pPre=(void*)*(DWORD*)(*(DWORD*)m_pDevice+0x44);//获得IDirect3DDevice9::Present的地址指针" I9 w$ b; s1 h% ~  R0 p
        memcpy(pren5bytes,pPre,5);//保存IDirect3DDevice9::Present入口的5个字节# S' W/ g$ p+ H
        DWORD oldpro=0;
: W6 p, I- K3 X, U. u0 {        VirtualProtect(pPre,5,PAGE_EXECUTE_READWRITE,&oldpro);9 e8 x, H  S, S) L4 ]' i, m# A
        *(BYTE*)pPre=0xe9;
4 z, d: n# L* V# k3 ~5 b" s        *(DWORD*)((BYTE*)pPre+1)=(DWORD)hookedPresent-(DWORD)pPre-5;
: ^5 B$ i! `% ?) P  }/ w( Q# h
实际上这几个函数的hook都是同样的道理,现在,当程序运行到IDirect3DDevice9::Present后又会跳转到hookedPresent,而我们自己的绘制代码就是放在hookedPresent里面.在执行完自己的绘制代码后再调用原来的IDirect3DDevice9::Present.我的hookedPresent的关键代码如下:6 M& |( z9 o5 a0 x% K4 M* v
char strdraw[]="The drawing in directx game\nAuthor:RunJin\nEmail:[email protected]";
+ v4 D  t* B6 X2 [  t# Q2 p            DrawMyText(pDxdevice,strdraw,sizeof strdraw-1);//绘制文本% x0 g! z& R- J3 _2 i
            //在这里写入您的其它绘图代码
; i/ H0 A7 p# v* o. F
* F9 \4 f, s1 |
) T9 b- d/ O/ [* p9 {& k- q再来看看其中的DrawMyText,这个函数是我的绘制文本的函数:# T% d6 p5 I/ J; X6 }0 E* q- u
BOOL _stdcall DrawMyText(LPDIRECT3DDEVICE9 pDxdevice,TCHAR* strText ,int nbuf)
' F( J5 l, T2 R5 K6 s{
  u# e% H! m+ ~0 T2 D( b: i* {
3 i: ?* y6 S9 E    if(m_pD3D && pDxdevice){
# F1 Q3 _7 t" D
$ X/ I& Z& M# C& B        RECT myrect;; M* p, a; u9 I! `% m; a/ W
        myrect.top=150;  //文本块的y坐标9 x+ d: B1 c7 M. P
        myrect.left=0; //文本块的左坐标- W. R- E$ T& r0 u7 I
        myrect.right=500+myrect.left;  m4 d  a7 }5 H/ B  B! I8 `, S
        myrect.bottom=100+myrect.top;
' U1 D6 i9 T/ j        pDxdevice->BeginScene();//开始绘制
( R. M- U  _/ @3 l" v- P
; ]4 ?% @* b/ E1 F$ r4 K        D3DXFONT_DESCA lf;6 ?2 C/ J, y; M) W- T: S. f/ i9 R
        ZeroMemory(&lf, sizeof(D3DXFONT_DESCA));  A, Z' p% f/ H# X1 h2 @, e
        lf.Height = 24; //字体高度1 u0 R! ^& u  |
        lf.Width = 12; // 字体宽度
: A0 A0 W2 C- q9 t        lf.Weight = 100;
4 X8 `- w9 a) L2 z) i, Z* N, h        lf.Italic = false;
8 d3 v3 l! s! J* b8 f6 Y3 `        lf.CharSet = DEFAULT_CHARSET;! W" o# {3 s2 b
        strcpy(lf.FaceName, "Times New Roman"); // 字型" M: k5 K) K1 R$ N1 J' a$ Y! `5 D# n
        ID3DXFont* font=NULL;
$ V$ }! R+ i3 a1 g+ }/ b1 b9 b0 U5 I        if(D3D_OK!=D3DXCreateFontIndirect(pDxdevice, &lf, &font)) //创建字体对象
# u2 M7 A2 I; g* h* {) ?            return false;
9 r/ a! E% p% P! ]
' ?& Q0 u/ {9 g) |        font->DrawText(9 E' B+ h3 ?' I6 J. H* T: I) _$ b
            NULL,
1 d, \) G, `' }: Z1 R            strText, // 要绘制的文本
, B4 M  Y" K6 j6 ^, Q! L            nbuf,
( L. D5 L/ D+ z7 Q) C$ ^            &myrect,
8 ?) C  w9 ]2 w! a            DT_TOP | DT_LEFT, // 字符居左显示7 K6 M7 o6 ?& y6 |7 ^
            D3DCOLOR_ARGB(255,255,255,0));
" N8 I4 }. f; M7 c" ~
' P5 C2 L7 }) |+ V9 }3 \6 J, W        pDxdevice->EndScene();//结束绘制
4 F# U: I9 ^4 i2 h  U        font->Release();//释放对象
* w& l  g1 Z( v% Y4 A2 O! U. a    }
: d2 X2 l3 F, C& q! n/ l+ J    return true;
+ F9 r8 J* X5 [# w! v8 t}4 b' Z, d7 w- ?
+ w3 B+ N  q6 y
效果图:
& y9 V- O1 f2 a * _! ~) f1 }& B2 r" Z) J

8 U* T7 n) q0 u6 o) z& O& T: v4 ^4 v" w; D7 f2 a
  " j+ _) [; T4 F; e6 c: S

' a8 K5 J+ ^: t3 {0 [0 I
! v! S/ R6 V6 _2 O( o后记: 代码是以前写的,因此文章就按照着代码来讲.然而现在看来,把函数入口点的5个字节改成跳转指令这种hook方法并不是那么好,其实可以直接改掉虚函数表中的函数指针,这样更加的安全保险.' P1 S- }% u' z% J
/ |/ o, ]$ e1 d! D' Q3 Y8 F

" a' A: t* `) H- V* B

本帖子中包含更多资源

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

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

使用道具 举报

沙发
发表于 2010-2-11 01:06 | 只看该作者
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
+ N" X% M0 I0 C+ \* o( D7 [, z" ]5 T- H6 u5 k+ `3 w, _1 D- D
发一篇希望有帮助
回复 支持 反对

使用道具 举报

板凳
 楼主| 发表于 2010-2-11 07:51 | 只看该作者
引用第1楼byp100于2010-02-11 01:06发表的  :
( J+ D% Y3 X; s1 Q& V2 nhttp://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx* I5 `( U0 q2 a4 H+ e3 I

! r& {9 Y% C! _0 B发一篇希望有帮助

0 a- A  a$ U# V5 h1 K收到,多谢了,这篇文章我也早就找到过。: ?7 g( s# V1 {2 `- M7 ?% a8 [
目前就是要研究如何把汉化和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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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