【转帖】Windows Hook (3) API Hook 续 拦截API

上一篇 / 下一篇  2010-01-20 12:04:24 / 个人分类:C++

 
51Testing软件测试网+Z'N.{ h.I*\dV oA

51Testing软件测试网z;T8A/O(Z)}

51Testing软件测试网:^%~ F E {

    本来计划中是没有这一章的,但自从我的Windows Hook 易核心编程(3) API Hook发表以来,得到

p5xe?1Fh0

F6~C[i ],`I(~0了广大易友的支持,这种情况很令我感动,于是再接再力,写出了这章,希望没有辜负广大易友对我的51Testing软件测试网#~y$[!p(L#C%O

51Testing软件测试网;U.F3B,}j Vk

支持与信任,好,废话不多说了,我们言归正转.

|\1xJ)p'[ o C Y051Testing软件测试网U0E0[%u ZsY8q6C8N [

   在开始之前,让我们先来回顾一下:

2a zIi8A,x0L5F051Testing软件测试网~4TN5^ h h2gla)M

什么叫Hook API?51Testing软件测试网 [-wP2u-hu#SP9T
   
b3pk-W%K/cl0    所谓Hook就是钩子的意思,而API是指Windows开放给程序员的编程接口,使得在用户级别下可51Testing软件测试网,K1U$q2bi Me*b

)WUAP K6mg0以对操作系统进行控制,也就是一般的应用程序都需要调用API来完成某些功能,Hook API的意思51Testing软件测试网U,UX#FT(n_M

~1GC5U#cZ0就是在这些应用程序调用真正的系统API前可以先被截获,从而进行一些处理再调用真正的API来完

+x KH)\6U`fH@e0

G Mp/r }#Oi,c)l,tY0成功能。在讲Hook API之前先来看一下如何Hook消息,例如Hook全局键盘消息,从而可以知道用户51Testing软件测试网.L.@z `(c Y;k!F ~

o _X.dBd$nNy-m]0按了哪些键.这种Hook消息的功能可以由以下函数来完成,该函数将一新的Hook加入到原来的Hook

?2L%F:v5l;i:t0

`5^!x.K7G9h0链中,当某一消息到达后会依次经过它的Hook链再交给应用程序,这个在我的Windows Hook 易核心

u1Po"r#hB/S0

{;wT%F \d0编程(1)和(2)里有具体的说明和应用,大家可以看一看.51Testing软件测试网hV+p4kL_ W~T

51Testing软件测试网8C,aE/IY,I

   .DLL命令 api_SetWindowsHookExA, 整数型, , "SetWindowsHookExA"51Testing软件测试网\F/`+[)?
     .参数 idHook, 整数型, , Hook类型,例如WH_KEYBOARD,WH_MOUSE51Testing软件测试网~ NKp-v*Em&w Vw8F
     .参数 lpfn, 子程序指针, , 钩子回调函数,Hook处理过程函数的地址,51Testing软件测试网#Cl;K;N;l*Fw
     .参数 nMod, 整数型, , 包含Hook处理过程函数的dll句柄(若在本进程可以为NULL)
j:[ Y%dP_0     .参数 dwThreadID, 整数型, , 要Hook的线程ID,若为0,表示全局Hook所有

(}g Z2DVf*K0

g7y}(L;Ul%^9Q0
5~B:A7Nd~\/~0.DLL命令api_UnhookWindowsHookEx, 逻辑型, , "UnhookWindowsHookEx"
;d{E/L'Bi b,ET0     .参数 hhook, 整数型,要关闭钩子的句柄.51Testing软件测试网Z~|^(wr0yp Y{{

51Testing软件测试网4j!BSH(]/[9P ~$]

    这里需要提一下的就是如果是Hook全局的而不是某个特定的进程则需要将Hook过程编写为一个51Testing软件测试网ia/o9Th&v!g0nhNUS

51Testing软件测试网xp/j'}H o/z`

DLL,以便让任何程序都可以加载它来获取Hook过程函数。而对于Hook API微软并没有提供直接的51Testing软件测试网,k/|h!O*]gw

n%C{|@+?0接口函数,也许它并不想让我们这样做,不过有2种方法可以完成该功能。第一种,修改可执行文

_*x l#V*_R051Testing软件测试网1q[5^*gF$d#a

件的IAT表(即输入表),因为在该表中记录了所有调用API的函数地址,则只需将这些地址改为自

_(C6i2|Xb:pe0

u}5l)r@2}0己函数的地址即可,但是这样有一个局限,因为有的程序会加壳,这样会隐藏真实的IAT表,从而51Testing软件测试网A8fGXA}

51Testing软件测试网_l U u$J

使该方法失效。第二种方法是直接跳转,改变API函数的头几个字节,使程序跳转到自己的函数,

