下沙论坛

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

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

跳转到指定楼层
1
发表于 2004-11-5 18:09:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
- p$ r3 Y* m0 y7 F, ?  Z
发表日期:2003-10-30作者:tomh[] 出处:
5 ?) k5 d" \* p8 K' aApi拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。
" K( m* W) {: {* C5 u: a  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, , _  G& i; D. N7 b
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
) H  |" w2 t% g6 ], v5 l3 ^, n     BOOL VirtualProtectEx(
( B, {& _: F4 K/ w5 `1 E4 h                HANDLE hProcess,   // 要修改内存的进程句柄
2 d5 K% g- ]7 G. [9 ^/ s7 A                LPVOID lpAddress,  // 要修改内存的起始地址
& ?6 |7 d* c7 o! U                DWORD dwSize,    // 修改内存的字节
; M6 S2 g  [8 D1 f9 u                DWORD flNewProtect, // 修改后的内存属性
, X1 r" h! c! W& w                PDWORD lpflOldProtect // 修改前的内存属性的地址
$ }3 K  r. T# q' V& T                ); 5 F& V9 w- f5 \' |' g7 {
    BOOL WriteProcessMemory( ! m5 G* n& L, P" s( @5 C$ T3 X
                HANDLE hProcess, // 要写进程的句柄
' ]5 s, C; P- [, Z3 W! E                LPVOID lpBaseAddress, // 写内存的起始地址 $ i) C0 G& G! o
                LPVOID lpBuffer, // 写入数据的地址
, o, O3 @. C8 f' e                DWORD nSize,   // 要写的字节数 " W/ _1 q. j. ^) v8 X0 D  H
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
/ l+ Z1 n2 z6 ^! S; b2 x$ X                ); 7 h: R' Z; I; o5 T9 X
    BOOL ReadProcessMemory( ) s. ~" y1 }3 O! H) @
                HANDLE hProcess, // 要读进程的句柄 3 t5 g* t% q4 ~4 G9 X! b, l, M% U: Y( m
                LPCVOID lpBaseAddress,  // 读内存的起始地址 9 G2 E' K: f/ d! c
                LPVOID lpBuffer, // 读入数据的地址 , a) O( q' s/ C: a4 S
                DWORD nSize,   // 要读入的字节数
, t5 g7 y4 X2 k! u! ?                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数
5 n7 I% N# `7 Q  ?- l* U                );
: P7 Q& Q" S3 \" Q% d9 k% ^具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同,
: l9 l4 Z3 x+ H& T* [; A4 @因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明:
9 v, h  a, i6 F+ d. a其中Dll文件为: ) Z' C% _6 N# J6 }2 B# H; G
     HHOOK g_hHook;
6 q4 X# R( P& D# o* t1 y: {% ?+ h/ f. ?     HINSTANCE g_hinstDll;
8 D4 `. i) Z. @( m" g     FARPROC pfMessageBoxA; + W4 ?$ a% {  s$ N$ D
     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); 5 F& \* r: P$ i' [; S8 \/ T0 S
     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; # O7 ~- j3 m& ?' e
     HMODULE hModule ;
1 k) A" @, s' n     DWORD dwIdOld,dwIdNew; , S1 Q' r3 N' t3 ^
     BOOL bHook=false; / d, u1 v! C# L; n' s
     void HookOn();
! P) r" b5 g/ s2 K' K/ Z     void HookOff();
# S- F9 E7 D# ^7 \7 X" f     BOOL init(); & h$ i+ u$ ]3 Z4 A) x0 ]  y
LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
* v, v0 V: P' ?BOOL APIENTRY DllMain( HANDLE hModule, ) S* s' w5 U! C1 z% s
            DWORD ul_reason_for_call, 0 P/ E* a+ b  ^  }( K
            LPVOID lpReserved
! R$ A! J5 H2 }5 C" |% ~( C% a           )   G' F7 }7 i3 a
{ - f! p% b% l1 y3 q0 e
  switch (ul_reason_for_call) 4 v# J" q/ d  S# \1 s: Z) n, `
  { 6 U( ~, l2 Z  o. W6 Z- E$ R
    case DLL_PROCESS_ATTACH:
; H  O' p; A* P" j* ~* V7 U      if(!init())
" u; I. \  k+ Z: ?      { ) V% T5 u0 \/ d, o2 L/ ]) v/ z
             MessageBoxA(NULL,"Init","ERROR",MB_OK);
) e) Q% R7 {, a# Z             return(false); * i# F9 h. q% {- r6 F4 f" w9 ~
      } : X; H6 F" f6 D# i/ l: B1 r/ C
    case DLL_THREAD_ATTACH:
' ]% G; i) F0 n. y    case DLL_THREAD_DETACH: 7 ^, t: z+ ]3 |# u% Z4 Z, f
    case DLL_PROCESS_DETACH:
( Q3 n7 S1 _) {           if(bHook) UnintallHook();  ) T3 C6 M' q( a( Q3 h
          break;
  l0 M% X% A7 r0 k! ]+ @' d1 E2 O  }
