下沙论坛

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

用新浪微博连接

一步搞定

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

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

# A# e2 |: K( a+ n发表日期:2003-10-30作者:tomh[] 出处: ' Y$ t% s9 O3 j( F1 B" w: K0 X
Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。
3 S" j4 {, o) Q  O0 q3 B  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现,
9 ^  j+ V0 b; M其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
3 h9 T& M6 U* u7 Z( j; l- R     BOOL VirtualProtectEx( ) b# o# _- E5 w* W6 P
                HANDLE hProcess,   // 要修改内存的进程句柄 . M9 N1 P: c5 J3 I
                LPVOID lpAddress,  // 要修改内存的起始地址 ; t0 `: L' t# b. c3 Q7 J
                DWORD dwSize,    // 修改内存的字节
$ q$ L( i% V: {+ o4 `% r% B                DWORD flNewProtect, // 修改后的内存属性 5 _7 R% U" Y) N  h  ]
                PDWORD lpflOldProtect // 修改前的内存属性的地址
+ _) ?6 E0 c& j9 ~0 l                ); , Z9 l; c; ^( N2 H' A4 ?/ r% ~
    BOOL WriteProcessMemory( 4 X, X0 ]. t5 I6 S3 X
                HANDLE hProcess, // 要写进程的句柄 - N: K3 t0 U* ~) w' G- M+ O* `7 D2 i
                LPVOID lpBaseAddress, // 写内存的起始地址 2 o  L- z0 ?. o, I
                LPVOID lpBuffer, // 写入数据的地址
3 k8 d; N, O2 [- _                DWORD nSize,   // 要写的字节数 , F0 r1 T2 [- r7 l8 S  e# S
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 & }  k: k8 U$ n- v7 k- C/ }/ j0 x
                );
# f; |8 H2 n% Y5 ~    BOOL ReadProcessMemory(
  A3 [. b' q' A- _: v  X                HANDLE hProcess, // 要读进程的句柄 * n  ^: @1 w* E( X( ?5 `( P
                LPCVOID lpBaseAddress,  // 读内存的起始地址
9 F/ v* {' V) J  \3 T' }                LPVOID lpBuffer, // 读入数据的地址
$ }1 S* T" f7 }% b                DWORD nSize,   // 要读入的字节数
5 x; t. O! o3 c' h  t4 i: ^, Y$ m                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数   K9 ^1 G4 m& L" I
                ); 3 l, b4 H& A* F; M- h
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, , a- A! J& L. D  H
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: ( a" g% T  W! ]
其中Dll文件为: * }# W+ U. ?% {/ v1 s3 M
     HHOOK g_hHook; - V8 r! r* B! {4 L0 {
     HINSTANCE g_hinstDll;
7 d; [$ o, X% d/ z     FARPROC pfMessageBoxA; ) m6 n0 ~( L  G) {
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
3 l" o, [+ _* q5 L     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
3 E0 T" v: e- o! v  \2 R8 a     HMODULE hModule ; 1 c* {7 s, J0 M, H
     DWORD dwIdOld,dwIdNew; 4 e3 S# C$ v3 z) ~: x. a0 D
     BOOL bHook=false;
+ t5 ]9 v- H8 G     void HookOn(); " X, G9 l$ d' G- N6 V9 S
     void HookOff();
( i. J2 g6 t4 |4 Y, S     BOOL init();
# s& b, ]5 N( K" L/ iLRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
. {$ F8 ]5 ?% BBOOL APIENTRY DllMain( HANDLE hModule,
5 P9 P  _7 [2 G+ i  @" o5 ?6 @            DWORD ul_reason_for_call, . a( E/ h$ p% S' ^$ @
            LPVOID lpReserved . S& ]8 J- X! M7 S: B0 f
           )
9 A$ @$ m, u) h) R- a/ m{ # K8 \) a+ S; Y
  switch (ul_reason_for_call) & d* l; Y  e" {5 ?  X0 s: K/ k) c) ?
  { 4 H4 a9 K' j" H* Z
    case DLL_PROCESS_ATTACH: - _" M6 _" j+ Y4 w! N' k9 h: `6 I* e
      if(!init()) ; ]% M) w; \: y2 R, w) q3 `3 j2 i
      {
0 v. J  ], F+ j! b/ o9 C2 ^             MessageBoxA(NULL,"Init","ERROR",MB_OK);
/ l9 o! Y9 b  O- b1 X7 [& d' k+ y             return(false); ; W- _* H9 t' g. n  {" a
      } 3 a$ u+ n2 I/ Z* \% B1 x6 j1 {
    case DLL_THREAD_ATTACH:
" c5 S5 T9 ?" i( n3 A    case DLL_THREAD_DETACH: $ q0 x4 {9 \# \" y
    case DLL_PROCESS_DETACH: 8 W- X. W1 a6 z- w" H# {9 V
           if(bHook) UnintallHook();  
0 C  T8 Y) F8 U2 R          break;
0 Q! W- r4 V- x1 O' Z6 b1 [) y  }
0 ^- X% Z  k# \; a5 G5 o* |  return TRUE; % g$ _/ z, U8 z: W- `0 s% i1 N0 g
} 0 `2 m+ l! s2 n
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 ' r, c# w( r. w* N( s1 M
{
& d- q/ T0 Y$ u   
7 l( ]2 A* P3 ~5 ?% u) o3 P  return(CallNextHookEx(g_hHook,nCode,wParam,lParam)); ) h/ C7 j1 n& d# Z# _
} , y' C1 ~4 W3 O  O! ~% l- s# o
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
+ q/ b3 A! }; ~6 P) E9 o{  
; v3 P, \; K! p9 |2 ?" h3 q  g_hinstDll=LoadLibrary("HookApi2.dll"); , |% S" h/ c" v* E! ]3 n  Q% e
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0); & W2 j. L" e' y+ e5 _" x- u+ E
if (!g_hHook) % a" U8 g' y: ]  q; v9 G; G
{
: w: X# Q4 F# J7 o    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
( [/ F/ X1 L: V2 m    return(false); : M% p* j2 ?) K% R( E8 ]+ _
  } 3 {* W! z( e0 \5 x1 U& k* @+ n( I* k
  . l7 S% y+ j4 N: }
      4 }/ m: S6 i' `: x$ q) j
  return(true); 9 W$ ?* }/ S0 |5 H$ p. x+ |2 Z
} # o) O' O. J7 r/ O
HOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数 , _% X8 p7 _! r- q& S' n& \
{
* {1 r3 j: I5 x( z' m- S! C/ ?  
) u0 y) m) I. G  return(UnhookWindowsHookEx(g_hHook)); ) l# f- D1 Q9 D% @5 o2 U0 _5 n- Y' g
} 4 k' I: q0 c+ m! Y
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令 % ^1 Y2 f- ^) p; H  m3 J3 y
{ * b" W) t, r4 T
  hModule=LoadLibrary("user32.dll"); " ?4 w. S! G$ C2 E$ O
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
$ Q0 D4 U/ D0 N& @# y, Y( L  if(pfMessageBoxA==NULL) 7 i7 N) F/ y* G1 E
   return false; " e2 Y: n: P& L8 M
  _asm
- C  `; j$ S: F  { / E* V( B5 @. d8 b
    lea edi,OldMessageBoxACode   u9 W* s, L! W0 C
    mov esi,pfMessageBoxA
- z: o' s1 ?) K' b    cld / a2 \8 s. \$ y) n4 F  c
    movsd : u2 o) [# M$ i5 l
    movsb
7 U+ U6 P0 Z, X8 C  } * T, Q) |8 ~5 d- _! i0 ~
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 , l3 o$ b% V  N+ G; A2 @
  _asm ( v* C4 C; Z: C
  { ) q! n! p# d& J0 p1 P! o
    lea eax,MyMessageBoxA 2 E. F6 v5 d7 d+ d+ g
    mov ebx,pfMessageBoxA
8 Y( j7 h5 u/ U7 C4 d* e    sub eax,ebx " G4 }" L# S  N7 i, z! ~% B! H
    sub eax,5
) P' F# s2 a) m7 w    mov dword ptr [NewMessageBoxACode+1],eax
5 z1 u. t' O7 B1 ~  }
) I& b' @6 d- {. p, T  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
4 K0 g" H, l& r' r# r. {$ U0 u  dwIdOld=dwIdNew; 1 U: t; r: S! S1 y' g7 K' T7 O) e
  HookOn();//开始拦截
6 K8 [1 }- k4 ~4 J  return(true); . Z: f7 x  o% }* Q% p4 \, p
} 8 S3 l9 ?6 I3 r, {8 o
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
5 H4 l# H1 f8 q: n) Q  V2 D. e( a{  
% Z4 A0 F: U9 u  int nReturn=0; : G: }( L8 s2 ^1 n2 ^" o2 i
  HookOff(); * h+ B5 J7 r* t# g1 [/ q& ^+ n
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
1 T9 E+ X4 i- j) r* n" \  HookOn(); 7 C- @3 E+ ~4 s) ?( J" F
  return(nReturn); " w0 u  m8 C9 l) j
}
4 ?; k# p) C/ }. [5 }void HookOn()
$ Z/ p5 g! a1 @( w' r{ & a; p, y" K- b1 r: \9 r7 R
  HANDLE hProc; 7 Z0 a( Q( d$ z2 p
  dwIdOld=dwIdNew; : ]! ?( e/ E1 X( s5 P! R
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄 5 L7 N  j) S2 y; j  o& m5 q
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
: N4 Q4 n+ J, F6 w6 Z/ Y  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA / Z# H1 B9 D0 u. A. e( i
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 % j9 ^( j$ j+ d2 H
  bHook=true; + W4 T( F( E, ^$ S
} * v1 M' _/ y3 P
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA ' [0 S4 P4 j" F# z' ]% s
{
0 b3 M1 B, {+ w, z2 ~$ i9 r  HANDLE hProc;
' p8 V6 e. N) @* Y" Y3 a3 h4 f! W  dwIdOld=dwIdNew;
+ ^6 T! z% M% Q0 u- S! F; H  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
7 Q) P; M0 x) r+ J( O% ~0 U  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld); ! I# R: y3 p$ o/ a" b$ b" H; J6 s
  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); ; G8 p, N1 q( g7 @3 ~
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); ! l% D% A/ m5 i. B
  bHook=false;
, i; v: N, h+ X3 C}
6 ~2 j" O7 I7 F; r* Q, n//测试文件: ; ^" v$ I5 A* o# N) v
int APIENTRY WinMain(HINSTANCE hInstance,
- \  H' A' E' G) S. t( `+ q6 N+ _" ?           HINSTANCE hPrevInstance, # k6 k9 J) r- V6 @2 y
           LPSTR   lpCmdLine,
% m/ m# D( ]8 V           int    nCmdShow) $ o& q+ S% Y- D
{
6 i+ G/ `( d1 C7 H: b3 Y$ [% X   
/ a6 j( W# D2 {: o5 ^2 B  if(!InstallHook())
6 ~7 ~9 S& b$ q' @; V  { ' c  O. Y* _  p6 R0 Y/ X4 J- x
    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
8 T, `! F5 [- R1 U% t$ x    return 1;
$ I- x$ Z* k5 o0 a; Q: b  \9 K: u  }
# P4 b; B/ m2 k% f+ |9 C   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
" v; ^6 w8 Q# I6 E0 d9 U6 t  if(!UninstallHook())
$ v- Q9 P# x# ]2 Q' ?  { # j* ?, H5 ?" j9 N3 R
    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); ' o' q5 n- i: ?
    return 1; & Q" [* f5 @9 w( R5 y0 g
  } ! C  C' g" W! h0 ~
  return 0;
! `8 ^; F/ J( d( a! T3 L! o} + d( c- w, A: C/ E: _3 o# @
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

. |$ p& i$ o. Y) |% B7 m
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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