下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

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

2 P8 }% q) p- t7 F发表日期:2003-10-30作者:tomh[] 出处:
1 K! k) f$ M  s" E/ F" V3 MApi拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 1 W6 p5 o/ N* P( s! `0 ^+ F2 B5 }
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, & ?# J( O" Z( U; N
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: - a  q/ {' r- z3 {' W
     BOOL VirtualProtectEx( ! z% W4 |* Z  K9 i! J- @7 Z2 O
                HANDLE hProcess,   // 要修改内存的进程句柄
* v( B- `3 w, Q8 ]; v0 H4 z( \                LPVOID lpAddress,  // 要修改内存的起始地址 , E. U( [/ P6 S5 i1 d
                DWORD dwSize,    // 修改内存的字节
- j" n/ I) X2 _% a- V                DWORD flNewProtect, // 修改后的内存属性 8 r4 `2 k3 ]  k9 P+ L$ a
                PDWORD lpflOldProtect // 修改前的内存属性的地址 ; D8 i  |; A1 p3 D
                );
2 M7 U+ @! u$ b. A    BOOL WriteProcessMemory(
9 H) {% r. V$ p& u! Y* ]                HANDLE hProcess, // 要写进程的句柄
- C1 m+ r" S7 f7 ^( \                LPVOID lpBaseAddress, // 写内存的起始地址
* d: x' \( ^  ]- |/ F6 ^                LPVOID lpBuffer, // 写入数据的地址 2 \( \, N2 z3 }& `. o0 Y1 ~% R! T1 u7 |
                DWORD nSize,   // 要写的字节数 ) G5 Y0 U. V1 }+ P7 b$ p3 U7 h  k
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
' z5 f8 k8 p& a1 K1 M                ); ! h$ E0 a. X, Z6 a) ?  d
    BOOL ReadProcessMemory(
8 i7 O' m" l- V% l, }# s% Y                HANDLE hProcess, // 要读进程的句柄 ; U" ~3 l/ i' W- z( |" e
                LPCVOID lpBaseAddress,  // 读内存的起始地址
. c" Y2 u3 @' ^; f! m                LPVOID lpBuffer, // 读入数据的地址 2 x% E! X& \( w+ {! |& u7 ]( v
                DWORD nSize,   // 要读入的字节数 7 p1 |' w8 I  ?" a& l
                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数
6 ~4 k1 L2 t2 }6 ?                ); 9 S- N! z7 i$ d4 `5 C, X
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同,
6 t8 t2 f( s; c, b( c- w' \因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: 9 `- Q. e2 f; e( ^' u: Z/ d
其中Dll文件为: - r2 [; X0 h7 ]
     HHOOK g_hHook; 6 V/ r  Y5 \9 d7 r: o8 U+ x. K5 L* O
     HINSTANCE g_hinstDll; 2 u/ m& Z9 U# S6 a, G" z4 B& Y+ Q
     FARPROC pfMessageBoxA; & R/ f! P- N; r# F# P
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); 9 F* J) i4 f% y6 x" {  e. M
     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; 2 q; Z2 X/ \# ]1 n  h7 k
     HMODULE hModule ;
* D3 o4 v: q! V4 f" T     DWORD dwIdOld,dwIdNew; , T% X7 j1 M1 D3 X' Y* |
     BOOL bHook=false;
# m+ J2 q" N; R8 k     void HookOn(); 0 d" u- T8 H  j. m* x
     void HookOff();
