下沙论坛

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

用新浪微博连接

一步搞定

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

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

' c. O" ^" `$ z3 a发表日期:2003-10-30作者:tomh[] 出处:
5 f8 g; N9 q  h7 z) T# tApi拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。   U7 K# \6 L) K" P( H8 a( Y9 `
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, 9 V( E' w/ K; l8 {$ E/ a1 R; x
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: 2 Y5 ?- I) k* y1 T' l9 x
     BOOL VirtualProtectEx( - ^: R7 Z, i# B/ j3 A
                HANDLE hProcess,   // 要修改内存的进程句柄
$ U9 F; I) M9 S6 r+ v4 ]4 b) T                LPVOID lpAddress,  // 要修改内存的起始地址
* f( T: k6 D) x4 H- G                DWORD dwSize,    // 修改内存的字节 * ?8 Q4 E- F! y: Q3 G6 T
                DWORD flNewProtect, // 修改后的内存属性
$ k. `0 S+ j+ A, t7 U                PDWORD lpflOldProtect // 修改前的内存属性的地址 # C' n9 d+ ]9 p: H- q: I
                ); 6 N( |; y6 J) M
    BOOL WriteProcessMemory(
* O* N6 u# ^; r1 Q0 \1 f( S                HANDLE hProcess, // 要写进程的句柄
' s( H  @$ C/ h! s                LPVOID lpBaseAddress, // 写内存的起始地址 ! I4 _; a+ a1 A
                LPVOID lpBuffer, // 写入数据的地址 % x8 r( J: x- x* D+ {# Z
                DWORD nSize,   // 要写的字节数 # t9 `4 P0 s+ W: }
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
1 ~0 R' N* h' y4 e                );
# |! }0 \% F8 J/ ~    BOOL ReadProcessMemory( * l2 d! v1 U6 @" k- F) g% K/ H
                HANDLE hProcess, // 要读进程的句柄 - m7 E' A* N, ?0 ^8 @+ {  O+ t
                LPCVOID lpBaseAddress,  // 读内存的起始地址 * F) @5 d5 e3 n7 k% N
                LPVOID lpBuffer, // 读入数据的地址 - p- v: C+ M; Q& L' M( z  h
                DWORD nSize,   // 要读入的字节数
