下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

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

' g$ e$ z; w, b; c$ a3 R- P发表日期:2003-10-30作者:tomh[] 出处:
1 g/ }, V' k% i0 UApi拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。
: X4 Z" X/ ~. ?4 ^7 I  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, . }% e+ j* [! L3 K5 d# C
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: - B# T1 m  R% B, F  p9 V% O) |
     BOOL VirtualProtectEx( ' ~! t& H0 u( j, {5 [
                HANDLE hProcess,   // 要修改内存的进程句柄
1 j2 f, e' Z* p& G3 B                LPVOID lpAddress,  // 要修改内存的起始地址 ! E, D3 Y" ~' \& ~7 ]% l, l  t
                DWORD dwSize,    // 修改内存的字节 ; Z) {0 x. A" R+ F
                DWORD flNewProtect, // 修改后的内存属性
/ N9 B' z# N( T' d' ^) t7 i  W                PDWORD lpflOldProtect // 修改前的内存属性的地址
( |% ^& B8 I% @0 J9 ?5 |. M" l" b                ); / ?: w; K  O5 A7 s9 O  t
    BOOL WriteProcessMemory(
' p  R, u6 ?! z                HANDLE hProcess, // 要写进程的句柄
% Y7 K2 l7 k7 z* g: g" @                LPVOID lpBaseAddress, // 写内存的起始地址
' Q% ^- t. a$ `5 g# x7 G; W                LPVOID lpBuffer, // 写入数据的地址 " c  ?% l7 g  T6 E5 v& M
                DWORD nSize,   // 要写的字节数
( F/ @% C& i7 F( c6 n! i5 J                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
: s% Q# i/ ]3 W7 B% c5 U                );   u0 p  G( u+ @! k% H
    BOOL ReadProcessMemory(
4 o% S2 O6 D% Y7 E0 q                HANDLE hProcess, // 要读进程的句柄
, u/ U! e& [8 A9 Z                LPCVOID lpBaseAddress,  // 读内存的起始地址 ' h, S% }( g! `! y3 I: N
                LPVOID lpBuffer, // 读入数据的地址
; ]; o3 B: g% W- p# G5 [: ?                DWORD nSize,   // 要读入的字节数 ' R, G8 Y4 _9 H0 o( H
                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数 / D6 G; y1 F1 Z- O4 |
                );
# p5 S+ @' P# K  I7 H( n具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同,
  b. S+ n* w, f6 W8 g& K因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: 5 u" C+ [' _4 s$ ~& R$ v
其中Dll文件为: ' Z  g" `% z" [& o2 e  Z7 G3 ?
     HHOOK g_hHook; - M9 V9 O( h! o( e1 m6 c/ K1 [! @
     HINSTANCE g_hinstDll; " ]4 m: j' [) ?" q. H- M: l- U
     FARPROC pfMessageBoxA; . P8 J/ W+ m& ~# e, T, s5 ?
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); 4 _" F' d3 ^  d; @1 Y8 |# x" U) b' ?
     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
( I# w7 ^* M* b1 r5 F6 m     HMODULE hModule ;
, B6 F, K4 G! L+ M# _8 b     DWORD dwIdOld,dwIdNew;
* \+ K" p! ^& g* ^! T2 M     BOOL bHook=false;
1 t2 a1 s/ C3 s' ]+ I     void HookOn();
+ P: k6 ]  Q/ Y     void HookOff();
8 B3 b1 G, ~9 |; k- h     BOOL init(); - U. A0 P- d+ I/ V' U% ~" N
LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
& u7 h+ ?; [, J2 A" w/ DBOOL APIENTRY DllMain( HANDLE hModule,
, }- O/ p( J/ B2 p, F0 u            DWORD ul_reason_for_call,
6 A: {/ l8 G9 ]" v0 w" S            LPVOID lpReserved
6 s- h: v3 X3 h: R           )
' w6 }# i9 j$ K; Z# x+ y{
; N4 U8 }. N, N6 q% A+ e0 L$ C  switch (ul_reason_for_call) + S4 n, q" P8 G4 n
  {
7 m8 Y1 t6 k" ?4 o9 O, r    case DLL_PROCESS_ATTACH: " p9 X. d0 c$ H8 o  X- \% ?
      if(!init()) 5 x. V2 ]$ W4 a! t* ?5 a5 `
      { 6 U" S; k/ z7 S1 f
             MessageBoxA(NULL,"Init","ERROR",MB_OK);
/ c" c7 I7 M( E% \& M8 y             return(false);
7 ^+ \2 n; [$ r1 [. O! k. [. ~. ~      }
) {/ Z- K/ `5 B2 }$ k8 K2 w# v* K    case DLL_THREAD_ATTACH: ' ^( s: }# m7 t, G5 P: h3 I+ E
    case DLL_THREAD_DETACH: . f; W# F; i* ~
    case DLL_PROCESS_DETACH: ! X4 g' u( {6 M' `$ J
           if(bHook) UnintallHook();  ! ~2 ~& v- q0 c0 h- i  }9 }1 x
          break;
. d3 e% a9 I9 u* {/ [: l  } , r4 J, R: A6 ]' y, J
  return TRUE; " R5 [/ |( l* @" b) }8 }+ n
}
; {# s" Q' @7 ~( Q4 B9 oLRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 9 i' N0 H7 Y' F5 j# A  m3 r
{ * b# M- X% a2 `1 z, K
   
% o( z0 j/ t" }' z/ D  return(CallNextHookEx(g_hHook,nCode,wParam,lParam)); . Y* }) \: Q9 B8 V8 w
} - h* p- e* Q# e
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数 5 f9 v, j2 ^/ ]
{  ! z! ?& j1 A& ^) T' t( |- d$ L- {
  g_hinstDll=LoadLibrary("HookApi2.dll"); # ~( E$ [* l( {& p4 u
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
! [% }# v  _( T- U& L3 g( L- ~6 \if (!g_hHook) 0 E( G% p3 C3 g/ v  b
{ ) z! a) O5 R4 J2 p2 V
    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
