下沙论坛

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

用新浪微博连接

一步搞定

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

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

8 H* O) o& j) ~& `# W" p1 @' K发表日期:2003-10-30作者:tomh[] 出处: 5 p; X( @/ [: ?, _# m! \0 j( f  @
Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 9 O3 @& T: y4 f& p- W4 }  B3 R
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, 1 a. f; G/ N, w1 m: a  z# U
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: ; }" R, l4 f0 V$ v) I1 h9 n
     BOOL VirtualProtectEx( ! D$ P" j: s* I" `
                HANDLE hProcess,   // 要修改内存的进程句柄
6 {+ V$ V( f$ Q6 O! G; g, s; T) |9 r                LPVOID lpAddress,  // 要修改内存的起始地址
7 E* R( z7 L& b$ E5 }* U                DWORD dwSize,    // 修改内存的字节 " w2 ~3 ~/ }8 q6 W
                DWORD flNewProtect, // 修改后的内存属性 : K, T' W% n. R5 |" |+ c/ ?  z9 O
                PDWORD lpflOldProtect // 修改前的内存属性的地址 * b5 I2 J  Y' o/ y7 S: ], }- y
                );
% A. a+ k' f, u+ s% s% h  F% f    BOOL WriteProcessMemory( 2 t2 W- G! k" ]1 a+ K1 X
                HANDLE hProcess, // 要写进程的句柄 6 C3 X+ u1 l& h4 n* |
                LPVOID lpBaseAddress, // 写内存的起始地址
, ^$ ]* I7 o$ h                LPVOID lpBuffer, // 写入数据的地址 ( r8 M: [% o  P* `1 O$ H
                DWORD nSize,   // 要写的字节数 ; A/ M( f; Q& Q0 e5 W/ u0 S
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 & V' G$ Q5 u4 T+ z# k- t6 G7 N
                );
& T" p2 h# J. z    BOOL ReadProcessMemory(
- V; }5 N# G# N- r  }                HANDLE hProcess, // 要读进程的句柄 0 ?; j( Q4 ]/ b" m
                LPCVOID lpBaseAddress,  // 读内存的起始地址
1 f. G) k8 V( _& q                LPVOID lpBuffer, // 读入数据的地址
+ U  Z) ?  ^2 o  R5 ]7 f! I4 u                DWORD nSize,   // 要读入的字节数 2 S3 d, }6 u/ ~! w
                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数 * u. c" k' X# b2 |9 r2 f% i2 i6 a1 a
                ); " D. ^7 B0 H1 S
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, " C! M, J5 W, q6 s& P; y' Z* v
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: ( a: f7 u: O+ t( m/ Z/ X8 M
其中Dll文件为: : q) F* d& L: I2 `2 P5 u
     HHOOK g_hHook; / M5 m3 h4 U( U  p' b
     HINSTANCE g_hinstDll;
4 Q5 s% u1 P  l9 w; m! x% h3 M     FARPROC pfMessageBoxA;
- W: x6 u8 A, T& [5 z& l# h/ i     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
1 {+ \: ^$ h6 w5 t% F. V* V1 y& p     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; 0 t# h  b- N/ R, I
     HMODULE hModule ; 1 S# G2 H6 S( N% p* Y) Z0 V
     DWORD dwIdOld,dwIdNew; . f2 r8 y1 I( Z: W
     BOOL bHook=false; # t" x" Q1 Z, H1 a& ?. G
     void HookOn(); 6 e' T* c% X2 z* |( ?# L3 `+ W
     void HookOff();
; w/ a  Y4 y: a& W2 P8 M     BOOL init(); $ R: R" I6 ?' T
LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam); 3 ~# n1 T- z- i. E8 f, [0 f1 c
BOOL APIENTRY DllMain( HANDLE hModule, $ `' z1 w6 l, h; M! \$ t
            DWORD ul_reason_for_call, ; X& o4 R* k0 |& z9 a
            LPVOID lpReserved 1 b, Y  G- e1 C) M" G- v1 @
           )
- X/ U' @. z3 b# n{ , F& f% V) J- G5 O! _
  switch (ul_reason_for_call) : G% k6 }- Q3 B  O
  {
! V' Z6 O/ a4 \    case DLL_PROCESS_ATTACH: 5 F& ]$ C6 a5 d& L: q! `
      if(!init())
  ^  D8 j- T5 N3 U. e& m' ]      {
- s5 d* z, m/ Y2 d, h             MessageBoxA(NULL,"Init","ERROR",MB_OK);
6 y- f/ k' B, g: F, _1 q) o: X             return(false); 1 z& Z+ J1 \. i8 B1 Q3 |8 y
      } 7 j& Q1 Y8 w6 j7 a
    case DLL_THREAD_ATTACH: + b0 B" A1 W8 Y, W1 E3 A6 H) x
    case DLL_THREAD_DETACH: + g- k6 F' G1 |! _7 G" \
    case DLL_PROCESS_DETACH: # [/ b9 i. m+ E3 ]
           if(bHook) UnintallHook();  
