下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

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

$ T) d" c' s( k发表日期:2003-10-30作者:tomh[] 出处: + J6 [0 O" m% a) @; b) [& h
Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。
( j0 e  N7 u, O! O) `  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现,
5 Q0 T( L: V  E& [3 E+ q  l3 b8 c其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
( g8 W3 b! S" |5 u# n     BOOL VirtualProtectEx(
: }9 U/ Q6 l& e9 k7 G7 T                HANDLE hProcess,   // 要修改内存的进程句柄
, \3 e; H! K  m1 s+ p; @( {                LPVOID lpAddress,  // 要修改内存的起始地址 9 t8 G) n) s. O. F
                DWORD dwSize,    // 修改内存的字节
* ^- |: p5 V( O" \: ~! j- F8 k" Q                DWORD flNewProtect, // 修改后的内存属性 & j  j7 I2 N. F9 g8 c9 I4 @
                PDWORD lpflOldProtect // 修改前的内存属性的地址 2 {3 X. |7 Q, X. z
                ); $ I8 e+ K' ^0 D
    BOOL WriteProcessMemory(
6 q! u4 M$ x% K2 C                HANDLE hProcess, // 要写进程的句柄
2 b; k7 Q( ]( ^, ~                LPVOID lpBaseAddress, // 写内存的起始地址
" o% q6 g! E8 |9 S# ?: g& `                LPVOID lpBuffer, // 写入数据的地址 3 ]) _7 q( g) ]# V0 s
                DWORD nSize,   // 要写的字节数
$ e/ Q6 t3 L, _9 ^$ }6 Y5 H1 E                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
: }. N4 \( ^1 P2 C& I                );
; T- B& u- z& X5 V1 x' A% H5 U    BOOL ReadProcessMemory( 9 x7 w+ m+ Y4 v0 s) v
                HANDLE hProcess, // 要读进程的句柄
" J/ d9 C% c5 G* i8 T  q6 U                LPCVOID lpBaseAddress,  // 读内存的起始地址
3 J! D  C* z& p6 i& x  G                LPVOID lpBuffer, // 读入数据的地址 : l( [5 K6 |  T2 p) u8 j. b
                DWORD nSize,   // 要读入的字节数
/ R7 Z2 x1 @# n7 t8 B) r- Z! L                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数
8 B' t" E, q7 ^1 R  \                ); ! C# e! K; m6 P% ~" A! Z
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同,
( V! x, T3 N/ h4 \. v因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明:
3 G% I/ T" u2 L- d% U0 a, ]其中Dll文件为:
' N1 u, y! \6 ^0 I0 r/ R1 U     HHOOK g_hHook;
/ S% \9 O2 f* ?- C1 X* k3 S     HINSTANCE g_hinstDll;
7 J, X+ M0 L- p; \! ^& Z2 C     FARPROC pfMessageBoxA; / S+ T4 |7 M# V) q) N' M  F. f& d
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); - G% ?: T* X; l, t' q- Y
     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; % m/ l# [( o" C& B; ]
     HMODULE hModule ; " I. B/ [0 A8 V  Y  E
     DWORD dwIdOld,dwIdNew;
& c# k& _. f# h* T. L     BOOL bHook=false;
% M' [; O2 H7 d! o; v     void HookOn(); ) b, z  K4 d3 r- G6 ]& k
     void HookOff(); ' Q! x  _# _4 t5 w# c7 e9 w  ^1 K3 i
     BOOL init();
: r" b0 Q. l6 oLRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam); ( c& G6 Y1 H2 r' Z& e6 W- ~- i
BOOL APIENTRY DllMain( HANDLE hModule,
& l+ R( b8 P: K8 |# n            DWORD ul_reason_for_call, + T/ k3 O- L. t+ c. v9 X6 v7 {% P" E
            LPVOID lpReserved + k+ d) m- d  ^4 j+ P
           )
7 n; c/ _% }- D- e+ \) X6 ~; q{ ! f* o! e% E/ ~5 X
  switch (ul_reason_for_call)
9 ~' x: e7 O8 f2 [" n  v! Z, ^  G  {
0 x- [8 q- ]. }$ P    case DLL_PROCESS_ATTACH: $ x1 a0 x8 F2 N' |2 r7 G
      if(!init())
