下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

跳转到指定楼层
1
发表于 2004-11-5 18:09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
2 S" o# r& C; b# z' B
发表日期:2003-10-30作者:tomh[] 出处: 7 D/ X  W" ?8 }5 K  O
Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。
3 c# g5 U: T! W- T  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现,
( S/ o" {; M* h0 L其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: ' }& r4 _: e9 X3 q
     BOOL VirtualProtectEx( 0 e: a0 X5 N' E3 ]$ X
                HANDLE hProcess,   // 要修改内存的进程句柄 " a( l5 ^4 c7 V9 k. x
                LPVOID lpAddress,  // 要修改内存的起始地址
6 e: o- c2 e# d6 r# D0 a                DWORD dwSize,    // 修改内存的字节
8 b* a% h; c9 L& n                DWORD flNewProtect, // 修改后的内存属性 $ ?$ ]+ R: d# r& b
                PDWORD lpflOldProtect // 修改前的内存属性的地址 5 y3 }/ l* |2 H0 i3 q
                );
3 ?+ Y# Q# _* A. _( \  L    BOOL WriteProcessMemory(
! {  t1 F: U5 A6 B; \3 i0 [                HANDLE hProcess, // 要写进程的句柄
/ e$ W+ T8 _& k. O, X7 X: G                LPVOID lpBaseAddress, // 写内存的起始地址
6 ]& w$ K9 z4 \( u9 {( r! u! ^. Z                LPVOID lpBuffer, // 写入数据的地址   L1 c6 c6 N8 ]  T$ [
                DWORD nSize,   // 要写的字节数
  j7 w) x3 R0 s                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 + ~; p% Z/ J8 c. P
                );
6 o/ h' M$ j6 w3 X: @    BOOL ReadProcessMemory(
; h. s' ]' q/ k: Q/ ^                HANDLE hProcess, // 要读进程的句柄
5 C/ S$ O" ]& d8 C: x+ y                LPCVOID lpBaseAddress,  // 读内存的起始地址
9 r, I0 R: D% P5 o2 V) ^8 _                LPVOID lpBuffer, // 读入数据的地址 # M5 ?8 v1 q, \. p1 z
                DWORD nSize,   // 要读入的字节数 : U1 n6 d; Q9 m3 s( a' N; Y/ {$ |
                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数 # K( F- @6 m5 H+ L" {) W
                ); 6 y' F, U" K; }( Y
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, 9 F+ h& {" l! \$ Z1 C
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: & u6 [- S6 j" M
其中Dll文件为:
* Z7 _1 p. t& ~& q4 N     HHOOK g_hHook;
; w; d" T' o' V" j8 ^  u! ~: w     HINSTANCE g_hinstDll;
, |& n  t2 c" O& ^6 U. K4 I  i     FARPROC pfMessageBoxA; 8 n: Y1 T6 \, S! ~+ _
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); - R+ ]2 E6 {3 O  U+ Q; l' \6 U
     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; + R" f1 F4 _3 r8 _( b) n7 y
     HMODULE hModule ;
0 D) ^! F2 C: p3 U& J9 [& |     DWORD dwIdOld,dwIdNew; " O" d  J% T' ~# X  M; c; q+ H- p3 Y
     BOOL bHook=false; 8 n- s( M1 Y/ o; R/ Q" v* Y
     void HookOn();
) z) x9 a, I' y9 r' U5 |     void HookOff(); / F9 m0 k6 P1 E- H/ p; A
     BOOL init(); 2 \$ ?+ [( _- z. O* j
LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
* ~3 \. V) V  I9 I2 SBOOL APIENTRY DllMain( HANDLE hModule, 5 L9 P' |- V4 _, I, [1 @
            DWORD ul_reason_for_call,
+ L( T9 d" \7 F            LPVOID lpReserved 3 f: v* M4 |/ |1 R! [( c1 ^# ?3 `
           )
3 ~/ O6 ?9 I# L( O{ & J& z+ S3 Q& N+ S
  switch (ul_reason_for_call)
, g, |1 X  d9 x4 `% e  {
# W" ~& z$ Q( l    case DLL_PROCESS_ATTACH: % V# T$ }6 ^& y* j1 ^
      if(!init()) 1 g7 B' {5 o) a+ {# G
      {   ?3 M& G" C/ l
             MessageBoxA(NULL,"Init","ERROR",MB_OK);
5 k, E( y- M# g1 `- ]0 E) l+ E             return(false);
. ^& X1 Q4 }3 B. Q$ ^6 z      } 5 I6 `5 C/ M7 G8 D* g4 g* g. V7 {
    case DLL_THREAD_ATTACH: 8 }0 u& h: z! d7 }" [' U3 X
    case DLL_THREAD_DETACH: ; O0 j! P( H( W5 J
    case DLL_PROCESS_DETACH:
& |4 E9 d9 P( ^9 k+ n% b           if(bHook) UnintallHook();  ' N" V7 t/ h" `; d' ^5 {) Q. {$ T  v
          break; . I$ A( D% _, L
  }