- H8 L8 q$ @- W  return TRUE;
! u! z: y# N. c- E  R& c3 q} " e, W' y8 r7 X* X. o
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
( r* [- f) {8 i" k8 w{
' [1 U: {1 K6 ]   
: m# _/ Q* p8 \: y  return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
- n/ t, I5 s# b& ^) x) D} & [" A/ W; s" m3 k. A
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
4 }+ l; J8 b/ `* S  O  r: F{  
$ b4 B: C8 G: I  g_hinstDll=LoadLibrary("HookApi2.dll"); ( N8 l- g* m/ p" a  p) P: C
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0); & S: v) }5 G* j
if (!g_hHook) + a; Z" y2 ]2 i$ t- \
{
2 W2 Z. R7 N/ f4 Q    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
# W3 p% R% M( k6 r2 u    return(false);
8 M7 s+ H! D$ E( o1 H/ `. K8 A  }
# M9 Q$ Z1 P  ?+ a* ^' E! x1 q  : `4 {! X! j3 w
      
* [4 }% b# K" c: K3 p$ L  j  return(true);
- Q5 S: }3 o2 X( J# n  b2 @} / l. f& K$ t& y6 A
HOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
8 B1 D6 p/ ^9 t) b# S{ 3 F. C1 w! n1 x
  
