下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

跳转到指定楼层
1
发表于 2004-11-5 18:09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

  l1 m) f2 i2 J4 x" X+ }发表日期:2003-10-30作者:tomh[] 出处:
7 C+ F2 r9 d; q2 GApi拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。
/ P# C4 d8 h2 f  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现,
2 M  z/ }) N% j5 p0 J其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
: G% Q7 k- Z$ e! K' N     BOOL VirtualProtectEx( ; K. @& ~& O2 ^
                HANDLE hProcess,   // 要修改内存的进程句柄
7 g8 J1 m3 M6 k7 O# `/ E+ Y5 x                LPVOID lpAddress,  // 要修改内存的起始地址
+ z; P# w1 p8 f. k                DWORD dwSize,    // 修改内存的字节
. a* ]3 i) \* y+ l# B                DWORD flNewProtect, // 修改后的内存属性
. A6 Q2 W2 u; V* m                PDWORD lpflOldProtect // 修改前的内存属性的地址
3 a2 r3 R$ u( g0 a8 k                ); ( W1 {/ ], P1 z2 v8 q
    BOOL WriteProcessMemory( : L$ V2 y' I+ V4 o: Y
                HANDLE hProcess, // 要写进程的句柄
( H, {1 w; l5 h7 W                LPVOID lpBaseAddress, // 写内存的起始地址
9 q6 D- M1 ~! ]  D; L2 Z4 N                LPVOID lpBuffer, // 写入数据的地址 ( z5 e* ]- [" d' _- ]
                DWORD nSize,   // 要写的字节数
  p$ G" Y' i  q5 N* t: z% r                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
. d6 O) Z9 X  N: m                );
! S+ {; n, H4 q1 Y' P    BOOL ReadProcessMemory( 9 P$ m5 b3 H1 T" r, }# H
                HANDLE hProcess, // 要读进程的句柄 & \) A  X! F' O7 o5 ^0 y8 M  i
                LPCVOID lpBaseAddress,  // 读内存的起始地址
, z0 S% t5 Y& S6 B                LPVOID lpBuffer, // 读入数据的地址
! e+ u9 ]  f- E7 t, L6 ^* A                DWORD nSize,   // 要读入的字节数
7 @9 @- X, v3 S% Z2 A5 E) n                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数
  o4 k- D3 U# k, x- S* q: U8 Q& M                ); & M$ w* s  f. t% @7 y
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同,
8 x5 o9 R6 V. I2 U8 G5 ~' I2 b5 K因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明:
. J, J+ Z# K$ L, ~- w) E9 t其中Dll文件为: 6 R$ m9 T1 ^: E' E$ B
     HHOOK g_hHook;
2 `( H. l6 L8 v1 b- C+ V     HINSTANCE g_hinstDll; 4 I9 N& J) K* T5 A: }& A! a0 P
     FARPROC pfMessageBoxA;
2 h& t" c4 P" [3 B+ z     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
. t# m) a: E1 a+ y2 x" S     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
$ e8 i+ ]- p$ M; ~1 H8 ~2 s     HMODULE hModule ; , Y+ b; z, R/ f/ i# a" W! a
     DWORD dwIdOld,dwIdNew;
! q$ U' r9 [2 G6 [7 [     BOOL bHook=false;
, [, ~& [3 T. S3 }: F8 m. `     void HookOn();
1 ^; f. {( i  ^     void HookOff(); 3 Z* i- L& T7 k
     BOOL init();
$ N4 w: J0 S: `  K  a7 gLRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
: X. R8 T* Y( @4 p, XBOOL APIENTRY DllMain( HANDLE hModule,
7 G$ p/ g: O! k1 y& P0 R            DWORD ul_reason_for_call, 8 F) e* `6 h' j% P3 G
            LPVOID lpReserved / |# @4 R6 ~: f9 x" n; l- i
           )
4 [4 r* B0 e: l{ 0 D& }0 n$ l5 j) _5 ?6 f: G
  switch (ul_reason_for_call)
" x0 W% v- C) S# ^3 l( s  { / B2 K# Y' \* Z! g) M6 @  [7 Y
    case DLL_PROCESS_ATTACH: / N5 g! [; Y; f4 _! u! n: O6 W' f
      if(!init())
/ o+ [9 @( E" x' d/ Q7 K9 g8 o8 F      { ; J. d# F+ Z! m& i5 c/ |0 y
             MessageBoxA(NULL,"Init","ERROR",MB_OK); ; Y% K; ]5 d. q; q& m0 D/ A) G+ r' `
             return(false); % B( |8 B: l) I2 p; l' Q" `& U) N
      } * w! E. f% v0 o/ F
    case DLL_THREAD_ATTACH:
, C% d% a4 ]1 O    case DLL_THREAD_DETACH: ) u% ]- ^9 {: m# |* i* p. |& p
    case DLL_PROCESS_DETACH: + N0 e* k4 a3 Y- S# Q/ A
           if(bHook) UnintallHook();  ) K# `/ a, D' @
          break; ' |0 _  y- R9 Q& q, l. l/ t
  } 5 P5 ?9 l/ }0 A. Z' c
  return TRUE;
