下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

跳转到指定楼层
1
发表于 2004-11-5 18:09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
3 D# x( Q& I( t
发表日期:2003-10-30作者:tomh[] 出处:
- j6 f0 P3 M$ N2 c4 U# qApi拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。
; n) B3 R4 `* a9 J9 T( e  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现,
8 g: D$ A. v. H其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: 3 \0 u( O2 m8 v0 W, |2 v; G- f% x9 L
     BOOL VirtualProtectEx( / P1 Q' f( C4 c+ Q2 t+ m; N, l
                HANDLE hProcess,   // 要修改内存的进程句柄 & `" m6 U* h1 ?" H/ C* c
                LPVOID lpAddress,  // 要修改内存的起始地址
0 U9 \. F2 D' _9 G" F                DWORD dwSize,    // 修改内存的字节
8 P+ G) {! `3 N# }& o* g                DWORD flNewProtect, // 修改后的内存属性
7 u" ^  d- V: ?' k                PDWORD lpflOldProtect // 修改前的内存属性的地址
/ W8 l# N2 P0 ^2 }                );
5 e; i! r6 M5 R" ^    BOOL WriteProcessMemory(
2 f, Y* a$ E# m$ S  R, N                HANDLE hProcess, // 要写进程的句柄 5 d2 I5 W6 A% f/ P1 R! h8 k+ `+ C
                LPVOID lpBaseAddress, // 写内存的起始地址
' W1 O* J1 `1 \9 Q5 [* ]) g- X9 z                LPVOID lpBuffer, // 写入数据的地址
: Q7 _2 H4 p+ ^; f, D/ U                DWORD nSize,   // 要写的字节数
* Q- o  D3 d: q9 x% I                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 % e/ S  B! I- g* V9 L; B
                ); + m) T$ i  }: ^5 h) ]5 S
    BOOL ReadProcessMemory(
  o! W  I- q  b  c4 r                HANDLE hProcess, // 要读进程的句柄 ' b8 r' d0 D4 Q* a5 K4 z
                LPCVOID lpBaseAddress,  // 读内存的起始地址 , ?, W/ k) M0 H
                LPVOID lpBuffer, // 读入数据的地址 + a* Y) ~) ?6 }$ K
                DWORD nSize,   // 要读入的字节数
9 x* J" w0 ]/ \* a( A4 q                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数 & v; d- G: ?! V) V- E. b& k) X* j( N
                ); 5 \2 D* `7 M7 ^# F+ i2 O! ]
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, 0 }3 U6 p6 p  @- W
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: ) K  o4 \7 t; I: b; n
其中Dll文件为:
4 l) D7 B* @& N( w1 q     HHOOK g_hHook; ) y' `( D6 L7 N( f. r& ]
     HINSTANCE g_hinstDll; 2 q' w+ P# }! V0 B8 V+ z
     FARPROC pfMessageBoxA;
: S3 t  l: s  o     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
: H8 e- i7 a9 b% z: f     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; # d; [5 E  F! y0 Z9 g) ^( l  ]
     HMODULE hModule ; ( T9 q% T, |2 p, l7 N- F9 O, i! d
     DWORD dwIdOld,dwIdNew;
' v1 o. d) J5 ]& n6 _0 F5 M     BOOL bHook=false;
5 Z, `4 P' O! p9 R+ s$ \% W8 G6 Z     void HookOn();
% V& E2 z1 q; P/ U$ H  b& f2 k7 O1 d     void HookOff();
2 l& p  ?8 |, E+ Z     BOOL init();
0 x/ W9 r& u& r4 \6 rLRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam); ) i6 |0 P0 ?; i5 v0 H. }
BOOL APIENTRY DllMain( HANDLE hModule, ; t8 k" d1 R" J% y3 q  x
            DWORD ul_reason_for_call, 7 F. G8 c& [) F' f
            LPVOID lpReserved
$ G" |7 ~9 {/ Y  ]$ O) o3 s           ) ! C9 D. l! ^' X6 ^
{
% c& g- H$ |) p, B* l) {2 E4 S* J# P  switch (ul_reason_for_call)
' u2 T0 d2 t. E9 k  { 6 B+ j/ f, R+ j- G' `
    case DLL_PROCESS_ATTACH: & g9 t0 I) C$ X+ N" _; i, `+ K+ J6 G. |
      if(!init()) 1 \& L. Z2 v6 n, e' c
      {
- M6 }" ?/ T- w6 A% a; p             MessageBoxA(NULL,"Init","ERROR",MB_OK); * d+ `8 {- ]5 \: q
             return(false); # n2 J" y1 G) {  I
      } 3 v. N. B5 e  q2 p
    case DLL_THREAD_ATTACH:
* T( c# F( M' U    case DLL_THREAD_DETACH:
6 j5 p) V8 Q  }    case DLL_PROCESS_DETACH:
) C" i( E; w. F( x; c' }8 c6 ]           if(bHook) UnintallHook();  
0 h8 K$ ?% s0 V0 W+ S9 g          break; 2 f" j, S6 r: Q' a0 @
  }
4 ]* k9 E8 d( p5 c. @$ t  return TRUE;
1 B* B! o9 X9 O* s: w/ D2 ~}
  }4 B( a' C# R  F, WLRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 9 p  z* K8 d: x& R" O( J6 k
{ ' ]4 w3 [; z/ X; m: b7 A) ]. b
   % v4 ]  d: B5 }2 F* D
  return(CallNextHookEx(g_hHook,nCode,wParam,lParam)); ' k- G) U, h2 N
} , E5 F* a: R; ]1 R, C4 r* c
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数 ) ?1 B. k# n$ g, r) S& d: y, L
{  
9 R( O9 @. E- B' |5 S  g_hinstDll=LoadLibrary("HookApi2.dll");
0 E# F1 Z7 |' u1 x: ~  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
( I( z1 S( M% D! j/ R  zif (!g_hHook) 4 k" X- E  J# \. Y! {
{ $ t: x& s* k5 u- ~. r. q# s
    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
5 j, m; N4 {0 K  J& Y    return(false); . G- C0 @+ q- ^. F* F2 P4 ~! g! v
  } 8 g, |" P, F; V6 T  A6 Q/ z* k
  9 \  W2 z$ `. T7 C; O5 |
      , L  i8 X) w  t8 k
  return(true);
: u, \$ ], g" V& \: L, I' U} 8 j) {) e& x' k6 C; G7 }
HOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
/ M8 k+ }; a. E* A% X4 ]{
! f4 z) N( W3 d* O0 S  e! W  
' j1 F* p: a" t  return(UnhookWindowsHookEx(g_hHook)); 7 d+ s" v1 B* {4 u( E* I) v0 A
}
8 m" e2 z% \, }% GBOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令 ! u  d/ d4 m5 H$ e# _" J
{
- k& G: f8 l% @. j9 Y3 U  hModule=LoadLibrary("user32.dll"); 6 k! o# v# J/ Z& I' g& o- }
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
) v. k3 g! ]: L* k3 c, Y; h3 Y  if(pfMessageBoxA==NULL)
1 k! w. b" S  [% x. p% }   return false;
+ h# ?  O* W5 w: M  _asm
/ C: p' {/ c6 y, n. M6 j( {( g  {
8 S: E- X; T; |' T/ m    lea edi,OldMessageBoxACode
' h3 R* ]8 F( B8 I! `    mov esi,pfMessageBoxA . v) e8 {. I: r2 T
    cld 6 F/ I  z" s% K
    movsd
8 Q' t, E# l; i9 J/ H    movsb - \& ^9 O9 [* f
  } , e+ ~) T2 X9 n0 J1 b
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
4 e/ E4 Z6 Z  p. v  _asm + v0 E* f+ e- n7 C; q7 s- Y
  {
" [, H; a+ @: |% |3 D    lea eax,MyMessageBoxA
; Q1 t* |& W6 [  w$ L$ o4 {/ b    mov ebx,pfMessageBoxA 6 r% l: L& k+ ?
    sub eax,ebx
9 q  Z8 T/ w+ B! [& w, b    sub eax,5 # L  ~" r( |* a
    mov dword ptr [NewMessageBoxACode+1],eax
$ Z9 L0 V8 f$ `! ^8 n# X. I) }8 `  }
9 h+ \/ ~' r  C. H  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID / F, @# a/ O) M! ?
  dwIdOld=dwIdNew;
6 e, m: I( Q6 U7 \' N& h" a  HookOn();//开始拦截
+ E% F3 a0 v* q, Y5 ^; E0 ^  return(true);
* H* [+ [4 u! n7 U8 s% W2 x; W! o} % I9 \( M2 _% u& I- s
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
% y3 x% M) C/ y{  2 @: `- U2 g+ d0 C* J
  int nReturn=0;
; _& ~7 N$ ]) c, P$ P  HookOff();
8 `: f  |* h' `7 p  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); ! Z- a# _1 C) s1 _. K; X. P; k
  HookOn(); + N- U. G! [- I1 E
  return(nReturn);
) K, g6 E. ^/ s" ^; E4 F}
8 n5 y, p; C0 e  G) R* O7 dvoid HookOn()
+ \% S$ y( }6 M0 G! i{ 4 X1 ]& [, U/ ^
  HANDLE hProc;
, g1 s5 Q/ p* E$ F$ o; f" f  dwIdOld=dwIdNew;
6 o  n7 _# F6 i, [  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄 ; B2 e' W# ^9 A; }$ Y
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 - V+ |! \! P! @. s, `
  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA ! A. l5 W8 P& ~3 s  S; n/ e. ]
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 : d2 O* p. T9 m7 D7 E
  bHook=true;
# D* G$ p3 {; x# A" E6 A} 2 d/ ?" A$ z) L. ?7 n7 z3 L! K* w# K  u
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA % m+ f0 G: H. m$ z
{
+ I4 A5 X7 k; z' M  HANDLE hProc; , g! e% h+ \! C5 X: |& e+ K
  dwIdOld=dwIdNew;
$ J  a9 K& U) R* ~0 m0 C4 y  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); ! }* K. _2 W8 |0 u! ]
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld); 7 e7 N  @" }! T- I3 T* t
  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
% Q" n+ |: G* l: R: D( Z1 c  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
; i4 A0 u& \+ M( x5 S- b  bHook=false; 9 ~% T) ]4 B: \
} # w0 a/ d) G, G1 o: F
//测试文件:
. A. o- P7 q( o+ t/ zint APIENTRY WinMain(HINSTANCE hInstance, . u, M8 a- P% M  N5 D9 W6 M* ^1 K3 x
           HINSTANCE hPrevInstance, 5 l$ C+ I+ G7 `2 U
           LPSTR   lpCmdLine, 3 Y  E* c! q$ \% V, D$ `) C; O
           int    nCmdShow)
: v- B: o4 m( ^5 {8 ?8 }{ / K3 H& a" m3 o& s  s
   
0 t3 s# j( F, Q  if(!InstallHook())
# W6 T) e0 {6 T8 N6 K. T+ e  {
0 m' C) j' _& Z7 }    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); - |. z! e( G5 d( Z' {5 T' M  w1 H; s
    return 1;
6 r% ]- j$ d8 y* A3 k3 {! @  }
7 p5 Y3 [' M( N/ z" m* a* l   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 5 H: E5 h9 G; T! K
  if(!UninstallHook()) 5 I  G+ H* d/ w3 r% v
  { 8 {- _; R- ?% N, f8 \- C
    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK);
( o, }0 E5 A5 ?    return 1; 7 z$ J6 t3 x5 X& I3 X& B
  }
: l. f8 ]* f0 x  Z  return 0;
! ^+ {- s2 j' j6 }' m}
$ @. ]  n6 `  j! c+ {7 }
[此贴子已经被作者于2004-11-5 18:12:27编辑过]
! B/ i6 S% G8 H% V5 \4 {2 @
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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