+ L9 k& F) N, P: ^, T9 g, V% p' E  return(UnhookWindowsHookEx(g_hHook));
2 e7 `4 B! p6 Q+ {/ b3 N} * [/ r# N& M' U. T: \
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
# W1 `. w  {! \2 h% M{ 1 f  b* F/ W' B% Z
  hModule=LoadLibrary("user32.dll");
) V2 z2 Y- r+ a% `, c9 `2 R' X9 x  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); 9 S' c" h6 h- H0 o# i# a. T7 w4 e! t
  if(pfMessageBoxA==NULL) 1 A  g" }5 a& B
   return false;
3 L. x% `5 c3 r* ~  V  _asm # I5 p, t; d$ H9 b# \
  {
) r8 \7 N7 \$ A$ i# T    lea edi,OldMessageBoxACode 3 @% E: ]0 r+ i/ G
    mov esi,pfMessageBoxA
1 |$ C6 C# W& s% O    cld : l3 k. M5 {/ ]: q! m0 J0 k
    movsd ( k  F, f6 @0 x, t" |
    movsb
2 H) m- e+ j# V' X+ t  } 8 @& s7 n" x4 b/ g) r
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 3 [* a' i+ o" ?- c+ e5 r
  _asm
0 s3 _& ^% U* [1 K- J8 O* o5 `! L0 [0 M  { 0 I$ P+ _; x( V( D8 t+ p# ?
    lea eax,MyMessageBoxA 9 M5 t$ y2 K8 K. }6 q
    mov ebx,pfMessageBoxA 9 d+ Q2 A0 j5 P. l
    sub eax,ebx
2 }) _! m7 _& I& J/ r( ?6 }, x    sub eax,5
! C( ]- D: n; [0 M& B. H! b0 V0 J* a    mov dword ptr [NewMessageBoxACode+1],eax . {4 M1 t- m  Y! g- g0 _* o/ e
  } 6 w. r5 v( |" a8 L* I1 I. t# i% @( i- }
  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID 9 }2 j) y+ p4 W9 m$ R: a& z% x
  dwIdOld=dwIdNew;
; G0 x$ g% T4 O- z9 \6 H0 T9 z  HookOn();//开始拦截
6 B5 S: T* {, x. Z5 @% s3 @, T  return(true); : j; f1 I% O' `! C; }( `
} ; F+ Q' L$ v3 G# I
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
- |" e3 w2 y% W+ V* ?+ \9 `{  " n9 i( r+ I7 N' k% {, |( u3 k- l
  int nReturn=0;
$ C9 U3 f/ q5 B+ t2 V  HookOff();
8 f9 f4 @6 |$ j: a$ F  u  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
' g# v/ z, {8 S7 ^0 B$ Q  HookOn();
) A0 a; z! {5 m! q( n. V  return(nReturn); 4 @+ l! F$ g+ Z8 L1 A. Y8 s* p
} 8 Q$ C3 S+ ?4 L9 \, ^7 C- Q! o2 Z' @
void HookOn()
2 U+ y+ q7 }' \7 m6 d7 _{
/ |0 Q9 F2 M% ?1 _2 i+ O  HANDLE hProc;
7 v8 X3 O  i% p/ ?6 f4 |& t9 d$ L  dwIdOld=dwIdNew; % B, K: z& C6 V
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
- K6 X8 n9 z: @2 l8 l# `) A( {  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
' D8 O2 F1 W1 D4 R+ R  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA $ `! Z" M. I7 H2 D; R1 {% R, `
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 " [/ G6 @; V$ V; i! C
  bHook=true;
: G9 S. K' o' T} 8 m: M6 ~2 e% t4 y( j
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
. [# @  S5 }2 v7 @* h* N; a+ j7 V- T{ & {- g1 z5 E" G8 `. N) r. [  ^, w
  HANDLE hProc;
/ {: N' A5 u% F0 N/ J/ H  dwIdOld=dwIdNew; 3 j9 l1 a( y9 n0 B: @' J8 i
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); ' e) d+ c0 N) b2 V0 y" Y# D2 ^
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
8 v: r5 g3 v3 j3 r  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
9 v$ B" i- t, ?& F$ `8 n7 K7 b  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); - s( @: T0 y2 M+ N7 u8 N8 N
  bHook=false; * a, ?5 b; J- q+ L
} & V6 D9 z* w0 `  k3 @8 _2 M! c! o; O
//测试文件: 2 B, f6 j* i0 v" r
int APIENTRY WinMain(HINSTANCE hInstance, 3 V1 }: E: n& U0 D, _
           HINSTANCE hPrevInstance,
  i* O. C/ M& K2 g; y! q9 b: ~8 n           LPSTR   lpCmdLine,
. r9 p1 j% j  u9 x  [8 J# }0 \  X           int    nCmdShow) 7 u$ l) @8 I- Z: g  b
{
3 S# R+ l" m% n# i) U! M) d0 c   1 C& @% b- g1 A! t9 K
  if(!InstallHook())
2 V: j" Z) \' i8 v3 X  {
. q; N* Z- W% R    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
, ]2 ?: k3 x6 ~+ N* P; L    return 1;
2 `- u" h  Y6 l" C2 R7 Y, ~3 i8 \0 @  }
2 O0 b" o% o0 K8 `% k6 c: U; }8 z   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 . z0 a4 g" I( d  o" z( M7 x$ d
  if(!UninstallHook()) 9 T* L, m% Z" o. ]5 D
  {
. Y9 }9 y+ S  h) {    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK);
( [  W# \3 v0 H    return 1; 6 D% m) h4 B) C7 l4 s, Z# f8 w
  } + S; a3 D/ s0 v' j, e, z" T( M
  return 0;
  o; q/ [9 f& d2 N} 7 Q: o* Y# ^$ q/ i7 ~8 D9 g* d: n
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

" X1 V4 Y4 {; k& ?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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