$ |8 l# u8 H) C5 b6 A# p    return(false); * b2 P/ X2 d5 y5 ~# \* r/ ^4 B) O: l
  } & ?9 r5 s0 t( O# z; V
  ! D  y8 K6 |4 L
      
1 b5 V; C4 h* q( r8 E  y$ ^" Z1 K  return(true); 4 x% H& v" G$ N2 m+ l' ]" d
}
5 s" p0 v( n" {- SHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数 $ P8 p! j: P4 x0 `6 J, E8 f
{
9 F9 P$ K8 Z3 }  
6 }$ w- S4 L! h  return(UnhookWindowsHookEx(g_hHook)); $ p# |6 O! e3 A7 o& m$ o( t
}
  ?6 K1 B) m$ V! b& M  j+ |8 e3 S4 pBOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令 * t4 P6 d9 i" G; B& H) E% d. S
{
, ?' x9 d) I0 I+ T" e9 B( b  hModule=LoadLibrary("user32.dll"); & L: X! `. P# q' [0 x/ t
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
  C2 E& k4 j6 y: N. W+ B  if(pfMessageBoxA==NULL)
/ K* K5 m7 G, o; d. J1 Q   return false;
& l; m4 F+ P* R4 M& i( r9 Q  _asm 8 t  G+ P1 X& M* H$ ]
  {
. R8 H. n8 v* n* F, k- [# @    lea edi,OldMessageBoxACode
& t: H; G) \5 t    mov esi,pfMessageBoxA : T9 @; M% ~, w' {" I, a8 H
    cld
/ Y9 K* q+ g7 R9 Q    movsd ) h# Y6 J9 t, u$ r, M
    movsb ( N5 ^+ _* W: Z
  } - A0 P; }  S* P+ V
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
" ~4 k: A1 h6 M  P% H: @' Y& ?  _asm ; k# y- _2 M3 H( W: J0 a
  {
# C) G/ Z$ O7 w" M) W% }    lea eax,MyMessageBoxA - n8 ]4 F# f2 S0 v
    mov ebx,pfMessageBoxA
" P7 b2 I8 b3 m1 o& }    sub eax,ebx
  H# i; F) J6 R; S    sub eax,5 : M! T% S0 Q" y1 ]8 L
    mov dword ptr [NewMessageBoxACode+1],eax
5 E! H" l: z: c3 W* D  }
$ ^) I4 y" n; r7 x, o8 q- J& G7 J  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
- h$ i2 B- v! m- x' R  dwIdOld=dwIdNew; / ]9 n- H% g1 G+ {1 R% V+ W
  HookOn();//开始拦截
3 O7 O; u0 s& p; X3 M- M/ s  return(true);
/ G* _5 k) j- a' B* l( L}
* _. c' K$ X3 }1 O9 Y1 o/ ^& g! uint WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数 ) d, U) V5 }; S: ?
{  
4 c- g7 |9 g- n( `, R- J, L& I  int nReturn=0;
+ H" r" z/ }0 C( J( e9 s  HookOff(); $ L) ~* x- Z6 y
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
% \7 u3 k* F! K% @, ?! m6 N  HookOn();
7 q; }3 u9 j2 o/ C/ R* y% B' Q  return(nReturn); 5 ?* `4 ]+ o- o$ K
}
* O# M5 C) c. F+ v7 C* ?0 qvoid HookOn() / ?2 u/ o8 J: X2 y
{
9 N* _& a4 U% A9 v  HANDLE hProc;
# J% Q8 }$ O' v% o7 e+ Z  dwIdOld=dwIdNew; , o5 _& g& T* P0 k
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
$ I9 U- _  V: j# c  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 , Q9 _9 w$ V2 \( C: @% _
  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
) _3 S/ s" D( X) @5 a  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
: G7 y% Y- M: g4 `  _; H  bHook=true; ) P; U0 S+ _! H4 r( W4 @3 V
}
3 G1 N! d9 k$ j3 ^, }void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
9 A( @7 G# `# y{
' p6 y$ M6 g) V4 v8 W' E  HANDLE hProc;
: V% P7 [6 V7 D3 s, M5 h  dwIdOld=dwIdNew;
3 k7 s4 L/ W+ G1 X, c  H4 F  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
+ Y; _- d9 A9 ]4 ]! [8 p% D  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
* B/ k  b# b* u  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); 1 X3 k/ ~( G" o& K
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
/ M/ _( Y+ `1 m% e  bHook=false; ; h# N5 S1 f9 n' ?
}
/ Q9 i& r! P5 l) ^5 q( {6 [. P, e//测试文件: 4 g% J$ V# P' d" }2 |( w
int APIENTRY WinMain(HINSTANCE hInstance,
# N- l8 W; n) O- G( r           HINSTANCE hPrevInstance,
4 p* P8 |4 o& g5 X           LPSTR   lpCmdLine,
: ^$ P- c2 @+ ]* K           int    nCmdShow)
  p( b( x+ B- [" Y* r  }. Q{ / z4 ~: m4 w) e( \
   # ^" K* {! N3 }6 h5 `( c, @* d
  if(!InstallHook())
" ?. u1 q, I9 Y$ S! h2 A& \7 U% x  { 5 U5 b% G/ F9 z; `3 v
    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); 5 _1 o- F" h9 G) N3 g
    return 1;
7 F" U" C2 x: `5 j" I  }
5 i. O: V( \3 ?* T7 \3 }   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 # _; o2 A: v, I5 P6 E2 L
  if(!UninstallHook())
5 i/ G9 V% N4 }1 g8 N( x  { ' ~4 G5 {7 n) @+ K  `) Z
    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); $ O7 ~: S0 I, a) l0 p% @
    return 1; 9 a3 f0 m9 M) L# p2 b( @* v
  } , m+ K4 u5 r: c% w# H3 i
  return 0;
# w3 i  T# }' A- r+ @( n3 b}
" [2 y. f* B5 E! k8 t: X
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

5 D1 ?2 l& b4 h- ?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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