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

汉化工具 HookDx

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

[汉化工具] HookDx

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

HookDx

本帖最后由 shane007 于 2021-2-13 22:23 编辑 1 h5 T% |: p4 j2 |8 R2 [+ ~
- }4 Z5 f9 {/ p4 E7 j
DirrectxHook 工具6 s& U/ y" \; y+ f3 f. y
" i& @# r, Q0 B3 g( O
标 题: 【原创】高手莫入 在游戏中显示自己的文字和图形的方法
1 @# K4 T4 ]3 x( H3 c作 者: runjin
  O6 c* x+ h. b+ z时 间: 2009-04-03,23:44$ E9 }2 E' r5 k: b& k/ K
链 接: http://bbs.pediy.com/showthread.php?t=85368
& n" p7 K% g9 W3 D* h( i+ C7 n5 s
" Y0 N1 K$ L" U0 V$ u8 Q% j6 yHook Directx:在游戏中显示自己的文字和图形的方法/ C# S  M- E6 _% t4 U" G8 M/ h

8 S$ Z: e# O/ o1 c$ O这个方法出自我大概两年前的一个项目,现在经整理后贴出来和大家分享一下,利用该方法可以在一般的directx游戏里面绘制文本甚至图形对象.! z9 @8 P, N! |. G: |. J/ K" I
其实思路上非常简单,大致是这样的:要在directx中绘制文字和各种图形对象,只要获得一个类型为LPDIRECT3DDEVICE9的设备对象指针.怎样获得这个指针呢?我的方法是首先hook掉Direct3DCreate9以获得类型为LPDIRECT3D9的Direct3D对象的接口指针,这个Direct3D对象有一个成员函数为 IDirect3D9::CreateDevice,设备对象指针就是在这个函数里面创建的.所以,只要根据Direct3D对象接口指针找到Direct3D对象的虚函数表,再根据虚函数表确定IDirect3D9::CreateDevice的内存地址,就可以hook这个函数,从而获得类型为LPDIRECT3DDEVICE9的设备对象指针,然后就可以随意绘制文字或者图形了.
+ @% H4 V8 |' {8 w* O' Y: S* i还有一个要hook的地方,即IDirect3DDevice9::Present,这个函数用于交换当前后备缓存区,刷新窗口.要使得我们自己绘制的东西一直显示在屏幕上,比较好的处理方法是hook掉IDirect3DDevice9::Present,在程序真正调用这个函数前插入我们自己的绘制代码.只要根据设备对象指针找到设备对象的虚函数表,根据虚函数表找到IDirect3DDevice9::Present在内存中的地址就可以hook了.下面是对hook directx的详细说明.
7 j  v  X0 s  d" F首先是找到Direct3DCreate9的内存地址,然后把入口的5个字节修改为跳转指令.
! w  M7 S" P0 }' Y1 O/ @0 h    pC=GetProcAddress(GetModuleHandle("d3d9.dll"),"Direct3DCreate9");//获得内存地址" k+ k' q/ i3 K/ L# X" d+ m
    DWORD oldpro=0;/ U5 K* N  v) D6 v" g
    memcpy(d3dcen5bytes,pC,5);! @9 @9 D7 u1 i- o& R. d4 F
    VirtualProtect(pC,5,PAGE_EXECUTE_READWRITE,&oldpro);
