下沙论坛

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

用新浪微博连接

一步搞定

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

跳转到指定楼层
1
发表于 2004-11-5 18:09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
& D  q1 f8 b& }# f! S2 z' q
发表日期:2003-10-30作者:tomh[] 出处:
$ T6 V. V: T* p( e* pApi拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 ; h) G: X* H; r
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, 0 @$ e& o# q" t
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: . O, K) p8 A+ E2 C
     BOOL VirtualProtectEx( ) |+ m# Q3 ^' F9 I
                HANDLE hProcess,   // 要修改内存的进程句柄
8 l4 V+ D6 i+ x  s; G, g4 I7 s                LPVOID lpAddress,  // 要修改内存的起始地址
2 \- N1 ?% f+ I9 j' L1 ]                DWORD dwSize,    // 修改内存的字节
3 G) @3 E4 ~( l$ a- w; r/ t% N0 y                DWORD flNewProtect, // 修改后的内存属性
, v4 ~0 k, E; z, i. U7 d+ l                PDWORD lpflOldProtect // 修改前的内存属性的地址
/ j( V  Z8 m+ P2 C' {; Q0 @! T) }- V9 J                );
+ R" D3 l' N, d# _9 ~  w    BOOL WriteProcessMemory( & x8 _2 t1 W8 y! ?2 }
                HANDLE hProcess, // 要写进程的句柄
' G" [. d+ H  G: M$ _! ?                LPVOID lpBaseAddress, // 写内存的起始地址 3 K- v9 X# ]' J1 L  m8 ~
                LPVOID lpBuffer, // 写入数据的地址
1 `* g) C# ?" b. F4 J/ F                DWORD nSize,   // 要写的字节数 1 v; e7 f& t- n% j; X
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
+ y, v( q. e& a  ]2 b" f& Q                );
% u2 C0 f! n, K& |2 x    BOOL ReadProcessMemory( " v3 e; T% z; w% Z7 {& C# c
                HANDLE hProcess, // 要读进程的句柄
( g; T1 |, H: K. a                LPCVOID lpBaseAddress,  // 读内存的起始地址
+ m% `0 F: d9 `' j                LPVOID lpBuffer, // 读入数据的地址
. S0 S, t/ d! p$ h7 ~, y3 N7 M. b                DWORD nSize,   // 要读入的字节数 5 s  z! r1 Y5 ]  B0 V
                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数 3 ]2 W2 Y2 ]& z7 l% f9 g
                );
5 A; |) Y& x& r, n  D! k具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, 3 n/ M0 ?" s. @8 ?( ~5 a$ F
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明:
: R, s+ Z. h$ \& F其中Dll文件为:   H. m) _1 Z2 E& M* U) S2 a  t
     HHOOK g_hHook; ! S. F, R( i: j6 Q/ O4 a- j8 D) Y+ P
     HINSTANCE g_hinstDll; . k( ~. G1 x2 X' v* m
     FARPROC pfMessageBoxA; $ Y/ P, ~8 Q/ m3 E; t$ R' b1 S
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); 9 w2 n# F) f6 A' K/ r4 @7 R
     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
2 Z& j9 {& K# \' b     HMODULE hModule ;
! K3 U8 U) @" ]4 E  e     DWORD dwIdOld,dwIdNew; 5 v0 M0 }$ q3 U
     BOOL bHook=false;
; c3 `3 s% G1 i7 y+ f2 u* F     void HookOn();   I6 u, {+ i# v
     void HookOff(); ( s! T" m) {+ u% E( `6 v
     BOOL init();
/ f( T" |/ G/ x6 t- c1 A( E6 F  |) YLRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
! t6 P3 N: d* n! F3 v: L) eBOOL APIENTRY DllMain( HANDLE hModule, ' a1 M2 b* l1 ]6 O3 y  k# z5 e
            DWORD ul_reason_for_call,
" v9 d, B7 n0 l+ `            LPVOID lpReserved
2 D) j2 M  l% h  D- E" ^. I" G9 r           ) % {3 ]9 l( i8 q' c3 \. R
{
$ l. H6 t$ ]- y! C1 l3 H9 z; D  switch (ul_reason_for_call) : r& {7 s) W1 j  j
  {   m& z& w2 N- }( U  i8 H' V" v
    case DLL_PROCESS_ATTACH: + R/ u( p8 Q% v- p4 i0 c/ A9 c
      if(!init())   G# c8 ^7 g2 H- t+ H
      { % e7 M% m3 W" p: |5 k+ D
             MessageBoxA(NULL,"Init","ERROR",MB_OK); 9 \8 z' M# B9 ~: r1 H  F
             return(false);
3 n3 Z; w( Y1 n# m2 V! ]$ K      }
6 ?' v8 s: t5 L" @# v    case DLL_THREAD_ATTACH: . v: W% ?* P- n9 i) K; b
    case DLL_THREAD_DETACH:
1 j6 R! A  A9 I9 T    case DLL_PROCESS_DETACH:
3 c. q& W. n5 p           if(bHook) UnintallHook();  $ `7 _; A$ r. T9 F) J4 J6 z3 `7 _, N
          break; ' x5 s0 E8 z" P& a( f5 x/ q
  } + V- \9 `5 ?( B0 X) a5 q) `  f
  return TRUE; . R! ]+ T) c0 M. L! S; Q5 l
} 1 p6 w2 G" s3 m, @
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 : p8 ]6 m# e1 k4 z" w: q4 e7 b
{
: R- H) ]) j) {; R- k1 {( r   
( m+ Z. e  U4 M  G7 O: x7 q  return(CallNextHookEx(g_hHook,nCode,wParam,lParam)); " L; x! Z) ^# F( |3 T
}   u  }0 V. g, \+ ?/ ^' m3 ?
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
" U3 {$ E* ~3 ?6 o$ ?) w{  & e8 _; |) p/ d6 Q7 d1 ~
  g_hinstDll=LoadLibrary("HookApi2.dll");
& r- C7 N$ y# t: G4 J) g# M  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
, p  M2 c" Z8 R: N. q* r# Wif (!g_hHook)
5 U  b. A$ h7 ~- B# P{ # W& m) ?( X' |7 p; ]/ Z4 S; O0 ^
    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
8 U8 ^4 x5 d- r$ k, J9 g    return(false);
$ J1 c# `+ Z, B* p2 A  } + P8 o. @0 f" P6 c2 F
  / k8 @1 C$ a# R: i7 W  {: }1 Z
      
( @) i- R/ f$ C; s/ h  return(true);
0 Y5 g. d( X1 s' e}
8 d0 ~  `& z8 U: h3 FHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数   I! x9 @6 w5 B. f
{
) {' c  P# c, ]. d2 S  
4 P' d+ w4 u' S0 Z/ |4 Q  j( c  return(UnhookWindowsHookEx(g_hHook));
1 {8 p% H; ?" j9 s1 `& \; t% O} + I5 R9 Z" M! |! ~% X
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
; N8 T& E& h2 H# u3 h{
* u: Z+ K9 c+ K4 C" s. W  hModule=LoadLibrary("user32.dll");
3 z; d# m  \# ~  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); 1 ]: o' M' f) y+ b5 G
  if(pfMessageBoxA==NULL)
$ d) E& N% P6 W2 N' Q9 @1 m1 O& w   return false; ! {4 d3 u+ R( {* ?' f/ b) v
  _asm