& A4 n2 Y$ z1 K" o/ y, r4 s                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数
1 G4 W" h$ I9 j4 y# H4 _, z. T                );
0 ^7 v( G8 F- {# f具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, / T/ U3 l; P3 w/ ~* g. ]& V1 K
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明:
# [/ O" C+ W+ D2 e! k其中Dll文件为:   A. G% f' y4 a: t5 x
     HHOOK g_hHook; " G6 G2 ?9 k: L; e( g5 w
     HINSTANCE g_hinstDll; 9 }; Z, D- {  x
     FARPROC pfMessageBoxA;
* J0 ]2 l# R( V+ G% h  Q: E     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
# h5 l+ v2 D, h7 E6 |3 W     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
, O  l* o3 k4 e0 o% E     HMODULE hModule ; 3 k' t0 B1 j# N/ e8 |% |
     DWORD dwIdOld,dwIdNew; 0 k3 j2 c' H8 D$ |
     BOOL bHook=false; 8 Y. n6 I- b" q
     void HookOn();
* G' H- |; e8 d     void HookOff(); 8 `% J8 A1 B+ I. e8 U
     BOOL init(); ) C) L9 A- E5 N2 L- F0 D+ `
LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam); # b! K% ]( ~: @. z* N# t/ N* G& _% V& e
BOOL APIENTRY DllMain( HANDLE hModule,
) k) \: G* v6 |, A7 o% e( n            DWORD ul_reason_for_call,
/ H7 X0 `' a% K7 s6 S            LPVOID lpReserved
" r# ]9 z6 J& a9 l( x- `" ?% ]( ?( J, ^" v           ) 3 |- m/ }. j2 f7 Y4 s: u4 B
{ + q0 W) e: N8 M, N, T9 v) M( }/ [
  switch (ul_reason_for_call) # v5 \. Y' J; t
  {
4 |. ]/ P4 J( ]. C4 m6 a8 C    case DLL_PROCESS_ATTACH:
" }' V* K4 {6 K) i) R3 ~' ?      if(!init()) 3 e7 ~$ h7 E- d) s
      {
& a8 k- H, [- ?2 \5 F5 o$ d             MessageBoxA(NULL,"Init","ERROR",MB_OK); + i* k. w! e; O" i8 ^
             return(false); ; H+ n0 C: @, z3 a1 E
      }
8 H+ y$ E5 d  ?; j7 K3 p    case DLL_THREAD_ATTACH:
" k& C8 o1 }# k    case DLL_THREAD_DETACH: : \0 p7 e+ U0 ]1 n
    case DLL_PROCESS_DETACH:
7 U9 L" g4 ?$ {) F# F; i# ]           if(bHook) UnintallHook();  
' [, ~: x$ M7 i. Z' M2 S8 x' _          break;
$ q, C, E" }  L; W  } $ [  E5 f! W3 m* M4 i
  return TRUE; . k- s; Y/ \! j8 M' Y, \' j
} + s9 w3 Z0 B" J3 x7 N) v
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
5 h# T+ b* `2 m! m( Q/ k{
1 d7 s% s7 w* q8 c   
  ~6 F8 [. d: j" }  return(CallNextHookEx(g_hHook,nCode,wParam,lParam)); 8 u. ]6 o. l9 {7 b
}
" D( g2 S8 g9 U, ^0 \' tHOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
+ r1 u6 U( T% M' _! I$ T{  
0 ~* `  H; A+ \$ R7 q6 M  g_hinstDll=LoadLibrary("HookApi2.dll"); - t+ c+ Q( I4 Z) h" a
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0); + W. t0 U% N5 O
if (!g_hHook) % S0 s6 P% `( U+ V5 W
{
5 x& e: Y0 u: n! k: H- c- D    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK); 9 s$ P7 A+ N- m! d4 X# q1 q0 i
    return(false); 2 i, F, q0 l# T0 z
  }
9 A# [; W* l) e: |  
3 N2 h' t. @7 r4 s1 G      % I+ ]( b7 h2 y
  return(true); 7 N# ?% Z4 U  q8 ^; C* _3 f
} 9 G1 Q4 ]  T- u3 s8 c9 ]
HOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
3 C- L! O) e. X! a  s& J{
1 |8 a6 l7 \- z# u, P  
5 s( @4 a7 f; S8 I. z- U4 F  return(UnhookWindowsHookEx(g_hHook));
& A3 n  [8 K7 S- y; v} 8 d* u# R' C% b/ w% S+ r# _
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
$ G( Z: B! ^) \+ a" P/ O0 q{
+ q% v% z% s; m3 e/ y$ W5 Q3 W) M  hModule=LoadLibrary("user32.dll"); ! w, i3 X, b% n2 H1 W, F; B
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); 8 e. M+ Z% m5 y7 x2 G8 w. X2 e
  if(pfMessageBoxA==NULL) & ^" V0 [! m& `) D; l5 f. ]2 ^
   return false; 7 {3 H$ Q* x" j* B/ Z5 ^
  _asm
4 ], [! q! ~0 @2 R9 h2 c& \  { - Y( \8 y: ?3 b" i5 a. m
    lea edi,OldMessageBoxACode 9 g, z* k' l' P/ ~3 p# H: n8 a3 t3 C
    mov esi,pfMessageBoxA ' k0 D  h! }( p! V: r& t% E) I) C) J! y
    cld
" M0 i+ i) x! t8 Q2 O, t4 z    movsd ( S6 q0 d8 S5 P) ^6 W. v
    movsb
# H8 ]5 {6 N+ `1 Y. m+ l  } 6 X6 A5 b% E; j( v, ~9 z  P
  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 0 T+ Z3 n& P, k1 I
  _asm ' T" G5 l! ~( [. A+ R* `
  { # G2 K0 L3 {8 L8 C+ c
    lea eax,MyMessageBoxA 4 S% [- j" j+ e5 ?
    mov ebx,pfMessageBoxA
2 M( J( n; A1 j! E    sub eax,ebx + q  W6 _. x* l% S" t5 H4 s( P  r
    sub eax,5 % r( f3 }5 }  r6 [  u$ _! N9 ^
    mov dword ptr [NewMessageBoxACode+1],eax
/ p% P) @% K9 Q; N. [1 q  } # W  |0 y8 o1 i
  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID 5 J  B* Q  X  ]' u  Q2 `
  dwIdOld=dwIdNew; + i7 z7 o* G3 {% X: D0 K- t
  HookOn();//开始拦截 & k# D1 E. b. E# Q# F* H
  return(true); 0 v$ s& S$ V; T5 y1 Z1 C
} + s& K8 A; Y  Q0 ]" V$ d* x1 I$ a" L
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数 4 x* o3 N5 U4 |" D# r+ C
{  ) \  x1 k, }+ Y1 a% \+ T8 y
  int nReturn=0; 7 {; t% g( D) s/ ~2 K: k9 X1 [5 e
  HookOff();
  b0 r; o" {/ G' z5 d5 C& M& x  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
; a$ q+ M7 c# R$ P( U5 [8 I( B& X6 \  HookOn();
% X. P3 l! _  f7 E5 q  return(nReturn);
$ z1 R- I  H: \: n- ~0 M2 k$ q3 f} / ?; u* A* D7 ^: {3 b6 q" U9 X4 ~
void HookOn()
- s0 P% ]: x! z* G9 }% Z{
% G$ y! j1 W& l  HANDLE hProc; # y6 A' x* V# i6 o
  dwIdOld=dwIdNew;
. u9 Y! Z2 Z% J' M  ^, Z; c  d' A( z  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄 + K- k$ p" k2 c7 A$ ]
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
% F1 h7 o' h' w+ c* y  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
* B8 j: ]1 H  ^  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性 . c6 n" Y+ o/ D" Z8 V0 T" w1 [
  bHook=true;
" {4 Y1 D8 j- B- }) V}
' v( `( |( ]/ d1 yvoid HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA ; o" g8 v9 R, o4 B  g, b
{ ) s6 }1 v8 R+ w
  HANDLE hProc;
# V; s! r$ B8 ^; w/ ^! |$ C  dwIdOld=dwIdNew; $ S; w! e9 ^+ a& F# |6 J* M, ?
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); + @$ |* s# _) T+ V; C9 F; X/ i$ P
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
: Q2 U+ \3 ^$ Y/ _/ _  R  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
: L% {  D& V) O8 ]  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); 1 G! M& R* O- m  a) d: F3 }/ i; f1 B& A' R
  bHook=false;
