冒险解谜游戏中文网 ChinaAVG

标题: GDI32.DLL的代理DLL(solidji 请进) [打印本页]

作者: shane007    时间: 2010-4-9 20:42
标题: GDI32.DLL的代理DLL(solidji 请进)
solidji
7 R$ w# Y# |  [8 m9 U; a, G' _" f- k7 h- A1 B% M1 r
 你好,先给你安排一个小任务,这个任务对你来说应该很简单。
. y* [: p1 l$ K6 ?* D/ [: i http://aluigi.altervista.org/mytoolz/dllproxyskel.zip
4 p2 d: M7 L2 }" M" g: l
* T. a  l. |+ \9 I 上面是老外开发的一个制作代理DLL的工具,他的网站上面也有例子。# t/ q+ N7 k  m5 M9 R- V
 但是比较复杂,我暂时没有时间仔细研究。
3 R5 |# W& X# v& C  \ 请你用上面的工具作一个GDI32.DLL的代理DLL,HOOK其中的1个函数即可,- p, o. w+ l  g. B3 y
 比如Exttextout,也就是说想让你做个最简单的例子。以备扩充修改。/ B0 p* y( y2 `" t9 {1 `, [
    请发布代码。
作者: solidji    时间: 2010-4-10 20:41
标题: dllproxyskel.c
显示AlterVista# H% L( ^2 Y# c: |5 ^: ]
打不开页面,我搜索看看( j0 P# P- m) B: o. ^7 |$ x
-------
( S1 d  M, [" V哦有了dllproxyskel.c,就两个文件,代码很少
作者: solidji    时间: 2010-4-11 00:55
标题: dllproxyskel
dllproxyskel使用起来比较简单,dllproxyskel自动从你输入的原始DLL中提取所有导出函数符号
& [1 ]. E0 k' \  o4 Q2 i2 _* [然后按一定的格式生成.c文件,自动将所有的dll函数信息记录进.def, 做好替换 函数在.c,
9 S2 q* D) P$ i2 H通过在.c文件中#ifdef DLL_PATH 来寻找原始DLL路径(默认为\\system32),原始DLL里的函数调用是原函数名前面加个下划线_
! r1 u9 d2 L6 N- m5 v1 K' b$ R比如Exttextout,在.c里做完自己的事后可以调用 _Exttextout 来完全其原本的工作% r; X- e2 w+ @/ F# E" H: `
+ O2 m% n* b7 R4 i6 {
命令行输入
- l( L6 U) `7 p( Mdllproxyskel.exe <input.dll>' n0 F' E0 p# w
- open file D:\\项目\\dllproxyskel\\input.dll
( e' P4 I' J% B9 f$ L% R [attach]15892[/attach] & [5 i0 ]0 W. p' P

; O+ K9 [  X( a, M# ^------------------------------------------------------------------' Z. N0 o- E( |
我们需要额外添加的代码! Q+ q/ X5 n0 ^* a: U4 s
#define _WINGDI_    //这个值从wingdi.h里获取,仅仅在代理系统DLL的时候需要
/ x9 M. @& \. X& ^1 j//定义了两种声明代理函数的宏,CALL_FUNCTION与CALL_FUNCTION2: g! _/ n/ B- S/ ^9 I
//这里我采用第二种,将返回值与函数名与参数列表一起作为宏内容,下面第一个参数BOOL 是ExtTextOutA的返回值* }0 x+ O9 _; f& X
CALL_FUNCTION2(BOOL, ExtTextOutA,
/ d: I! p0 q9 C* a              HDC hdc,9 ?# ~9 U5 ^. p, n% i
              INT         x,9 X& U! F4 z4 c6 Q/ Y; S. b
              INT         y,: g/ X. G2 a( h3 h# P! {: O& L; c
              UINT        flags,
4 M5 V. z/ U: `- ?              const RECT* lprect,
4 k9 H1 S( q7 F$ m0 h- |; {              LPCSTR      str,& j& _/ p! l9 C" l  C. _2 O6 Q. j
              UINT        count,* U8 E: b8 z. p& I% T2 [
              const INT*  lpDx$ P; D) Q! o" {/ V! ^( e
) {
( e1 u; H6 ?2 L0 r4 _    //这里可以做任何你想做的事了,HOOK成功- x/ i+ K2 v9 G; {' A# l3 s
    outputdebugstr("HOOK ExtTextOutA suscess!");
8 ?5 s8 l2 R) P0 @2 v; i       BOOL result = _ExtTextOutA(x, y, flags, lprect, str,count,lpDx);//调用原始函数  _0 v( |* y  {6 a+ f
       return(result);- [7 i$ @  J% c7 H% W' z1 s
}
2 ^( ]2 D; O( u% O4 Y8 ^
6 f! r  H& R1 {5 a; x+ g注意,生成的代码需要用gcc/mingw来编译,
. }/ }- S" }6 L) h# i6 t2 s$ {7 }主要是因为其中使用了gcc宏扩展
0 h1 k* x8 l% P/ Y+ K#define CALLING_CONVENTION WINAPI       // default for Windows DLLs
! z8 n% Q0 Q) Q) S9 Q#define PROXY_FUNCTION(FUNCTION_NAME)   /* for the proxified functions not modified */ \\0 ?' L0 w+ y2 g, [2 x5 a
        void CALLING_CONVENTION  FUNCTION_NAME(void)
# o/ d* e8 m9 \# C* T; I#define PROXY_FUNCTIONX(FUNCTION_NAME) \\! D0 g+ Y" B# s0 L' R+ T
        static PROXY_FUNCTION(*_##FUNCTION_NAME) = NULL; \\
; D5 S1 a: r0 V7 e0 g$ x        PROXY_FUNCTION(FUNCTION_NAME) { \\
# T+ F; p4 P# t# Y, f7 A            POP_EBP __asm__("jmp *__"#FUNCTION_NAME); \\4 X6 N/ `5 p5 F
        }
( _9 D$ I0 s. a+ n% `7 M#define CALL_FUNCTION(FUNCTION_NAME) \\2 d: s0 O4 Q4 t
        static CALLING_CONVENTION FUNCTION_NAME##_(*_##FUNCTION_NAME) = NULL; \\
' j3 X4 U2 S3 o4 [! w        CALLING_CONVENTION FUNCTION_NAME##_(FUNCTION_NAME)  c! C/ F; Q% o# i- @8 W
#define CALL_FUNCTION2(FUNCTION_RET, FUNCTION_NAME, FUNCTION_ARGS ...) \\
, a( \( s$ J6 j9 F        static CALLING_CONVENTION FUNCTION_RET (*_##FUNCTION_NAME)(FUNCTION_ARGS) = NULL; \\
/ c' j- |+ [% Y2 K        CALLING_CONVENTION FUNCTION_RET FUNCTION_NAME(FUNCTION_ARGS)4 b' X0 [. H/ y) [7 [
& Q4 [& R. [6 ^8 L7 k% N* B8 |
4 B% Q: g/ g9 P- N& R
等我回头翻译到VC里
! j9 n3 E+ ^  d  m! n, v1 F待续
作者: shane007    时间: 2010-4-11 06:38
收到。等待你的vc版代码。
作者: scgame    时间: 2010-4-12 09:02
哦...那看来在不知道函数拿几个arguments的话是不能替换的吧7 A; x) m% z# o4 F8 V; B" F1 }
那除非用的是GDI的createText画字的游戏,别的似乎还不能用hook解决啊
作者: shane007    时间: 2010-4-12 11:16
引用第4楼scgame于2010-04-12 09:02发表的 : & o  M7 p; A  f
哦...那看来在不知道函数拿几个arguments的话是不能替换的吧
; u$ Q" G  Q/ Y' P那除非用的是GDI的createText画字的游戏,别的似乎还不能用hook解决啊
, N8 e1 c3 ^$ ]6 ]2 Z* K" E* o
2 _0 o" l+ J+ h$ z1 l+ N
windows GDI 的API查查msdn就知道参数了,看vs里的头文件也能知道啊。3 }3 G& X1 [7 ^  |
这个工具对directx 的com 接口的hook还是不行的,需要用别的办法。
/ z  ?! B' L: i
/ r. O3 |0 _. \. u对了,想等vc版的代码出来以后,我想安排你做exttextout的文本替换部分,行吗?
* }) `4 v$ u: Z# G5 q( T+ M! c" ^* x我会给你写个简单的设计书,你照着做即可。请先找一下关于hash的代码。
作者: scgame    时间: 2010-4-12 11:59
哦,solidji的不可以直接用吗?我是用CodeBlocks+MingW的,不用写成VC的我也可以( C. x" d+ F& h7 r. h
- p9 [3 g6 p. ^8 o
这个我可以试试看,蛮有趣的
5 M+ V8 R' K; p6 k$ O是用hash链表把中文字"归类"吗?
作者: solidji    时间: 2010-4-12 15:24
directx 的com 接口的hook,4 l, f6 M8 k5 g; {- A: B% l2 u
因为不是直接导出函数的DLL, 有很多接口是通过对象的方法来调用,
6 }5 e1 Z  R* x. K- `- p7 Q无法这样通过枚举PE文件头里的导出模块名来取出某个"对象方法"
, p0 P# ^" S- b4 D- o# N3 ~  }) B
6 c8 i9 |4 l( ?4 Q007之前有篇贴子的办法才行,就是在创建对象的时候COM对象整个替换掉
作者: shane007    时间: 2010-4-12 17:07
引用第6楼scgame于2010-04-12 11:59发表的 : & Q+ ~7 q! G; y8 S5 r
哦,solidji的不可以直接用吗?我是用CodeBlocks+MingW的,不用写成VC的我也可以 0 ]) Z  D- O7 Z) p; w2 d& M

0 o! _2 k- Y- e: K这个我可以试试看,蛮有趣的 , |8 z  }! ^0 {9 q/ o
是用hash链表把中文字"归类"吗? 5 }" U1 g: R1 S7 ^7 q/ z  p+ G

9 J& p5 k# f) Q+ n: {1 f* e# h.......
# |: f7 U- a6 L- N" G/ x! D
' Y8 z' Q  ~  Y1 ]. C# D' P' t9 X
最近几天我把设计书写好,你按要求编就行了,请关注。
作者: solidji    时间: 2010-4-13 20:15
非常遗憾的说,鉴于VC严格的格式检查,命名规则等原因。。。这份自动生成gcc的C代码很难改成通过VC编译的了2 F4 H! T% k1 t" e1 N, n5 f! u
另外由于gdi32.dll是一个比较特殊的系统DLL,<windows.h>用到了大量由<wingdi.h>定义的的结构如LPDEVMODEA  f& H" |9 x$ M
所以无法通过 #define _WINGDI_ 来取消重复定义的问题
& {& z  Y5 G# R说白了就是你自己想生成一个gdi32.dll,这个DLL里的导出函数与原来的DLL一样,都有exttextout
/ o4 q0 C9 e7 `# d& f  I0 G可是你自己定义导出函数exttextout的话,系统会提示你exttextout已经在wingdi.h里定义过了
8 s* o# P: z8 B如果是一般的DLL,直接不让wingdi.h载入就是了,可是windows.h又必须载入wingdi.h,这样就绕不开这个重定义的麻烦
# G# O) ]- G' D! z6 u- R! X+ p' x. J/ E
我想的解决方法:1 ?# R# ^' ~9 |8 I7 C, p6 Q3 `8 X
1,定义自己的名字空间namespace,将exttextout这些包含进去,或者/FORCE 这类强制链接命令强制跳过检查通过链接8 z4 B) F) }3 Z  z  Q& R
2,去掉#include <windows.h>这一句,而自己用到的全部自己定义,(在很大量的情况下就比较麻烦)% ?1 O9 @0 N/ y. e/ b
    #define DECLARE_HANDLE(n)   typedef struct n##__{int i;}*n
$ u( n( P9 P" H- @) t         DECLARE_HANDLE(HINSTANCE);
4 v' ]; @' u( X# h2 C  N        typedef HINSTANCE HMODULE;$ [- y0 G: ~- @, ^- d' _/ Z
        DECLARE_HANDLE(HWND);
8 M  z. I8 ~7 T" }' T* S7 g        #define LPVOID              void *
; p+ B2 S# H& G3 Z        #define DWORD               unsigned int4 X6 r/ H. Q; q# H, Z# F4 [) c2 g
        #define UINT                unsigned int; B) j! a: F% P6 L. w& v3 b5 a6 h
        #define LPCSTR              char$ u( j1 B8 n) H' ~# c& F
       #define LPCTSTR             char 9 @, l) T5 e& q& f
       .............像这样用到多少自己定义多少( ^3 S, i# z# F" Q; O* O, R

- W, }0 \5 \, n3.改造def,使用函数转发器
" W; k( U9 m! c. Y/ `2 n5 z$ ~在.def  文件里转发,
, Y; g$ `* E6 O3 HEXPORTS. v# C8 e2 [0 w/ t* U1 o/ Q
  AbortDoc=myAbortDoc @16 }0 d3 {* i5 {/ v# _+ M$ E
  AbortPath=myAbortPath  @20 \! M: K5 j% ?! C: ]
  ExtTextOutA=myExtTextOutA @222
* z4 l  S- z3 [; O, x% H4 s然后.c里声明myExtTextOutA 来实现函数部分,这样导出函数就还是ExtTextOutA,但是转发到了myExtTextOutA
/ i1 \/ w0 s; g3 @" E& d你实现myExtTextOutA 自然不会和wingdi.h出现重复定义的冲突了  X: x5 Y0 H2 z( q/ a9 O* m6 m9 ^

- Z% ~5 c" W7 R( q算了,等我用函数转发器的办法另外实现一个吧,dllproxyskel完全拿他当个PE文件“导出函数”模块名导出器使用
作者: shane007    时间: 2010-4-13 20:39
收到,那我等你实现的版本。
作者: scgame    时间: 2010-4-14 07:56
我也碰到这个问题了,MingW的编译不了 [s:102]
作者: scgame    时间: 2010-4-14 12:39
发现有个叫APIHijack的库很受人推崇,终于把代码问题解决了,没有前面所说的问题,不过再编译他的cpp里的汇编出问题了...我觉得可能是我用code::blocks+mingW的关系,他给的例子我都编译不了 [s:102]
) s2 Q4 g" {( V( O' u/ C/ a
/ V2 W& n! N4 Y先下个VC++试试看吧
作者: solidji    时间: 2010-4-14 15:34
标题: gdi32  code
改好了,用第一种方式实现的.
$ x/ T! b3 m* I8 t; P3 D: D如果需要用到的系统头文件定义变量过多的话,可能不太适合,看你自己主要想实现什么功能吧
1 \# N4 r+ G! A# S, \
# ?* ~8 _' ^/ R2 q2 K  l, z  _1 v代码先贴出来,gdi32.h里的东西是我从生成的gdi32.c里拷贝 分离出来的,原本是想改进一下,
3 t3 h' Z: B2 q2 v7 e让gdi32.c里#include <windows.h>正常使用,gdi32.h里放重复定义的导出函数
" d3 f+ Q6 J2 T% ~* }% x. v这样尽量减少自己需要自定义的结构. 这一步还没分离完成,不过仅仅是想HOOK ExtTextOutA的话已经够用了 % @  A' G8 E# G- G3 r; n; J
[attach]15911[/attach]
, x1 ^* l" U2 M; x2 c# Y! \  n
  G- F- J. C* ?8 E- `相对原始生成.c文件,修改的部分有
; W' Y- V. f" k" s1,    //_ExtTextOutA = (void *)GetProcAddress(hm, "ExtTextOutA"); 9 r" `, k4 E9 D/ U
    _ExtTextOutA = (ExtTextOutA_)GetProcAddress(hm, "ExtTextOutA");
' \+ x2 q% [: [/ J2 U  H$ ~2,//PROXY_FUNCTION(ExtTextOutA) 0 I- T$ g' S, c1 I8 F
    由自己定义的钩子函数ExtTextOutA取代 : w: {) X( e* t" |! W* l
3,gcc宏移值
* z) {# O, c, C, x* i. I#define POP_EBP     __asm{pop ebp}
/ Z; K/ Z% `6 [8 {' t#define PROXY_FUNCTION(FUNCTION_NAME) \\ ' v$ g: }3 e) r. Q5 }- U
        PROXY_PROTOTYPE(*_##FUNCTION_NAME) = 0; \\
9 X. C8 I& N/ t7 t7 g        PROXY_PROTOTYPE(FUNCTION_NAME) { \\
% d$ V9 D5 ?4 x3 b9 e9 \" e9 l# \        POP_EBP __asm {jmp _##FUNCTION_NAME} \\
/ L2 z+ m# H3 @* l4 A5 T& O        }
" r8 n. Z5 h) A6 b! _6 C+ L. j9 x5 T& U" i& o' p, B
记得为VC链接命令行添加 /DEF:"gdi32.def" 1 K* }- D1 p, ]: _' N) v) u
PS:APIhijack好像只是打钩子,而不是伪造DLL
作者: shane007    时间: 2010-4-14 17:14
收到,多谢了。
' V- V% t( a( [/ E0 s4 V对了,是否能加上一个vc的工程文件?- H  q! ^9 I4 O. d2 m7 A' R- w
还有,_ExtTextOutA 建议改名为real_ExtTextOutA,更容易明白。/ q8 ?9 d9 N! Q2 I1 a3 B
我们修改过的ExtTextOutA等函数能否独立出来放在一个文件里,这样结构更清晰。
作者: solidji    时间: 2010-4-14 17:53
这样命名是根据原作者的风格,我整理下在改吧,
( j9 J* Y% I$ X- l; h看能不能把重定义的部分分离得更彻底一些
作者: scgame    时间: 2010-4-14 20:39
我不明白ExtTextOutA_是哪来的 [s:105]3 n. W) a/ u. ^
p.s 原来那个叫钩子.我还是第一次接触这个概念,嘿嘿
作者: scgame    时间: 2010-4-14 21:56
VC 和VC++有区别吗
- n) j4 _* B8 ^" n9 J! ^& h我下了个VC++ 2008的,编译不了啊' Q9 \; E- M* n
    _CreateFontIndirectA = (void *)GetProcAddress(hm, "CreateFontIndirectA");9 A9 M  V5 |+ R8 s5 W, V% g
等等都有这么个错  y! ?; o9 T1 r( q/ O+ w
Conversion from 'void*' to pointer to non-'void' requires an explicit cast
1 I, W9 n6 j; R8 m
# H2 ?4 X* w; W% N$ \我先用钩子试试看看能不能编译
作者: shane007    时间: 2010-4-14 22:49
试试看http://sourceforge.net/projects/dev-cpp/8 e' w0 ~9 z' b4 g( h& B8 V2 C% L
这个呢?是gcc的。
作者: scgame    时间: 2010-4-14 23:52
原来是VC++是cpp不是c的原因  [s:116]
作者: scgame    时间: 2010-4-19 05:46
我再来求救一下,编译好的gd32.dll好像没起作用嘛,我加了个while(1);( y$ V% Y) Q, V+ b
运行了个测试程序还是没成功啊$ G: S  K% ~& [& g
8 B/ ?! A. J, d+ m6 A
我还是看得不是很懂,比如说
! |) f4 I/ p3 t/ G2 J# ?这个BOOL,有一个#define,还有一个typedef
6 U' D" u8 b. V那在我们改的函数那里就是% ~" @+ y1 q% J) @  v
BOOL ExtTextOutA(blah blah)" T) i7 y' j' {& M3 g
那是不是说我们的定义就是
  1. (WINAPI *ExtTextOutA_)(
  2.                 HDC         hdc,
  3.                 int         x,
  4.                 int         y,
  5.                 unsigned int         flags,
  6.                 const RECT* lprect,
  7.                 LPCSTR      str,
  8.                 unsigned int        count,
  9.                 const int*  lpDx
  10. );
复制代码
还有就是不明白
3 D* P9 s1 C* B8 GExtTextOutA_ _ExtTextOutA = 0;0 f9 H' {& B# F5 p
这个ExtTextOutA_和_ExtTexOutA又是怎么定义的
作者: solidji    时间: 2010-4-20 11:34
typedef BOOL (WINAPI *ExtTextOutA_)) q% t0 Z6 L1 L# G5 E$ ^
就是定义了一个函数类型,我们故意把他定义成和原始的API ExtTextOutA一样
, a* N4 ~( M* w, H就是为了ExtTextOutA_ _ExtTextOutA 声明一个与原始API ExtTextOutA一样一样的函数指针- g  j: F$ K" ~  X6 R3 m
然后_ExtTextOutA = (ExtTextOutA_)GetProcAddress(hm, "ExtTextOutA"); 为这个函数指针赋值为原始API的函数地址$ N# k: a6 ^0 O0 B7 i, M& _% \
这样_ExtTextOutA  就是real_ExtTextOutA的意思,完全把他当原始API ExtTextOutA 来使用就是了; S2 v/ h; k0 y" j. z- W- Q

, ?, g3 B4 d0 {1 [你编译的DLL有点问题,我打开PE文件找到  ExtTextOutA  部分,发现虽然你导出了ExtTextOutA ,但却不是你实现的那个9 g4 i- Q0 J1 M5 o

1 q3 F  y/ E6 ~$ p' t4 e- V3 H+ _1 C( y5 p7 d7 G+ |+ [- o5 m
[attach]15939[/attach]
' O/ m8 }4 E% P$ O
! I; q! K2 |# p! O
  1. //6A80偏移处你 实际上的函数体代码,可以看到只是个简单的代理,明显不是你自己实现的那个
  2. 10006A80 >  8B4424 20           mov eax,dword ptr ss:[esp+20]
  3. 10006A84    8B4C24 1C           mov ecx,dword ptr ss:[esp+1C]
  4. 10006A88    8B5424 18           mov edx,dword ptr ss:[esp+18]
  5. 10006A8C    50                  push eax
  6. 10006A8D    8B4424 18           mov eax,dword ptr ss:[esp+18]
  7. 10006A91    51                  push ecx
  8. 10006A92    8B4C24 18           mov ecx,dword ptr ss:[esp+18]
  9. 10006A96    52                  push edx
  10. 10006A97    8B5424 18           mov edx,dword ptr ss:[esp+18]
  11. 10006A9B    50                  push eax
  12. 10006A9C    8B4424 18           mov eax,dword ptr ss:[esp+18]
  13. 10006AA0    51                  push ecx
  14. 10006AA1    8B4C24 18           mov ecx,dword ptr ss:[esp+18]
  15. 10006AA5    52                  push edx
  16. 10006AA6    50                  push eax
  17. 10006AA7    51                  push ecx
  18. 10006AA8    FF15 80520110       call dword ptr ds:[10015280]                            ; GDI32.ExtTextOutA
  19. 10006AAE    A3 24570110         mov dword ptr ds:[10015724],eax
  20. 10006AB3    C3                  retn
复制代码

( N, W1 P% E% v& D& }2 P2 L: X+ o2 ^! y* ?. R9 q0 B3 ?
我想主要是你定义ExtTextOutA 的时候漏了个int, VC认为这是你另外一个内部函数,而导出的是另外一个
  1. int ExtTextOutA(
  2. HDC         hdc,
  3. int         x,
  4. int         y,
  5. unsigned int         flags,
  6. const RECT* lprect,
  7. LPCSTR      str,
  8. unsigned int        count,
  9. const int*  lpDx)
  10. {
  11.   
  12. // MessageBox(0, "i'm in ExtTextOutA now!", 0, 0);//做你想做的事情
复制代码
) R. m. }& y* g* k: u3 Y# @
另外附上我重新帮你编译过的DEBUG版DLL
4 A! R& y. y9 L  w, p# l# I9 |
) @9 U- n5 Y3 x3 S) j' t% ~$ L4 {  e[attach]15940[/attach]
作者: shane007    时间: 2010-4-20 11:53
solidji,请放代码,把scgame错误的地方注释说明一下,便于大家学习。
作者: solidji    时间: 2010-4-20 12:19
他的代码就漏了个函数返回类型BOOL或int,
. i) N- `1 V: i" L" Z' w- G( N
int
ExtTextOutA(; I# r" b6 ?1 V
导致了导出函数链接没对
# l" A5 u! e  E0 l3 B4 D直接看他的代码就行了
作者: scgame    时间: 2010-4-20 21:31
啊,原来是这样,
+ U, J4 X) j$ M! ]$ S谢谢,solidji9 t2 f" {4 T8 y
solidji能不能再推荐些教程
" c6 |* N' L" [# Q% w+ L我对这方面(导出,API)之类的不太了解




欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/) Powered by Discuz! X3.2