PE文件(五)代码节空白区添加代码

news2025/1/23 4:09:35

学习目的

本节的目的就是教会我们在一个可执行文件的代码节的空白区添加一段代码。

大致思路:正常的文件中OEP记录着程序入口的地址,现在我们将此可执行文件的程序入口OEP地址指向call0 x123456指令的地址,使其先执行我们添加的代码,执行完指令后再jmp 0x456789跳转回原来正常的文件OEP指向的程序入口地址,之后程序正常运行

注意在代码节空白区添加代码相当于给在硬盘上的文件中添加数据,添加完后再运行文件。该过程可以理解为文件注入。但是我们平时说的注入,则是文件在运行时把代码添加进去,这个过程可以理解为内存注入

在本节课中,我们将以添加一个MessageBox函数到一个可执行文件的代码节(.text)空白区为例进行讲解。

预备知识

MessageBox函数原型:

int MessageBox(

HWND hWnd,

LPCTSTR lpText,

LPCTSTR lpCaption = NULL,

UINT nType = MB_OK

);

四个参数说明:

hWnd:表示窗口句柄,用来该对话框属于哪个主窗口。如果该参数为空(0/NULL),则该对话框不属于任何窗口

lpText:字符串,指显示在对话框中的内容

lpCaption:字符串,指对话框的标题;如果此参数为空,则默认使用“错误”作为标题

nType:指定显示按钮的数目及形式,表名使用的图标样式、缺省按钮是什么、以及消息框的强制回应等

MessageBox()函数功能是弹出一个标准的Windows对话框,相当于程序的一个断点。该函数不是以C语言函数库的标准函数的方式去执行,而是通过使用MessageBox函数去调用Windows的API,即MessageBoxA。使用该API时需要包含头文件windows.h。如果一个程序关联了user32.dll动态链接库,则此程序就有Windows API函数MessageBoxA

我们知道一个文件是由一堆二进制数据组成的,所以我们要想将MessageBox函数加到一个可执行文件中,不是直接把函数加进去,而是需要把这个函数对应的二进制数据添加到文件中

由于一个函数的二进制数据过于复杂,所以我们将MessageBox函数的二进制数据添加到文件中是一件很困难的事情。所以我们只需要使用push指令将该函数需要的4个参数传入,找到此文件中的MessageBox函数的地址,使用call指令调用它,此时该函数会调用MessageBoxA API,于是我们便完成了添加MessageBox函数的操作

指令硬编码

由于计算机只认识二进制数据,所以我们需要知道call指令 jmp指令 push指令的硬编码以及使用它们需要传入的各种参数的硬编码

硬编码查看:当一个程序编译以后,我们可以进入反汇编中,右键打开code bytes选项即可显示硬编码。此时我们可以看到每条指令的左边都是它对应的硬编码。硬编码都是二进制数,在本节学习中用十六进制显示

call指令有不同类型的硬编码,一般都是E8类型的。其中当call指令的硬编码为E8时,使用该指令时后面加上4个字节call要跳转的的相对地址。而call指令的硬编码为FF15,使用时后面加上4个字节call要跳转的地方的绝对地址,即ImageBase + RVA后的地址值

jmp指令的硬编码是E9,使用时后面加上4个字节大小的jmp要跳转的相对地址

push指令的硬编码是6A,使用时后面加上需要传入函数参数的值

相对地址X的计算公式:X = 文件在虚拟内存状态下真正要跳转的地址 – 文件在虚拟内存状态下E8这条指令的下一行地址。由于call指令的硬编码固定一共占5字节,即一字节call硬编码和四字节地址,所以E8指令的下一行地址为E8当前地址+5。所以公式最终为:X = 要跳转的地址 - (E8的地址 + 该指令长度),

实例说明

构造一个需要调用函数的C代码:

#include <stdio.h>

void Function(int a,int b,int c,int d){}

int main(int argc,char* argv[])

{

    Function(1,2,3,4);

    return 0;

}

查看反汇编:

其中E8为call指令硬编码,E8 7F FE FF FF 为调用函数相对地址,00101014为调用函数的这真实地址。

根据公式:X = 要跳转的真实地址 - (E8的地址 + 该指令长度)可知:0x00401014 - (0x00401190 + 5)= 0xFFFFFE7F,由于内存小端序存储,所以为内存中存储的地址为7F FE FF FF,因此最后call指令的硬编码为E8 7F FE FF FF

预备工作

在我们使用call指令和jmp指令前,需要获取MessageBoxAPI函数的地址和程序本来的入口地址

1.获取MessageBox函数的地址:使用OD打开可执行文件,在左下角的命令栏输入bp MessageBoxA后回车。由于弹窗代表着断点,所以该指令表示在此函数起始位置设置了一个断点。接着我们点击上方栏中的B按钮查看断点,接着双击我们刚设置的断点就会跳转到断点所在地址,这个地址就是MessageBoxA函数的起始地址

