下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

跳转到指定楼层
1
发表于 2004-11-5 18:09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
9 k7 H; Y, p# D# G2 b
发表日期:2003-10-30作者:tomh[] 出处:
/ L4 q% }+ s' j* l% TApi拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 & x) t1 o0 ?+ H8 X0 y
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, " q! L( Z1 Z* N' J5 k  P' F
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
4 l- b0 ~1 j. u: c  a; A3 p8 O     BOOL VirtualProtectEx( 1 c; |0 H/ P- T- R8 ?. h% Y
                HANDLE hProcess,   // 要修改内存的进程句柄 9 [, W' [" y! B* P8 O' \$ G/ j
                LPVOID lpAddress,  // 要修改内存的起始地址 9 l/ [' N2 B% M$ z# Y
                DWORD dwSize,    // 修改内存的字节
* w! l, Y! @; |0 s( T                DWORD flNewProtect, // 修改后的内存属性 $ y' h3 g' Y3 ^$ F  P
                PDWORD lpflOldProtect // 修改前的内存属性的地址
" d/ ]3 M& R& h- Q3 z7 L                ); 5 _' E7 C+ r# E7 j7 e0 D, }& Y2 `
    BOOL WriteProcessMemory(
8 _" x- A. l: |& c( h                HANDLE hProcess, // 要写进程的句柄 % \# ]0 Y& s4 e& Z0 w8 L* Z. i
                LPVOID lpBaseAddress, // 写内存的起始地址 ( S- b+ {# M/ J; D2 J
                LPVOID lpBuffer, // 写入数据的地址 3 L6 `- `' R+ K* H" E. E1 f
                DWORD nSize,   // 要写的字节数
, g) M' \" A9 n# D                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 2 v( u- d0 W9 o; ]' X' ]
                ); 1 q7 \7 z: ?( M2 V
    BOOL ReadProcessMemory( 2 S7 U* U: `; D2 v3 J) D
                HANDLE hProcess, // 要读进程的句柄 ) ]" q" D- X+ f! D: X/ t
                LPCVOID lpBaseAddress,  // 读内存的起始地址 $ w5 k- M- j- z4 M5 x
                LPVOID lpBuffer, // 读入数据的地址 ; l7 A1 P1 K+ b' d
                DWORD nSize,   // 要读入的字节数 ! v% |# I3 ^" k' J, \) g+ C
                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数
" |$ H: c' C* F  n1 R7 q0 {9 y: g: _                );
% b6 h4 L+ i& t: j: y具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, * U* m( M( C- o7 v( j9 N
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: ; S+ l2 s$ H- M4 k5 |! k1 {/ S
其中Dll文件为:
, I0 o) S8 B, U' b$ P. n     HHOOK g_hHook;
0 W! q; u  ]1 t  h% x" w     HINSTANCE g_hinstDll;
# B) D/ N8 o) r, s9 l. B     FARPROC pfMessageBoxA;
# n: M, `2 U8 o+ y, L3 m     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); 6 p& Z6 Z/ Z# k4 Z
     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; & w* b0 _4 @' T" U
     HMODULE hModule ;
7 @5 u. S0 X) x- K2 s# i$ L+ P     DWORD dwIdOld,dwIdNew;
& ]- t- @# O; o+ W" G# K& z- s     BOOL bHook=false; : x+ |  e! g# i# B6 Y' ^- f
     void HookOn();
