当前位置: 首页 > news >正文

计算机系统——模拟病毒感染ELF可执行文件

事先声明:本文所述制作简易病毒的操作,只适用于计算机系统这门课中加深对于ELF可执行文件的理解,是一个等价的“安全实验版本”,禁止用于其他违反法律的用途!

我们的目的是感染干净程序,让被感染的程序先输出“Welcome to HNU CSAPP!”,然后再执行原有的后续功能,并检测同一目录下未被感染的所有文件,将它们全部感染。

一、可执行文件的核心结构(Linux下64位)

1、ELF 文件头:存整个文件核心信息,最重要字段 ,操作系统把程序加载到内存后,CPU 第一条执行指令的虚拟地址。

2、程序头表 Program Header Table:告诉操作系统:这个文件有哪些段、每一段在文件里偏移多少、加载到内存哪个地址、权限是什么(可读 / 可写 / 可执行)。 我们程序正常代码段 .text 就是一个LOAD类型、R-X(只读可执行)权限的段。

3、节区头表 Section Header Table:调试、链接用,运行时操作系统不读取。

4、文件数据段:.text代码段(原程序所有指令)、.data数据段、文件尾部对齐填充空白区

与普通.c文件的区别:.

c是纯文本源码,直接字符串插入即可完成感染;而ELF 是二进制机器码文件,不能直接改字符串,需要修改程序内存布局、注入恶意指令、修改程序入口地址,实现运行优先执行病毒逻辑,再跳转回原程序正常功能。

因此想要感染可执行文件的难度更大。

二、感染步骤

步骤一:制作病毒标记,避免重复感染 先做防重复感染校验

1、在 ELF 文件尾部空闲对齐区域,写入一段固定魔数(比如HNUCSAPP_VIRUS)

2、程序运行 / 扫描时,先读取文件末尾,检查有没有这个标记

3、有标记 = 已经感染,跳过;无标记 = 健康文件,执行感染。

部分代码如下:

步骤二:编写位置无关 PIC 病毒机器码

病毒完整逻辑:

1、打印 Welcome to HNU CSAPP!

2、遍历当前目录所有 ELF 可执行文件

3、对未感染文件,重复整套感染流程

4、所有传染工作做完,无条件跳回原程序入口,让原程序正常运行

这里有一个硬性要求:必须编译成PIC位置无关代码,因为:

①ELF 每个程序加载地址都不固定,绝对地址跳转一定会崩溃

②PIC 代码不依赖固定内存地址,无论加载到内存哪个位置都能正常执行

编写PIC位置无关代码的步骤:

访问字符串(必须用 RIP相对寻址,不能访问绝对地址)—>函数调用(汇编代码中的call是相对跳转,自动变成 PIC)—>跳回原程序入口(用 RIP 找到存储的原始入口)—>保护现场(不破坏宿主程序寄存器)

部分代码如下:

步骤三:追加病毒代码到 ELF 文件尾部

1、把编译好的病毒二进制机器码,拼接在原 ELF 文件的最末尾

2、利用 ELF 天然的页对齐冗余空间,不破坏原有任何正常代码

3、计算病毒代码在文件内的偏移、加载到内存后的虚拟地址

部分代码如下:

步骤四:修改程序头表,新增可执行 LOAD 段(核心关键)

操作系统只会加载程序头表里声明的 LOAD 段到内存执行:

1、在原有程序头表末尾,新增一个 Program Header 项

2、类型:PT_LOAD(操作系统必须加载到内存)

3、权限:R-X 只读 + 可执行(和原代码段权限完全一致,合法合规)

4、填写:病毒代码在文件里的偏移、文件大小、内存虚拟地址、内存大小

5、更新整个 ELF 文件的总大小

做完这一步,程序运行时,操作系统会自动把我们的病毒代码,和原程序一起加载进进程内存。

部分代码如下:

步骤五:劫持程序入口 Entry Point(感染灵魂操作)

1、先备份原来的程序入口地址,存到病毒代码固定位置

2、修改 ELF 文件头里的Entry Point字段,把原本指向原程序第一行指令的地址 → 改成我们病毒代码的起始内存地址

