下沙论坛

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

用新浪微博连接

一步搞定

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

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

6 J& V; u% C. }! X) C1 r发表日期:2003-10-30作者:tomh[] 出处:
4 t; Z. k2 A" v/ z. X) K; N9 c. C' \8 [Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 2 ^$ A( }" O+ Z3 p0 z! i& S) @) P1 g
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, , X9 z5 K+ h/ _) `
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为:
# |1 Y8 N  o2 `. ?7 `     BOOL VirtualProtectEx( 2 K! z/ {  H6 L; c% W* h+ Z2 U8 r
                HANDLE hProcess,   // 要修改内存的进程句柄 0 Q: T+ G9 O$ z4 V5 _; }1 n
                LPVOID lpAddress,  // 要修改内存的起始地址 + M. f# H% q5 E2 H+ O
                DWORD dwSize,    // 修改内存的字节 6 k2 X% p5 n8 x! w" ~  H% ~! F
                DWORD flNewProtect, // 修改后的内存属性
6 ?0 H3 M8 R% {  F                PDWORD lpflOldProtect // 修改前的内存属性的地址
! R* v2 g& X: @  n* v: O5 `+ X                ); , e  y( ]4 f- _' C5 I- i) k* p- Y
    BOOL WriteProcessMemory(
) y4 X1 }9 \( p0 X$ l( S/ t+ l                HANDLE hProcess, // 要写进程的句柄 ( ], Z1 t1 {& ]3 [! e. }3 c
                LPVOID lpBaseAddress, // 写内存的起始地址
. F: Y' f6 t* |# v, A; y                LPVOID lpBuffer, // 写入数据的地址 6 V3 E, C0 g6 |, v% G/ V
                DWORD nSize,   // 要写的字节数   @$ \: O4 ^, j! o
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
- b: Y; j+ J  c0 B                );
/ g; x" t* O0 M3 l    BOOL ReadProcessMemory(
  f5 v: q8 \' o                HANDLE hProcess, // 要读进程的句柄   x$ ]9 [2 z6 n, D8 S
                LPCVOID lpBaseAddress,  // 读内存的起始地址 2 E4 _; b5 y3 s- C8 l
                LPVOID lpBuffer, // 读入数据的地址 ) @6 _" B( ?' E
                DWORD nSize,   // 要读入的字节数
/ K( ~: y" @/ {- A6 A+ c2 o+ c                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数 5 X' f& `4 L! ^7 D) S2 E" f
                ); * f( G% p* c- [5 f% w
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, . ]( p/ R7 O) P' X% G
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明:
5 {- P# l' U* T# W4 R" e6 U其中Dll文件为: ' }' _% N9 X2 V2 Y
     HHOOK g_hHook; 4 n' i, W) h% D8 r) q/ m( }* E
     HINSTANCE g_hinstDll;
" |+ f3 C' _" f: Y     FARPROC pfMessageBoxA;
& c( k. G: M6 {, ~2 u/ u8 C9 a( H     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
4 w( N, ?+ b; d" F" b' X5 @     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5];
1 X7 n8 Y$ D" T" X     HMODULE hModule ; 4 }/ Y+ G  S3 {. \
     DWORD dwIdOld,dwIdNew; 8 P; @# j3 l! j6 h; h* N
     BOOL bHook=false;
. l# O$ f7 P; \! Q3 i: N4 a# f7 Q7 [8 N     void HookOn(); 3 W& O& {9 d! K: B
     void HookOff(); 7 r3 {% u" a  B/ S8 Z. A
     BOOL init();   w, z- Q( h6 r8 p5 y3 T& O
LRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam); % `3 ^+ Q+ v' ?( u) \# ?+ E+ P
BOOL APIENTRY DllMain( HANDLE hModule,
/ N6 T/ c! X+ J* U9 x' m            DWORD ul_reason_for_call,   l" l1 A3 p$ x# O
            LPVOID lpReserved 7 B  M% O4 p0 m% i8 F" Y
           )
# ^6 r: f! h  ^' C- y{ ) A! e5 K3 ~/ k( K7 W! ^+ I* ]
  switch (ul_reason_for_call)
) o: H$ \; s& d; c  { $ ]; u, ~7 h; J8 b! d- h/ a
    case DLL_PROCESS_ATTACH:
- ~' M$ I/ y9 C+ P      if(!init())
- N' G5 j) d" ]4 Z: ^( V      { 7 K$ P! a0 y9 w1 w6 N
             MessageBoxA(NULL,"Init","ERROR",MB_OK);
9 W# r3 s* j9 U! \             return(false);
  [1 I) N( Y+ o# L' a% w      } # |$ r' |% I4 x. t0 |2 d
    case DLL_THREAD_ATTACH:
4 d6 ?: N8 F. e, j+ E. j    case DLL_THREAD_DETACH: 3 p0 a" v7 c; U- X8 Q# O
    case DLL_PROCESS_DETACH: / |. q0 I3 ^& ^: L6 x# m
           if(bHook) UnintallHook();  3 {6 Y) i1 ?7 l( d, @; j
          break;
, p5 S3 f- O8 O9 _  }
. I4 |: n0 T: U$ B* [  return TRUE; & ]1 n: H% g* i) }
} % U" e$ \1 e2 W6 E  d( r" z8 n* R
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
1 X* g% c% W; l; n0 m- @{ 0 u/ u6 h2 v7 j9 N
   
8 H$ T5 X1 R5 W2 T/ ]; _* M  return(CallNextHookEx(g_hHook,nCode,wParam,lParam));   G1 V( E1 e2 G5 Q9 S5 c9 {$ ^
} ; b8 ^8 A4 z  v) ^
HOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数
! n0 G4 y  d! [+ r5 d& c{  1 S: \! D$ {: _2 M5 |
  g_hinstDll=LoadLibrary("HookApi2.dll"); 1 |7 c# J0 D% E  l$ L/ a
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
5 a& `5 u& n! f1 ~# _% lif (!g_hHook) 7 Z0 Q. C4 X) d6 v5 |) E$ b
{
( |& Z: U/ T9 m% g    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
+ `) m, r* L0 R- d4 H! Z    return(false);
1 M9 _% ?) m8 V* T1 S7 f  E  }
, @# l( o4 |* O4 i& F; S" U  
- A9 R4 _% w$ V9 x1 V2 i      
2 v9 a2 O6 ~. q! H6 w( d$ t  return(true);
2 y' K: N! a$ Y}
$ V/ N: }4 F/ |6 S7 L! W" LHOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数
9 s/ ^0 [; J) g1 l% t5 C{ . P4 K3 b; Z. K2 `. X& f8 V
  : F% v4 ^' F# j
  return(UnhookWindowsHookEx(g_hHook));
# v+ q# M7 w4 |% G} 1 W4 `! `7 o! p0 k3 f  W. Z0 F
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
4 D3 g% z) e% _5 _{
7 T: J$ y2 R# t, a* C3 r, k# u  hModule=LoadLibrary("user32.dll"); & N/ S/ e0 \9 ^
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA"); 8 n1 O! h) k5 Y/ _) j/ l, Y
  if(pfMessageBoxA==NULL)
$ \7 {; o- I1 x/ z* N   return false; . M/ ^) j  V3 a1 I5 y% f* d- |7 x
  _asm
( l( O# G- T: H3 h8 S* Y" o7 j) D  {
% j& M/ ]/ I/ R) y  Z- S/ [# L3 T) c4 T5 P    lea edi,OldMessageBoxACode : A% m8 @% P0 y  `4 @6 n
    mov esi,pfMessageBoxA
# D0 z; Z5 B/ {) ]1 V, O    cld . i% Y% u% X# c8 `/ j
    movsd - a( N( B( w% o( a
    movsb + j0 l9 [2 O# ?3 A. G
  }
# G2 B1 v& O  O2 M' L& a  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令
+ e5 t8 c$ S6 Z/ E1 R  _asm   w* G* B) p0 X
  { ( ~! I/ [4 p" q# K( W4 N* @4 R
    lea eax,MyMessageBoxA 5 x3 z5 w) U( I; a8 q8 W+ C
    mov ebx,pfMessageBoxA
4 i+ q' g+ v7 c! J7 C    sub eax,ebx 2 v0 P% W$ ]7 F# g7 @) k6 i0 e/ C$ A
    sub eax,5
/ E+ I: p# W; K' c    mov dword ptr [NewMessageBoxACode+1],eax # I0 b% ]8 W. x( b+ [
  } % @' c0 }" J( I8 u
  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID 8 g/ e0 N5 M. n5 W4 C+ Q, T
  dwIdOld=dwIdNew;
! t; _" h8 c: d$ |' X# I  HookOn();//开始拦截 + x! ~1 y2 X" |" c1 i+ c$ z! G! h
  return(true); 1 M& G& {' B( q+ t- i& ^# O
} ; t& Y9 I" y# l/ o
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
: _: G, \/ k, u* ]. T; _& X{  " ~$ ^- d& v7 w
  int nReturn=0;
% X2 ^; q, i8 q  w7 |) A  HookOff(); 0 ?3 e4 i! S( c' B( X- M% _5 X
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType); : U* y) I7 B' @  `) |
  HookOn(); 5 u6 d8 i; Q( [* O
  return(nReturn);
% M- r1 S+ ^* `1 s} ! N$ [/ J9 `  y  j# C4 g
void HookOn() 8 S3 J% f# T+ M1 |2 y1 n" d
{
3 g: @: f" U0 w7 F) O$ W: ?, n# m  HANDLE hProc;
* y- ]# ^1 _$ Z- v2 a7 D$ R/ W2 H  dwIdOld=dwIdNew; % l5 F! ?' W1 J& ^8 T% s( G7 f
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
' A4 j1 g9 B0 `% R  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
$ L) i4 Z0 P4 R& V" i  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA
3 P; U0 q4 \: [6 V6 v+ A  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
) b# @1 s. W( D! U- G/ m% |3 b  bHook=true; # v) `) u7 W9 C! }) \
}
( `7 [& t- z- R; yvoid HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA
4 x/ x; R2 ?. m{
6 A6 O; y5 n: p- G, F  [  HANDLE hProc;
- L7 j  @' k4 v6 Y  dwIdOld=dwIdNew;
, K- N+ I: u9 c3 y  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
2 s# y4 i# Y$ D7 k  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
: R8 J* w* b5 u- K  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0); : B0 R& ]6 y  m0 Q
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);
# M. z# s2 U  c: J- d  u" S  bHook=false; 5 ?, T. \! h0 Q; Y
}
) {+ t3 @! A1 t  p/ e+ \) j9 w//测试文件: 8 u8 k8 ?+ H2 Q( J1 w: h
int APIENTRY WinMain(HINSTANCE hInstance, 9 _: u- X* ]* H! Z
           HINSTANCE hPrevInstance, 4 z8 V; i& j1 W
           LPSTR   lpCmdLine,
. Y& `" z! L4 F4 s/ `: c- M: I           int    nCmdShow)
6 _) b! S8 N* U3 R1 ?! c  g{
. n% y" l: Q0 y2 Z: i7 g& i: a  F   - t% q1 d4 P6 n! M; h# G
  if(!InstallHook())
. H4 ~0 d7 y* ?; I0 |" @  { ; ^8 `! |9 R4 X' F: [, L7 Y8 T  W' m
    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
0 a7 D* ~- c- ?% v% V: ~    return 1; & V; J  s; K6 |
  } 7 L: a& v3 f( R6 U
   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见 & i# [! h  Q  J& ~4 v+ c
  if(!UninstallHook())
6 |! o5 o' ?6 A: \( B  {
0 L) ~% Q$ s; s$ z    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); 1 k5 P$ a" d3 T$ {! b- r
    return 1; * x% P# Y, g; z5 x. M
  }
% Z5 J- N; j: C0 g# U5 k: Z) s  return 0; * ~8 [/ t5 [3 z4 }: ^: T5 [, q  E0 _
}
& O( _6 o' r- l" w7 `
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

( ?: E9 K  I% [% F# R' ?; o
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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