下沙论坛

 找回密码
 注册论坛(EC通行证)

QQ登录

QQ登录

下沙大学生网QQ群8(千人群)
群号:6490324 ,验证:下沙大学生网。
用手机发布本地信息严禁群发,各种宣传贴请发表在下沙信息版块有问必答,欢迎提问 提升会员等级,助你宣传
新会员必读 大学生的论坛下沙新生必读下沙币获得方法及使用
查看: 4112|回复: 2
打印 上一主题 下一主题

[资料库]Win2K下的Api函数的拦截

[复制链接]

该用户从未签到

跳转到指定楼层
1
发表于 2004-11-5 18:09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
9 t0 [  A* y; }$ Y8 E
发表日期:2003-10-30作者:tomh[] 出处: & x+ D0 [. ~) ?' Y, ]) S
Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 % e  _% l$ d2 i; e3 M
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现,
$ M5 g5 D/ i6 j6 s. Y9 @1 s其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
  J" `/ s; q  _; p8 ~     BOOL VirtualProtectEx(
/ K4 n! @) s) U' _4 Z  W                HANDLE hProcess,   // 要修改内存的进程句柄
" @4 ^( o/ @' [; G                LPVOID lpAddress,  // 要修改内存的起始地址
9 t) M' P' t& U, A9 Y/ s- l                DWORD dwSize,    // 修改内存的字节 4 l9 D/ ]. T2 {, A( z
                DWORD flNewProtect, // 修改后的内存属性