( B; E2 U2 W1 a- H: {; p) T          break;
" A# _( I$ u4 G4 \; s  } ( ?4 [, v, @+ A# D, B+ m' P
  return TRUE;
) w2 V; M& |6 C3 B} 4 P% x1 V# E7 _5 K$ M0 x0 c; j
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
4 e- k5 \* O  t; T. ]/ J' ]{
4 T1 b) \' L: g- j, `* d) L   
6 \% p, w  [! h. C4 l3 p  return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
1 H4 |- X* F' s) T}
% Z- B+ l" l" Q, o+ DHOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
( I7 F! R7 {' y8 F. t% I! \1 D0 H{  
" E- V9 M! l" h3 ?+ T  g_hinstDll=LoadLibrary("HookApi2.dll"); 2 m8 B$ p0 p, {: o
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
( }1 {, g5 y" U3 J- U3 B9 Sif (!g_hHook) 6 u2 {0 v  w6 _9 j# h, {# Q
{ * p- ?9 @+ S5 _  _2 y' D
    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
! C$ w' C8 c6 S! _% |2 T0 n0 U    return(false);
! o! h; h! K# D' z0 u* U( R. _$ {  } $ C, ~, m" |( ^: r/ B; q
  
8 s/ W) S1 ^0 w$ }7 S      
1 Z9 e7 P) S( e" \7 r4 x  return(true); , g1 x, S& N, {% _$ J) v/ \
}
; C, {: L) ]& \/ x5 [( ZHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
, l6 x- R- A4 M9 O$ i; t' L{
4 v" g) ]5 {; s7 N/ H- T, q# [  : F/ v; l7 {7 b$ T  ]( Z
  return(UnhookWindowsHookEx(g_hHook)); 5 p0 J, z+ C' Z* A. A) s
} - e$ w: n5 O& B/ x# `
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令 & m. W' p8 j, t1 q" |
{
: W" F. _  S0 }$ R' e  hModule=LoadLibrary("user32.dll"); / \) Q. [8 Y* G. O2 w% J/ h& D- s
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); ' H- B* A8 n; L! l5 z4 R5 L  y
  if(pfMessageBoxA==NULL)
6 F) Z0 g# {1 d$ j. C   return false; ( C- {# S, U. `  [3 A* o
  _asm 9 X/ d/ b8 J% I
  {
+ y3 y. d% s' z# u) d    lea edi,OldMessageBoxACode . `8 T: w# d: i/ S- k: h3 `( h
    mov esi,pfMessageBoxA 5 J+ t7 a# S7 i* [& k8 h  u! W
    cld - J) x; O8 ?( l) H9 a. U
    movsd ! p8 Q+ u8 X; A( B* [1 R& ]" l* y4 N7 f
    movsb / X% z3 l1 E' c( W3 T5 f
  } ! s7 }$ B5 K! `. y, N! k
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 6 j, D# r' h7 b- }3 s; B# _1 A
  _asm ' e. h' l$ m3 Z& _8 i8 {
  { - P3 G7 |8 z% ]$ c7 J( i
    lea eax,MyMessageBoxA
' W8 o8 U2 f/ Z8 h    mov ebx,pfMessageBoxA
" ~% g7 V- |+ @* t% I7 a/ x+ M7 g    sub eax,ebx
- U5 z& ~2 J. J9 j3 B" h( m9 T) l    sub eax,5 1 S  L5 N+ h, L3 H4 F) C
    mov dword ptr [NewMessageBoxACode+1],eax
% k; W8 m( |3 w$ G) f  }
. k/ [$ Y0 j/ e. p  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
( K- U$ C5 R. L' }8 Y( w  dwIdOld=dwIdNew;
& d  M7 N* f5 |: o, k  HookOn();//开始拦截 7 Y1 i/ w9 _3 h$ O% T% R# E
  return(true);
# Q' N! w) |. N2 Z8 x* n0 Q/ x}
  w1 W1 ]2 C! X4 P( R6 g3 N5 [int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数 9 }0 Z$ t$ \+ Q3 A5 A" \( F' P
{  
, K& |: @0 J5 b0 |# s" l5 a( Z5 m  int nReturn=0; , ?5 l' e* C1 h/ o$ ^1 [
  HookOff(); 3 |$ x  J. a/ q' E( `
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); ; i8 T7 I1 z: _
  HookOn();
) H+ G$ }& t5 p: }7 O0 P" R  return(nReturn); & Z. y+ i' d/ h: r' @1 p
} 0 N/ [2 P7 U/ A9 n  Z- W* s
void HookOn() & g( y2 R" _7 M% u$ x
{ - Z9 }7 _- W( u" R1 p6 }
  HANDLE hProc;
- U! g2 w5 R% @) A8 w0 o  dwIdOld=dwIdNew; : ?+ X7 u; P7 F. y5 K, l2 c
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
) s( p- _5 K3 G% {# X  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 , N" `2 O: g8 _
  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
, E% Y! F7 E1 ?8 {0 R  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
) M1 J$ E# _& v/ r. J2 w  bHook=true; : R" X& c0 X7 G: S- ~
} 3 E% C' t  S' x) L, W: S1 E) M
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA   x4 K9 F$ E+ i( K2 Z. x
{ 6 ~9 G: l' Y) \
  HANDLE hProc; 0 S& \; d4 [* N" }" [) H( ?
  dwIdOld=dwIdNew;
( E" v: F+ [; o) S- ?" q  @$ _: G7 C) b1 a  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
; y9 i0 R4 |- W- g- O0 d% x7 o  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld); : m! k# q+ z4 L$ O, i
  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); 8 b7 F* L. H1 e8 d7 v
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); ) ~: `1 \% d& o2 N" V
  bHook=false;
5 D$ m- W7 M# c. `}
( {( M/ h! {' p0 ]1 \* k- F( A4 h  b//测试文件: , i5 s$ q) U( I
int APIENTRY WinMain(HINSTANCE hInstance,
( `: N6 {) [+ c( m8 U+ k, x. `           HINSTANCE hPrevInstance,
3 j0 z4 }* f# K& y$ _# t           LPSTR   lpCmdLine, ! r( _: C, r# P: B7 l, I
           int    nCmdShow) 8 K$ b- |, G" U1 C0 [
{ " I2 M% j- r9 I1 G; G& a! K, d$ M
   $ d5 S' z! j& h, K; E$ t/ g
  if(!InstallHook())
! U6 G8 y7 R% c$ w3 C6 B, {+ H  { ; r9 l0 F1 s2 A
    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
  K0 j# A3 z* G, Y    return 1; 2 N* p9 {5 d. b+ ?9 I
  } * ?$ t. W. e( J" _; ?
   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
& [1 G7 w4 u& Y* l3 T8 c! h  if(!UninstallHook()) 2 a5 E7 H1 o; l7 S' N1 l0 f
  { 2 L- K( \, w; C# G9 M6 s% X
    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); / T. d( P3 L+ T& \- A- I5 P1 o
    return 1;
. E+ M0 N1 W$ e+ F  } ; T: F5 d$ b* d& T/ p, x% c
  return 0;
. l+ i& N! C- _}
/ j& n7 ~& s& R5 Y( W
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

; i3 \% d; L% R, q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

该用户从未签到

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

该用户从未签到

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

好眼熟……

关闭

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

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