该用户从未签到
|
8 H* O) o& j) ~& `# W" p1 @' K发表日期:2003-10-30作者:tomh[] 出处: 5 p; X( @/ [: ?, _# m! \0 j( f @
Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 9 O3 @& T: y4 f& p- W4 } B3 R
本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, 1 a. f; G/ N, w1 m: a z# U
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: ; }" R, l4 f0 V$ v) I1 h9 n
BOOL VirtualProtectEx( ! D$ P" j: s* I" `
HANDLE hProcess, // 要修改内存的进程句柄
6 {+ V$ V( f$ Q6 O! G; g, s; T) |9 r LPVOID lpAddress, // 要修改内存的起始地址
7 E* R( z7 L& b$ E5 }* U DWORD dwSize, // 修改内存的字节 " w2 ~3 ~/ }8 q6 W
DWORD flNewProtect, // 修改后的内存属性 : K, T' W% n. R5 |" |+ c/ ? z9 O
PDWORD lpflOldProtect // 修改前的内存属性的地址 * b5 I2 J Y' o/ y7 S: ], }- y
);
% A. a+ k' f, u+ s% s% h F% f BOOL WriteProcessMemory( 2 t2 W- G! k" ]1 a+ K1 X
HANDLE hProcess, // 要写进程的句柄 6 C3 X+ u1 l& h4 n* |
LPVOID lpBaseAddress, // 写内存的起始地址
, ^$ ]* I7 o$ h LPVOID lpBuffer, // 写入数据的地址 ( r8 M: [% o P* `1 O$ H
DWORD nSize, // 要写的字节数 ; A/ M( f; Q& Q0 e5 W/ u0 S
LPDWORD lpNumberOfBytesWritten // 实际写入的子节数 & V' G$ Q5 u4 T+ z# k- t6 G7 N
);
& T" p2 h# J. z BOOL ReadProcessMemory(
- V; }5 N# G# N- r } HANDLE hProcess, // 要读进程的句柄 0 ?; j( Q4 ]/ b" m
LPCVOID lpBaseAddress, // 读内存的起始地址
1 f. G) k8 V( _& q LPVOID lpBuffer, // 读入数据的地址
+ U Z) ? ^2 o R5 ]7 f! I4 u DWORD nSize, // 要读入的字节数 2 S3 d, }6 u/ ~! w
LPDWORD lpNumberOfBytesRead // 实际读入的子节数 * u. c" k' X# b2 |9 r2 f% i2 i6 a1 a
); " D. ^7 B0 H1 S
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, " C! M, J5 W, q6 s& P; y' Z* v
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: ( a: f7 u: O+ t( m/ Z/ X8 M
其中Dll文件为: : q) F* d& L: I2 `2 P5 u
HHOOK g_hHook; / M5 m3 h4 U( U p' b
HINSTANCE g_hinstDll;
4 Q5 s% u1 P l9 w; m! x% h3 M FARPROC pfMessageBoxA;
- W: x6 u8 A, T& [5 z& l# h/ i int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
1 {+ \: ^$ h6 w5 t% F. V* V1 y& p BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; 0 t# h b- N/ R, I
HMODULE hModule ; 1 S# G2 H6 S( N% p* Y) Z0 V
DWORD dwIdOld,dwIdNew; . f2 r8 y1 I( Z: W
BOOL bHook=false; # t" x" Q1 Z, H1 a& ?. G
void HookOn(); 6 e' T* c% X2 z* |( ?# L3 `+ W
void HookOff();
; w/ a Y4 y: a& W2 P8 M BOOL init(); $ R: R" I6 ?' T
LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam); 3 ~# n1 T- z- i. E8 f, [0 f1 c
BOOL APIENTRY DllMain( HANDLE hModule, $ `' z1 w6 l, h; M! \$ t
DWORD ul_reason_for_call, ; X& o4 R* k0 |& z9 a
LPVOID lpReserved 1 b, Y G- e1 C) M" G- v1 @
)
- X/ U' @. z3 b# n{ , F& f% V) J- G5 O! _
switch (ul_reason_for_call) : G% k6 }- Q3 B O
{
! V' Z6 O/ a4 \ case DLL_PROCESS_ATTACH: 5 F& ]$ C6 a5 d& L: q! `
if(!init())
^ D8 j- T5 N3 U. e& m' ] {
- s5 d* z, m/ Y2 d, h MessageBoxA(NULL,"Init","ERROR",MB_OK);
6 y- f/ k' B, g: F, _1 q) o: X return(false); 1 z& Z+ J1 \. i8 B1 Q3 |8 y
} 7 j& Q1 Y8 w6 j7 a
case DLL_THREAD_ATTACH: + b0 B" A1 W8 Y, W1 E3 A6 H) x
case DLL_THREAD_DETACH: + g- k6 F' G1 |! _7 G" \
case DLL_PROCESS_DETACH: # [/ b9 i. m+ E3 ]
if(bHook) UnintallHook();
( B; E2 U2 W1 a- H: {; p) T break;
" A# _( I$ u4 G4 \; s } ( ?4 [, v, @+ A# D, B+ m' P
return TRUE;
) w2 V; M& |6 C3 B} 4 P% x1 V# E7 _5 K$ M0 x0 c; j
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
4 e- k5 \* O t; T. ]/ J' ]{
4 T1 b) \' L: g- j, `* d) L
6 \% p, w [! h. C4 l3 p return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
1 H4 |- X* F' s) T}
% Z- B+ l" l" Q, o+ DHOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
( I7 F! R7 {' y8 F. t% I! \1 D0 H{
" E- V9 M! l" h3 ?+ T g_hinstDll=LoadLibrary("HookApi2.dll"); 2 m8 B$ p0 p, {: o
g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
( }1 {, g5 y" U3 J- U3 B9 Sif (!g_hHook) 6 u2 {0 v w6 _9 j# h, {# Q
{ * p- ?9 @+ S5 _ _2 y' D
MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
! C$ w' C8 c6 S! _% |2 T0 n0 U return(false);
! o! h; h! K# D' z0 u* U( R. _$ { } $ C, ~, m" |( ^: r/ B; q
8 s/ W) S1 ^0 w$ }7 S
1 Z9 e7 P) S( e" \7 r4 x return(true); , g1 x, S& N, {% _$ J) v/ \
}
; C, {: L) ]& \/ x5 [( ZHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
, l6 x- R- A4 M9 O$ i; t' L{
4 v" g) ]5 {; s7 N/ H- T, q# [ : F/ v; l7 {7 b$ T ]( Z
return(UnhookWindowsHookEx(g_hHook)); 5 p0 J, z+ C' Z* A. A) s
} - e$ w: n5 O& B/ x# `
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令 & m. W' p8 j, t1 q" |
{
: W" F. _ S0 }$ R' e hModule=LoadLibrary("user32.dll"); / \) Q. [8 Y* G. O2 w% J/ h& D- s
pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); ' H- B* A8 n; L! l5 z4 R5 L y
if(pfMessageBoxA==NULL)
6 F) Z0 g# {1 d$ j. C return false; ( C- {# S, U. ` [3 A* o
_asm 9 X/ d/ b8 J% I
{
+ y3 y. d% s' z# u) d lea edi,OldMessageBoxACode . `8 T: w# d: i/ S- k: h3 `( h
mov esi,pfMessageBoxA 5 J+ t7 a# S7 i* [& k8 h u! W
cld - J) x; O8 ?( l) H9 a. U
movsd ! p8 Q+ u8 X; A( B* [1 R& ]" l* y4 N7 f
movsb / X% z3 l1 E' c( W3 T5 f
} ! s7 }$ B5 K! `. y, N! k
NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 6 j, D# r' h7 b- }3 s; B# _1 A
_asm ' e. h' l$ m3 Z& _8 i8 {
{ - P3 G7 |8 z% ]$ c7 J( i
lea eax,MyMessageBoxA
' W8 o8 U2 f/ Z8 h mov ebx,pfMessageBoxA
" ~% g7 V- |+ @* t% I7 a/ x+ M7 g sub eax,ebx
- U5 z& ~2 J. J9 j3 B" h( m9 T) l sub eax,5 1 S L5 N+ h, L3 H4 F) C
mov dword ptr [NewMessageBoxACode+1],eax
% k; W8 m( |3 w$ G) f }
. k/ [$ Y0 j/ e. p dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
( K- U$ C5 R. L' }8 Y( w dwIdOld=dwIdNew;
& d M7 N* f5 |: o, k HookOn();//开始拦截 7 Y1 i/ w9 _3 h$ O% T% R# E
return(true);
# Q' N! w) |. N2 Z8 x* n0 Q/ x}
w1 W1 ]2 C! X4 P( R6 g3 N5 [int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数 9 }0 Z$ t$ \+ Q3 A5 A" \( F' P
{
, K& |: @0 J5 b0 |# s" l5 a( Z5 m int nReturn=0; , ?5 l' e* C1 h/ o$ ^1 [
HookOff(); 3 |$ x J. a/ q' E( `
nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); ; i8 T7 I1 z: _
HookOn();
) H+ G$ }& t5 p: }7 O0 P" R return(nReturn); & Z. y+ i' d/ h: r' @1 p
} 0 N/ [2 P7 U/ A9 n Z- W* s
void HookOn() & g( y2 R" _7 M% u$ x
{ - Z9 }7 _- W( u" R1 p6 }
HANDLE hProc;
- U! g2 w5 R% @) A8 w0 o dwIdOld=dwIdNew; : ?+ X7 u; P7 F. y5 K, l2 c
hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
) s( p- _5 K3 G% {# X VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写 , N" `2 O: g8 _
WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
, E% Y! F7 E1 ?8 {0 R VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
) M1 J$ E# _& v/ r. J2 w bHook=true; : R" X& c0 X7 G: S- ~
} 3 E% C' t S' x) L, W: S1 E) M
void HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA x4 K9 F$ E+ i( K2 Z. x
{ 6 ~9 G: l' Y) \
HANDLE hProc; 0 S& \; d4 [* N" }" [) H( ?
dwIdOld=dwIdNew;
( E" v: F+ [; o) S- ?" q @$ _: G7 C) b1 a hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
; y9 i0 R4 |- W- g- O0 d% x7 o VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld); : m! k# q+ z4 L$ O, i
WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); 8 b7 F* L. H1 e8 d7 v
VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); ) ~: `1 \% d& o2 N" V
bHook=false;
5 D$ m- W7 M# c. `}
( {( M/ h! {' p0 ]1 \* k- F( A4 h b//测试文件: , i5 s$ q) U( I
int APIENTRY WinMain(HINSTANCE hInstance,
( `: N6 {) [+ c( m8 U+ k, x. ` HINSTANCE hPrevInstance,
3 j0 z4 }* f# K& y$ _# t LPSTR lpCmdLine, ! r( _: C, r# P: B7 l, I
int nCmdShow) 8 K$ b- |, G" U1 C0 [
{ " I2 M% j- r9 I1 G; G& a! K, d$ M
$ d5 S' z! j& h, K; E$ t/ g
if(!InstallHook())
! U6 G8 y7 R% c$ w3 C6 B, {+ H { ; r9 l0 F1 s2 A
MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
K0 j# A3 z* G, Y return 1; 2 N* p9 {5 d. b+ ?9 I
} * ?$ t. W. e( J" _; ?
MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
& [1 G7 w4 u& Y* l3 T8 c! h if(!UninstallHook()) 2 a5 E7 H1 o; l7 S' N1 l0 f
{ 2 L- K( \, w; C# G9 M6 s% X
MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); / T. d( P3 L+ T& \- A- I5 P1 o
return 1;
. E+ M0 N1 W$ e+ F } ; T: F5 d$ b* d& T/ p, x% c
return 0;
. l+ i& N! C- _}
/ j& n7 ~& s& R5 Y( W[此贴子已经被作者于2004-11-5 18:12:27编辑过]
; i3 \% d; L% R, q |
|