* n) s+ F! W, p     BOOL init();
3 r( i3 V" o2 d9 ULRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam); - I, W  u# n5 W4 _
BOOL APIENTRY DllMain( HANDLE hModule, + s" B$ f  N3 A. r
            DWORD ul_reason_for_call, ; p9 Y* B% l5 H4 }! N
            LPVOID lpReserved 9 t1 G( z, [' D  P2 y( w+ @7 ~
           ) ) a" M$ h' O9 b# C8 r" Y
{
  d' G9 }. c+ u8 o; s1 P  switch (ul_reason_for_call)
# O4 s% g" m9 {1 z' j  { # K' Y+ z+ h- s6 I1 D% a& D
    case DLL_PROCESS_ATTACH: " j- J4 r( H* H7 D; D6 s
      if(!init()) 5 G+ x" c+ W& z3 j/ ^2 t+ l  E
      {
+ ~, s! e5 H' C             MessageBoxA(NULL,"Init","ERROR",MB_OK);
1 `. H( W( z# Z) C$ x3 A             return(false);
, I: M, Q7 Y' ^* E      } ! o5 V8 h  o7 _# Y6 J
    case DLL_THREAD_ATTACH: ; W& v  I  }" c/ \/ y9 r" t7 s" V% h
    case DLL_THREAD_DETACH:
5 n5 j" ~& |* f/ j6 M% T    case DLL_PROCESS_DETACH: ' |9 T1 [2 m2 f& p7 B6 K+ `6 d& |0 }* c
           if(bHook) UnintallHook();  4 s4 G) {) y) N& X* I1 ~
          break; 6 i9 w/ U& g$ u+ @
  } ! Y! S; h/ V- N6 c* `
  return TRUE;
4 `  B" Q* N  \$ ~! _}
8 a/ c5 s9 g7 [0 tLRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 : n, M4 O" D8 ?3 E& \+ K% k
{ % U5 k1 f- _0 v8 C
   5 b! o# w" R: G; U4 S
  return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
# D8 |, h6 H" X3 g0 R( I( I} : I2 g. w& Z0 v) q- o
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数 6 G, N: z! m% `1 O! O0 R
{  : j! D' l) B6 H: h- Z
  g_hinstDll=LoadLibrary("HookApi2.dll");
; ]1 e" r. U* r6 ]" n/ Y& {9 V  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0); 0 \1 |9 Z5 o: ]# `
if (!g_hHook) ! L0 E( }. ~+ v
{ 6 k6 q$ i. h/ a% i+ {
    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK); : y5 O. q0 \% D0 B
    return(false); + V6 @  x& W. t8 t9 R
  } * p1 V  g5 Q1 f5 s2 R
  
+ r: Z  B0 Y. V% X) G/ O+ ~      ; s5 ~  m( M1 L; |+ @, O
  return(true); 3 w- b, m0 Q- k, o0 j+ j
}
7 p$ w& T% g$ F* z3 kHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
( U. H9 e0 l6 Z  F/ l{
8 E' L9 v/ n* J: V" `0 `5 [  
( n3 _. u, @! Y* A  return(UnhookWindowsHookEx(g_hHook));
* K$ s$ K4 k+ i* N$ m} ! H- ]! u: Y0 T
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
6 A" l+ C2 D0 z{ " o  E0 C* f! V8 e" k
  hModule=LoadLibrary("user32.dll");
2 x: a- `( g4 Q, f  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
( i0 x0 I/ l0 r& M1 j) u  if(pfMessageBoxA==NULL)
3 d0 ~) ^! |% ~2 }: K1 t* {) l   return false; % B. X8 P' z5 B1 _
  _asm
9 j4 S. G8 _' n# e& C9 V  {
0 B4 B0 S$ N/ R; W    lea edi,OldMessageBoxACode & Z$ Q( O/ y8 Z4 `1 n& q
    mov esi,pfMessageBoxA
( d( Z, h* M" L' q+ ^2 o# v    cld + j% X- K; c' `  D8 ]2 C; Q
    movsd 6 E: f0 Z2 m; Y1 j" U& X* M
    movsb . l9 x+ z8 R; S8 {" n) o3 f& Z& n
  } / O7 q9 z( h) u9 j
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 2 s2 y$ _# R& D
  _asm 3 r5 ], n' s* l/ p- W
  { + j: e' R2 D9 [
    lea eax,MyMessageBoxA
5 o1 ]$ {' x. z' m0 w    mov ebx,pfMessageBoxA 4 l; x; l0 U" {0 b9 B6 n
    sub eax,ebx + `! M% k: J  S. F9 M
    sub eax,5
3 B$ `9 K6 m6 W6 e) _3 l    mov dword ptr [NewMessageBoxACode+1],eax ; \# u, c( F0 V; T5 e0 X
  }
: {, }" V1 a) a# e  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
( b! {8 p; L: f" h  dwIdOld=dwIdNew; 8 h/ M& Y$ S7 ]* V: z7 L1 ~
  HookOn();//开始拦截
2 H. [9 l! g7 T8 r  return(true); # s2 k  [, v6 [) ~' }, ^7 o
}
; u% L/ t; O3 o; \4 i" {int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数 5 @% D' D- O% M7 g( X9 C) F9 \/ t. |
{  ! y% [$ x$ k! z* x, @& m# w' f9 Z/ R
  int nReturn=0; 4 S/ h% C- c$ q$ g. U
  HookOff(); ! x2 Z( o- ^4 ]; @- x  K
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); 8 `) s' y, W5 l0 c9 b
  HookOn();
  {* `9 ]" Q- s  return(nReturn);
9 Z# K8 ?8 _  u' i* ?* y6 Z5 Z} % `6 m7 P: t  m: w" f! l
void HookOn()
/ h: `7 Y" R/ F; d3 ?- r/ d{ , L, n, A+ V. O+ T5 \
  HANDLE hProc;
% b4 H; V$ V  Z1 y7 ~4 M% R  dwIdOld=dwIdNew; 5 S3 ?, ^( _$ i8 r0 D
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄 % G! h0 k# T2 Q" Y
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 & z) a- r$ M4 [- t$ E- r# Q# |) g6 T+ @
  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA / R5 T4 j" y/ T' u1 V) T% f
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 2 `/ l) E' o) X( q, j
  bHook=true;
) c! N/ y- c# k0 }) S( ]}
2 {4 O7 z5 H" z! Ovoid HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA 5 b8 H8 \+ H9 G/ z+ u
{
) U( [* ?- [$ j1 L; A% o3 }  HANDLE hProc; ) }: B% }6 |  }
  dwIdOld=dwIdNew; " l- ~8 S4 d# H  R4 ?- u0 D
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); 7 m+ }* Q/ C% [  t  \3 Q
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
1 [, q( T. q$ g4 x) o, l  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); ' j3 I( J& Y, ?( w. N2 u7 Q
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); : ]1 x! K# ~# D$ h
  bHook=false;