: t% R: W( o8 X/ a- C; ?    *(BYTE*)pC=0xe9;//0xe9在汇编中是跳转指令操作码
2 }8 m$ h. d; ~, [  ~3 [$ |. L    *(DWORD*)((BYTE*)pC+1)=(DWORD)hookedDirect3DCreate9-(DWORD)pC-5;//目标地址-原地址-5
5 |; Z1 `6 C2 C( ]; W1 m& J9 D  C
5 F) B3 E! U4 ~) |3 y) B, b* c$ Z4 M5 i$ q8 _8 J
这样,在程序运行到Direct3DCreate9时就会跳转到hookedDirect3DCreate9,在这个函数中,首先是还原Direct3DCreate9入口的5个字节,然后调用真正的Direct3DCreate9,如果函数调用成功,就会返回类型为LPDIRECT3D9的Direct3D对象指针,这正是我们所需要的,得到这个指针后,就可以根据Direct3D对象的虚函数表确定IDirect3D9::CreateDevice的内存地址,然后就可以把这个函数入口的5个字节修改成为跳转指令,跳到我们自己的函数中去. 有个地方值得注意的是,在directx的虚函数中把this指针作为第一个形参入栈了.例如说sdk中IDirect3D9::CreateDevice的函数说明是这样:
5 A8 Z) X) J: C' Q3 `HRESULT CreateDevice(2 \* \. _1 i, m: e2 }, J
  UINT Adapter,
+ _: ^/ z( A/ T/ C  D3DDEVTYPE DeviceType,
) H$ o( [: T, n9 N! Y2 }4 p' P/ z+ _  HWND hFocusWindow,
! O* p4 W' I7 B  v7 t+ H  DWORD BehaviorFlags,6 f* I1 k9 }; S0 B' [6 R6 N( d
  D3DPRESENT_PARAMETERS * pPresentationParameters,. c) j- \7 x2 X' R6 K0 w7 q
  IDirect3DDevice9 ** ppReturnedDeviceInterface
9 j" S# e) ]( ?% Y: g6 ?) {  G% M);
, \% d- ^6 Q8 N. j' Q' k! W& B9 k: Z  `, m; S% v* r1 o

. U. t4 w9 p4 `- Z/ Y/ ~而为了程序跳转到我们的代码执行完后保持栈的平衡,hookedDirect3DCreat9函数声明应该是这样:
4 t$ A- z4 X9 D2 C. Z/ VHRESULT _stdcall hookedCreateDevice(
1 ], Y- |: C& M9 q3 C& B1 w: W% O! ~                                  LPDIRECT3D9 pDx9,5 ?) w8 v  w1 H2 m# x# [( f
                                  UINT Adapter,
' i6 P$ Y  k$ r$ e                                  D3DDEVTYPE DeviceType,$ F8 ~& t; x# D
                                  HWND hFocusWindow,: r9 y7 H3 o5 M9 g, h* {
                                  DWORD BehaviorFlags,
% Z2 v8 q+ a; Q% @0 k. g. Q& _                                  D3DPRESENT_PARAMETERS * pPresentationParameters,7 N; @( x& x+ O9 n9 e) A
                                  IDirect3DDevice9 ** ppReturnedDeviceInterface  u2 _4 n" p" a3 z' v2 }& p

: n* [- _# c0 s! R# y2 p- c                                  );' W) ~! L4 q9 Q4 ]3 ~

& {; }+ M# F5 d* G4 T0 o7 Q其中的LPDIRECT3D9 pDx9就是this指针.1 K$ X/ m2 e- j% j

! J! M; @/ _4 G9 [5 ~9 W& ohookedDirect3DCreate9的关键代码如下:! i1 {: C8 t( M- q" }- I
pCdev=(void*)*(DWORD*)(*(DWORD*)m_pD3D+0x40);//获得IDirect3D9::CreateDevice的地址指针
) [4 v2 ^3 V8 w2 T, `2 K  H7 D8 O$ ^( g: D; Z
        DWORD oldpro=0;9 ]! b! N% S/ G  W
        memcpy(devcen5bytes,pCdev,5);//保存IDirect3D9::CreateDevice入口5个字节
% t  J9 ?3 M  D        VirtualProtect(pCdev,5,PAGE_EXECUTE_READWRITE,&oldpro);
! _" g# E! N. u  _; R        *(BYTE*)pCdev=0xe9;
, N) q9 G2 H: t8 q) A1 Q        *(DWORD*)((BYTE*)pCdev+1)=(DWORD)hookedCreateDevice-(DWORD)pCdev-5;
! Q$ b  O( U0 f% K1 L
% D* Q; Z- t/ D3 ~7 r+ P在hookedCreateDevice中,首先还原原来的CreateDevice函数入口的5个字节,然后调用原来的函数, IDirect3D9::CreateDevice的最后一个参数是一个二重指针,如果函数调用成功,这个二重指针所指向的指针就是我们所需要的设备对象指针,由此找到设备对象的虚函数表,然后确定IDirect3DDevice9::Present的内存地址,然后又可以改掉入口的5个字节为跳转指令. hookedCreateDevice的关键代码如下:
/ R% V8 h. I: {" Y/ n5 g, XpPre=(void*)*(DWORD*)(*(DWORD*)m_pDevice+0x44);//获得IDirect3DDevice9::Present的地址指针- l+ O# c1 r1 G- X
        memcpy(pren5bytes,pPre,5);//保存IDirect3DDevice9::Present入口的5个字节
! J+ H0 ~  y* w  I3 Y* J        DWORD oldpro=0;$ ^1 h- m( Z1 W# N% N0 i* i
        VirtualProtect(pPre,5,PAGE_EXECUTE_READWRITE,&oldpro);  c7 I4 K+ u' X* I' z! ^8 H
        *(BYTE*)pPre=0xe9;
: \* ?1 G8 p( h( [. X        *(DWORD*)((BYTE*)pPre+1)=(DWORD)hookedPresent-(DWORD)pPre-5;
2 a4 L) B& @) x, d! u2 q8 Y4 l# K+ o" y9 b
实际上这几个函数的hook都是同样的道理,现在,当程序运行到IDirect3DDevice9::Present后又会跳转到hookedPresent,而我们自己的绘制代码就是放在hookedPresent里面.在执行完自己的绘制代码后再调用原来的IDirect3DDevice9::Present.我的hookedPresent的关键代码如下:/ U7 ^6 [4 ]+ K  y2 M* u" {" S
char strdraw[]="The drawing in directx game\nAuthor:RunJin\nEmail:[email protected]";
' J( g$ }* T' s6 S' k% a$ z6 r            DrawMyText(pDxdevice,strdraw,sizeof strdraw-1);//绘制文本
5 o& i  d+ F/ V$ P% U$ u            //在这里写入您的其它绘图代码# n% P$ M; @6 l1 [; n) V

/ N5 ^+ Y0 o. V4 C% u+ P- C- N/ `7 h- k, x, t
再来看看其中的DrawMyText,这个函数是我的绘制文本的函数:
6 M  {# H" U& K9 F$ DBOOL _stdcall DrawMyText(LPDIRECT3DDEVICE9 pDxdevice,TCHAR* strText ,int nbuf)1 K3 C+ v& ^7 @9 h
{
, h: Y' x3 a* K" k; R
' S+ M) J6 ?8 _; c4 U8 ^% k    if(m_pD3D && pDxdevice){3 j" f3 R' G+ J0 P1 K& C7 n- V& c" v, m
9 e5 B' Y; C2 |# K
        RECT myrect;. G  @, ?9 F3 M/ _1 Q
        myrect.top=150;  //文本块的y坐标+ K+ r% \* S0 I) x, U" ?8 j
        myrect.left=0; //文本块的左坐标
8 d" x7 ^% ]0 y! Z        myrect.right=500+myrect.left;
$ E  I* N$ s' ]7 e' S! V. x. _7 t        myrect.bottom=100+myrect.top;( A2 c* D: g9 t  _) g; v+ s7 g6 [
        pDxdevice->BeginScene();//开始绘制
3 _( O8 s7 l3 P* j6 o
; J1 a7 r. m) e% W) Y) m. ^; F) @        D3DXFONT_DESCA lf;
7 T; u. l8 c) @8 I) ?$ D        ZeroMemory(&lf, sizeof(D3DXFONT_DESCA));
( n' j2 C5 ?* m1 e2 G. S, u; N2 j" V. T        lf.Height = 24; //字体高度$ c' T' T7 z: v( L7 ]( ]4 U
        lf.Width = 12; // 字体宽度
3 \3 Y; {5 o# B3 {4 d        lf.Weight = 100;
. E6 ?( T& X) s  M        lf.Italic = false;! N4 j, @5 W0 ]+ N& M* m$ A
        lf.CharSet = DEFAULT_CHARSET;
+ j+ L/ h) M1 M) k' y+ T  _- l        strcpy(lf.FaceName, "Times New Roman"); // 字型
( b8 b$ X" V- T& a8 l9 L        ID3DXFont* font=NULL;) s( R; j' o" o; i) k
        if(D3D_OK!=D3DXCreateFontIndirect(pDxdevice, &lf, &font)) //创建字体对象& ~) Y1 O  _7 N/ U3 Q4 B. a
            return false;
& A  y( F* P! c; C0 Y/ P2 Z( ?' R; a" R
        font->DrawText(
9 ?4 }! ^7 B& W/ c            NULL,
: E8 s, j1 F0 r9 e' @7 h; q            strText, // 要绘制的文本
2 S6 V4 H3 h2 U( ~            nbuf,
0 s- m; c, m' k, W. I% B; a            &myrect,
, X; b4 j: v2 R1 C6 }" f! O8 Z0 ?            DT_TOP | DT_LEFT, // 字符居左显示. r, b# `8 e/ ~
            D3DCOLOR_ARGB(255,255,255,0));
3 x, ~, {3 r& z. j7 C9 ^! i7 B; J6 D" Q8 e2 a4 y0 S
        pDxdevice->EndScene();//结束绘制0 y' k+ @$ m+ \& {: T2 ^
        font->Release();//释放对象8 K! D6 N, z$ P/ i2 B5 C/ p9 J
    }! J- f) V- }1 k$ X9 {3 `
    return true;' p) \  x, w( g) w
}" y; i- g) t. R5 z. ?7 @$ u

1 {) T3 h9 ^( H$ x; ~& J6 O4 E效果图:) q8 Y$ }# D! W* o( ^

* K' t  j) |% p8 B7 Q6 F1 @3 }
& _4 N0 R  V3 c4 u1 f4 R( e) a1 \0 G4 Z/ |# |/ x
  
6 |( ]! d! x8 L
; S1 D2 F! m8 h4 Z5 ^7 h: |
, |& |0 M2 q& m; [; V4 ]后记: 代码是以前写的,因此文章就按照着代码来讲.然而现在看来,把函数入口点的5个字节改成跳转指令这种hook方法并不是那么好,其实可以直接改掉虚函数表中的函数指针,这样更加的安全保险.7 R- M& z; J/ a7 x9 M' }8 ~

' @9 r& d4 N( s0 D* D2 g& l  H) O. V; |& G, B: T

本帖子中包含更多资源

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

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

使用道具 举报

沙发
发表于 2010-2-11 01:06 | 只看该作者
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx6 q" J7 U; {  e% @

* q* N9 t! ]' I0 E9 ]8 K+ r发一篇希望有帮助
回复 支持 反对

使用道具 举报

板凳
 楼主| 发表于 2010-2-11 07:51 | 只看该作者
引用第1楼byp100于2010-02-11 01:06发表的  :1 A2 D& w- B- g% G3 P
http://www.codeproject.com/KB/system/Hooking_DirectX_COM.aspx3 t5 G' n. \% y7 }4 c0 i

7 }- r# f! a$ e* p) `. ]7 |发一篇希望有帮助

4 A! B) A& @+ x& w  m收到,多谢了,这篇文章我也早就找到过。& y! d/ e$ q& {" Q3 Y
目前就是要研究如何把汉化和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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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