ELF-Code-Injection-Technology
实验目的
学习几种将代码注入现有 ELF 二进制文件的基本技术,从而允许修改或者扩展二进制文件的行为。
实验原理
使用常用分析工具。
实验环境
1. 使用 binary 虚拟机,即在 Lab 2 中已经配置过的环境(包括时间戳)。
2. 实验所需文件位于/home/binary/code/chapter7 目录。
Task 1:使用十六进制编辑器修改 Bare-Metal 二进制文件
观察 off-by-one 漏洞
步骤:
1、输入 gcc -o xor_encrypt.c xor_encrypt.c 指令编译出可执行文件xor_encrypt。
2、输入 ./xor_encrypt xor_encrypt.c encrypted foobar 指令,将文件xor_encrypt.c加密为文件encrypted。
3、输入 xxd xor_encrypt.c | tail 指令,查看文件xor_encrypt.c。
4、输入 xxd encrypted | tail 指令,查看文件encrypted。

观察输出结果可以对比发现,只有最后一个字节 0x0a 未被加密。
修复 off-by-one 漏洞
步骤:
1、查找导致漏洞的字节:输入 objdump -M intel -d xor_encrypt 指令反汇编二进制文件。

由输出结果发现与指导书不同,在 0x400b11 处发现了 test 指令,可以得知我们需要将 0x400b34 处的 jne 指令改为 jae 指令。
2、替换违规字节:输入 make 指令和 hexedit xor_encrypt 指令在十六进制编辑器中打开 xor_encrypt。按 \ 健,输入 75ea 查找 jne 指令,将其改为 73ea,即 jae 指令。


输入 objdump -M intel -d xor_encrypt 指令反汇编经过修改的二进制文件,发现0x400b34 处的 jne 指令已经被改为 jae 指令。

输入 ./xor_encrypt xor_encrypt.c encrypted foobar 和 xxd encrypted | tail 指令,发现 encrypt 的最后一个字节也被加密了,且前面的字节与修改前完全一致。

Task 2:使用 LD_PRELOAD 修改共享库行为
堆溢出漏洞
步骤:
1、输入 ./heapoverflow 13 'Hello world!' 指令,正常输出。
2、输入 ./heapoverflow 13 'perl -e 'print "A"x100'' 指令,发现程序崩溃。

Q:根据执行结果,程序出现崩溃的具体原因是什么?
A:根据执行结果,程序尝试执行 free() 函数,由于内存分配或释放过程中出现了问题,导致了 free(): invalid next size (fast) 错误。而程序接收了命令行参数 13 和 "A"x100 作为输入,输入的100个 "A" 太长导致堆溢出。
修复堆溢出漏洞
输入 LD_PRELOAD='pwd'/heapcheck.so ./heapoverflow 13 'perl -e 'print "A"x100'' 指令,在启动 heapoverflow 程序时,改变LD_PRELOAD 环境变量的定义,这使得链接器预加载指定的库文件 heapcheck.so,成功检测到不安全的复制行为,输出错误,并安全地终止程序,因此程序没有崩溃。

Task 3:注入代码节(Code Section)
步骤:
1、输入 ls hello.bin 指令,查看文件 hello.bin。
2、输入 ./elfinject 指令查看 elfinject 的使用方法。
3、输入 cp /bin/ls . 指令使用 /bin/ls 的副本作为主体二进制文件。
4、输入 ./ls 指令发现注入之前表现正常。
5、输入 readlf --wide --headers ls 指令查看 ls 的头部信息。

6、输入 ./elfinject ls hello.bin ".injected" 0x800000 0 指令将 hello.bin 文件注入 ls 二进制文件中,将节附加到二进制文件的尾部。
7、输入 readelf --wide --headers ls 指令显示 ls 二进制文件现在包含了一个名为 .injecte 的代码节,以及包含此节的 PT_LOAD 类型的新可执行段。


8、输入 ./ls 指令发现二进制文件现在启动时会运行注入的代码,输出 hello world!
消息;然后,注入的代码将执行权交还给文件的原始入口点,以便恢复输出目录列表的正常行为。

Task 4:调用注入的代码
入口点修改
步骤:
1、输入 gedit hello.s 指令打开 hello.s 文件,发现原始入口点为 0x4049a0。

2、输入 nasm -f bin -o hello.bin hello.s 指令将 hello.s 汇编到原始二进制文件hello.bin中。
3、输入 cp /bin/ ls.entry 指令 将/bin/ls 二进制文件复制到 ls.entry。
4、输入 ./elfinject ls.entry hello.bin ".injected" 0x800000 -1 指令将刚刚准备好的代码注入加载地址为 0x800000 的二进制文件中。
5、输入 readelf -h ./ls.entry 指令查看 ls.entry 的头部信息,可以看到二进制文件的原始入口点 0x4049a0。

6、输入 readelf --wide -S ls.entry 指令可以看到 0x800e78 是新地址。

7、输入 ./ls.entry 指令发现与正常的 ls 指令一致。
8、输入 hexedit ./ls.entry 指令打开十六进制编辑器,按 \ 健,由于是小端编码,于是我们输入 a04940 查找原始入口点,将其改为780e80。

9、输入 readelf ./ls.entry 指令查看 ls.entry 的头部信息,可以看到二进制文件的原始入口点 0x800e78。
10、输入 ./ls.entry 指令会在显示目录列表之前输出 "hello world"。此时已成功覆盖了入口点。

劫持构造函数和析构函数
步骤:
1、输入 nasm -f bin -o hello-ctor.bin hello-ctor.s 指令将 hello-ctor.s 汇编到原始二进制文件hello-ctor.bin中。
2、输入 cp /bin/ls ls.ctor 指令 将/bin/ls 二进制文件复制到 ls.ctor。
3、输入 ./elfinject ls.ctor hello-ctor.bin ".injected" 0x800000 -1 指令将刚刚准备好的代码注入加载地址为 0x800000 的二进制文件中。
4、输入 readelf --wide -S ls.ctor 指令可以看到 0x800e78 是新地址。

5、输入 hexedit ls.ctor 指令打开十六进制编辑器,按 \ 键,由于是小端编码,于是我们输入 a04940 查找原始入口点,将其改为 780e80。

6、输入 objdump ls.ctor -s --section=.init_array 指令查看 .init_array 节的内容。
7、输入 ./ls.ctor 指令发现先显示"hello world"消息,然后按正常方式输出目录列表。