* R* T+ a5 d% q  return TRUE;
" F/ D- L3 m" V/ S" R; w}
1 C$ g. Y4 Z8 \3 }: T' fLRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 # k# K$ L/ c! n- F% K% p5 t
{ + l; Y+ b7 Z& i- C4 s$ i
   
, b/ @, a* Z# H' w& j6 }: {  return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
8 N# n. ?, P1 P: ~1 L# @} / |2 j% f0 b) }4 o" h! t
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
9 h# d0 X+ \7 V0 n2 h5 {{  
( z, m2 v; H- W" A  g_hinstDll=LoadLibrary("HookApi2.dll"); 5 L1 B$ D5 f  Z" t! L& U
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0); . Z, x( E. F; w
if (!g_hHook)
& r9 P8 u+ S$ j/ b& U' a$ e{
7 ?9 Q% s4 J6 Q! R, \8 z    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
  L( @, h% ?& N. }# d    return(false);
7 }+ E$ G2 k: {9 B& i, P  }
, g/ b0 V# _( ?+ X' r1 z. n  
4 y* P3 s8 j+ x+ b" H1 x      
2 [! e+ j8 N( u' `/ D  return(true); 4 l- L2 j  n* o- `2 u2 {$ x0 T
} 8 A4 }; H, a5 H' d; a  b6 `( r
HOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数 ' @' Z: u( D8 |, n% w
{ % s$ _# r! @6 s$ B' R' J9 M
  + W6 _5 b# R% o) J3 u
  return(UnhookWindowsHookEx(g_hHook));
* B9 _: C2 d' M; \" k1 g5 {. ?% U, K' l}
+ [, v$ Q4 r0 yBOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
6 `! z. V- E( ^$ x. z{ 8 B, u! D& ^! g% F1 ^( K, w
  hModule=LoadLibrary("user32.dll");
' J" C9 S, {- K* {+ W* b* i1 t& a  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); 4 r9 T, i# n, v
  if(pfMessageBoxA==NULL) ! g& o) F6 U' R, k5 d2 S$ S
   return false;
1 H; c. S1 Z5 U+ F# I  R* ~8 g  _asm , X- v7 M; U, @6 Z7 {: P" K
  {
+ Q* b; a- J$ Y    lea edi,OldMessageBoxACode
! e( r4 Y' u. B' \% T# l9 O' U* ?    mov esi,pfMessageBoxA * v- a+ u1 H/ Q9 h/ i) M8 J) ?
    cld 1 k8 v" Z: f, w! D' S3 X9 r
    movsd
( y; b4 x2 U+ M    movsb ( ]2 q. k2 F$ Q2 l4 L( k9 K
  } + _9 r8 ^! B6 @: j' K" t( O
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
0 _# [5 _# W/ w0 E4 _2 `* e  _asm
: b3 o/ l! q9 z. D" R  l1 l: Y/ s  { : ~( U& s  p, q; ]
    lea eax,MyMessageBoxA
$ i$ {+ m4 L* m# ~- Y    mov ebx,pfMessageBoxA " d" E# u! ^5 J7 ~) K* w
    sub eax,ebx ) Y; r. S7 p, |+ ]8 z4 ~+ ^
    sub eax,5 # q2 h7 ^* Y5 U" x7 A6 s
    mov dword ptr [NewMessageBoxACode+1],eax
$ v7 C# B& y0 u1 T) Y) ^  } $ u" M  ^2 T) l5 v
  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
; M) x  A; g& ]* Y' @& K, P5 b% C4 B! c  dwIdOld=dwIdNew; 5 D% b1 t1 A1 r8 d: D" U" b
  HookOn();//开始拦截 4 I/ ^$ m1 G/ ]' L
  return(true); 5 L9 a! j4 q* T  {; K; e
}   i5 n3 @6 r) V& L
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
* a+ N% @6 d9 L5 @2 {{  # ?3 z9 g3 y9 a7 i/ E4 [7 O) L. }+ }
  int nReturn=0;
! a; m  g2 |# k4 u2 c( w  HookOff();
) T9 I8 [' g/ }  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); 6 ^' K+ A' P$ Y
  HookOn();
6 o" ^5 V8 V/ o. e& q6 w  return(nReturn); 6 k& j! V: B! _( e
} * Y" f0 t5 C8 f5 F+ E6 r3 u
void HookOn() 4 J# p% {) D: H1 |% i1 G+ f
{ * d+ ^0 _" J: m3 w# G; E4 u9 q
  HANDLE hProc;
3 m" r* r/ v* P+ _4 l  dwIdOld=dwIdNew;
7 ?! ~. P2 ?2 c% v8 E5 p% ]  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
2 w% \* Y% x6 R$ N+ u$ P' p0 F  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 5 I7 n3 R7 X  v$ d4 n
  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
! K/ q4 V4 v  Q1 X  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
+ A0 N2 Z) U: y) y1 \5 P  bHook=true;
+ n- `0 Z$ P' x9 T: H}
8 ]' {6 X2 v: r5 h. qvoid HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
. a8 U3 B. D# |- S7 w1 p{ / _% u) a* H! w; I* b+ v1 W
  HANDLE hProc; ' I9 k; `) {' W% r
  dwIdOld=dwIdNew;   M/ U7 z. @, L# r5 t) N
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
/ X2 [5 Y- ~' A" `2 P  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld); 1 }6 J) Z+ _9 [  M
  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); " b9 I. B+ z% T+ t" }: g
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); + [* d- l+ d% o- r: W; `  j2 K/ G
  bHook=false; 0 {8 y: y8 V1 i0 k% \+ T
}
7 \" [- O# I& a. o6 o7 c  F" r, K//测试文件: + Q2 j( V; x! ^
int APIENTRY WinMain(HINSTANCE hInstance,
4 b% {4 J6 T  t$ T4 ]7 [           HINSTANCE hPrevInstance, 2 b* Z5 V; Q0 C$ U2 _
           LPSTR   lpCmdLine, . o2 {" ?% M4 M& s. Z/ }
           int    nCmdShow)
0 m+ h6 g. N/ ^8 c; q) X! A{ # g/ y& J+ z; I
   
/ X% |: O: j9 X, W/ I5 Y( Z# v" h  if(!InstallHook())
: |: C) @2 i0 G2 M0 \* s6 I  {
/ b7 g. g& s) k( @; b+ b- T- b    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); ' `( B4 Y/ L# q# X9 y8 k0 s
    return 1;
/ r2 i6 l8 f# I' [  }
! D0 O# y; K6 L1 M   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
4 j( i( {+ `! z  if(!UninstallHook()) " |* B' ~! U3 O! b0 i8 ^$ a
  {
  w0 b' U! I8 F8 [* c$ v$ c    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); 7 u0 }$ F& \! n( `' P1 [/ s
    return 1;
* ~3 `0 F7 z, q( x( f  }
- K( B" T) S+ X  P" C( X4 u/ q  return 0; % D- F1 U! X) q; X" ?, |1 e
} 6 ^5 l+ A; N( N
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

+ z6 @3 ~, \5 C# O0 v! z0 D" Y
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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