8 l8 i- ^5 S5 L0 d} $ y& w9 L# t: E2 C
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
$ l& |( X+ N# I5 G{
) U, Y: X( n$ A  ?$ s9 h" d5 P   3 I. l5 v- i) y( X% O
  return(CallNextHookEx(g_hHook,nCode,wParam,lParam)); # k' c$ i- v" D' g$ G  X' p
} 9 y8 k3 B2 L" O( U' M
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数 / F: }' ^) j: v1 S" Z
{  
1 z5 F! n. T0 _" M& Z% S" @# r  g_hinstDll=LoadLibrary("HookApi2.dll"); " @- L' ~7 s8 r; w2 ]
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0); ) n2 W2 O4 U( l6 G$ F
if (!g_hHook)
7 i3 {% i! c; B* k* B{ ) O( C. H& x% Z6 g6 E% K' ]8 f
    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK); 8 q  B% N& t+ h( f& s
    return(false);
0 r2 P, e' \, P! B2 l! H  }
0 h  v6 N# h( m  ?  . ~/ q9 H" B. n1 x1 N1 Z( ^
      
' {7 x( c! ~$ s$ x  return(true); + t& x+ l  a* Q2 r, ^8 a4 `
}
2 A8 K/ E( x, O4 u- EHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
+ P- z; |* E. b7 w{
% `" ^) @5 F8 K; @& x7 f% u  
/ z$ D+ H( G3 z* C2 ^8 t9 s1 v  return(UnhookWindowsHookEx(g_hHook));
5 @7 Z7 f  ~9 I* E' \- a} : M- o. G$ A' ?$ l: u
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令 9 L7 g) K2 q  V% U4 h
{ ( R4 p* H' y5 C' ^, n+ J$ ?
  hModule=LoadLibrary("user32.dll"); ; E  H. I2 J2 M
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); 6 w3 G% r" w, ?+ Q% w
  if(pfMessageBoxA==NULL)
& g: ?# [/ r5 g. I5 `  y$ T' [   return false;
; X  H; W& e7 v  _asm
, ]. h) X% B. G! f  { . z1 H8 q# I2 l: C1 N
    lea edi,OldMessageBoxACode
, Z( V' z4 |8 n7 E7 E" v$ ~. `9 Q% ]$ W    mov esi,pfMessageBoxA # X  e& B5 F( Y' v; z
    cld
2 F' {6 y* S* s$ q    movsd " g# }$ X. O% J0 j  V
    movsb ; L8 ?% ]9 N: v4 u# l
  } . ?. z2 Y9 }, |, F8 O- {" i
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
( p) I9 X1 w; ?6 e! U0 h, e  _asm
) V* y8 ]* [. C, w) L  {
4 ~, p* }  S( w- e5 B# a8 I    lea eax,MyMessageBoxA 1 @6 A3 f" Y4 N4 u; O
    mov ebx,pfMessageBoxA
& k: G% a) x3 E& Z3 S* @    sub eax,ebx
  ^, U$ Z6 H; x  X- F    sub eax,5
