作者:重楼 
时间:2009-09-01 
前言:让程序按照自己的代码来走,这是个很有意思的事情。 HOOK 其实是一个很有意思的东西,他能让你在枯燥的外挂学习中感受到一丝乐趣 

HOOK的原理:修改函数的首地址 跳转到你想执行的代码 然后返回。 

这就好比正常的程序 就像一个汽车 在公路上行驶(代码正常运行) ,而这个时候 警察 在半路设下了一个路障(修改原始地址 JMP 我们的代码地址) ,要求 汽车靠边停靠(修改原始程序代码,JMP 地址  跳转到我们的代码区),这个时候 汽车 过来了,看到路障 并且停靠在右边(跳转到我们的代码区了) 并且接受检查(执行我们的代码),恢复路面(将修改的代码复原),检查完毕后 (比如说代码执行了 数据拷贝,或者一些特殊功能  比如说send  恢复代码后 可以直接执行,也可以拦截不发也可以修改数据 在发送。),汽车继续行驶。 

HOOK的方法有很多,修改CALL的代码 跳转到我们的程序 执行完我们的代码后,复原CALL 然后在调用。 
或者直接在 函数头跳转。 

HOOK的方法有很多种,但万变不离其中

封包助手 是一款类似于 WPE 截包的软件,今天我们来看看他是如何HOOK send 封包函数的

此次的目标还是前几天我们用到的模拟器 

我们先来看一下 正常的 send 函数头部 按下CTRL+G    输入  send    回车 (打开OD第一次需要找2次应该是OD BUG) 

好了 跳转到如下地址 


  

然后我们来看下  用封包助手 加载程序后代码的变化 



  


mov edi,edi 
push  ebp 
push ebp,esp 

这三句话  修改成了 

JMP PACKASSI.13148F88 

这句汇编指令的意思就是  强行跳转到  13148f88  这个地址去 (开始设置路障

好了 我们下 bp  send  然后 按模拟器 进入或 加血 让程序 断下 

然后 按F8  单步运行,  这个时候 强行跳转到了 封包助手 设置的位置.(汽车靠边了



  

这里就是我们跳转的地方了.也就是说 封包助手处理 数据的地方


  


这里有3CALL  我们来看看 都有什么功能

我们进入第一个CALL里面    看到 OD 分析出几个CALL的函数 


  

getsockname() 获取一个套接口的IP和端口 

ntoa()  将网络IP地址转换"."格式的字符串形式 

ntohs()  将一个无符号短整形数从网络字节顺序转换为主机字节顺序。 



  


看来 这一层是封包函数处理 一些 封包数据的地方.        (检查完毕后 ) 

我们来看看第二层CALL 

第二层CALL压入堆栈的数据 跟send 一样  我们看看他跳转到何处 


  

这里我们发现 

push ebp 
mov  ebp,esp 

一般函数头部都有这2句 

然后我们继续往下 

JMP WS2_32.71A24C2C 

这里跟函数头部是不是很近
呵呵 我们继续跳转 看看他到哪里


  

程序跳转到 刚刚修改过的下面那句

我们连起来就是 相当于运行 

push ebp 
mov  ebp,esp 
sub  esp,10 
...... 
...... 

这里就相当于 运行原来的  send发包功能.因为封包数据 我们已经拿到手了.(恢复路面


第三个CALL  压入的参数跟send  一样 ,我们进入到CALL内部看一下 




  


  

这是里面的2个被OD标出来的函数 
第一个用于查找 窗口句柄 
第二个用于向窗口发送消息 

根据 findwindow  压入堆栈的 标题来看 应该是给 封包助手 主窗口发送消息 

这个CALL应该是处理  DLL跟封包助手进程之间 的 数据通信,  因为封包助手要HOOK send 必须把检测代码注入到目标进程 ,这个时候 获得数据的是 注入进目标的DLL 而不是 封包助手主程序那么封包助手如何获取拦截的封包数据 并显示呢,  这里可以用 sendmessage() 来达到目的

看来 第三个CALL是应用于 DLL与主程序之间的数据传递



好了 下面我们来写下 sendmessage()  这个CALL ,欺骗一下封包助手

我们先来看看 中断在CALL的位置时  堆栈的情况 


  

这个是 CALL  sendmessage 时候的 堆栈状况

我们现在来看看 CALL的时候 有没有用到哪个 寄存器 

我们进入到 sendmessage  的内部.(要经过一个跳转



  

好了 到了内部了 

如何找 CALL有没有调用 寄存器呢?  一般CALL调用的寄存器是 (EAX,EBX,ECX,EDX)4个 
看看 代码中 有没有  类似于 mov  esi,eax   push  ebx 这种需要从寄存器读取数据的 之类  这里我们没有找到任何读取这4个寄存器的指令 

好了 这样的话 我们只需要写入堆栈就可以了  按照堆栈的顺序 写入 到 CALL注入器 里 


  

OK~调用成功了 ,  因为我们没有往堆栈地址写入数据(为什么要说数据在堆栈地址呢,在上一层中 这个CALL所压入的堆栈中的数据 和send 发送的数据一样,其实我们应该调用上面那一层的). 


好了 我们试试写 上面那一层的  CALL 看看 


  

这个CALL跟上面那个一样 我就不多说了,这个时候 在数据里就可以显示了 



  

将 长度 和 套接字 改变了下  封包助手接收到的数据也随之而改变


后记: HOOK的方式不只是这一种,不过千变万化不离其中.

posted on 2011-10-17 12:02  巅枫  阅读(2801)  评论(0编辑  收藏  举报