:@$o|+`o R@p T:_q051Testing软件测试网lO6z x2]%G+d

然后恢复API开头的几个字节,在调用API完成功能后再改回来又能继续Hook了,但是这种方法也有51Testing软件测试网3B/h_Lze

J/H}%` X*G$xt0一个问题就是同步的问题,当然这是可以克服的,并且该方法不受程序加壳的限制。

3N!^}9s"]O r#h051Testing软件测试网Q4c7CeqH


"T5G{sn7{5@0   51Testing软件测试网J rA,a1{?(Bn/P
    上一章我们就是用的第二种方法,通过直接改写API函数ExitWindowsEx入口点为{195}(即汇编的51Testing软件测试网(^}.~ t'L

f$_X q5?7erS0返回命令retn),达到关机失效的目地,其实这不算是真正的API HOOK,没有实现自定API函数的功能.51Testing软件测试网F#qF\aF YS

51Testing软件测试网m6Fx7Ox$g

记得我说过,如果要实现自定API函数,可以写入一个跳转指令,JMP OX00000(其中OX00000为自定API51Testing软件测试网(g$Q%d_!baSX

Zo8ZEq*h]T%pL0函数地址),最后还给大家留了一道题,就是参照论坛上的教程写出自定API函数的功能,不知道大家

4C NgPx \u0

9_cmJ0cN0完成的什么样了,呵呵.

cV]pC0g5R1mxL0

A9Gk/C Yl n~051Testing软件测试网7ZDo{0A
    其实,要真正实现API HOOK,用JMP OX00000是不能达到我们的目地的,因为要转移参数,我们先要51Testing软件测试网@)|4@ H s*D.N|/qXJ

51Testing软件测试网%b:EHD4O7A(t+bb

mov eax OX00000 ,然后再jmp eax,在易里面用用字节集连起来表示就是:51Testing软件测试网Mr7o:BTq

51Testing软件测试网P aiv&P

        { 184 } + 到字节集 (到整数 (&new_api)) + { 255, 224 }

F6YX'TKh051Testing软件测试网'K4?"@-X(Vo#U$Yn

   其中new_api就是新的自定API函数地址,结合上期的内容,我们现在就来解析核心代码:

ea h-S7Z3me051Testing软件测试网 H0p,| cq|}`

===================================51Testing软件测试网-JuS x4F
.子程序 修改API首地址, 逻辑型
S{@ay x:\0?,BDQ0.参数 Process, 整数型, , 目标进程句柄51Testing软件测试网&n"{#F/p9E7sV*K
.参数 Papi, 整数型, , 要修改的API函数地址51Testing软件测试网'? _ Jo Dx
.参数 type, 字节集, , 要改写的内容,字节集
6b}8{5T,^ S0.局部变量 mbi, 虚拟信息51Testing软件测试网#Yam;MR8B;z)HB
.局部变量 结果, 逻辑型51Testing软件测试网FB)q"F*qD@5YV5y
.局部变量 MyAPI, 整数型51Testing软件测试网C!\Bf y
.局部变量 Ptype, 字节集51Testing软件测试网 v_:`P!^T$g]:d

51Testing软件测试网 RD;uhM"@l\ A

.如果真 (Papi = 0)
KFC5K}XC&[0     返回 (假)
.DE+e FZ0|0.如果真结束
~#DZ}\~Ar0.如果真 (返回虚拟信息 (Process, Papi, mbi, 28) = 0)
K,j)uZ|9a p \0     返回 (假)
tZjr.Q:?B p0.如果真结束
$_%D lI']}:N(w!s0.如果真 (修改虚拟保护 (Process, mbi.BaseAddress, 取字节集长度 (type) + 1, #PAGE_EXECUTE_READWRITE, mbi.Protect) = 假)51Testing软件测试网7?9x2e"x s ?P)KG1`
     返回 (假)51Testing软件测试网&AW i5w A1o