2.获取程序本来的入口地址:通过可选PE头中的AddressOfEntryPoint字段值可以知道程序入口地址的相对于PE头偏移量,再通过可选PE头中的ImageBase字段知道文件装载到虚拟内存中的起始地址。根据ImageBase + AddressOfEntryPoint可以得出来程序在4GB虚拟内存中的真正的入口地址

添加流程

1.判断要添加代码的空白区内存大小是否能存放得下添加的硬编码(使用节对应的节表中的Misc.VirtualSize – SizeOfRawData即可计算空白区的大小)。因为我们使用一个push指令长度为2字节(一个一字节push硬编码大小,一个一字节地址大小),MessageBox函数一共需要push四个参数,所以需要四个push指令一共八字节大小。call和jmp指令长度为5字节,加起来一共是18字节。所以要留空的空间至少需要18字节

2.将要添加的代码转换成对应的硬编码:由于需要计算call指令E8 和 push指令E9后面的地址,所以要用公式X = 要跳转的地址 - (E8的地址 + 5)进行计算。

当我们使用UE编辑器或者winhex打开可执行文件进行编辑修改时,由于UE编辑器打开的文件的状态是在硬盘上的状态,所以我们修改的数据是FileBuffer中的数据,而不是ImageBuffer中的。此时计算公式的地址需要从文件地址转换成内存地址后再计算的

如果可执行文件是ipmsg.exe时,其文件对齐和内存对齐是一样的,所以该文件在硬盘上的数据格式和加载到内存中的格式是一样的。此时那使用UE打开文件时,上面显示的地址可以直接使用

但是如果可执行文件是notepad.exe等时,由于文件对齐和内存对齐不一样,从硬盘加载到虚拟内存是需要拉伸的,所以如果此时用UE添加硬编码计算E8 E9后面的地址值时需要使用内存地址,所以多了一个FOA转化成RVA的过程

3.定位到任意一个节后面的空白区,作为添加的硬编码的起始地址,数据最好添加在代码节中(一般默认为.text),这是因为代码区的属性一般是可执行的。所以数据加到代码节中不用修改节的characteristic属性。

由于我们添加的硬编码中有call和jmp指令后面的地址都是在虚拟内存中的地址,所以我们如果写程序来模拟这个过程,需要在拉伸后的文件中添加硬编码,这样更方便计算E8 和 E9后面跟的地址值。如果我们在文件在硬盘上的状态中添加也可以,但是计算E8 和 E9 后面跟的地址值在使用公式前,需要先把文件地址转换成内存地址

4.最后找到程序的AddressOfEntryPoint字段所在地址,将此字段的值改为添加的硬编码的地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1673552.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中通云仓科技又开了十家冻品体验店,持续在新零售领域加码

5月12日&#xff0c;中通甄选十家冻品体验店联合开业仪式在山东青岛隆重举行&#xff0c;仪式现场金鼓喧闹、雄狮起舞。随着地爆球爆破&#xff0c;礼炮齐响&#xff0c;掌声四起&#xff0c;与会领导拿起金剪共同为此次开业剪彩。 在中通甄选冻品体验店内&#xff0c;人头攒动…

【机器学习】AI在空战决策中的崛起:从理论到实践的跨越

AI在空战决策中的崛起&#xff1a;从理论到实践的跨越 一、引言二、AI技术的崛起与空军决策技术层面作战结构 三、AI在空战决策中的前景展望四、结语 一、引言 随着科技的不断进步&#xff0c;现代战争已经步入了一个全新的时代。其中&#xff0c;空战作为战争的重要组成部分&a…

使用VSCode撰写Latex文档

参考资料&#xff1a; 如何使用VSCode编写Latex&#xff1f; 概要 先安装texlive,然后安装VSCode. 我这里步骤是全的&#xff0c;但说的不那么细。 只介绍VSCode中的配置方法。 VSCode配置步骤 1. 安装LaTex Workshop插件 2. 配置Latex编译环境 将下列配置粘入settings.j…

搜索整个文件夹的所有日志

grep request * 这里的*就是全部文件 grep -e A -e b" * grep -rine "关键字"

小米/红米手机刷机错误:Missmatching image and device

报错&#xff1a; Missmatching image and device。 场景&#xff1a; 该解决方法只适用于手机是通过EMT解锁的。 解决方法&#xff1a; 打开刷机脚本&#xff0c;并注释检测脚本&#xff1a; 刷机脚本根据不同的刷机方式&#xff0c;选择编辑不同的脚本&#xff0c;例如&am…

tomcat--java的安装

组成 语言、语法规范。关键字,如: if、for、class等源代码 source code依赖库&#xff0c;标准库(基础)、第三方库(针对某些应用)。由于底层代码太难使用且开发效率低&#xff0c;封装成现成的库JVM虚拟机。将源代码编译为中间码即字节码后,再运行在JVM之上 jdk和jre 概念 j…

