zoukankan      html  css  js  c++  java
  • Hook 初学习

    Hook
    概念

    百度上的概念

    每个Hook都有一个相关的指针列表,后加入的Hook再链表的开始,先加入的在链表的尾部

    后加入先获得控制权

    Hook 原理

    原本的流程

    graph LR id1(MessageBoxA)--<br>原本的进程-->id2(MessageBoxB); id2(MessageBoxB)-->id1(MessageBoxA)

    hook后的流程

    graph LR id1(MessageBoxA)--<br>step1:Hook-->id2(My_MessageBox); id2--<br>2step:return-->id1; id1--<br>step3-->id4(MessageBoxB) id4--<br>step4-->id2 id2--<br>step5-->id1

    就是在执行MessageBoxA的API时,先jmp到我的My_MessageBox,执行完之后再return回到MessageBoxA继续执行

    利用这个技术,我们可以监控API,比如应用程序会调用loadLibrary,那我们把它Hook了,把Dll路径改成我们的,那加载的就是我们的dll了,当然 Hook的API很多,因为只要是Windows的API都能HOOK

    Hook的思路
    1. 获取MessageBoxA函数的地址
    2. 修改函数的内存保护属性(便于写入jmp的二进制)
    3. 找到MessageBoxA前的5个字节的位置,写入jmp

    具体代码和地址的计算

    Hook实例

    手动尝试hook一个程序

    源码

    编译环境:win10 1909+gcc

    #include <windows.h>
    
    int main (){
      int a,b;
      a=3;
      b=2;
      int c=a+b;
      char tmp[8];
      memset(tmp,0,8);
      itoa(5,tmp,10);
      MessageBox(NULL,tmp,"Hook",0);
      return 0;
    }
    

    正常情况会弹出一个弹窗,标题栏写着Hook,下面写着5

    我们尝试用hook把5改成0

    Step1:

    ida打开a.exe,找到主函数部分,可以看到代码的大概位置

    .text:00401410 ; __unwind {
    .text:00401410                 lea     ecx, [esp+4]
    .text:00401414                 and     esp, 0FFFFFFF0h
    .text:00401417                 push    dword ptr [ecx-4]
    .text:0040141A                 push    ebp
    .text:0040141B                 mov     ebp, esp
    .text:0040141D                 push    ecx
    .text:0040141E                 sub     esp, 34h
    .text:00401421                 call    ___main
    .text:00401426                 mov     [ebp+var_C], 3
    .text:0040142D                 mov     [ebp+var_10], 2
    .text:00401434                 mov     edx, [ebp+var_C]
    .text:00401437                 mov     eax, [ebp+var_10]
    .text:0040143A                 add     eax, edx
    .text:0040143C                 mov     [ebp+var_14], eax
    .text:0040143F                 mov     dword ptr [esp+8], 8 ; size_t
    .text:00401447                 mov     dword ptr [esp+4], 0 ; int
    .text:0040144F                 lea     eax, [ebp+Text]
    .text:00401452                 mov     [esp], eax      ; void *
    .text:00401455                 call    _memset
    .text:0040145A                 mov     dword ptr [esp+8], 0Ah ; int
    .text:00401462                 lea     eax, [ebp+Text]
    .text:00401465                 mov     [esp+4], eax    ; char *
    .text:00401469                 mov     eax, [ebp+var_14]
    .text:0040146C                 mov     [esp], eax      ; int
    .text:0040146F                 call    _itoa
    .text:00401474                 mov     dword ptr [esp+0Ch], 0 ; uType
    .text:0040147C                 mov     dword ptr [esp+8], offset Caption ; "Hook"
    .text:00401484                 lea     eax, [ebp+Text]
    .text:00401487                 mov     [esp+4], eax    ; lpText
    .text:0040148B                 mov     dword ptr [esp], 0 ; hWnd
    .text:00401492                 call    _MessageBoxA@16
    .text:00401497                 sub     esp, 10h
    .text:0040149A                 mov     eax, 0
    .text:0040149F                 mov     ecx, [ebp+var_4]
    .text:004014A2                 leave
    .text:004014A3                 lea     esp, [ecx-4]
    .text:004014A6                 retn
    .text:004014A6 ; } // starts at 401410
    .text:004014A6 _main           endp
    

    正常来说,我们可以用patch来改,这里尝试hook的方式

    在赋值3,2完成之后,写入jmp指令,随便jmp到一块不影响程序,且在程序中的地址上(不一定要紧跟在jmp后面,只要在调用MessageBox函数之前随便的五个字节,要是没有刚好5个字节的指令,可以凑到至少5个,多的就nop掉),jmp指令破坏掉的指令要在jmp到的我的hook中修复,这样才能不影响程序原本的运行

    Step2:

    od定位到相应位置,双击指令,开始修改(也可以在ida中patch修改)eb

    3KopsP.png

    我选对程序无影响的地址401305这块地址3KIfPJ.png

    我选择在add eax, edx后插入jmp 00401305,因为这条汇编是5个字节,会覆盖掉两条汇编指令,变成了

    3KIxxI.png

    所以在我的hook,也就是00401305处我要补上

    3KoQdU.png

    解释一下

    mov eax,0x0                        ;jmp 来之前eax中的值是5,给覆盖成0
    mov dword ptr ss:[ebp-0x14],eax    ;这是照着原来的写法,把jmp时覆盖的指令补上
    mov dword ptr ss:[esp+0x8],0x8     ;同上
    jmp a.00401447                     ;这是跳回原来的地方继续执行
    

    step3

    保存:右键-->复制到课自行文件-->全部修改

    如果发现报错,可执行文件中无法确定数据。首先不管报错,直接保存文件,看看是否可运行,不行考虑换个离源代码位置近的地方去添加跳转代码,再不行就考虑增加区块

    Hook实例2

    具体参考

    hook api 反OD调试的一种思路

    HOOK API入门之Hook自己程序的MessageBoxW

    截获 Windows socket API

    vc++ 编译dll

    原理

    windows 系统函数都是以dll封装起来的,程序应用到系统函数的时候,要先将dll加载到进程空间。我们只要在我们要hook程序调用dll之前,jmp到我们自己构造的dll中,就可以达到效果

    几个要点:

    1. 怎么让被hook的程序加载我们的dll

      采用上面文章讲到的方法,调用windows现成的鼠标钩子,响应到所有鼠标点击事件,然后载入我的dll。鼠标钩子只是用来载入我的dll到被hook的程序,做事的还是我的dll

    2. 怎么加载完成后修复原来被我们的部分

      这个方法有很多,可以在我的dll中去修复,先记录下原来的数据,在执行完我们dll的主要内容后再把数据恢复,跳转回去的时候就不会再执行jmp到我们dll了。也可以像上一个实例一样,直接在我定义的dll执行,在调会主函数,再执行进入下个dll

    3. 怎么在加载正常dll前获取地址

      可以调用GetProcAddress函数,来获取dll的入口地址

    操作……还没操作,之后再补

  • 相关阅读:
    Apache 2.4+php 5.4 安装
    Linux 进程状态
    解决Redhat Linux AS使用yum时出现This system is not registered with RHN的问题(改用CentOS的yum)
    nagios 事件处理
    awk调用shell命令的两种方法:system与print
    磁盘性能分析
    如何通过JQuery将DIV的滚动条滚动到指定的位置
    GCC Windows Linux 下编译学习1
    Linux命令
    GCC Windows Linux 下编译学习2
  • 原文地址:https://www.cnblogs.com/militray-axe/p/12344427.html
Copyright © 2011-2022 走看看