效果:程序一启动,CPU 不再先跑原程序,优先执行我们的病毒代码

部分代码如下:

步骤六:病毒收尾长跳转(RIP),还原原程序执行

病毒代码执行完所有逻辑(打印标语 + 传染其他文件)后,最后加一条无条件跳转指令: jmp 原程序备份入口地址

这样执行完病毒,立刻跳回原来程序的正常起点,原程序功能完全不受影响,用户完全感知不到异常(病毒隐蔽性极强)。

部分代码如下:

这样我们就执行完了病毒感染的六个步骤,总结下来就是:追加病毒二进制代码→修改 ELF 段结构与地址对齐→劫持程序入口点→优先执行病毒传播逻辑→跳转回原程序正常运行→写入标记防止重复感染。

感染后程序完整运行链路:(自我复制、横向感染、不破坏原程序功能)

操作系统加载 ELF 到内存→ CPU 从新入口(病毒地址)取指令执行→ 执行病毒:打印标语 → 遍历目录感染其他 ELF 文件→ 病毒执行完毕,RIP相对跳转回到原始程序入口→ 原程序正常执行自己原本所有功能。

三、ELF 感染三大核心准则

1、地址对齐严格约束:ELF 所有段必须按内存页大小对齐,偏移地址不满足对齐要求,操作系统拒绝加载,程序无法运行。

2、地址重定位问题:动态链接ELF不能用绝对地址,全程必须用PIC位置无关编码,否则换环境程序直接错误崩溃。

3、栈上下文不破坏:病毒代码必须保存并恢复所有寄存器、栈基址,不能打乱原程序栈布局,不然原程序运行异常、崩溃。

与感染.c文件进行对比:

感染对象修改方式格式约束
.c文本源码 易字符串文本插入几乎无约束
ELF可执行文件 难追加代码段、修改程序头、劫持入口地址

严格 ELF 格式、页对齐、地址合法

四、实际操作

讲完了理论,我们在Ubuntu里面实际操作一下,体会这个流程。

这里我们使用Ubuntu自带的一个编辑器来保存我们的代码(如果使用vim的话可能需要另外安装,稍微麻烦点)。

先编写干净文件:

1、直接输入

nano clean.c

2、打开后,粘贴下面代码进去:

#include <stdio.h> int main() { printf("我是干净程序\n"); return 0; }

然后按Ctrl+O保存,回车后再按Ctrl+X退出。

之后想要再查看,依旧是输入nano clean.c:

3、编译干净程序

gcc clean.c -o clean

输入以上代码,将clean.c文件编译生成可执行文件(ELF)。

输入ls,会看到:

其中的clean.c就是一开始编辑的源文件,而clean就是编译生成的ELF可执行文件。

4、运行干净程序

./clean

运行后你会看到:

证明干净程序无误。

接下来编写病毒代码:

5、输入:

nano virus.c

进入编辑器后,粘贴以下代码:

#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *in = fopen("clean.c", "r"); FILE *out = fopen("infected.c", "w"); if (!in || !out) { printf("文件打开失败\n"); return 1; } char line[256]; while (fgets(line, sizeof(line), in)) { // 找到 main 函数,插入病毒代码 if (strstr(line, "int main()")) { fputs(line, out); fputs(" printf(\"Welcome to HNU CSAPP!\\n\");\n", out); continue; } fputs(line, out); } fclose(in); fclose(out); printf("感染完成:生成 infected.c\n"); return 0; }

然后按Ctrl+O保存,回车后再按Ctrl+X退出。

6、编译病毒程序

gcc virus.c -o virus

7、执行感染

./virus

8、感染完成,你会看到:

9、检查感染结果(很重要!)

cat infected.c

你应该看到:

这是感染后的等效C代码。

10、编译“被感染”程序

gcc infected.c -o infected

11、运行最终程序

./infected

你会看到输出:

被感染后的文件先执行了病毒代码,然后再执行原有程序 ,符合预期,说明我们设计的病毒正确。

五、中途报错,可能出现的问题