' r1 S$ `$ S3 A  d7 v0 S} ! d# y  U4 F/ ?! t( V6 ^
//测试文件:
" A, ~3 ]' o7 L% {9 R! L0 F& `int APIENTRY WinMain(HINSTANCE hInstance, * K6 L( `3 H% b: F% E
           HINSTANCE hPrevInstance,
8 Q6 l5 ?. @6 s. ^           LPSTR   lpCmdLine, " ~7 x1 p% q# Z6 Z$ C
           int    nCmdShow) 8 k. J! w7 l7 q' r
{ & [0 T( w& e! n8 w
   
" D4 ^4 _: T/ h) j3 B  if(!InstallHook()) ' J- B2 E6 X! P2 D
  {
1 j- P% w0 U6 _    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK); ; I- b8 r1 u# s/ c# d
    return 1;
4 v, Q# F: s( P" B+ Z  }
+ ]2 t: r% \; S' N$ r* Q5 C   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
# I0 L' {5 s$ r8 S$ [8 ^  if(!UninstallHook())
. ~2 @+ F. J' }8 W  {
0 @! I: ?. d& I& H, }  [    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); + S( t/ x! ]% X# W7 |, e3 f
    return 1; " b9 ?# m1 f5 z& S" I
  }
0 b. _. ]6 b/ O. \9 e  return 0; 3 u; b$ Y* s% W6 P+ A4 X, h0 V
}
/ ]- Z% _6 _" `6 o2 Q6 j
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

6 I, h8 ~1 [& k9 U0 b
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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