下沙论坛

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

用新浪微博连接

一步搞定

QQ登录

QQ登录

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

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

[复制链接]

该用户从未签到

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

3 @: K2 d+ D- U; \- c9 _% {发表日期:2003-10-30作者:tomh[] 出处:
; W: w+ @8 o5 [Api拦截并不是一个新的技术,很多商业软件都采用这种技术。对windows的Api函数的拦截,不外乎两种方法,第一种是Mr. Jeffrey Richter 的修改exe文件的模块输入节,种方法,很安全,但很复杂,而且有些exe文件,没有Dll的输入符号的列表,有可能出现拦截不到的情况。第二种方法就是常用的JMP XXX的方法,虽然很古老,却很简单实用。 ! v0 ^/ k* q7 L7 j6 w/ Q
  本文一介绍第二种方法在Win2k下的使用。第二种方法,Win98/me 下因为进入Ring0级的方法很多,有LDT,IDT,Vxd等方法,很容易在内存中动态修改代码,但在Win2k下,这些方法都不能用,写WDM太过复杂,表面上看来很难实现, ; P* S  F8 m/ k1 V
其实不然。Win2k为我们提供了一个强大的内存Api操作函数---VirtualProtectEx,WriteProcessMemeory,ReadProcessMemeory,有了它们我们就能在内存中动态修改代码了,其原型为: " Z- ~" l! b$ j2 y3 o+ q# P) @& ^
     BOOL VirtualProtectEx( 9 ^+ [- p% |. n
                HANDLE hProcess,   // 要修改内存的进程句柄 1 w, F* J" p5 B3 Z5 a+ _" C' @' ~3 {
                LPVOID lpAddress,  // 要修改内存的起始地址 + n0 ?  x: V0 G9 f! [- \+ G
                DWORD dwSize,    // 修改内存的字节 # ^  ~6 c6 t$ J
                DWORD flNewProtect, // 修改后的内存属性
. }# g/ T3 P& n0 c/ w                PDWORD lpflOldProtect // 修改前的内存属性的地址
" {7 f" O5 g0 a) E2 \( g. g                );
8 w' J( E8 {9 Y7 F    BOOL WriteProcessMemory( 7 m% [3 O' j6 X+ K
                HANDLE hProcess, // 要写进程的句柄
; |- G# `2 Q( E/ n. x( R/ Z                LPVOID lpBaseAddress, // 写内存的起始地址
$ O6 {3 U+ N7 r, w$ }                LPVOID lpBuffer, // 写入数据的地址
/ ^, {  ~3 i: n  b                DWORD nSize,   // 要写的字节数 ! y) R0 Y6 i( I2 M6 W4 e( c& h
                LPDWORD lpNumberOfBytesWritten // 实际写入的子节数
5 e) `; D1 t3 P# y0 G                ); 5 }2 \2 ^' K1 E8 L
    BOOL ReadProcessMemory(
, Y2 }8 d; s+ X, `- R                HANDLE hProcess, // 要读进程的句柄
) ], H1 v+ }# M                LPCVOID lpBaseAddress,  // 读内存的起始地址 ) L1 ~, M, |# J9 A8 D, J
                LPVOID lpBuffer, // 读入数据的地址
& r  W3 ~' W7 a8 V! {  L                DWORD nSize,   // 要读入的字节数
. k  F7 Q+ G& a" U                LPDWORD lpNumberOfBytesRead  // 实际读入的子节数 2 F2 i+ D$ K% m  q8 L; Z* J8 Z
                ); ! e& U% X. h$ N
具体的参数请参看MSDN帮助。在Win2k下因为Dll和所属进程在同一地址空间,这点又和Win9x/me存在所有进程存在共享的地址空间不同, ) K" Z: o/ l; h
因此,必须通过钩子函数和远程注入进程的方法,现以一个简单采用钩子函数对MessageBoxA进行拦截例子来说明: # u, R, P: D5 ]4 S3 J
其中Dll文件为: ' f, }5 V  f% p) v
     HHOOK g_hHook; + A, R; m$ N" F8 t# a
     HINSTANCE g_hinstDll;