9 o8 P  X6 i3 Y      { / r, |. l  y+ z7 r# Y) a
             MessageBoxA(NULL,"Init","ERROR",MB_OK);
- L  [7 D9 C% y* I4 }- v             return(false);
2 T1 _. z3 i9 G! F! D# {8 ^8 ?      }
/ w8 S. V' L: u; X$ l0 I    case DLL_THREAD_ATTACH: % O/ t+ ^' f4 E' q. I, t
    case DLL_THREAD_DETACH:
+ k& `5 E/ J* w: I) C! s    case DLL_PROCESS_DETACH: 8 f1 n7 ~2 G$ w2 I- z/ ?9 d
           if(bHook) UnintallHook();  
' @1 w% h4 X- F% r6 H1 d0 P' W5 I          break;
! J, R4 z( x  p6 D- o  } . x" k7 }2 X# r; F8 A
  return TRUE;
/ r% {/ D7 Q  u6 X  [} 1 @: H: K8 D/ A+ z4 v6 d
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 ) O4 c. a( o$ U; _1 @  a. Z
{
% a1 G* \  \+ K' |! k   
+ {; J" t9 g+ V7 M( G  return(CallNextHookEx(g_hHook,nCode,wParam,lParam)); ! `+ H2 w& m( p- p9 T
}
0 u. J% s  R! m+ J" I9 i! tHOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
2 n% @4 L! x% A8 E0 h{  
+ a& Y  k2 v$ d/ E) \  g_hinstDll=LoadLibrary("HookApi2.dll");
: z$ ^+ I; u% R- a8 w  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0); % Y/ F9 B( m0 _6 M
if (!g_hHook) ! Z" C6 N& r; L0 \7 V4 j/ m
{
: i* t* \/ U$ F5 E* ^% M3 y/ y    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK); 0 e+ p6 m+ `) P5 N
    return(false);
' b9 g* F# w5 d4 z+ d! f- \9 F+ X  }
4 q( |/ h# w9 s7 @- r. _  
* j' B& N* \" G5 ?      # o; w8 _6 x& L
  return(true); , |6 G3 ]6 J9 o/ ?* d
}
# o+ A. M* A: U- c; t& e% {; _! w8 BHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
8 m# m1 c9 v3 J3 L; k: ?1 w! |{
# y% _5 n! Q$ N8 Z6 e% {) U  
- k# I: @' k  n" l5 L: e, _  s) ]  return(UnhookWindowsHookEx(g_hHook));
9 _  v8 ]! ^7 t  n0 x}
6 }- C0 C1 J. t# l* u8 cBOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令 3 j% [) J, d) Q- S
{ 7 V+ t0 S, j* x
  hModule=LoadLibrary("user32.dll");   i8 e. W* I1 S6 x1 f& A% ^
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
% b( d  o0 E3 \8 X$ F( k  if(pfMessageBoxA==NULL)
+ y  H, ]( j; G& S2 o   return false; 1 t+ w' ]( z. @/ A' a/ m! p0 a
  _asm / c1 ]  @) I; |6 z# r6 V7 g
  {
7 `- p9 C4 ~- z4 X" X/ @9 c    lea edi,OldMessageBoxACode
5 c8 F7 F$ F- ?- q    mov esi,pfMessageBoxA
6 f+ \2 ]7 _- {    cld ' G4 a3 m1 P2 J7 M- j+ `
    movsd 5 [/ D' ]  p/ K4 r6 t9 \, _+ J0 A
    movsb
9 u% q) \& ~: Y2 v" a  }
6 h' a3 g7 n( H7 N' H0 I  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 / L; t( ?4 t9 h1 F) D
  _asm ! J( D5 I. _- \7 G1 A4 g
  {
2 d+ m7 I% l* D) E  L* l    lea eax,MyMessageBoxA
" \  H  h# Q! U# y3 L; T' N9 |    mov ebx,pfMessageBoxA
6 t+ h$ D' v2 x$ G* k# G5 P- K    sub eax,ebx / R) O: ]# G8 J3 M3 C2 T4 }
    sub eax,5 4 _# O  k. y$ A; \; b2 W
    mov dword ptr [NewMessageBoxACode+1],eax + Y5 P* t. R6 d# P5 X5 j
  }
" O6 \2 \! M' V4 F  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID ! ^, }& y* t* M- G
  dwIdOld=dwIdNew; ; v. |  e9 r8 h
  HookOn();//开始拦截 / \9 }! J# o0 T! L: ]& e1 M0 R) D" u
  return(true); + l: A3 A6 U8 @, [# v/ O7 F
}
( _- v/ I! c( S0 ?- lint WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
- D, ?3 T) H: a' N5 {{  
- ~$ q5 C! m/ x- _* @: Q  int nReturn=0;
# o" \7 {, T8 c4 {: r# s: ?  HookOff(); 9 S- W3 r! W: V+ T" M1 w6 Z+ U4 R
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
) j/ c1 e  \2 g  HookOn();
0 o* m/ Y* q" L( T  return(nReturn);
4 }+ R5 P% w+ M( K  L; T}
- h& R- }6 B( W5 dvoid HookOn()
0 Y$ S; Z0 v2 _. t7 `{ 6 l% i7 d# ^" H# B
  HANDLE hProc; 7 p& p4 W+ I1 {# H- d8 V
  dwIdOld=dwIdNew;
6 {4 Q0 V; l, Z% @2 _+ h6 s  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄 % ?+ E- W) @1 @7 ~3 i% d% h
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 8 _2 C4 p- S/ F" j1 v
  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
4 X0 T$ p1 Y* U# M5 l" ]6 y  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
! S' ^: w8 {# q3 J3 W6 d( ?  bHook=true; # w; i' o4 v0 k5 K$ t
}
5 I' t7 I) r  \0 P4 Z* Y4 k+ tvoid HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
0 s" w4 q) o- {9 j{ " M3 d5 D: o& ?
  HANDLE hProc; 9 r! o3 B( k6 d( e
  dwIdOld=dwIdNew;
- ]3 G7 v0 m/ E7 m( V$ {$ v' v  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); " e/ i4 O$ N6 Q0 T9 E9 @
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
) k3 m/ f/ |# R( ^# F9 _! `$ |  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); , z/ x' X0 R2 E* g' o
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); , \( ?, Z  z$ o
  bHook=false; " a- m  s  t, e& @1 o  V# H. {9 v
}
" I8 K- [- O: b" Z. E//测试文件:
% `& p$ ^9 R( \/ Tint APIENTRY WinMain(HINSTANCE hInstance, ; v3 ~8 P, Y/ r+ P
           HINSTANCE hPrevInstance,
/ i! j4 y; ?2 M           LPSTR   lpCmdLine,
; D+ P' [* p+ J+ A           int    nCmdShow) & S0 E0 x" J3 y( U
{ . ?& Y- a8 f4 r$ I. k
   : j" y$ _: Y0 E+ g9 T! X# _( E+ @
  if(!InstallHook())
$ K, A6 a3 M! p, S3 D' S" s6 M8 h  { * l, h( P! ~5 p" t: b- Y( h4 H2 A
    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); $ n) m/ T  u2 B/ f; Q& Z: _+ I
    return 1; ' K1 G: ~$ l# f$ ]+ P2 J- q9 `: Q# n
  }   Y0 K0 c6 u& V6 F: B
   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 . Q  e4 o9 |- U' J; s
  if(!UninstallHook())
0 T& C2 E4 ?/ G$ s- |1 _9 C! h  {
9 b# U5 @4 p) M0 T' Z    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); & i" s6 Z- h0 v0 R" n9 p
    return 1; / G: Y/ s0 p& q
  } $ U4 C& s7 F4 O+ r7 n% J6 l
  return 0;
5 X: k& X, ]  w} ) d5 Q9 N9 v3 P, @6 V
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

! L0 z  H% p& N) k6 y6 Q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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