: {/ o* G9 g. Y; u5 h9 \/ g}
! O8 t3 [+ p7 a$ a2 C2 G//测试文件: * d* s5 v" ]( l& r
int APIENTRY WinMain(HINSTANCE hInstance, , L, G7 E0 }6 Q1 l  O) w
           HINSTANCE hPrevInstance,
1 C+ E' q# L/ S8 z) b3 G6 p           LPSTR   lpCmdLine,
1 k5 X# b7 U1 F- U+ l: L: m4 p           int    nCmdShow) % F* z) A6 _3 H2 ~# r# K. A4 F
{ . l7 i$ j; i. S  s/ R# N
   
9 G1 N3 n1 X+ T) E$ `& H- g4 O  if(!InstallHook())
" V4 s3 ?8 ~7 v' i3 a, `' I  {
. @' g! G# a5 b8 V+ h! X6 d* e    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
. S0 q3 V- c3 L/ F    return 1;
: p6 n8 k+ F7 O, D- h  }
9 b2 V+ w" G0 C$ j- O   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 % g! W0 C% c) E+ O7 U* X, P3 p
  if(!UninstallHook())
( D- j, O/ i+ o0 @6 \) s1 p  {
. }, L% F, ~6 p' D    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); ( d# w7 _( l) S( p; Q
    return 1;
1 b9 e$ ]- B" ?; ?" [  } 3 O; _" o4 l1 q
  return 0;
9 d/ F7 a; ?4 O* j# P6 f% e}
* u2 X" _9 h) |9 @3 K7 e
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

2 F. H  {# k- y7 G. X8 j4 h% c
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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