/ j" U: O& h1 {$ V  {
7 {0 x) B$ v/ S    lea edi,OldMessageBoxACode ) L2 y& y9 I7 j
    mov esi,pfMessageBoxA
1 @0 g; d4 D; u1 [9 h; H    cld
5 M0 _! X% g" D    movsd
- \! @8 s# r# ]- p) ^" {) @    movsb + B* g1 f+ _% G
  } 5 E' I7 z- l" J4 Q, Z' p; z2 t
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 + M  N  s5 J  k
  _asm
4 ]/ t6 L! r4 I& M6 a4 _+ g4 h  {
! N7 E, k5 w1 a) C# i# y6 R    lea eax,MyMessageBoxA 3 Y& P3 d7 t: k3 i( G
    mov ebx,pfMessageBoxA 3 v* x) \2 b& N! M5 J
    sub eax,ebx # f$ l. {0 V* S7 Y5 ]% A
    sub eax,5 # f3 J$ M% U- e. Z1 a
    mov dword ptr [NewMessageBoxACode+1],eax . \' X1 g; L) ~. @4 y
  } ; M( t6 Y" H4 S! Y
  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID ( V: @/ K: ?7 l: h8 T  r) p6 J  @* j
  dwIdOld=dwIdNew; 1 i4 O' t; d6 y: U7 U
  HookOn();//开始拦截
/ Q* \- [) o& ?* j; e/ H  return(true);
' m1 y8 W4 {' [7 K$ E* w} , ]: U  T' e$ h( u5 d
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数 4 z! _$ B* |/ A! X+ z* c
{  8 A3 M' K. {! y
  int nReturn=0;   }& ~0 F1 t! s0 y
  HookOff();
