代码空白区添加代码(手动)

代码空白区添加 MessageBox

  1. 测试代码,寻找目标地址

    #include "stdafx.h"
    #include <windows.h>
    
    void fun()
    {
        printf("Hello Cntf\r\n");
        MessageBox(0,0,0,0);
    }
    
    int main(int argc, char* argv[])
    {
        fun();
        return 0;
    }
    

    上面代码编译执行,弹框,实现MessageBox的功能;

    我们需要找到MessageBox在程序执行的起始位置;

    在OD工具里面设置断点,命令行输入bp MessageBoxA,然后在菜单栏找到"B" 点击进去就发现了设置的断点;
    然后双击即可查看MessageBox的断点位置,如下:
    77D5050B > 8BFF MOV EDI,EDI
    最终确认MessageBox在程序中执行的地址:0x77D5050B

  2. E8,E9的计算
    E8是call的硬编码,E9是jmp的硬编码,6A是push的硬编码

    公式一:

    真正要跳转的地址 = E8这条指令的下一行地址 + X
    即:X = 真正要跳转的地址 - E8这条指令的下一行地址
    该指令的下一行地址为待执行的地址,因为当执行call指令后,机器的硬编码将不知道将执行哪一部分,所以如此设计了,加入了返回后该执行的地址编码(本人理解)

    • 验证E8 call后面4个字节
      如下为上c代码,进行编译,调试,进入反汇编得到的结果

      15:       fun();
      00401098 E8 68 FF FF FF       call        @ILT+0(fun) (00401005)
      16:       return 0;
      0040109D 33 C0                xor         eax,eax
      

      解释:
      E8 —> call的硬编码
      E8后面的4个字节是通过计算的出来的,我们上面的公式就是要验证确认他们的计算方式

      根据公式,已知:真正要跳转的地址和E8这条指令的下一行地址;

      开始计算

      X = 真正要跳转的地址 - E8这条指令的下一行地址
      X = 0x00401005 - 0x0040109D = 0xFFFFFF68

      小端存储,通过上面对比得知他们是一样的;

    • 验证E9 jmp后面4个字节

      生成的反汇编代码

      @ILT+0(?fun@@YAXXZ):
      00401005 E9 16 00 00 00       jmp         fun (00401020)
      @ILT+5(_main):
      0040100A E9 71 00 00 00       jmp         main (00401080)
      

      开始计算
      X = 真正要跳转的地址 - E8这条指令的下一行地址
      X = 0x00401020 - 0x0040100A = 0x00000016

      小端存储,通过上面对比得知他们是一样的;

      公式二:

      要跳转的地方 = (E8当前的地址 + 5)1 + X

      即:X = 要跳转的地址 - (E8的地址 + 5)

      MessageBox的反汇编信息如下

      10:       MessageBox(0,0,0,0);
      00401045 8B F4                mov         esi,esp		// 反汇编后,发现MessageBox有4个push的参数
      00401047 6A 00                push        0
      00401049 6A 00                push        0
      0040104B 6A 00                push        0
      0040104D 6A 00                push        0
      0040104F FF 15 8C 52 42 00    call        dword ptr [__imp__MessageBoxA@16 (0042528c)]
      00401055 3B F4                cmp         esi,esp
      00401057 E8 F4 00 00 00       call        __chkesp (00401150)
      11:   }
      

      所以总结下来,需要向程序的代码区域插入如下18个字节的代码即可,而E8,E9后面的四个字节是需要算的

      6A 00 6A 00 6A 00 6A 00 E8 00 00 00 00 E9 00 00 00 00 —> 18个字节大小

  3. 在代码区手动添加 shellcode 代码

    VirtualSize:            0x000001f8     000440A2     [V(VS),内存中大小(对齐前的长度).]
    VirtualAddress:         0x000001fc     00001000     [V(VO),内存中偏移(该块的RVA).]
    SizeOfRawData:          0x00000200     00045000     [R(RS),文件中大小(对齐后的长度).]
    PointerToRawData:       0x00000204     00001000     [R(RO),文件中偏移.]
    

    00045000 - 000440A2 = F5E - - -> 此处计算结果必须大于我们上面要插入的18个字节大小,不然会出问题

    使用16进制编辑器打开exe二进制文件
    在第一个节后面的代码空白区域添加我们的代码;就是在SizeOfRawData -> 0x00045000的后面

    理解:
    第一个节从PointerToRawData 文件偏移开始–> 0x00001000开始向后数,数到0x00045000结束;
    然后根据对齐宽度是1000H,所以向后再加上1000H就是0x00046000是第二个节的开始位置;
    这里需要注意,我使用编辑器打开ipmsg.exe文件之后,找到0x00045000的位置发现还有数据;
    向后扩展1000H到了0x00046000位置是对的,刚好是下一个节的开始位置,而这期间;
    0x00045000 - 0x00046000这里面开头一点还是有数据的,到了一定的位置发现都是00,那么确认此处;
    0x00046000开始的上一个字节位置都是空白区域,都是可以填充数据的;

    我这里找到代码空白区域的位置是0x000450a2开始,从这里开始的,我们从此处的下一行开始填充代码;

    也就是从0x000450b0位置开始,具体如下:

    000450b0h: 6A 00 6A 00 6A 00 6A 00 E8 00 00 00 00 E9 00 00
    000450c0h: 00 00
    

    添加执行函数call汇编指令和jmp汇编指令后面的硬编码数据

    • 添加E8 call 指令

      需要的MessageBox数据 ----> 0x77D5050B,根据公式二:X = 要跳转的地址 - (E8当前的地址 + 5),来计算E8,E9后面部分的硬编码

      填充数据:
      要跳转的地址 = 0x77D5050B
      E8当前的地址 + 5 = 下一个jmp的汇编指令开头 —> E9的位置 —> 0x000450bd

      得到上面的地址,一定要再考虑(ImageBuffer里面的偏移)内存偏移和 因为我们加入的代码;
      最终是要在内存中运行,所以一定是要考虑在内存中偏移和对齐;
      要考虑这两个 —> VirtualAddressPointerToRawData

      VirtualAddress:    0x000001fc       00001000        [V(VO),内存中偏移(该块的RVA).]
      PointerToRawData: 0x00000204      00001000        [R(RO),文件中偏移.]
      ImageBase:       [地址(RAW):0x0000012c] [长度:04h]   [偏移量:e_lfanew+0x34]
      [数据:0x00400000]   [基址,程序默认装入的基地址.]

      本次测试使用的程序很巧,刚好文件和内存中的偏移是一样的,都是1000H
      ImageBase和内存偏移地址1000H得出地址:0x000450bd + 0x00400000 = 0x004450bd

      X = 要跳转的地址 - (E8当前的地址 + 5)

      要跳转的地址 --> 0x77D5050B (这里要跳转的地址就是上面我们找到的MessageBox的地址)
      (E8当前的地址 + 5) --> 0x004450bd(上述所计算的地址)

      X = 0x77D5050B - 0x004450bd = 0x7790B44E

      0x7790B44E --> 77 90 B4 4E --> 小端模式 --> 4E B4 90 77 --> 放入E8的后面
      000450b8h: E8 4E B4 90 77 - - -> 这就是最终的E8后面的数据

    • 添加E9 jmp指令

      加入代码之后,需要再回到程序的入口处,所以E9要跳转的地址就是OEP的地址

      AddressEntryPoint     --> 0x000441EC
      ImageBase             --> 0x00400000
      OEP地址   --> 0x000441EC + 0x00400000 = 0x004441EC
      

      要跳转的地址 --> 0x004441EC
      (E9当前的地址 + 5) --> 0x004450C2

      X = 要跳转的地址 - (E9当前的地址 + 5)
      X = 0x004441EC - 0x004450C2 = 0xFFFFF12A
      0xFFFFF12A --> FF FF F1 2A --> 小端模式 --> 2A F1 FF FF --> 放入E9的后面

      000450bdh: E9 2A F1 FF FF - - -> 这就是最终的E9后面的数据

  4. 修改OEP的值,指向我们设置的 shellcode

    修改的 shellcode 地址:0x00450b0
    原来的OEP地址位置:0x000441EC
    对应位置是可选PE文件头 --> 00000120h: EC 41 04 00
    将其更改为这个地址内容 --> 0x00000120 --> B0 50 04 00

  5. 修改图示

    display1

    display2
    参考文献https://www.cnblogs.com/autopwn/tag/逆向/default.html?page=4


  1. 5为 call 或者 jmp 后面的5个字节跳过,则 E8 + 5 恰好为下一行的地址 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值