获取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个字节
修改OEP
OEP = RVA_shellcodeAddr - ImageBase = 19CC20 - 400 + 1000 + 400000 - 400000 = 19D820
在可选PE头里找到AddressEntryPoint 修改其值为19D820:
保存再次运行程序,同样能够运行成功,不过启动前会有弹窗,说明添加代码成功:
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1666739907@qq.com