" F' l3 [2 d& Y1 a6 B+ G  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
9 g0 ], d2 X: d( \) j6 d  HookOn();
* A9 z; p( G' C/ D; j( v. _  return(nReturn);
1 J. p8 t9 y$ i- k: x% w; ]} / U8 P' B) M  b$ ^! E
void HookOn()
+ q0 q, \$ G- `0 a: d% r{
7 P0 m4 o! j! f! y* H  HANDLE hProc;
0 B( Q2 Y' w0 \  dwIdOld=dwIdNew; * u8 B+ J! V0 X. ~) a
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
9 c6 t# w5 ^$ M" N) R, ^4 E  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 5 _- o, s6 S) @" y3 e# d; ?$ x
  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA 8 R4 w7 p7 A5 K* U, n) q5 k1 J
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 ' W# j- z$ j  u
  bHook=true;
0 b) H+ H% k" I: a: q3 f} # S  ?; O* ~! I/ i3 ~0 N. V  c
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA 6 u- w5 m; g# I' y0 B5 [
{
3 I# m7 |% k* V! v  c  HANDLE hProc; 6 R/ P. h& S  _8 d
  dwIdOld=dwIdNew; . w) |* f4 }7 W+ `8 m$ g7 h
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); # b, j- Y. h$ }; Z. {, Q3 X6 f% }
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
. E( i2 [( M. b  I1 h  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
" H' ?) K  P$ p0 ]6 H1 R  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
/ {* D6 e* Z7 I: V6 {5 i$ k  bHook=false;
5 X6 m$ }% A" d8 p% {7 ]# X}
/ k2 T' O1 P- p  j/ S//测试文件:
* G7 z2 X# H6 E6 wint APIENTRY WinMain(HINSTANCE hInstance,
& l* E3 k/ ?- B           HINSTANCE hPrevInstance, 4 g- k0 `4 A' l8 k0 n1 P
           LPSTR   lpCmdLine, . L  ~6 I" s* y2 S
           int    nCmdShow) - |. ~6 N- F* Q: B2 u( D! N
{ + G( E6 Y& |( C7 q1 [+ T5 B
   # `! V4 \0 W6 {; g3 n. \: J4 ]; s
  if(!InstallHook())
# n0 }/ s" b5 k- ~" O1 _# _  {
) o( A! f. a( v, f$ e* f    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); * f6 a2 p4 n5 c% o* |; p3 T
    return 1;
& `/ H# ]/ J+ e7 V/ b  l8 E  }
- d! }; H' J% g6 r9 L1 E" G! ?   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见   k+ Y9 C  ]3 k3 c0 N8 _
  if(!UninstallHook())
& E# I9 j  X1 _  {
0 ~  D# V: G- Q. A2 ?    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK);
1 `8 E$ [. P5 p6 o    return 1;
: d; q0 R; B7 q- h3 R; O  } 2 K3 R/ B' ]$ n. ?: I% q8 w0 q
  return 0;
/ D# Z( u, g! [) Y3 d}
# \* l, @) \5 V% O
[此贴子已经被作者于2004-11-5 18:12:27编辑过]
( |9 z3 d- z* L' V$ I* J* d
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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