zoukankan      html  css  js  c++  java
  • inline hook原理和实现

    inline hook是通过修改函数执行指令来达到挂钩的。比如A要调用B,但人为地修改执行流程导致A调用了C,C在完成了自己的功能后,返回B再执行。
    修改这段指令前首先要获取修改权限
    由于要修改的代码位于PE文件的代码段,而PE文件载入内存时默认代码段的权限为“可执行,只读”。通过函数VirtualProtect 修改这段代码所在内存空间的权限(保护属性)。
     VirtualProtect函数原型:
    BOOL VirtualProtect(  
      LPVOID lpAddress,  //基地址:内存起始位置,也就是要修改代码的地址
      DWORD dwSize,  //    长度  :要修改多少个字节的属性,此处为一条jmp指令的长度5字节
      DWORD flNewProtect,  //    新保护属性  :修改后的内存保护属性,此处为64代表“可执行可写”。
      PDWORD lpflOldProtect  //    旧保护属性:原始的内存保护属性
    );  
     代码实现:
    //dwTemp保存旧保护属性。便于hook后续恢复原状
    DWORD dwOldProtect , dwTemp;
     
    //修改为可读可写可执行
    if(VirtualProtect(add , 5 , 64 , &dwOldProtect)){
        //jmp to fake_add
    }
    //恢复为修改前的属性  
    VirtualProtect(add , 5 , dwOldProtect , &dwTemp);
    以上实现修改add函数附近的5个字节码权限为为可读可写(flNewProtect设置为PAGE_EXECUTE_READWRITE(0x40)即64)
    定位原函数地址时,可以像本例通过函数名(例如 LPVOID originFunction = MessageBoxA),或者如果该函数是存在在一个DLL并且已声明公开,则可以通过GetProcAddress( 功能是检索指定的动态链接库(DLL)中的输出库函数地址)函数来获取函数的地址。
    比如要获取kernel32.dll里面的WriteProcessMemory函数:
    LPVOID lpvWriteProcessMemory = GetProcAddress(GetModuleHandle("kernel32.dll") , "WriteProcessMemory");
    权限修改好后就可以改写代码了,通过WriteProcessMemory将add函数开始部分改写为:jmp <fake_add的函数地址>,此处的jmp为短跳转,注意位移量为相对偏移
    JMP 的 3 种类型
    1. 短跳转(Short Jmp,只能跳转到256字节的范围内),对应机器码:EB
    2. 近跳转(Near Jmp,可跳至同一段范围内的地址),对应机器码:E9
    3. 远跳转(Far Jmp,可跳至任意地址),对应机器码: EA
    短跳转 和 近跳转 指令中包含的操作数都是相对于(E)IP的偏移
    远跳转指令中包含的是目标的绝对地址。
    计算jmp位移量
    jmp指令占5字节,执行该指令后,IP先加5,然后在加上jmp指令的位移量
    所以 新函数的地址– 待修改函数的地址 – 5 = 位移量
    RVA = fake_add - add - 5;
    知道了地址可以开始改写内存写入jmp指令了,
    //写入该段内存
    if(WriteProcessMemory(currentProcessHandle , originAdd , shellCode , 5 , &dwWritten) && dwWritten == 5){
         MessageBoxA(NULL , "Write Hook Success !"  , "Hook add" , 0);
    }
    函数原型:
    BOOL WriteProcessMemory(
    HANDLE hProcess,//所写入的进程句柄
    LPVOID lpBaseAddress,//写入内存的基地址
    LPVOID lpBuffer,//待写入数据的地址
    DWORD nSize,   //写入长度(字节)
    LPDWORD lpNumberOfBytesWritten
    );
    //返回值非0为成功
    运行效果
    点击确定后
     
     
     
     
    参考资料:
  • 相关阅读:
    剑指offer(45)扑克牌顺子
    剑指offer(44)单词翻转序列
    剑指offer(43)左旋转字符串
    剑指offer(42)和为S的字符串
    剑指offer(41)和为S的连续正数序列
    剑指offer(40)数组中只出现一次的数字
    剑指offer(39)平衡二叉树
    面试金典——字符串压缩
    LeetCode——恢复二叉搜索树
    LeetCode——修剪二叉搜索树
  • 原文地址:https://www.cnblogs.com/Archimedes/p/14823218.html
Copyright © 2011-2022 走看看