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

汉化工具 HookDx

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

[汉化工具] HookDx

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

HookDx

本帖最后由 shane007 于 2021-2-13 22:23 编辑 + F* x% Z$ O  f# t; k, n6 E& g+ B
9 x7 a* [, a8 s/ g, b
DirrectxHook 工具2 }; s! j  E5 F1 K
1 S3 _/ }1 F5 a  _
标 题: 【原创】高手莫入 在游戏中显示自己的文字和图形的方法9 d/ e& o0 j9 M2 }) U2 G
作 者: runjin
2 U0 q- {$ V* b" q时 间: 2009-04-03,23:44
3 @' T- D$ N3 e0 q链 接: http://bbs.pediy.com/showthread.php?t=85368
6 f$ L) r7 j% t- n* E- b6 g
% U- e) m+ E+ {( \9 p) {4 u; `Hook Directx:在游戏中显示自己的文字和图形的方法4 q4 A. W7 k3 y  [" |
/ A8 U/ y9 K+ g$ ^% ]6 q/ F6 \
这个方法出自我大概两年前的一个项目,现在经整理后贴出来和大家分享一下,利用该方法可以在一般的directx游戏里面绘制文本甚至图形对象.* y8 `+ g- Y9 d8 u
其实思路上非常简单,大致是这样的:要在directx中绘制文字和各种图形对象,只要获得一个类型为LPDIRECT3DDEVICE9的设备对象指针.怎样获得这个指针呢?我的方法是首先hook掉Direct3DCreate9以获得类型为LPDIRECT3D9的Direct3D对象的接口指针,这个Direct3D对象有一个成员函数为 IDirect3D9::CreateDevice,设备对象指针就是在这个函数里面创建的.所以,只要根据Direct3D对象接口指针找到Direct3D对象的虚函数表,再根据虚函数表确定IDirect3D9::CreateDevice的内存地址,就可以hook这个函数,从而获得类型为LPDIRECT3DDEVICE9的设备对象指针,然后就可以随意绘制文字或者图形了.8 Y( D2 _& N; q( M0 I1 y! c4 i
还有一个要hook的地方,即IDirect3DDevice9::Present,这个函数用于交换当前后备缓存区,刷新窗口.要使得我们自己绘制的东西一直显示在屏幕上,比较好的处理方法是hook掉IDirect3DDevice9::Present,在程序真正调用这个函数前插入我们自己的绘制代码.只要根据设备对象指针找到设备对象的虚函数表,根据虚函数表找到IDirect3DDevice9::Present在内存中的地址就可以hook了.下面是对hook directx的详细说明./ z" Z$ e+ r- Z. X1 j
首先是找到Direct3DCreate9的内存地址,然后把入口的5个字节修改为跳转指令.) I/ x* z$ J, x7 h: Z9 \8 Y0 B
    pC=GetProcAddress(GetModuleHandle("d3d9.dll"),"Direct3DCreate9");//获得内存地址
( x' ?3 k$ l) {0 Z    DWORD oldpro=0;
  p) p: E( B( N    memcpy(d3dcen5bytes,pC,5);2 |5 X5 e, F5 t9 z# o9 N
    VirtualProtect(pC,5,PAGE_EXECUTE_READWRITE,&oldpro);+ b9 A5 ]5 E- T- o
    *(BYTE*)pC=0xe9;//0xe9在汇编中是跳转指令操作码
0 J' ~  m8 F: O5 c    *(DWORD*)((BYTE*)pC+1)=(DWORD)hookedDirect3DCreate9-(DWORD)pC-5;//目标地址-原地址-5
- |0 ]9 j; P1 ]' I' y* u6 w# q$ {9 ^( L
  a. X( @+ a# y6 X
这样,在程序运行到Direct3DCreate9时就会跳转到hookedDirect3DCreate9,在这个函数中,首先是还原Direct3DCreate9入口的5个字节,然后调用真正的Direct3DCreate9,如果函数调用成功,就会返回类型为LPDIRECT3D9的Direct3D对象指针,这正是我们所需要的,得到这个指针后,就可以根据Direct3D对象的虚函数表确定IDirect3D9::CreateDevice的内存地址,然后就可以把这个函数入口的5个字节修改成为跳转指令,跳到我们自己的函数中去. 有个地方值得注意的是,在directx的虚函数中把this指针作为第一个形参入栈了.例如说sdk中IDirect3D9::CreateDevice的函数说明是这样:
8 {; J2 T( d  r3 Z& e. iHRESULT CreateDevice(* _0 D+ _% ]+ q0 g8 X* m
  UINT Adapter,
: ]4 s: n% U6 d$ f3 ~- L  T. Q  Z  D3DDEVTYPE DeviceType,
( F) _& i: ?+ @) I+ C  HWND hFocusWindow,
' s0 A/ X7 U' A5 t1 w  DWORD BehaviorFlags,
! }7 F3 P( `' F+ Z5 Z% R  D3DPRESENT_PARAMETERS * pPresentationParameters,
' \3 t/ o) h: M4 @- |! _/ P) W  IDirect3DDevice9 ** ppReturnedDeviceInterface
6 A* W# r) L0 [);
# Q1 X  H9 C8 X6 A2 O- g
" d2 O7 j* o2 P) N: d, m
# k/ H- o9 o3 {! x. |6 u而为了程序跳转到我们的代码执行完后保持栈的平衡,hookedDirect3DCreat9函数声明应该是这样:7 f+ f" i( c) s) D# ], k
HRESULT _stdcall hookedCreateDevice(
# D- c0 ~( }' W' a2 L: Z                                  LPDIRECT3D9 pDx9,
1 W' E+ b' ]4 L0 A& v3 k                                  UINT Adapter,
; m; E- W0 v- _. e- @                                  D3DDEVTYPE DeviceType,
' w( {" I" G3 \: B# }& o                                  HWND hFocusWindow,4 d) j% S# X2 i" e
                                  DWORD BehaviorFlags,' U1 `- i3 S. ]6 ^0 x
                                  D3DPRESENT_PARAMETERS * pPresentationParameters,9 @, m/ T1 x6 e4 O5 v$ V; p
                                  IDirect3DDevice9 ** ppReturnedDeviceInterface' L6 W! K5 U4 Y% d

8 D* q! k5 ?" R9 M5 _2 N) T! q5 \                                  );: b) o  M* g. ?) i% z# M

1 T/ G+ U' A4 V, [+ y/ H1 }4 y其中的LPDIRECT3D9 pDx9就是this指针.6 R4 L) q, R3 B
& Q  Z; E, S$ g8 L* a" f% Z6 r
hookedDirect3DCreate9的关键代码如下:
& N7 J0 t( X, m: w$ Z' w% ^pCdev=(void*)*(DWORD*)(*(DWORD*)m_pD3D+0x40);//获得IDirect3D9::CreateDevice的地址指针$ ?* Y: \0 C6 s
; O( S+ T3 f( F# V
        DWORD oldpro=0;
+ E$ s7 d' j5 ~: ^0 H$ Q+ P        memcpy(devcen5bytes,pCdev,5);//保存IDirect3D9::CreateDevice入口5个字节7 O- m" c) @+ X
        VirtualProtect(pCdev,5,PAGE_EXECUTE_READWRITE,&oldpro);
) ]- l: A% o+ ^* Q( {+ V+ I( S        *(BYTE*)pCdev=0xe9;
; [7 T. h8 R' U% o" `# P6 e        *(DWORD*)((BYTE*)pCdev+1)=(DWORD)hookedCreateDevice-(DWORD)pCdev-5;
  G6 o! x' {/ Z' y* o9 z$ O
1 X" A: I7 T3 [  @9 I在hookedCreateDevice中,首先还原原来的CreateDevice函数入口的5个字节,然后调用原来的函数, IDirect3D9::CreateDevice的最后一个参数是一个二重指针,如果函数调用成功,这个二重指针所指向的指针就是我们所需要的设备对象指针,由此找到设备对象的虚函数表,然后确定IDirect3DDevice9::Present的内存地址,然后又可以改掉入口的5个字节为跳转指令. hookedCreateDevice的关键代码如下:; P) q( }) {1 T3 V
pPre=(void*)*(DWORD*)(*(DWORD*)m_pDevice+0x44);//获得IDirect3DDevice9::Present的地址指针8 c! a! l& m' U  ?; b
        memcpy(pren5bytes,pPre,5);//保存IDirect3DDevice9::Present入口的5个字节5 j" J3 r# r4 o6 u
        DWORD oldpro=0;) q2 u) M; H% w" J
        VirtualProtect(pPre,5,PAGE_EXECUTE_READWRITE,&oldpro);
* j5 a$ e& f+ x2 W        *(BYTE*)pPre=0xe9;5 i7 _, h8 u  a
        *(DWORD*)((BYTE*)pPre+1)=(DWORD)hookedPresent-(DWORD)pPre-5;
& G! r3 o* d2 y
4 {7 {, E/ o6 J% l% p9 k- X: T+ g实际上这几个函数的hook都是同样的道理,现在,当程序运行到IDirect3DDevice9::Present后又会跳转到hookedPresent,而我们自己的绘制代码就是放在hookedPresent里面.在执行完自己的绘制代码后再调用原来的IDirect3DDevice9::Present.我的hookedPresent的关键代码如下:. z& E' \' q" Y/ K, M# p" W! u
char strdraw[]="The drawing in directx game\nAuthor:RunJin\nEmail:[email protected]";2 N+ L  P' P, |) M" }3 H
            DrawMyText(pDxdevice,strdraw,sizeof strdraw-1);//绘制文本
5 V$ b! m5 J# b! S            //在这里写入您的其它绘图代码9 K0 Z$ _: X* d* a

* L) V- G, ?) ?1 P
+ ^9 i3 w; u- P3 Q! l4 y再来看看其中的DrawMyText,这个函数是我的绘制文本的函数:
3 U/ Y2 R2 U$ n; O' @1 GBOOL _stdcall DrawMyText(LPDIRECT3DDEVICE9 pDxdevice,TCHAR* strText ,int nbuf)* `: l7 Q2 h% z+ V2 T+ ~
{
+ _! V. w0 G) t1 d4 p: R& S
7 K% _9 q: z% ~+ \* G    if(m_pD3D && pDxdevice){" Z1 r, r& R5 Q" L$ }6 T0 N
# ~+ I% L% e# [' w. }* |
        RECT myrect;# S/ Y& \5 U9 b
        myrect.top=150;  //文本块的y坐标
+ ^+ J3 Q/ }9 U0 m* V3 }! F/ o        myrect.left=0; //文本块的左坐标& l) ]) j$ ]' A; K/ `6 c0 T
        myrect.right=500+myrect.left;( g' x6 L% h+ G5 L/ k
        myrect.bottom=100+myrect.top;
& u' w3 h! l' Y        pDxdevice->BeginScene();//开始绘制
' F) V8 l/ z8 X- C1 I7 N' O, H* w# d% }
" Q, \( M7 V+ m: u        D3DXFONT_DESCA lf;5 _6 F- r9 r- _/ {
        ZeroMemory(&lf, sizeof(D3DXFONT_DESCA));$ v, f( ^0 H! c/ I
        lf.Height = 24; //字体高度
- n0 y2 ]* f5 ^, I! ~0 z        lf.Width = 12; // 字体宽度
& e- W7 [2 H# W$ A; [7 n        lf.Weight = 100; 3 b1 I) ]3 U" Z3 P
        lf.Italic = false;0 N$ e6 [4 b# k0 p
        lf.CharSet = DEFAULT_CHARSET;
5 |, t% ^2 t/ T( @  D7 W4 u        strcpy(lf.FaceName, "Times New Roman"); // 字型2 A% P; I1 E( V) ]# K" f4 Z
        ID3DXFont* font=NULL;, N  d, f( g! K3 \, i* I. x
        if(D3D_OK!=D3DXCreateFontIndirect(pDxdevice, &lf, &font)) //创建字体对象
8 I9 s  q6 ~# C) c1 \            return false;
3 \/ H9 Z9 F0 h# l! E; c7 j2 u" x: u' j! R
        font->DrawText(
7 \! m- o% d4 z4 L* o            NULL,
* T5 d. ]  X$ s* d            strText, // 要绘制的文本* _" l5 Y. m7 n2 N2 {: Z
            nbuf, . U4 T6 z2 t/ Y: E3 a. w5 X/ m
            &myrect, % `6 X. h5 r, V2 e! s' @! Z% o
            DT_TOP | DT_LEFT, // 字符居左显示
. N! ?. b3 @$ S! G$ R3 u" C            D3DCOLOR_ARGB(255,255,255,0));
( l6 s6 z# W1 J8 L7 Q
5 M. e1 ]! m/ @7 E* r7 l. F        pDxdevice->EndScene();//结束绘制$ j# {" W: ]3 o  Y, u* z+ Y
        font->Release();//释放对象# D1 |/ C+ i! [& s, ]9 n8 d' m
    }
$ v$ H. l1 d: q4 S' q    return true;, \) v' o4 P/ V) V
}" O- t9 F, ^0 U7 q

4 M; S. ~% @% ^4 M9 c效果图:+ e" m5 M, k' J' Y& [

6 Y& T' M* H1 f+ i0 f/ N5 k  n
9 @3 q& I: P8 P/ Y; T7 ?4 p3 S
+ p, x. H" {) j! v/ ~) \, D  5 r, d3 O( u- T/ D- q6 x
0 e& |) r( y0 N" [; O* o

: u1 C# v  I/ ~6 T% y" q: D/ M+ K后记: 代码是以前写的,因此文章就按照着代码来讲.然而现在看来,把函数入口点的5个字节改成跳转指令这种hook方法并不是那么好,其实可以直接改掉虚函数表中的函数指针,这样更加的安全保险.
  \9 I# g  {- ]! j
" \% J, j, T8 z; S9 \; E
2 C& ~6 {0 [% n

本帖子中包含更多资源

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

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

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2010-2-11 07:51 | 只看该作者
引用第1楼byp100于2010-02-11 01:06发表的  :
! p- ?8 u# s- b) V; C! Lhttp://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
$ p( p- T* I' u4 S$ f
% x8 U' [  K8 v9 G# B3 w- K发一篇希望有帮助

6 N  D% V; b) v收到,多谢了,这篇文章我也早就找到过。
) \3 D$ e" w. o& @+ i" d  N( o! W9 D目前就是要研究如何把汉化和hook dx结合起来。
回复 支持 反对

使用道具 举报

沙发
发表于 2010-2-11 01:06 | 只看该作者
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx
3 [( ~  k" c6 i" S6 o/ x9 H! d+ ~) T1 ~' H( k2 R) H
发一篇希望有帮助
回复 支持 反对

使用道具 举报

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

本版积分规则

冒险解谜游戏中文网 ChinaAVG

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

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

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

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