.如果真结束51Testing软件测试网8n+DmL c
结果 = 写内存字节 (Process, Papi, type, 取字节集长度 (type), 0)51Testing软件测试网 WN&T]0REp
修改虚拟保护 (Process, mbi.BaseAddress, 取字节集长度 (type) + 1, #PAGE_EXECUTE_READ, mbi.Protect)   ' 改回只读模式51Testing软件测试网0^F)jG G0U
返回 (结果)
+O&u8dc5L"nW;K0==================================

"Y"D(|([s T\;B051Testing软件测试网b ~\p&V

这个子程序也就是上期用到的,上一期第3个参数是写的{195},这里换成 { 184 } + 到字节集 (到

"E:^hm R:vFF0

m8w-H-D%D F4q*p'ZEW0整数 (&new_api)) + { 255, 224 }就可以了,新的API函数要和原API函数的参数一样,还拿API函
h7Y5U's%Me0数ExitWindowsEx来说,看下面的新的API函数:51Testing软件测试网)q be!`yp0d y

51Testing软件测试网V]!v z] fn/t#Y2T

======================================
j,Ot6r{q"N0.子程序 new_api, 整数型, , 新的API函数,要与原来的API函数的参数一样
g?-uXx3{ ~|0cg,k9K0.参数 标志, 整数型
3O/rYcEd6R+}0.参数 保留值, 整数型

v5zAY'P?uljfB0

D i@,_ q9s8f0' 给自己留条后门先51Testing软件测试网 SU8L,S+Er
.如果 (保留值 = 3389)
#B b,A,K.D Qt0     HOOKAPI (假)51Testing软件测试网^Q/fH!GR b+y
     api_ExitWindowsEx (标志, 保留值)51Testing软件测试网fq.A_@9b,GnByK
.否则51Testing软件测试网n`|8U e8J [/Pt
     信息框 (“您的操作已经被易拦截了!” + #换行符 + “ExitWindowsEx” + #换行符 + “参数<1>:” + 到文本 (标志) + #换行符 + “参数<2>:” + 到文本 (保留值), 0, )
,Wtm*oT7i5Mwf0.如果结束
Y d O#bN{0返回 (1)51Testing软件测试网^F"^t%vT.M m

4z-Q^;`K#W0=======================================51Testing软件测试网6Ml%U(W:ed}O^7R&^&S

-N ?w9Kqu0   看下面的代码:51Testing软件测试网%P|t?pA"oM!j

;}(T#Jh bFeabE0.子程序 HOOKAPI, 逻辑型51Testing软件测试网{1j7I%O9d!^
.参数 是否HOOK, 逻辑型
3G6tl w;A;y O"`PV0.局部变量 TYPE, 字节集

0odV$]^1w%_051Testing软件测试网{*Sp@7uP7q

.如果 (是否HOOK)
zDjst.K:{-mc0     TYPE = { 184 } + 到字节集 (到整数 (&new_ExitWindowsEx)) + { 255, 224 }
B,FF.N Qf6}g0     返回 (修改API首地址(取当前进程伪句柄 (), API, TYPE))51Testing软件测试网}!@&VuS{#[
.否则51Testing软件测试网,Yt*iU0f(rv']+Kf
     返回 (修改API首地址(取当前进程伪句柄 (), API, API_BAK))

Q{;LR!s*W3qE0

\({$V;QO7I"j/|s0
;KkVAf F4FV V&^:r0当然,改写前,还是要备份和取API函数地址的:51Testing软件测试网Z+H*v5B4r!W*u1j-h_

%\xQp G0API = 取DLL函数地址 (取程序或DLL句柄 (“user32.dll”), “ExitWindowsEx”)

)Rd cDk ew+y0

5xBk%j!U0API_BAK = 指针到字节集 (API, 8)51Testing软件测试网K7F\ vud^6r0nrS

51Testing软件测试网s+@RBbA{,T

============================================51Testing软件测试网$Yky&o;i^6U/m)e(U
   这样,只要一句HOOKAPI(真)就可以轻松改写本进程的API函数,一句HOOKAPI(假)就可以还原API函51Testing软件测试网6w3{-noP6W5NfG$H*E1ZGF

51Testing软件测试网9j q%g.` o8b f v9M~!O

数,当然前提是在本进程,因为地址不能跨进程使用,要想挂勾其他进程,我们可以使用我前面提到

S c*_2qI7{0

qPV$A2]D0的Windows全局消息勾子,为了取得较好的效果,推荐使用WH_GETMSSAGE类的勾子.

6l8}?'aX'Kf;\n051Testing软件测试网3B)P:u8i2K2U

   要使用全局消息勾子,先要在一个独立的DLL里声明钩子回调函数,看下面的代码:

5YkDH*w FSC_0

F~ xV2h0Nw2W0============================51Testing软件测试网 z s2F;UV+Qi,Ty
.子程序 GetMsgProc, 整数型, 公开, 钩子回调函数51Testing软件测试网4FRG*|h#X/l `
.参数 code, 整数型51Testing软件测试网,h^qpH l n `
.参数 wParam, 整数型
m7q~S4ZYKti0.参数 lParam, 整数型51Testing软件测试网XU7D'^"g

51Testing软件测试网&Elu(`#Y}t

返回 (api_CallNextHookEx (hhook, code, wParam, lParam))   ' 钩子循环

)?)NS*z4AM0r[s051Testing软件测试网0Vv(_5@6G&W%^e

====================================
Uc5t*y[:{(u-\ PD+N ^0  51Testing软件测试网*{z1nbG8EN5i3Z$n2bWw
主程序通过调用SetWindowsHookEx就可以安装钩子 ,继续看代码;51Testing软件测试网/JjeG5cS7K*X0t

)}4R {a"i$f'CqI0.子程序 安装全局钩子, 整数型, , 安装全局消息钩子
2iE!x"I6op/u0.参数 DLLPath, 文本型,DLL名
#v5rlEx FK6p0.局部变量 hMod, 整数型
%f n*Z+mSlS0.局部变量 lpProc, 子程序指针

b|I&K$?9N t OTU0

K6m*C-e5@oL"P0hMod = api_LoadLibraryA (DLLPath)
D-w;cvp T0lpProc = api_GetProcAddress (hMod, “GetMsgProc”)51Testing软件测试网-wJA1Z!t.oBhqB
hook = api_SetWindowsHookExA (#WH_GETMESSAGE, lpProc, hMod, 0)51Testing软件测试网s3uwo5kJ(rv
返回 (hook)51Testing软件测试网,PGE~*r7q.KiH

51Testing软件测试网[ \z(`;U7\ gl

======================================51Testing软件测试网0XR2h&y]Eo
主程序通过api_UnhookWindowsHookEx(hook)就可以关闭全局钩子.

L(h2\2QFjc0

Gu9o9mRf0结合下面的子程序(上期的HOOK_API)便可以还原API.51Testing软件测试网 j{J3]6p)^ s*v
=============================51Testing软件测试网9M TI'Y6s c G
.子程序 还原API
X"h+o W S?k+l0.局部变量 i, 整数型51Testing软件测试网ts#^9jYo
.局部变量 结果, 逻辑型
/w5Aslx0.局部变量 进程信息, 进程信息输出, , "0"51Testing软件测试网,|K-O yS)XD o
.局部变量 进程句柄, 整数型51Testing软件测试网@~M2B:a-Jl
.局部变量 修改内容, 整数型51Testing软件测试网2OsJ ]l$~d4?

8M'JI#E7sk+LC-d!\0刷新进程信息 (进程信息) '这个在上期中讲过,我就不重复了.
0H J6X!Qv0.计次循环首 (取数组成员数 (进程信息), i)51Testing软件测试网@_4B)h0C2{9Q
     进程句柄 = 打开进程 (2035711, 0, 进程信息 [i].进程标识)51Testing软件测试网v)p;qHG)S'c7y
     .如果真 (API_BAK ≠ { 0 })51Testing软件测试网^Yj,rx9x!s*?
         结果 = 修改API首地址 (进程句柄, API, API_BAK)
N/N.q2B"hc8p0     .如果真结束
4D(w UT-ya0     关闭内核对象 (进程句柄)
4f/hO K7G C~0.计次循环尾 ()51Testing软件测试网V^)@ ~"d
===========================51Testing软件测试网Wb*^ xOy+h
    可以看出,我们创建的Hook类型是WH_CALLWNDPROC类型,该类型的Hook在进程与系统一通信时51Testing软件测试网3F5c'H`n9F _

d"~"hN)X{7Do^[4N0就会被加载到进程空间,从而调用dll的初始化函数完成真正的Hook,而在SetWindowsHookEx函数

\6s0F&wNcI051Testing软件测试网H)w(?4K2Q7w

中指定的HookProc函数将不作任何处理,只是调用CallNextHookEx将消息交给Hook链中下一个环节

lz^C%]0

`2W E*v$fS0处理,因为这里SetWindowsHookEx的唯一作用就是让进程加载我们的dll。51Testing软件测试网6G!ze&tD y(|1H(A

8Y-W0^,nq1_I0
s[]g7b?#w0     整个框架就是这样了,具体的就不在细说了.附件里有完整的易源码,大家可以下载下来研究.51Testing软件测试网y(cAQ3JI

:k{/O$d%FK0以上就是一个最简单的Hook API的例子,该种技术可以完成许多功能。例如网游外挂制作过程中

8\Bf Jb8Z ~)j0

g-yL}Y7\%R F*t0截取发送的与收到的封包(API函数send)即可使用该方法,或者也可以在Hook到API后加入木马功能

v6[,?p)Tk e0

Rm9IC2P0sx3{y%k0,反向连接指定的主机或者监听某一端口,还有许多加壳也是用该原理来隐藏IAT表,填入自己的51Testing软件测试网 \?#b&V`UC

jPW.j8x+[9b Z} H+f0函数地址,等等.

X,WVJ"CgO,K?V"^(H051Testing软件测试网"ALwj$inP

    希望本文能够对一些朋友有所帮助,当然,一定有许多不足之处,希望看了文章的高手51Testing软件测试网!B/| ZH*?D

b Zls!G2J)Awd8O0可以指出:以下程序在Windows XP +sp2和易4.02中测试通过,有什么Bug,请通知我.)51Testing软件测试网`knC;Az3X0L1rS


TAG:

 

评分:0

我来说两句

Open Toolbar