8 {4 p- F% F4 H( t" _2 e1 F     FARPROC pfMessageBoxA;
9 k5 G# t; `8 O5 g/ q4 C" Y     int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
* [) ^" M6 }7 E4 a  A     BYTE OldMessageBoxACode[5],NewMessageBoxACode[5]; 7 u) Q5 }# Y- I& m' D' v
     HMODULE hModule ; 4 ?7 ?5 B7 s3 T2 e$ A6 G# N9 n* ^8 _
     DWORD dwIdOld,dwIdNew;
5 [4 c' R( U3 `3 [1 t( ]     BOOL bHook=false;
) x+ _! n% l! x     void HookOn(); . c& l; `; u; z* b5 y' i2 b
     void HookOff(); 1 L5 n9 i# a! B9 ^2 D& R: m- H
     BOOL init();
3 q, B" U) g6 HLRESULT WINAPI MousHook(int nCode,WPARAM wParam,LPARAM lParam);
. V# v9 `1 \* ]3 X) d7 DBOOL APIENTRY DllMain( HANDLE hModule,
- k% `- D7 q, R1 Y( ^            DWORD ul_reason_for_call,
6 H4 U, ~( V/ T( V- @4 S! z            LPVOID lpReserved   |  U3 X' j2 N3 }$ Q8 J6 @
           ) 3 r4 s5 g6 L$ C" @; N6 H1 S# u5 l
{
& i0 u9 l3 N" }; j) f: U  switch (ul_reason_for_call) . ~- j: k! h& o) t: u; V
  { ( S: }" R) N% z2 |+ c
    case DLL_PROCESS_ATTACH:
/ |7 g6 }% @! c; _' Q0 U* {      if(!init()) 9 i- _% i1 G0 Q0 N+ s' L
      {
( L" V) p7 B$ ~: Y             MessageBoxA(NULL,"Init","ERROR",MB_OK);
( q# p6 i! `# B( g* S" @6 T             return(false);
0 F% G) }6 O6 r  G; w4 H$ V      }
% N* S" P( ~% h; J* i7 C  E    case DLL_THREAD_ATTACH: + G3 w  f/ `: G0 S
    case DLL_THREAD_DETACH:
( z4 K( ?! @' n6 ~% l0 ]& ~9 U5 Z: |    case DLL_PROCESS_DETACH:
$ R/ n, `+ \9 x+ y           if(bHook) UnintallHook();  ' N" s9 N$ Q4 r0 U! a
          break; $ P- B- a, n( n% h8 X; O  Q9 o4 X# N
  }
* f- f4 g3 [3 w1 ^: a+ j  return TRUE;
% N- K' ]4 h3 Q8 ]} 2 |. u' `5 g% j4 X0 x3 _+ J" _
LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
7 K6 V6 X. y, P  q{ - L+ F3 `& j9 e: v* K9 i
   
# w( t# S- f8 |3 R( Z9 {  return(CallNextHookEx(g_hHook,nCode,wParam,lParam));
2 r' ]' [9 B! ~- q}
3 O! }+ Q5 K' l9 W& OHOOKAPI2_API BOOL InstallHook()//输出安装空的钩子函数 ! A; q' t- ]* s9 m% ]' {
{  
0 U, z+ [2 \" a! Z4 D  g_hinstDll=LoadLibrary("HookApi2.dll"); 3 r9 S) `( u! {( p7 y! ~
  g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,g_hinstDll,0);
" v+ v; j( y/ l5 F9 n2 jif (!g_hHook) % `7 n& z( R9 _  r1 S+ v4 I' u8 ^/ X0 r
{
) @9 K, p6 X! m" w' l% y    MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK); ) {' J6 q/ u8 n: ~7 x+ h+ `% {
    return(false);
3 f! a0 Q; ?  `: m" ?$ b  } 8 t: @" |! L( y; a+ H
  ) `" I# F& g+ W" M  ]
      
# i0 U" R0 q6 m/ v8 x5 V1 u  return(true);
6 Y3 `/ ]6 z3 o3 J; H, D$ `' G} & X" U4 U5 l- r7 M4 ]
HOOKAPI2_API BOOL UninstallHook()//输出御在钩子函数 + Y4 P. x0 L1 x; _7 Y" Q) d
{
, |& H$ J, G" Y0 ]/ p: I  + H% Y0 i7 v+ \5 |6 V1 R
  return(UnhookWindowsHookEx(g_hHook));
9 W2 i* J; v1 }% G5 o6 F7 T# @} 4 C+ ?; u0 m& j. P1 S
BOOL init()//初始化得到MessageBoxA的地址,并生成Jmp XXX(MyMessageBoxA)的跳转指令
' P$ J" ^* X6 v3 A8 m# T9 L{ + B# d# e) W/ Y% n* Y
  hModule=LoadLibrary("user32.dll"); : X, `2 U' H3 z: ]$ o  \% o6 P
  pfMessageBoxA=GetProcAddress(hModule,"MessageBoxA");
5 b/ N$ P4 J) `& s0 d* _& X  if(pfMessageBoxA==NULL)
8 Q; o% v, p+ K& D/ T' j. P4 H4 i   return false;
  h) M6 l' |/ u' p$ h. Z  _asm
& h* ~2 }! u, G6 @9 Q  {
' U% v/ {7 o+ s* |5 q# b. d' H% R+ p    lea edi,OldMessageBoxACode
. }6 d& p2 U9 `: ^    mov esi,pfMessageBoxA
0 a* U8 n, U  I, z    cld 0 Y1 \4 \$ H, \# X
    movsd $ Q/ s! V' b8 M
    movsb
8 p: m" ~  K( j- ~# q! T7 u; Q& S  }
* Y# H, Q7 \1 _4 m* ~1 e4 h# {, S0 A  NewMessageBoxACode[0]=0xe9;//jmp MyMessageBoxA的相对地址的指令 + d8 n$ C5 J4 U+ M- S$ H
  _asm
1 c5 u, e. j  G* N3 u8 y  {
7 Z% `. @& F9 L. X& m- S; \    lea eax,MyMessageBoxA 8 B0 l$ i- `4 `5 W- j  `2 g6 h
    mov ebx,pfMessageBoxA " V; h9 l/ {1 o: a. R
    sub eax,ebx 1 Q" _9 v5 |  ^3 n& W8 m# c! e
    sub eax,5
1 C) G: C1 A' k0 @) h: J* O! O    mov dword ptr [NewMessageBoxACode+1],eax 5 ?: U2 y4 a* t0 a
  } ) U1 G% i! g$ u" Q  w: u* o
  dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
; i& \8 }; f0 z% \  dwIdOld=dwIdNew; - r3 Q0 ~5 U/ N0 Y% j
  HookOn();//开始拦截 $ ^3 T: m3 H5 R6 U( a% u
  return(true);
& u/ D' Y3 p! S3 ~; S% ~} ' B( I, x9 H% F& Q# \3 }$ }
int WINAPI MyMessageBoxA(HWND hWnd, LPCTSTR lpText,LPCTSTR lpCaption, UINT uType )//首先关闭拦截,然后才能调用被拦截的Api 函数
: S4 ]7 ^$ d" z' j; ]{  4 Q0 R, ?% \4 I
  int nReturn=0; . `  q; v' |+ u* |" \% L& z3 Z
  HookOff(); - F" j- B- T% E6 h
  nReturn=MessageBoxA(hWnd,"Hook",lpCaption,uType);
9 s  D# x2 E" H$ W6 k% ?# e% ?  HookOn(); 6 f6 P3 ]; A( H; I5 f
  return(nReturn); + r  }% ?$ @% ?- M
}
+ M0 P0 @' q2 |0 M' E+ \, Vvoid HookOn()
  a, Y+ |' K  [! B! n{ / _& |' k1 J( y" J
  HANDLE hProc;
' m9 e( S% Y! F  dwIdOld=dwIdNew; 0 X8 d' l8 y4 ?+ G
  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
; B- H6 E" L4 z9 U! v) U* ]% c  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为可写
. u5 J/ c! d; n. ~3 N  WriteProcessMemory(hProc,pfMessageBoxA,NewMessageBoxACode,5,0);//将所属进程中MessageBoxA的前5个字节改为JMP 到MyMessageBoxA 5 S4 E* Z  s& m( c1 y+ s* o
  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld);//修改所属进程中MessageBoxA的前5个字节的属性为原来的属性
