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

汉化工具 HookDx

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

[汉化工具] HookDx

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

HookDx

本帖最后由 shane007 于 2021-2-13 22:23 编辑
7 F+ B: i7 y4 H* A/ T' w) a
* `8 `; K8 k0 B$ CDirrectxHook 工具
+ u; D( t2 U$ b* n! c6 v3 L% k$ V/ l: @! s6 x+ N7 Q+ v
标 题: 【原创】高手莫入 在游戏中显示自己的文字和图形的方法/ W' q2 u. w1 y
作 者: runjin
, Z+ e% R% T% _1 T9 o; e) p9 r2 z时 间: 2009-04-03,23:44! S% w/ n6 A/ M5 o2 f
链 接: http://bbs.pediy.com/showthread.php?t=85368) B8 Z9 T) g: f# Z9 Y. t
7 d# n. i# X* C0 N5 F1 f6 ]* N
Hook Directx:在游戏中显示自己的文字和图形的方法2 g5 u6 Y9 S; R6 P  Y* J7 \

& Y1 j6 L+ i! Q* Q5 H6 e# L6 o这个方法出自我大概两年前的一个项目,现在经整理后贴出来和大家分享一下,利用该方法可以在一般的directx游戏里面绘制文本甚至图形对象.4 g) W0 l5 K; q* t& T+ B
其实思路上非常简单,大致是这样的:要在directx中绘制文字和各种图形对象,只要获得一个类型为LPDIRECT3DDEVICE9的设备对象指针.怎样获得这个指针呢?我的方法是首先hook掉Direct3DCreate9以获得类型为LPDIRECT3D9的Direct3D对象的接口指针,这个Direct3D对象有一个成员函数为 IDirect3D9::CreateDevice,设备对象指针就是在这个函数里面创建的.所以,只要根据Direct3D对象接口指针找到Direct3D对象的虚函数表,再根据虚函数表确定IDirect3D9::CreateDevice的内存地址,就可以hook这个函数,从而获得类型为LPDIRECT3DDEVICE9的设备对象指针,然后就可以随意绘制文字或者图形了.
+ \- s) a: Y- X; N- A4 R还有一个要hook的地方,即IDirect3DDevice9::Present,这个函数用于交换当前后备缓存区,刷新窗口.要使得我们自己绘制的东西一直显示在屏幕上,比较好的处理方法是hook掉IDirect3DDevice9::Present,在程序真正调用这个函数前插入我们自己的绘制代码.只要根据设备对象指针找到设备对象的虚函数表,根据虚函数表找到IDirect3DDevice9::Present在内存中的地址就可以hook了.下面是对hook directx的详细说明.$ u/ C8 O" c$ y
首先是找到Direct3DCreate9的内存地址,然后把入口的5个字节修改为跳转指令.3 ~( s/ e3 O( t5 k' ?
    pC=GetProcAddress(GetModuleHandle("d3d9.dll"),"Direct3DCreate9");//获得内存地址
" w+ ]1 |3 n' ^/ [1 `    DWORD oldpro=0;
* V( h: [, i3 W9 v6 T& t( a    memcpy(d3dcen5bytes,pC,5);
* ~/ w3 \3 j! E4 S) @8 |    VirtualProtect(pC,5,PAGE_EXECUTE_READWRITE,&oldpro);( C- v. D1 R/ {
    *(BYTE*)pC=0xe9;//0xe9在汇编中是跳转指令操作码+ M- R- F. F" [, g  C7 w: r
    *(DWORD*)((BYTE*)pC+1)=(DWORD)hookedDirect3DCreate9-(DWORD)pC-5;//目标地址-原地址-5( n3 K* `/ L3 ~/ P, p6 C

5 f% K( k) z& _, \1 h+ K! G, }
: d5 k$ \  A3 I8 u7 y, C9 Z这样,在程序运行到Direct3DCreate9时就会跳转到hookedDirect3DCreate9,在这个函数中,首先是还原Direct3DCreate9入口的5个字节,然后调用真正的Direct3DCreate9,如果函数调用成功,就会返回类型为LPDIRECT3D9的Direct3D对象指针,这正是我们所需要的,得到这个指针后,就可以根据Direct3D对象的虚函数表确定IDirect3D9::CreateDevice的内存地址,然后就可以把这个函数入口的5个字节修改成为跳转指令,跳到我们自己的函数中去. 有个地方值得注意的是,在directx的虚函数中把this指针作为第一个形参入栈了.例如说sdk中IDirect3D9::CreateDevice的函数说明是这样:
/ D3 F/ N1 o3 D* D' v! sHRESULT CreateDevice(% r2 O6 O; R( P: {
  UINT Adapter,
* V7 Q. ?7 _& w/ y  D3DDEVTYPE DeviceType,2 `& b2 \% c8 s# Q+ Q
  HWND hFocusWindow,; _0 Q) m5 {* F6 P$ t
  DWORD BehaviorFlags,  T6 [2 \- M  H" l
  D3DPRESENT_PARAMETERS * pPresentationParameters,) c9 J9 b4 q1 \6 q) Z7 H
  IDirect3DDevice9 ** ppReturnedDeviceInterface
+ L& s4 @7 f4 V* x& K* U( g" `% b);
! _8 a6 ]: A% |! p/ U. \* L5 |- T" J& p) ?3 f& l3 x
5 K/ c! o( |, }" r$ ]% V
而为了程序跳转到我们的代码执行完后保持栈的平衡,hookedDirect3DCreat9函数声明应该是这样:, x4 d) D- e' Z. `* `
HRESULT _stdcall hookedCreateDevice(+ r+ i2 [4 Z$ C0 D
                                  LPDIRECT3D9 pDx9,; B8 ]* H- H- {0 a) ^* F
                                  UINT Adapter,
- x+ S$ M/ T  r/ ~7 |, F- i5 `                                  D3DDEVTYPE DeviceType,+ S- l- q0 K. t+ b
                                  HWND hFocusWindow,& `, q1 u: q+ W
                                  DWORD BehaviorFlags,
; |% X) Q0 A, i7 r- F& W                                  D3DPRESENT_PARAMETERS * pPresentationParameters,
2 L, G" Z+ x* I1 a+ F/ W                                  IDirect3DDevice9 ** ppReturnedDeviceInterface0 @# A. V& T& J3 g& P3 I

8 t# N' i0 h, K' v6 i2 \* b                                  );! e$ G7 R7 r/ B# }& G$ l7 @" h- G
, I- Y' I/ ^6 P
其中的LPDIRECT3D9 pDx9就是this指针., g4 y$ Z% T2 C5 c

+ W  |" t4 w- C" D3 z  ShookedDirect3DCreate9的关键代码如下:7 ^" {4 O4 ~' G
pCdev=(void*)*(DWORD*)(*(DWORD*)m_pD3D+0x40);//获得IDirect3D9::CreateDevice的地址指针
: j, p0 h8 O7 i: h% G# d  j9 I' N! ]. F  L  [3 p
        DWORD oldpro=0;5 q3 _. K9 i8 h! w5 I  Z
        memcpy(devcen5bytes,pCdev,5);//保存IDirect3D9::CreateDevice入口5个字节
; x% y6 H2 w0 I! Y* \$ o' h" Q        VirtualProtect(pCdev,5,PAGE_EXECUTE_READWRITE,&oldpro);
' L8 R; \% u5 g" ?( t2 }7 ~        *(BYTE*)pCdev=0xe9;
) r- o( D* d' [7 J        *(DWORD*)((BYTE*)pCdev+1)=(DWORD)hookedCreateDevice-(DWORD)pCdev-5;
# ~; F; ^( T- u; @3 S- O' k% g6 R
2 o' S  u* l7 y+ F5 D1 f在hookedCreateDevice中,首先还原原来的CreateDevice函数入口的5个字节,然后调用原来的函数, IDirect3D9::CreateDevice的最后一个参数是一个二重指针,如果函数调用成功,这个二重指针所指向的指针就是我们所需要的设备对象指针,由此找到设备对象的虚函数表,然后确定IDirect3DDevice9::Present的内存地址,然后又可以改掉入口的5个字节为跳转指令. hookedCreateDevice的关键代码如下:# o7 G8 F; M8 ?' p' B/ Z9 C* M
pPre=(void*)*(DWORD*)(*(DWORD*)m_pDevice+0x44);//获得IDirect3DDevice9::Present的地址指针
1 m/ c3 X9 j9 X$ _3 v; M8 @        memcpy(pren5bytes,pPre,5);//保存IDirect3DDevice9::Present入口的5个字节4 Y# u( }1 Y, U' F; S1 J1 o
        DWORD oldpro=0;
  i9 h1 \6 z$ C" @        VirtualProtect(pPre,5,PAGE_EXECUTE_READWRITE,&oldpro);
) u- L, ^5 s( K% r        *(BYTE*)pPre=0xe9;
. C( S# @! m. S/ ?8 o# w- f        *(DWORD*)((BYTE*)pPre+1)=(DWORD)hookedPresent-(DWORD)pPre-5;
* S+ Z3 V  ~. v* N" G# d" f/ \5 j$ [$ {% ~# ]; D
实际上这几个函数的hook都是同样的道理,现在,当程序运行到IDirect3DDevice9::Present后又会跳转到hookedPresent,而我们自己的绘制代码就是放在hookedPresent里面.在执行完自己的绘制代码后再调用原来的IDirect3DDevice9::Present.我的hookedPresent的关键代码如下:
( `2 q8 D2 W# T2 c2 I8 Kchar strdraw[]="The drawing in directx game\nAuthor:RunJin\nEmail:[email protected]";& h  K7 ]6 v; c0 B- c" t
            DrawMyText(pDxdevice,strdraw,sizeof strdraw-1);//绘制文本2 C7 G$ h4 Q5 a! s( g' D
            //在这里写入您的其它绘图代码
% u- i; e6 ^. Z2 P. e
# P9 r3 S2 J9 T: `# l+ b
. {) x/ N/ |( s再来看看其中的DrawMyText,这个函数是我的绘制文本的函数:
' q9 [6 F3 n9 Z$ ~5 _' f/ p; vBOOL _stdcall DrawMyText(LPDIRECT3DDEVICE9 pDxdevice,TCHAR* strText ,int nbuf)
' a1 e& y/ v, V5 H5 S{+ u; o( D$ O9 o: W6 U5 {
5 G9 j$ ~! v& W9 l8 E
    if(m_pD3D && pDxdevice){
$ Z) M- ?& o6 K9 Q- h( u
( T  i, s! F* K3 p1 M, {        RECT myrect;
3 [( L2 h% O' z; I% i" C" M) u4 k        myrect.top=150;  //文本块的y坐标0 E# {' V0 q, k4 _
        myrect.left=0; //文本块的左坐标# {$ [, q- C5 m* x: y
        myrect.right=500+myrect.left;$ L1 A) d# r: S, f3 p. h* h
        myrect.bottom=100+myrect.top;- z2 m" {8 r8 c3 R3 V5 O( H
        pDxdevice->BeginScene();//开始绘制
! a4 ]: Y/ o* q, e( k# r3 N# k6 }; K* D/ M) J; I
        D3DXFONT_DESCA lf;5 i1 _* o2 [9 k  l1 X; R2 ?1 t
        ZeroMemory(&lf, sizeof(D3DXFONT_DESCA));
# C/ l5 {* f( s        lf.Height = 24; //字体高度8 c7 {+ a4 ?! \5 U  c+ C
        lf.Width = 12; // 字体宽度
: k/ ], Y' k0 \! x0 F        lf.Weight = 100;
9 s$ Q/ Z7 f% \) h/ f        lf.Italic = false;
; a! v  ~: o$ h        lf.CharSet = DEFAULT_CHARSET;
( O1 i+ H. ]; |( @& u: f. _& B- P        strcpy(lf.FaceName, "Times New Roman"); // 字型0 h2 a+ f4 Y, m: o/ q
        ID3DXFont* font=NULL;' Y- ?, J% t* B' D  Q
        if(D3D_OK!=D3DXCreateFontIndirect(pDxdevice, &lf, &font)) //创建字体对象
+ E1 o3 k9 E8 c! P; `6 |: w8 ]* h            return false;- `1 J- [/ ]& `0 z8 O, E
' k. B8 s7 L+ G
        font->DrawText(
$ e5 O9 T/ I! a% ]) p            NULL,4 c) L7 D3 {: d6 O5 L( V( _4 m: C  f
            strText, // 要绘制的文本5 k$ \, R" \( z6 F
            nbuf,
' F0 T  P3 h& K- \7 b: F            &myrect, $ z' Y& T, j7 f% Z& p& \) ~
            DT_TOP | DT_LEFT, // 字符居左显示
1 D+ z1 O' ~# `            D3DCOLOR_ARGB(255,255,255,0));
" E' v8 O+ _) i; v4 `8 l/ X% o0 }0 T  U
        pDxdevice->EndScene();//结束绘制( g- ]. ~2 ~. s0 `' ~
        font->Release();//释放对象0 p* U% K: W  u/ P5 F4 i" c
    }
# B, O' O3 j9 ~  P& g+ s& n& d% q    return true;
# t& H3 }1 |4 N0 v) A8 v. q1 ]8 c}
* L8 X8 [; W2 e$ a% L( Z
. s2 s8 r- t* K, j3 Y效果图:
7 S) q) G/ `' ^' ?0 h0 Z. @6 Z# k ' y9 F% \& `% ^. Y) y

% N% `) U. R/ b2 B. C+ z, N/ S% v7 C) i5 l; U
  
9 p4 l# K  B" C8 E% F" J" e
) U8 I3 p7 v4 X, S& ]+ \# R
3 E( z& l9 R! ?5 u& ^后记: 代码是以前写的,因此文章就按照着代码来讲.然而现在看来,把函数入口点的5个字节改成跳转指令这种hook方法并不是那么好,其实可以直接改掉虚函数表中的函数指针,这样更加的安全保险.1 t" f' z8 b+ {9 |; v
, |& ?; l/ ]  W+ |6 S

% n! @" i+ R  O

本帖子中包含更多资源

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

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

使用道具 举报

沙发
发表于 2010-2-11 01:06 | 只看该作者
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
. d, m) e$ O- b3 y6 r; a1 T( U9 l( E/ Q0 r  ]: F
发一篇希望有帮助
回复 支持 反对

使用道具 举报

板凳
 楼主| 发表于 2010-2-11 07:51 | 只看该作者
引用第1楼byp100于2010-02-11 01:06发表的  :* k* O4 A4 J& B6 }, j
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
, h. f: ^1 Y) w3 q9 `  k5 T5 z" ^! t. o" A
发一篇希望有帮助

% z1 p" ?% @  s/ O- e收到,多谢了,这篇文章我也早就找到过。
% s8 v. q2 W1 v2 y6 g目前就是要研究如何把汉化和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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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