React脚手架,配置环境变量(生产模式,开发模式)

项目搭建方式&#xff1a;react脚手架(create-react-app) 1. 下载依赖&#xff1a; npm install dotenv npm install dotenv-expandnpm install dotenv-cli -S 2.配置环境变量&#xff1a; 项目根部录下创建文件.env .env.pro .env.dev 配置package.json - scripts…

[Java EE] 多线程(九):JUC剩余部分与线程安全的集合类(多线程完结)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

视频短信时代来临!发送前必知的四大关键要素

随着移动通信技术的迅猛发展&#xff0c;视频短信作为全新的沟通方式&#xff0c;正逐渐融入我们的日常生活。作为行业的先行者&#xff0c;邦之信已率先推出视频短信业务&#xff0c;并获得了市场的广泛认可。 那么&#xff0c;在发送视频短信时&#xff0c;我们需要注意哪些关…

【循环程序设计-谭浩强适配】(适合专升本、考研)

无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 无偿分享学习资料&#xff0c;需要的小伙伴评论区或私信dd。。。 完整资料如下&#xff1a;纯干货、纯干货、纯干货&#xff01;&#xff01;…

启动项目时出现SELinux is preventing

问题描述 启动项目时出现SELinux is preventing**** SELinux正在阻止systemd对文件AB.sevice进行读取访问。 我的是启zabbix是报该错&#xff1a; 最终解决方案 方法一&#xff1a;暂时禁用SELinux setenforce 0 方法二&#xff1a;禁用SELinux 在配置文件/etc/sysconfig/…

【LeetCode】每日一题 2024_5_14 完成所有任务需要的最少轮数(哈希)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;完成所有任务需要的最少轮数题目描述代码与解题思路 每天进步一点点 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;完成所有任务需要的最少轮数 题…

酒店前台装智能酒精壁炉前和装后对比

在酒店前台装智能酒精壁炉之前和之后&#xff0c;前台区域的氛围和效果会有显著的对比&#xff1a; 装智能酒精壁炉之前 传统或简约风格&#xff1a; 在壁炉安装之前&#xff0c;前台可能具有传统或简约的设计风格&#xff0c;可能缺乏独特的装饰元素或焦点。前台区域可能显…

OrangePi Zero2 全志H616开发学习文档、基础IO蜂鸣器、超声波测距、舵机PWM基础开发

一.平台介绍 OrangePi开发板不仅仅是一款消费品&#xff0c;同时也是给任何想用技术来进行创作创新的人设计的。它是一款简单、有趣、实用的工具&#xff0c;你可以用它去打造你身边的世界。 特性 CPU 全志H616四核64位1.5GHz高性能Cortex-A53处理器GPU MaliG31MP2 Supports…

LeetCode—用栈实现队列

1.题目 2.思路—双栈 思路与双队列实现栈类似&#xff1a; 将一个栈当作输入栈&#xff0c;用于压入push传入的数据&#xff1b;另一个栈当作输出栈&#xff0c;用于pop和peek操作。 每次 pop或 peek时&#xff0c;若输出栈outStack为空则将输入栈inStack的全部数据依次出栈并…

前端笔记-day06

文章目录 01-浮动-基本使用02-浮动-产品布局03-浮动-清除浮动带来的影响04-清除浮动-额外标签法05-清除浮动-单伪元素法06-清除浮动-双伪元素法单伪元素和双伪元素CSS 07-清除浮动-overflow08-flex布局-体验09-flex布局-组成10-flex布局-主轴对齐方式11-flex布局-侧轴对齐方式1…

如何用Rust获取CPU、内存、硬盘的信息?

目录 一、用Rust获取CPU、内存、硬盘的信息 二、知识点 systemstat 一、用Rust获取CPU、内存、硬盘的信息 首先&#xff0c;需要添加systemstat库到Cargo.toml文件&#xff1a; [dependencies] systemstat "0.2.3" 在Rust代码中使用它&#xff1a; extern crat…

400元已到账,成交从认真开始

昨天发了一个值班的需求&#xff0c;收到了很多好友的响应&#xff0c;这里非常感谢关注创业程序员卡酷的老朋友、新朋友。今天分享一下&#xff1a;拓展、合作、成交 现在不管是IT行业还是其他行业&#xff0c;大环境可谓一片惨淡&#xff0c;35乃至30找不到工作的失业人员一抓…

el-table 多级表头 列添加fixed=left 列错乱

如图错乱显示 添加 this.$refs.tableList.doLayout();

Linux 操作系统多路IO复用

1.多路IO复用 多路I/O复用是通过一种机制&#xff0c;可以监视多个描述符&#xff0c;一旦某个描述符就绪&#xff08;一般是读就绪或者写就绪&#xff09;&#xff0c;能够通知程序进行相应的读写操作。 这个机制能够通过select/poll/eroll等来使用。这些函数都可以同时监视多…