/ h# W9 Q  Y: Z  bHook=true;
: Y" j* W4 v: e- V2 C}
  r6 B0 [+ @8 H) w$ nvoid HookOff()//将所属进程中JMP MyMessageBoxA的代码改为Jmp MessageBoxA ( a# m% b, H, ]3 G4 R
{   L# N" F4 E3 B8 @# S
  HANDLE hProc;
6 Q  @4 m/ c) c  dwIdOld=dwIdNew;
: k5 a0 V" c; a) S: v8 Q* q  hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld); : o, Q1 ?( v& [" e9 ]
  VirtualProtectEx(hProc,pfMessageBoxA,5,PAGE_READWRITE,&dwIdOld);
9 [7 F7 j- U  D  WriteProcessMemory(hProc,pfMessageBoxA,OldMessageBoxACode,5,0);
% f- M" {  m* b5 ~  VirtualProtectEx(hProc,pfMessageBoxA,5,dwIdOld,&dwIdOld); 4 u5 w& }; ^; @- K
  bHook=false;
# t5 x6 }3 H1 d& o}
" S$ {7 i" @5 A! {( F//测试文件: , y3 W7 O% p4 n/ }6 b' L
int APIENTRY WinMain(HINSTANCE hInstance, & c/ a# ^. a- Y7 w+ I
           HINSTANCE hPrevInstance, , b/ H2 u( Z7 T7 [
           LPSTR   lpCmdLine, $ h- a, @1 Y) R; ^+ Y
           int    nCmdShow)
  j1 r  B! @3 N3 d4 ?{
8 B3 I4 r, y2 D$ z# A  t* M$ |1 O   
9 Y1 I7 |, V. p' n* Z8 o7 g  if(!InstallHook())   m- T, D3 J' v* p" [
  {
! p# [5 H; V. P# Z8 q( z    MessageBoxA(NULL,"Hook Error!","Hook",MB_OK);
, Z7 U% O5 f& A7 |; T* L    return 1;
2 _  c/ X# M- I: I& Y: \, u  }
3 A: f; G/ f, k) W8 T: M9 q0 _   MessageBoxA(NULL,"TEST","TEST",MB_OK);//可以看见Test变成了Hook,也可以在其他进程中看见
. _3 y7 F* }, B4 y& d  if(!UninstallHook()) 6 d$ Q& O$ b% u! }
  {
6 u5 W& e6 y1 F! c4 a    MessageBoxA(NULL,"Uninstall Error!","Hook",MB_OK); : \2 z+ q/ U: b3 J
    return 1; 2 E! Y( h* B. q4 C# P( L- ]
  }
. y: E; M6 ?  Z# F# s# m5 l  return 0; 3 I( x6 T; ?/ L' H6 y
}
% g+ l. {7 _% X( @" A+ ]
[此贴子已经被作者于2004-11-5 18:12:27编辑过]

4 M/ y/ h# G' y/ o  C  O
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

该用户从未签到

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

好眼熟……

该用户从未签到

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

本版积分规则

关闭

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

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