代码空白区添加代码(手动)
代码空白区添加 MessageBox
测试代码,寻找目标地址
#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
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个字节大小
在代码区手动添加 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
里面的偏移)内存偏移和 因为我们加入的代码;
最终是要在内存中运行,所以一定是要考虑在内存中偏移和对齐;
要考虑这两个 —>VirtualAddress
和PointerToRawData
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后面的数据
修改OEP的值,指向我们设置的 shellcode
修改的 shellcode 地址:
0x00450b0
原来的OEP地址位置:0x000441EC
对应位置是可选PE文件头 -->00000120h: EC 41 04 00
将其更改为这个地址内容 -->0x00000120 --> B0 50 04 00
修改图示
参考文献https://www.cnblogs.com/autopwn/tag/逆向/default.html?page=4
5为 call 或者 jmp 后面的5个字节跳过,则 E8 + 5 恰好为下一行的地址 ↩︎
代码空白区添加代码(手动)相关推荐
- 代码节空白区添加代码
文章目录 一. 找个可以写二进制的区域 二.寻找本机MessageBoxA(最终要跳到的地址) 三.计算 四.修改入口地址 一. 找个可以写二进制的区域 二.寻找本机MessageBoxA(最终要跳到 ...
- PE结构-空白区手动添加任意代码(附实例代码)
PE之添加任意代码到空白区 预备知识 1.查找本机MessageBoxA地址 1.打开OD调试工具拖入要添加的exe程序. 2.在命令中输入 : (输入后按下回车键) 3.点击断点页面即可看到Mess ...
- 【转】反病毒攻防研究第003篇:添加节区实现代码的植入
声明 因为在评论区看到原博主说要把文章删掉...心想这么好的文章删了真的可惜,所以就先转一份... 一.前言 上一篇文章所讨论的利用缝隙实现代码的植入有一个很大的问题,就是我们想要植入的代码的长度不能 ...
- (20/24) webpack实战技巧:watch实现热打包和添加代码备注
(20/24) webpack实战技巧:watch实现热打包和添加代码备注 在前面的学习中,我们一直使用webpack-dev-server充当(本地)服务器和完成打包任务,但是当出项目团队联合开发, ...
- live2d 3行代码 为网站添加萌萌哒看板娘
3行代码 为网站添加萌萌哒看板娘 看板娘是一种职业和习惯称呼,也是ACGN次文化中的萌属性之一.简而言之就是小店的女服务生,也有"吸引顾客,招揽生意,提高人气"等作用类似品牌形象代 ...
- iOS - 添加代码片段(Code Snippets)
添加代码段目的是为了减少敲写重复的代码,xcode原生带有很多代码段,例如for语句.switch语句等,{}表示代码段. 代码段制作: 具体制作代码段也很简单.先选中一段代码,然后右键,选择Crea ...
- vscode代码格式化、vetur代码格式化取消末尾添加逗号
1.在vscode编辑器中插件应用里找到vetur并安装 2.点击卸载旁边的设置按钮 -> 进入 扩展设置界面 3. 在代码块区 底部找到 在settings.json中编辑 4. 找到这个字段 ...
- 如何在公众号内优雅地添加代码块?我推荐几款常用的发帖工具!
背景 在运营公众号的过程中,或多或少可能会碰到分享代码的场景,此时该如何将你的代码高端.大气.上档次的呈现呢?这个问题经常会被热情地读者提问到,一直希望我能够分享一篇这方面文章.那么今天我就跟大家聊聊 ...
- 利器 | 如何在公众号内优雅地添加代码块?推荐几款常用的工具!
作者 | 刘顺祥 来源 | 数据分析1480(ID:lsxxx2011) 背景 在运营公众号的过程中,或多或少可能会碰到分享代码的场景,此时该如何将你的代码高端.大气.上档次的呈现呢?这个问题经常会被 ...
最新文章
- 学者要研究真问题做真学问
- python 比较两个字符串
- 内部同步 外部同步 java_如何用匿名内部类实现 Java 同步回调
- 判断不为空和不为空串的方法java
- Web前端笔试面试题汇总(转自github)
- django之auth模块
- 加载类型库/dll时出错 的解决方法
- python怎么把写在一个文件的类导入另一个文件_跟我一起自学python语言 第9章 类(9.4 导入类)...
- idea破解永久免费
- 如何查询出指定地点对应的经纬度(高德地图)
- axios报错Error: Request body larger than maxBodyLength limit
- 分布式监控平台CAT原理
- Java提取成对括号内容 支持扩展多种括号
- java date dec_java – 将日期从“2009-12 Dec”格式转换为“31-DEC-2009”
- excel合并多个工作表_快速将多个Excel表格合并成一个Excel表格
- 计算机丢失XAPOFX1_5.dll文件如何解决?
- 【FFmpeg】【转载】图像拼接:画中画连麦
- JavaScript5:常用DOM操作
- opic4:Qt入门之常用qt控件认知之Button系列
- VB连接SQL SERVER 数据库时ODBC设置