代码节空白区手动添加代码

获取MessageBox地址

打开OD,在Command框输入bp MessageBoxA设下断点,按回车后查看断点得到MessageBox地址为75CE0EA0。

硬编码E8和E9

E8:相当于汇编里的call

E9:相当于汇编里的jmp

不同的地方:call和jmp后面接的就是跳转的地址,但E8和E9后面的内容需要计算。

计算方法:

记X为E8(或E9)后面的内容

真正要跳转的地址(call后面的)= E8(或E9)的下一条指令地址 + X

举例说明:

call 00401050

E8这条指令的下一条指令地址:004011FD

X = 00401050 - 004011FD = FFFFFE53

故call 00401050对应的硬编码是E8 53 FE FF FF

又E8(或E9)这条指令的下一条指令地址 = E8这条指令的地址 + 5,故计算方法可写为:

真正要跳转的地址(OEP)= E8(或E9)这条指令的地址 + 5 + X

在代码区手动添加代码

注:E8、E9当前的地址是指拉伸后的地址

1、构造shellcode代码

MessageBoxA对应的硬编码

shellcode[] = {
    0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00//push 0 0 0 0
    0xE8,0x00,0x00,0x00,0x00,//call MessageBox
    0xE9,0x00,0x00,0x00,0x00//JMP OEP,程序入口点
}//18个字节

2、检测代码空白区能否放得下shellcode

以IPMsg.exe为例子,找第一个节:

        [成员]          [地址(RAW)]    [数据:RVA]	         [说明]
Name:                   0x00000220     [.text]      [名称,长度:8位(16字节)的ASCII码.]
VirtualSize:            0x00000228     0019C819     [V(VS),内存中大小(对齐前的长度).]
VirtualAddress:         0x0000022c     00001000     [V(VO),内存中偏移(该块的RVA).]
SizeOfRawData:          0x00000230     0019CA00     [R(RS),文件中大小(对齐后的长度).]
PointerToRawData:       0x00000234     00000400     [R(RO),文件中偏移.]
PointerToRelocation:    0x00000238     00000000     [在OBJ文件中使用,重定位的偏移.]
PointerToLinenumbers:   0x0000023c     00000000     [行号表的偏移,提供调试.]
NumberOfRelocations:    0x0000023e     0000         [在OBJ文件中使用,重定位项数目.]
NumberOfLinenumbers:    0x00000240     0000         [行号表中行号的数目.]
Characteristics:        0x00000244     60000020     [标志(块属性):20000000h 40000000h 00000020h ]

对齐前的长度 = VirtualSize = 0019C819

对齐后的长度 = SizeOfRawData = 0019CA00

剩的空间 = SizeOfRawData - VirtualSize = 1E7>18,显然够了。找到空闲区起始地址0019CC20,所以我们往0019CC20到SizeOfRawData + PointerToRawData = 0019CE00之间添加代码。

在空闲区写下代码

计算E8后面的内容

真正要跳转的指令地址:上面获取的MessageBox地址

E8后面的内容 = MessageBox的地址 - E8的下一条指令的地址 = 75CE0EA0 - (19CC20 - 400 + 1000 + 400000 + D) = 75CE0EA0 - 59D82D = 7574 3673

19CC20:填入代码的起始地址

400:PointerToRawData

1000 :VirtualAddress

400000:ImageBase

D:19CC20与E8的下一条指令的地址相隔12

计算E9后面的内容

真正要跳转的指令地址:原始OEP的值

E9后面的内容 = AddressEntryPoint + ImageBase - E9的下一条指令的地址 = 1795E1 + 400000 - (19CC20 - 400 + 1000 + 400000 + 12) = 5795E1 - 59D832 = FFFD BDAF

完整的shellcode硬编码

shellcode[] = {
    0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00//push 0 0 0 0
    0xE8,0x73,0x36,0x74,0x75,//call MessageBox
    0xE9,0xAF,0xBD,0xFD,0xFF//JMP OEP,程序入口点
}//18个字节

image-20230831141811424

修改OEP

OEP = RVA_shellcodeAddr - ImageBase = 19CC20 - 400 + 1000 + 400000 - 400000 = 19D820

在可选PE头里找到AddressEntryPoint 修改其值为19D820:

image-20230831141856359

保存再次运行程序,同样能够运行成功,不过启动前会有弹窗,说明添加代码成功:

image-20230831142018686


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1666739907@qq.com
github