8 ]4 n. k6 ?9 N    mov dword ptr [NewMessageBoxACode+1],eax * T2 p% A6 r0 a3 Y3 L5 u
  }
$ A$ l8 v/ o  L$ U  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID % E; f0 F# I$ b6 p: X
  dwIdOld=dwIdNew;
- z' \$ K6 T7 M  HookOn();//开始拦截 1 R& o% h# n. l% w- O- I
  return(true); # I4 C2 a1 t! r* A" W7 P2 k4 Z% r
} 5 o1 K  T  \" E+ f3 f/ n3 f, D
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数 0 }( G. Q3 \/ @* D, T+ j# b! ]
{  
7 x& F: K* h0 L7 s+ a& y) w' I  int nReturn=0; " u1 @6 t0 J+ l, ~6 V- b
  HookOff(); - [! y! k$ L% a
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); 6 e' G: d7 g+ o# ]* ^1 Q8 m4 f
  HookOn();
8 h, T* F) Q% f# o% o  return(nReturn);
5 ?1 t' u: z  z2 F0 z, X" p} , D$ V; O5 U4 K+ r3 X2 \) {
void HookOn()
& v: \0 p5 z  g. E* ^{
% ^, f7 @, x& j* x2 H! X  HANDLE hProc;
& V+ f) |+ z" ?# w5 H2 ^  dwIdOld=dwIdNew;
, X- a6 x0 o1 r: p3 d' N# c  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
; K2 {: v/ F$ ?( ~( Y  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
6 H# c9 L- k8 |, w3 p4 w  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA 4 n& W  F' l% d6 @5 D+ `( X# P( M
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 - P5 W  |0 ]' Y  x3 M
  bHook=true;
) s/ r* J% O/ p}   v* B) l4 G$ g) H, `+ p
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
  Z" q( V/ Z. G  H{
+ \0 Y5 j" j- |% p  HANDLE hProc; , l! Q5 N8 {8 r- i3 p8 @
  dwIdOld=dwIdNew; , l5 ~) E( C6 P* C4 C" H4 l
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); 6 z" u# F$ [3 z3 k6 j% {! `
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld); 3 X( V* S" h" h
  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); 1 ^: S0 t0 Z9 c( \( Z7 O0 W
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
- s/ K7 K$ d- C; c% ?. @  bHook=false;
* T2 [8 C4 K/ |8 L} - f; F/ K" \! k( N% y' f( Z
//测试文件:
0 g, V* U( l( Iint APIENTRY WinMain(HINSTANCE hInstance, 9 i7 S( C( D0 s* F$ Y+ w
           HINSTANCE hPrevInstance, , c/ g4 ]0 [% _* ~4 V
           LPSTR   lpCmdLine,
& w3 M; O. d; O+ _/ \1 H           int    nCmdShow)
: z) N6 b6 R- `. y+ `2 q. O{ # l  \! K8 ~: M' k. A& C
   
6 m7 f- y, t. k4 p  if(!InstallHook()) & a7 T5 D9 ?0 X, m, L/ \" \3 D7 r
  { 6 a/ L, G8 f! z6 g* F, V; p
    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
% c0 l- m% `3 R1 @0 n    return 1;
1 ^+ ^& c8 s/ T, a2 z' z  } & T+ \& [+ V6 `9 V9 M
   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 ( }! \, j9 i. w; b- M
  if(!UninstallHook()) . h( q& l; Y! D: W9 k; S( ~
  { * U+ Q' w, c- G1 W! `3 r# V! x
    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK);
1 T& g! o, |/ k6 n4 P    return 1; 9 S2 V5 h  R- Y( ?/ O% Y
  }
- B# m! Y; G, p  b, n  return 0;
7 k0 ^9 {9 }1 T& J" I$ T) r}
5 `( i+ [3 Q4 H1 h5 Z
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

3 k' @* L. t, c, M3 `  l
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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