8 |# k+ K% P/ ^     void HookOff();
; M- I7 v6 R- E2 U     BOOL init();
% ?0 T1 {. Q  k+ w3 J+ y' U$ vLRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam); ! W0 m0 S7 s( a$ R7 _
BOOL APIENTRY DllMain( HANDLE hModule, 0 Y* _8 l+ c) D1 D5 R: g: g
            DWORD ul_reason_for_call, 1 l3 W9 m0 |* ~3 K
            LPVOID lpReserved
% d1 k' `+ T1 c4 F           )
' N9 y9 M, R; Z- w, V{ $ G& g6 Z  c! g' R# I( w
  switch (ul_reason_for_call)
; |5 ?! B7 d3 D2 g/ i  { ! |6 z% \3 U- T$ c2 C8 \, P8 F
    case DLL_PROCESS_ATTACH: 7 C2 O4 \  O6 l4 Q$ a3 K4 W1 E+ h
      if(!init()) : {  n4 @3 T( l4 ^
      {
7 c" B2 [+ a+ X' b9 O, _3 z             MessageBoxA(NULL,"Init","ERROR",MB_OK); ; D+ q( y3 I2 x# f( w
             return(false); : _+ K$ J' |5 {: c9 D2 J5 a! f- \
      }
# @/ o/ E+ t. e( J    case DLL_THREAD_ATTACH:
) W2 ~  L: ^" t" ~' y    case DLL_THREAD_DETACH:   ~' f. `1 n0 a  }1 x: a
    case DLL_PROCESS_DETACH:
' d; J3 \! X) G) Y* s& s' N           if(bHook) UnintallHook();    Z6 R/ ?5 C! j' V2 t- L
          break;
. z% P# R/ X# ]7 V4 z; c  }
" G0 r# j8 p# }& ~  return TRUE;
7 \1 h! j; R% K8 d}   }( J2 a$ ?5 m" T* {1 x9 q
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 3 r0 ?! ?6 k4 X+ M. V
{
5 E6 ^6 r- l* T9 @+ a& d$ @! P0 u   
4 n% _) |; [) B  B) K  return(CallNextHookEx(g_hHook,nCode,wParam,lParam)); 2 R( y! |" U+ [( P; K
} 1 Q0 m- G9 {3 S7 O  s+ l
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数 & l% O3 e0 E0 R/ G% U1 Q
{  
# P6 H- z3 T: F  }  g_hinstDll=LoadLibrary("HookApi2.dll");
2 i( V7 i5 t6 {8 {! H  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
5 E2 I; m( N+ {' ~' y& I9 ?if (!g_hHook)
, j6 ~; w  }) u& S6 ?& e, F- h{ , W, _! D+ u2 Q; X
    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK); 0 v9 S- v, d, j; @6 t% V
    return(false);
" Q- F8 [1 N/ A  }
  s6 k# H1 D8 b  
) ?7 o* J3 y1 ~% I- E      ) H+ s" U8 M4 X9 G/ b3 \* E
  return(true);
( W, U3 Q$ B, ~! X6 F} - H+ ?4 S, o0 ^. z
HOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
! R$ b# F" n; s, @4 h6 X# Q5 p, S{
/ q- y5 f8 _  {3 m6 U& `3 p  - @) T, Z6 k: L& ~4 q' r
  return(UnhookWindowsHookEx(g_hHook)); , `, x, A( h1 T7 P
}
) ]4 S- k, \+ c- `0 \BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
2 t9 u) n9 @- W9 L' D( n{ ' S1 c, w! O7 D
  hModule=LoadLibrary("user32.dll");
( a( b0 i7 t9 T/ s  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
3 }6 S- n, X1 C; S: @  if(pfMessageBoxA==NULL) 3 t  B1 C5 \1 o8 A  n$ m3 V
   return false;
9 G5 h) Z! k# n( W$ j9 E  _asm
7 w) O2 I- E$ c" K0 G6 s  { 5 e% Q4 Z9 H8 Q& W+ {( d1 N
    lea edi,OldMessageBoxACode
; t- k1 |& a4 ?7 G* T' H    mov esi,pfMessageBoxA ; a  f: O. w, _5 O7 g" M4 L6 w
    cld 2 }3 g/ I* p; l6 z7 h; E4 O. F
    movsd $ r/ @$ ~& U* \, r1 f
    movsb
) T  J$ b0 O4 m7 [6 [: G( z% A  } ( ~0 M3 C# R0 l7 x% m' r
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
! W+ b+ V' Q* q# V/ I3 m: l- s  _asm
& Z" n" K+ R( _0 W) @' V* c  { # k3 d" c1 C/ s( a$ K5 }7 w1 w
    lea eax,MyMessageBoxA
- K4 `% a) H8 r    mov ebx,pfMessageBoxA
& t6 F( ]8 ]  q7 \3 W5 W0 l* {    sub eax,ebx # A4 t! }# u$ U8 p/ X
    sub eax,5
3 u  G9 A: U' p, q2 O    mov dword ptr [NewMessageBoxACode+1],eax
( D5 d: b6 a4 I# w! {) u1 b) }  }
5 v" p$ {. i' a. H  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
" K* _1 g7 K3 U% e8 P7 U! b  dwIdOld=dwIdNew;
' W4 \( Q9 D6 P  HookOn();//开始拦截 3 B& v. M- [! `4 @: W% |
  return(true);
. Q1 a3 D, i: @7 c/ y3 K} ) V: E- m6 G; G
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
  W& |/ |: Q4 R7 A{  " U$ H7 ]" ~2 r# D- Y
  int nReturn=0; 5 u2 z6 k6 m- }& |  o- @+ M
  HookOff();
6 s6 J  V! U5 Y$ _# h3 Q0 m, Z  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); ( P- T# s) W& |; B  b8 f& U: D' S
  HookOn(); 4 o: |: u" i1 I+ E2 v+ [
  return(nReturn);   B7 G: }* y2 s& [' M8 d  y
}
2 Q# c$ Q4 v9 B2 K! p2 c9 r, T! Avoid HookOn()
( G# B9 E* G1 A4 R; Z{ % o9 z3 l0 f7 Z4 {+ w
  HANDLE hProc; , [! _3 _7 L* [0 Z! F! q9 J
  dwIdOld=dwIdNew; , g9 H" m3 U' s: \. S
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
6 E! \; D  x$ n: c% p+ U" S$ p  D0 ~  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
/ V$ c# F3 V% t" b0 X. q  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
5 I% H  i5 [! O6 V4 P+ B: K  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
8 m, u( H, o+ V3 O6 [  bHook=true;
7 {) k  W/ M" m! T+ ?}
3 v3 X. k+ \) F  y& {5 wvoid HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
% H0 M# u6 Q. T  _" |' c  l{
  F1 t. D6 p5 ^  HANDLE hProc;
# R& R; i" }0 y) t! M" c  dwIdOld=dwIdNew; ) T6 ?0 j, M, B% P
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); + P3 D  C) ~' f. z9 K3 [5 D
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
1 e' f3 G( r) f" q. y, _  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); ) `2 I3 c1 Z& I$ y) A& O3 B! U
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
( B/ g& W3 a( k6 L) x* N/ k3 e  bHook=false;   |4 A. k1 X3 x$ }
}
) U3 @7 M1 {2 h//测试文件: * Z5 s& v: ~  \) d) Y/ f/ W
int APIENTRY WinMain(HINSTANCE hInstance, / a6 ^9 `; L) t" y/ V  |
           HINSTANCE hPrevInstance, . l  P. U8 L+ V2 S1 b, C
           LPSTR   lpCmdLine, " ?# {/ _7 m$ g7 z1 y7 `) Z& ?7 ^: a
           int    nCmdShow)
/ c- c1 l. L0 `+ N# [* A9 a) j{ % m# A2 [* ^# V" i0 {" c; N- X% \
   
: ^3 s* a& T9 F/ d1 |& [  if(!InstallHook())
; [& W8 s  i4 x. v4 l. N  { . d  }/ T9 j, h' g* j: g8 r
    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); " C( E4 y  Z, `: g# o
    return 1; " C8 ~- L- j! P. l
  } + u% ~+ Z9 ]' g4 a4 t* `
   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 ! g/ l& Q" h% i
  if(!UninstallHook())
/ o3 O3 M  t8 k. Y) M! V  {
# e) z+ n' k2 b- X" y" b# Q    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); ' C4 ]7 d; A- d- Q
    return 1; ) W9 A- h6 \; P/ x3 \4 K; Z6 }. o
  } " R; R. _% c. `6 Z
  return 0; - ?$ ]1 I1 X& N- E7 H$ S
} 8 t# H8 g: y" h3 i5 ?
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

# p% ^- ^! C. b! Z" D. H" i
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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