下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

跳转到指定楼层
1
发表于 2004-11-5 18:09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
4 Q5 p5 N/ V- @
发表日期:2003-10-30作者:tomh[] 出处: 8 D  Q) X# Q- d# b" Y
Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 ) x" Z0 c. x! [
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, ! V! f  x, B6 |7 M" `1 @* f, A7 ]% U
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
/ Z3 e4 B( {+ L: `9 d5 b" d; L/ Y8 K     BOOL VirtualProtectEx(
9 o: N' I% q3 O                HANDLE hProcess,   // 要修改内存的进程句柄 1 q. o1 C' W- f: \8 n! \5 y# D0 A
                LPVOID lpAddress,  // 要修改内存的起始地址 * A9 d/ H4 E2 z0 ~9 n4 d
                DWORD dwSize,    // 修改内存的字节 5 E4 l8 S& I) D  `
                DWORD flNewProtect, // 修改后的内存属性
& {0 _8 T0 e( U" N& g- Z& B( `4 v0 }                PDWORD lpflOldProtect // 修改前的内存属性的地址
) J" N* _! @7 k                ); ; Y0 |: Q# U' G6 r5 o
    BOOL WriteProcessMemory(
# w) A/ y5 R8 u) L3 x                HANDLE hProcess, // 要写进程的句柄
7 X/ o! {7 Q9 l                LPVOID lpBaseAddress, // 写内存的起始地址 " S( o8 t8 K) `( }$ c9 ^
                LPVOID lpBuffer, // 写入数据的地址
, N6 v0 L3 c: ?                DWORD nSize,   // 要写的字节数 ' f7 L4 h3 l2 K8 E+ h; I
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 % A( A, [2 v/ l$ ]; f7 L
                );
; V2 e0 K3 d2 r    BOOL ReadProcessMemory(
0 g1 U8 o- g, d3 N$ {3 m( ]! {                HANDLE hProcess, // 要读进程的句柄
* |  {1 [) p' j+ M  M% i+ y4 P                LPCVOID lpBaseAddress,  // 读内存的起始地址 ! [) o/ k( B. C, ?& C" ?# ~$ X
                LPVOID lpBuffer, // 读入数据的地址 . i% w5 a7 K" A- S. h
                DWORD nSize,   // 要读入的字节数 # F$ P3 F% \6 [' a$ {- h4 N6 k; ^
                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数
) c0 M( a6 p1 y/ |0 N. O! H/ Y* j                );
: f5 f6 v& {1 W具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同,
) ^$ t3 {2 j' @+ e) y因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: 9 O% r- W2 t$ |# o' C( f
其中Dll文件为:
7 H% p* [& n! p& O     HHOOK g_hHook;
' d6 j! k& ]- e& e# w7 S# I     HINSTANCE g_hinstDll; # s# N0 S* [6 Z  c
     FARPROC pfMessageBoxA; + R; c6 f/ X+ r# E* S( ]
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); 8 y- Y- b9 ^1 w9 y+ }! {, E
     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
9 x7 i$ x- h% D% V' V     HMODULE hModule ;
% i! w- ~# X* d     DWORD dwIdOld,dwIdNew;
. v% y% y8 p6 G1 @4 k     BOOL bHook=false; : r; v4 }: q) U3 m
     void HookOn();
! ^" b5 _! b- g, a5 b& e     void HookOff(); 4 a( P! H' b6 `8 @2 m4 c& _6 a
     BOOL init();
" X( O1 V! S) k: s( b, }LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
3 o  V, W" r% x5 c1 RBOOL APIENTRY DllMain( HANDLE hModule,
4 G+ B( a. k7 \( e0 s" T) f            DWORD ul_reason_for_call, 9 e6 C* i7 A% l7 Z9 M% X+ x
            LPVOID lpReserved " ~1 f6 [8 r8 i( O
           )
5 M- F$ b) k4 q/ q1 J{ * T' r+ [6 S) O6 z; u( b
  switch (ul_reason_for_call)
+ b) u* ^7 y1 F& w( x( {" q# n  { 9 B6 D) k$ e6 w7 g% _1 ~, r+ L7 d
    case DLL_PROCESS_ATTACH: - e3 o0 z3 J7 H( O* d
      if(!init())
, [  @8 U/ G' b3 n! J4 y8 F! `, x      { ) P4 t- `# \2 m: U# p3 u, S7 e. D
             MessageBoxA(NULL,"Init","ERROR",MB_OK); 9 B5 U. M" z$ L, N# ~( h; l# l
             return(false);
" h2 J( v" h6 t$ w- m) @      }
# \' E  K6 `' y9 x    case DLL_THREAD_ATTACH: 7 P1 f: a, a6 P: X2 V7 p  H
    case DLL_THREAD_DETACH: - `+ k) t5 k, A  p
    case DLL_PROCESS_DETACH: * u1 L' _; t/ H# }6 y6 y
           if(bHook) UnintallHook();  . a1 v! ~6 p2 g- T+ o3 w
          break; ) x$ s3 v4 c- v! g& [
  }
$ f2 k, e$ l9 O: V  return TRUE; # F. [3 x( {/ E7 q9 ~0 A
}
" K) O- H' O. sLRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
6 T: R9 A5 `7 Z. y{ / l' w4 x6 L* ^* g  @9 @4 m- c
   : }. y1 [6 T' ]( ~9 [& I
  return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
+ `: F( F( a: q& q/ P0 N}
6 j5 |! {5 g; VHOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数 3 ?7 L1 u6 H5 H& V3 c% [
{  - ~8 E2 v: P9 a* P: \* u$ B
  g_hinstDll=LoadLibrary("HookApi2.dll"); / n' ^9 t; f- C- S2 g
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
) T" I$ Q; m! V! h# M8 Uif (!g_hHook)
- O) s3 B: b4 M$ d  _( f7 W{
1 M* G$ B4 T+ d' y. y    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
: b% S& H' f% h3 O$ F    return(false); " h& O4 I2 y0 h3 s
  }
1 I1 _( h- h# m9 w0 h6 }1 Y  8 ]' ~* ~3 O! b/ u  E
      
7 t! o  c$ K' X- }6 g  return(true); 3 x7 h# ?2 N) I  y4 h/ P& l
}
& ?9 F! t* ?+ @- G' Q: T) t& VHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
0 @( ], ?6 y9 M{
3 _9 C- ^( P  l4 [3 R  
: Y' h' V0 D9 `  return(UnhookWindowsHookEx(g_hHook));
2 F; {6 W* T4 a0 j$ a' E7 W}
6 U; n/ ^: t  }! `! ZBOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令 $ z; q, Z/ z8 |+ z( u: O& n- {+ Y
{
6 c4 }) I# g, i& H  hModule=LoadLibrary("user32.dll"); ' T: H0 j$ Z8 m3 }
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); + |0 q, z4 W6 r+ E& E
  if(pfMessageBoxA==NULL)
3 c) d. J9 }9 f   return false;   x6 i3 S$ u0 w- ^( l
  _asm
2 ?. D' |' J1 P  {
8 t$ S1 U, P, a6 t, ?0 o- N    lea edi,OldMessageBoxACode
% Y. X; n/ u9 q7 a# h% M% E2 j    mov esi,pfMessageBoxA 8 g% t) F1 x$ q5 f( i, ^" k
    cld " v4 V! Z) g4 i4 R) n- \+ }" C+ z- x
    movsd " |$ K7 Z$ n' S3 l
    movsb - o8 N* E: T0 C- ?" X6 V: i4 O4 B. P9 l
  } & T0 Z" |5 l5 Z. v8 X
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 7 K4 G7 Q: M6 i5 H. l" {8 u9 Y
  _asm
; P9 z4 H' |: A, E! D/ x: [4 h% a) N  {
4 J% y- m; x3 {; I% b3 R    lea eax,MyMessageBoxA ! O7 ]( m* m8 ^
    mov ebx,pfMessageBoxA & W6 G4 [6 s! T" w! b6 }, `
    sub eax,ebx 3 s- t' c( g5 U8 R9 l
    sub eax,5 2 ?: Y* ?* B% i! V2 j! O
    mov dword ptr [NewMessageBoxACode+1],eax
6 a7 b" d1 G; `9 c8 o  }
; U, u2 L# c1 j' j  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID 5 D2 s) s% }. S! |
  dwIdOld=dwIdNew;
# a6 h+ t+ \% R! D' s* G: q  HookOn();//开始拦截 & X) M6 d3 \& r
  return(true);
6 B, v, i; ?" G" _} : P9 O! ]+ @7 R8 E) m& a( o
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数 0 J3 H* q# W, F- L8 |; q  J
{  ! j3 P/ Y. U1 J2 B% [- O8 k+ ?6 H
  int nReturn=0;   X$ s0 Q* j7 t+ t6 f* t
  HookOff(); 0 X8 `# T4 ~( d1 H4 \% W2 _) x
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);   [4 q" q( }, G' B
  HookOn(); . }" \! m% y! a* _: a, p
  return(nReturn);
: D) q+ {% e. [1 |! Z" l} 5 P& L0 Z8 v7 e5 O% z7 [$ K
void HookOn() ! E& m' T; d1 j6 g& N5 W8 b5 Q
{ ! u$ y3 J# h( ~% Q
  HANDLE hProc; . P) s/ |# }3 Y, h
  dwIdOld=dwIdNew;
/ J8 M- D7 ], m+ \  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄 0 |# `( y7 o8 K8 Q7 F5 p, q8 ^
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
: t+ O" ]4 R. W" E6 \  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA * \* x: H. i& w# o
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 : K/ r- ?+ c( P3 v( L0 h
  bHook=true; 5 ^( H/ s/ n8 B( c9 u) i
} - s/ n2 O) }9 n2 p4 y* A  a
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA % _( F9 S( [) l) w1 v5 j. J2 F7 \- T
{
9 c: z3 Y) z' E- w+ S; D  HANDLE hProc;
' c! _5 r( v) ~: @; W4 o/ f" e4 b  dwIdOld=dwIdNew;
7 o, ~# R6 y% j% e' i9 z  T  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); . b$ C/ n) C& B" ~0 H$ t
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
- B3 d. A! K4 h  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
5 e) x8 L( l6 d& F. n! q  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
, J2 D8 q  w( `9 y  bHook=false; 7 m- C6 y) U" {: O5 J6 ]: N; L( P
}
) q6 ]- c* R. X//测试文件:
5 _; E' f& B# @; ^! `4 _int APIENTRY WinMain(HINSTANCE hInstance,
5 G% o" T! X& |6 n1 L           HINSTANCE hPrevInstance, ) \4 z2 O. O1 v( x
           LPSTR   lpCmdLine, ) u8 u# P  V; O, `# Z0 _
           int    nCmdShow) 6 r  O& r1 l) y9 }; r. I
{
  |8 a9 O3 s9 [3 Q     O+ W# q6 H) ^; _9 L! h1 {
  if(!InstallHook()) 3 Y0 b4 U$ z4 W6 R
  {
' m3 `" U( [7 ^    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); % ~9 N8 @- k5 S2 ~3 t6 c
    return 1; 1 c9 ~6 N9 i7 W+ }
  } ) ], P+ Y/ J9 v
   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
2 A/ H; x2 F& |1 R2 Q5 L: J  if(!UninstallHook())
# n* ?7 t1 N" P& [7 o  {
! ]0 v7 q0 t& s7 _1 j6 v& F  Q8 [: O    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); 7 p5 V1 b) A+ {
    return 1; : D! D' b: K6 Z( _# U8 c
  } 8 ?3 @( t( N8 d3 {- t' G
  return 0;
# y, a! F) `# h* p$ n" Q} ( Y% O1 n6 `0 A: i0 f0 z
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

4 ~% |4 E4 U7 t
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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