, v1 F' e6 s% F- {5 f  j                PDWORD lpflOldProtect // 修改前的内存属性的地址
: V- ~. R- w. C3 L$ L* U1 b: N                );
3 h+ w* m& i. V" O" J0 c    BOOL WriteProcessMemory( ; z' N* J! I( T" `8 Y# m& O
                HANDLE hProcess, // 要写进程的句柄 * _6 s4 w: c! N: b5 a
                LPVOID lpBaseAddress, // 写内存的起始地址
2 j4 f+ B. g$ d( Q  C( w7 Z                LPVOID lpBuffer, // 写入数据的地址 : O  A6 j' Z0 M! B
                DWORD nSize,   // 要写的字节数 2 }  ?6 \2 \$ a1 x6 C6 q
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 8 G$ [  p+ t5 k
                );
) J- b; l+ Y! g; s1 K8 h    BOOL ReadProcessMemory( ; r$ M' U; S/ _) V) A- ~0 v
                HANDLE hProcess, // 要读进程的句柄
9 P/ j  D  c) P; H1 a                LPCVOID lpBaseAddress,  // 读内存的起始地址
8 o+ f% o2 ]# J; ]7 y2 f  I" c                LPVOID lpBuffer, // 读入数据的地址
! ^$ K9 G) p' P3 t- c7 \$ g                DWORD nSize,   // 要读入的字节数 4 o. Y# ^" p  O/ z  B2 i+ f
                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数   c0 R# ^3 o6 ~
                ); , b) b' L) }4 E! R' Y- ?8 @
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同,
$ T% ?  k$ R) t% T9 U( G2 v$ Q因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: * i+ ^$ q$ K* D% X" w  C
其中Dll文件为:
: \6 [4 F" J! ?( n$ O     HHOOK g_hHook; 0 F0 `  [9 g; v* b5 y. s
     HINSTANCE g_hinstDll;
, d: f+ z- M2 J$ G     FARPROC pfMessageBoxA; 5 O& f0 k) @8 S5 C; X+ f: t
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
6 V3 ?7 I$ g( q- y& l; c/ Q     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
7 b$ ]0 W1 |" G# v+ U. N% g2 M     HMODULE hModule ;
  l# R! S6 C' o' h1 r5 Y     DWORD dwIdOld,dwIdNew;
$ z( A" W+ ]0 N7 p, |     BOOL bHook=false;
/ v* w/ X: o' J- s5 v7 R$ ?4 @     void HookOn();
5 h  j* J: J0 x7 d2 J. O" @     void HookOff();
5 D' n7 O- M6 [9 S     BOOL init();
2 |. O  b6 J# C* aLRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
/ Y; [, d# S0 f. m1 x7 R* XBOOL APIENTRY DllMain( HANDLE hModule,
+ \  d& ^1 o  M" V! M5 _/ w            DWORD ul_reason_for_call,
& z- z/ ^2 }' J* n! }            LPVOID lpReserved
* r% a8 \9 C2 s! @' p" {) s% P           ) 0 [0 g5 q( Q0 \9 Z
{
+ k, z$ G$ v& k6 R" _, b  switch (ul_reason_for_call)
+ q  }6 E- f5 M) T; ]( V  {
3 N- s! H( S3 D    case DLL_PROCESS_ATTACH: - H4 g$ d) d6 c" h: V6 |
      if(!init()) - I9 t; |, P; P- K
      { ( W6 ~" Y& @7 I; i. \
             MessageBoxA(NULL,"Init","ERROR",MB_OK);
4 v. [; A0 _8 [! ]# n3 y1 V% h             return(false);
. e! O* R* y2 e2 b  R3 P      }
; b  B% ?- F' w: o    case DLL_THREAD_ATTACH:
& V* P8 F3 u* L* F" t- S0 t    case DLL_THREAD_DETACH: 5 X+ l; D, T+ N0 L2 o( l
    case DLL_PROCESS_DETACH:
& [( w0 H# l+ @           if(bHook) UnintallHook();  7 d' e2 K$ T2 P' a; F- M. m
          break;
4 A% v* n2 x0 H; ?. J  } 4 l' U5 t) u, B  F3 {- c
  return TRUE;
8 O$ Q5 j% X3 n- H}
: g% j! q  y' w/ qLRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
& y4 P- v( X' d$ `$ r: n: g{ 4 D6 U# r/ N+ W6 H; _. ~% ?
   % `, K6 e5 M5 v, F; T  P6 ?% R
  return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
& t6 i5 z3 k% G: ?} 5 Z- G0 x. e: G! j8 X' W
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数 9 w( m2 _7 E8 g% g8 ~2 ?; H
{  2 w, \$ k& M" H# [$ X
  g_hinstDll=LoadLibrary("HookApi2.dll");
# ?- W  D. [0 ]) V  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
* h: C' F; K( b/ Y7 V. u- Xif (!g_hHook)
7 }' u4 V' Q( t{
, i% h2 |9 P& f; O: H7 @    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
* g: W" C* k( Q' X7 I. h    return(false); ( A+ \& K: x5 C
  } ' X: h7 _" ]+ r% I; o; r) a* B# m2 F
  % V5 |; o+ t- |, M& V& m' a
      . B: q) E. i% E/ W8 e
  return(true); $ l: D$ ~1 R0 Q$ L+ Y$ ^5 e0 C
}
. t8 ~4 W1 j2 ZHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数 1 p3 v5 P; A) W+ [- p: [; b
{
2 }& G9 U0 z, o) |; x  
4 w$ d  t( O1 A8 {2 `. X/ ^  return(UnhookWindowsHookEx(g_hHook)); : x' h& }7 k$ X' ]8 _
}
$ V3 V" N0 p. r5 _# C6 MBOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
- h9 b/ @) q" F8 I! h6 D8 S7 d{
2 H7 i* Z0 Z# g% \% O, i; d) |  hModule=LoadLibrary("user32.dll"); 7 q: \; @& i- ^% E# |- d2 l
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); 6 G0 p& H1 p$ r% p
  if(pfMessageBoxA==NULL) ) \, f& w0 i9 t
   return false;