1、gcc不存在:输入

sudo apt update sudo apt install build-essential -y

更新软件列表,安装开发环境,实际上就是给你的Ubuntu安装编译器,否则.c文件无法编译生成ELF可执行文件。

2、权限不足:

有时候你运行./clean,会报Permission denied,是因为文件没有执行权限。解决办法是输入

chmod +x clean

然后重新运行./clean。

这条指令的意思是给clean文件加上executable(可执行)权限。

3、strstr未声明或编译报错:

在写病毒程序(virus.c)时,可能会看到

warning: implicit declaration of function ‘strstr’

或者直接报错。是因为我们代码里写了

strstr(line, "int main()")

但没有包含头文件。正确做法是在virus.c开头加上

#include <string.h>

完整的正确头部应该是这样的:

#include <stdio.h> #include <stdlib.h> #include <string.h>

因为strstr()是字符串处理函数,它定义在<string.h>里。编译器有时候只是 warning,不是 error,所以这个疏忽很容易忽略。

再次声明:本实验所编写的病毒代码为简易且安全实验版本,不具备侵入其他文件的能力,仅用于学习与参考。请勿利用有关知识危害网络安全!

(本文中代码如有错误,欢迎指正)

http://www.jsqmd.com/news/728753/

相关文章:

  • 【js】浏览器滚动条优化组件OverlayScrollbars
  • 推荐一下都江堰中央空调、地暖
  • WPS-Zotero完整指南:5分钟实现跨平台文献管理无缝对接
  • 盗版屡禁不止,AI 如何重塑在线教育版权保护体系
  • 单GPU运行Mistral NeMo 12B模型的技术解析与优化
  • CS8759E 数据手册 - 高功率 D 类音频放大器 2130W
  • ARM ST4指令解析:SIMD向量存储优化与实践
  • Windows Internals 读书笔记 10.5.8:ETW 安全机制,不只是记录日志,更是权限与证据链管理
  • 统信UOS远程协助实战:从内网到外网,手把手教你用自带工具搞定远程桌面
  • W55MH32 RTThread+UDP通信测试
  • 告别VSCode卡顿与插件冲突:一份详细的缓存与插件数据清理指南(附一键清理脚本)
  • ModStart:基于 Laravel 的模块化开发框架,V11.0.0 版本新增 15 个特性!
  • 联创 DelBug:AI Agents 驱动,项目 + 缺陷 + 测试一站式管理,让交付更省心。
  • 2026年海牙认证服务机构名录:北京企业境外投资、吉尔吉斯斯坦海牙认证、境外投资备案审批流程、大使馆公证认证代办选择指南 - 优质品牌商家
  • 开源对话大模型MOSS:从架构解析到微调部署实战指南
  • 期货量化模拟转实盘检查清单:延迟、成交偏差与异常处理
  • 机器学习实验跟踪工具Neptune:从原理到实战的完整指南
  • 2026超高频工器具标签技术解析:耐高温电子标签/超高频4通道读写器/超高频8通道读写器/超高频工器具标签/超高频耐高温抗金属标签/选择指南 - 优质品牌商家
  • 深度学习图像描述生成技术解析与应用实践
  • 8devices Maca 2超远距离无线数据电台技术解析与应用
  • Transformer库实战:从原理到NLP应用部署
  • 数据库主键选型终极指南:从自增ID到分布式雪花
  • 构建AI智能体驱动的个人操作系统:从工作流自动化到认知增强
  • 告别枯燥调试!用CANoe Panel的CAPL Output View组件实时显示报文(附报文更新避坑指南)
  • 申博择导认知纠偏:打破固有误区,建立底层择导逻辑
  • 2026年4月全屋定制大揭秘,究竟哪家才是行业最强?
  • 深入AutoSar CAN通信栈:图解CAN IF模块如何桥接CAN Driver与上层
  • SERA代码代理训练框架:低成本高效AI辅助编程方案
  • 仅限前500名R工程师获取:Tidyverse 2.0自动化报告模板库(含FDA/ISO/金融监管合规元数据框架)
  • TSX07311628扩展模块