" j8 p0 {2 Q/ d- F  _asm
/ D5 ]1 e0 x- G! J  { / i+ U0 B) |1 p8 c% K: K1 `3 H. g
    lea edi,OldMessageBoxACode # u) `( X! b% r( P
    mov esi,pfMessageBoxA " J; B# n9 i- [' m
    cld
9 G: x; r, N* Z    movsd
/ O0 l  @! ~- V% C9 b1 D# [    movsb 5 y, y( M$ L$ M0 M$ f; ]% j; H
  }
1 f0 n1 n0 N, l+ M' y  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 ! Z1 D0 {8 O; D
  _asm 7 z( u& l- e. x: ~% I/ H6 o
  {
) \7 G/ B. O1 w! Q3 M  ^: C, S9 m    lea eax,MyMessageBoxA
$ h) u( A# x0 b5 ~5 K    mov ebx,pfMessageBoxA
5 J+ ?" l+ h+ t; o7 B; U    sub eax,ebx 7 H/ ^9 u. R/ I' B# t4 W
    sub eax,5 6 C4 d% H  p; s, r+ a( z
    mov dword ptr [NewMessageBoxACode+1],eax
* c% \) u& `# o* M9 W, C  }
4 h7 p3 l; x* A1 w& t  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID ; m( O0 o3 H4 ?  s3 L: S
  dwIdOld=dwIdNew;
; p5 j0 e" q2 g% |7 X4 d3 C  HookOn();//开始拦截
% U6 I! A8 v( e' e/ T  return(true);
% u$ Q$ d9 @) s* g2 C}
" u& Q& |7 r* p6 h; Hint WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数   U: T" P5 e2 q$ N8 Q5 ]
{  
( R9 }1 O' y9 U5 D4 ~2 k- v/ B  int nReturn=0;
: z8 k# ^2 ?( N6 ]; H  T  HookOff(); $ y- E7 Z/ x1 \/ P0 i
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); : A% I5 L5 o. {# J/ b
  HookOn();
- m+ ], {/ Y7 x$ ?' @% y6 _  return(nReturn); 7 j1 ?8 e# H: H) f' t7 i9 B
}
$ h" `+ b: G7 q( A6 n& }void HookOn()
$ H' R" q  Y! V/ W' T; b7 Z1 }{
; |1 Z3 r& D6 Y% E, F  HANDLE hProc;
# u# J0 C- i8 L  dwIdOld=dwIdNew;
9 p" l3 k" ~9 V4 ?$ [- F- {  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
0 A2 k" H* }2 ~# u  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 + N! T5 h* [3 p. \
  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA % k9 H0 w5 j3 i# _  e' N( q6 s: r
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 0 n5 ~1 ]/ `6 `$ Z& x
  bHook=true; * M+ X) R0 W2 A, `* v, ^, w3 w
}
3 Q  ?. i4 M) C: O" Svoid HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
6 L4 V" j# ]1 b& H6 t. f{ 5 F' N, p' a8 D
  HANDLE hProc; 8 K) I! }! L4 R  n
  dwIdOld=dwIdNew; $ z: [5 a7 |* I6 L1 C: S  O
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
: L; w9 B- i- V8 ]  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld); ) y! `0 ]- `5 Z
  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
" i5 L5 H4 K! Y" L+ k5 _' u  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); % a0 I* M+ [# R0 p
  bHook=false;
% }/ w" \# x* b: X7 S}
7 U7 \# @/ ~4 z* x2 N) g- H) Y//测试文件: # m! C! Q, Q+ I1 T* w! q& n  @
int APIENTRY WinMain(HINSTANCE hInstance,
$ ]' [" _6 ^, t% D0 F- @           HINSTANCE hPrevInstance, ! ^% E" ]# ?8 J0 _, d
           LPSTR   lpCmdLine,
( k9 F, a$ {2 L6 k+ N; @           int    nCmdShow)
+ j& w. B' ]5 t; |/ A) ~5 B{ 8 k# p8 w% h- F- o& V1 |  w
   . u* ?: I) Y0 k* u4 @6 m
  if(!InstallHook())
* r0 i& E5 j& W; M  { * C6 o+ g2 [: ]
    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); & k" u; K5 O/ L. W% X" x4 z2 e% r8 R' o
    return 1; 8 J- e  N" {7 u* m  ?# d+ d9 \- z
  }
+ F& {& W9 L& a   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 9 U/ W1 p6 q; y1 H$ j: i
  if(!UninstallHook()) 4 {: D! g* h4 v! }1 M+ p
  { 6 v, m% @& K! ~
    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK);
3 U) ~9 p& E! e# y1 h& W- n    return 1;
  w" Z7 H. M/ _$ |8 c2 P- H  } + W1 E9 t3 m& [- y7 h8 ]0 O' A7 K
  return 0;
2 X9 X* p" f2 ^} 2 l( v: V8 N5 t( Z3 A8 H7 F
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

; q7 k4 w1 B6 |+ V
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

2
发表于 2004-11-19 00:12:00 | 只看该作者

好眼熟……

该用户从未签到

3
 楼主| 发表于 2004-11-19 00:36:00 | 只看该作者
大家转来转去就这么一片。大概……

本版积分规则

关闭

下沙大学生网推荐上一条 /1 下一条

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