【CSAPP】-linklab实验

目录

实验目的与要求

实验原理与内容

实验步骤

实验设备与软件环境

实验过程与结果(可贴图)

实验总结


实验目的与要求

1.了解链接的基本概念和链接过程所要完成的任务。

2.理解ELF目标代码和目标代码文件的基本概念和基本构成

3.了解ELF可重定位目标文件和可执行目标文件的差别。

4.理解符号表中包含的全局符号、外部符号和本地符号的定义。

5.理解符号解析的目的和功能以及进行符号解析的过程。

实验原理与内容

每个实验阶段(共5个)考察ELF文件组成与程序链接过程的不同方面知识

阶段1:全局变量数据节

阶段2:强符号与弱符号数据节

阶段3:代码节修改

阶段4:代码与重定位位置

阶段5:代码与重定位类型

在实验中的每一阶段n(n=1,2,3,4,5...),按照阶段的目标要求修改相应可重定位二进制目标模块phase[n].o后,使用如下命令生成可执行程序linkbomb:

$ gcc -o linkbomb main.o phase[n].o [其他附加模块------见具体阶段说明]

正确性验证:如下运行可执行程序linkbomb,应输出符合各阶段期望的字符串:

$ ./linkbomb

$ 19210320303 [仅供示例,具体目标字符为每位学生学号]

实验结果:将修改后正确完成相应功能的各阶段模块(phase1.o, phase2.o, ...)提交供评分。

实验步骤

  1. 实验数据

学生实验数据包: linklab学号.tar

数据包中包含下面文件:

main.o:主程序的二进制可重定位目标模块(实验中无需修改)

phase1.o, phase2.o, phase3.o, phase4.o, phase5.o:各阶段实验所针对的二进制可重定位目标模块,需在相应实验阶段中予以修改。

解压命令:tar xvf linklab学号.tar

  1. 实验工具

readelf:读取ELF格式的各.o二进制模块文件中的各类信息,如节(节名、偏移量及其中数据等)、符号表、字符串表、重定位记录等

objdump:反汇编代码节中指令并提供上述部分类似功能

hexedit:编辑二进制文件内容

实验阶段1

要求:修改二进制可重定位目标文件"phase1.o"的数据节内容,使其与main.o链接后能够运行输出(且仅输出)自己的学号:

$ gcc -o linkbomb main.o phase1.o -no-pie

$ ./linkbomb

学号

实验提示:

检查反汇编代码,获得printf(根据情况有可能被编译时转换为puts)输出函数的参数的(数据节中)地址 。

使用hexedit工具(或自己编写实现二进制ELF文件编辑程序),对phase1.o数据节中相应字节进行修改。

实验阶段2

要求:根据强符号与弱符号的原则,判断符号表中的符号以及其所对应的数据区域。利用符号解析规则,创建生成一个名为"phase2_patch.o"的二进制可重定位目标文件(可以不修改phase2.o模块),使其与main.o、phase2.o链接后能够运行和输出(且仅输出)自己的学号:

$ gcc -o linkbomb main.o phase2.o phase2_patch.o -no-pie

$ ./linkbomb

学号

实验提示:

Phase2.o模块的符号表中,包含了类型为COM的符号。此类符号的特点是:未被赋初值。所以,其在ELF的数据节中并不真实存在。所以需要另寻解决办法,创造出真实存在的数据并对其进行二进制编辑,以达到输出自己学号的目的。

解题需要运用的主要知识为强弱符号的解析规则。另外,层序中包含了一个数值转换过程,学生需要根据反汇编代码确定其修改规则,并根据修改规则进行"反制"。

实验阶段3

要求:修改二进制可重定位目标文件"phase3.o"的代码节内容,使其与main.o链接后能够运行输出(且仅输出)自己的学号:

$ gcc -o linkbomb main.o phase3.o -no-pie

$ ./linkbomb

学号

实验提示:

检查反汇编代码,定位模块中的各组成函数并推断其功能作用。 根据反汇编程序的执行逻辑,修改函数中的机器指令(用自己指令替换函数体中的nop指令)以实现期望的输出。

为了实现输出功能,自行编写获得的二进制程序(可以通过编写汇编代码然后使用gcc -c命令的方式实现)可以"借用"其他函数中的"有用代码或数据",比如输出函数和数据引用等具体部分。

实验阶段4

要求:修改二进制可重定位目标文件"phase4.o"中重定位节和数据节中的内容,使其与main.o链接后能够运行输出(且仅输出)自己的学号:

$ gcc -o linkbomb main.o phase4.o -no-pie

$ ./linkbomb

学号

实验提示:

本阶段学生所拿到的.o文件中的"重定位位置"信息已经被抹除,学生需要根据实际情况确认冲重定位的发生位置,并根据重定位类型对位置信息进行恢复。若程序未能够正确修改重定位位置,则典型问题表现为段错误segmentation fault。此外,还需要学生根据程序所用到的数据情况进行数据部分的二进制修改。

实验阶段5

要求:修改二进制可重定位目标文件"phase5.o"中重定位节和数据节的内容,使其与main.o链接后能够正确输出(且仅输出)自己学号:

$ gcc -o linkbomb main.o phase5.o -no-pie

$ ./linkbomb

学号

You called touch2。若不完全满足题目要求,则会提示"Misfire" 和FAIL相关字段。

阶段5:使用ROP方式对rtarget进行攻击,调用touch3,且成功输出Touch3!: You called touch3。若不完全满足题目要求,则会提示"Misfire" 和FAIL相关字段。

实验设备与软件环境

1.Linux操作系统---64位Ubuntu 18.04

  1. gdb调试器和objdump反汇编指令

  2. 笔记本

实验过程与结果(可贴图)

实验工具

readelf:读取ELF格式的各.o二进制模块文件中的各类信息,如节(节名、偏移量及其中数据等)、符号表、字符串表、重定位记录等

objdump:反汇编代码节中指令并提供上述部分类似功能

hexedit:编辑二进制文件内容

阶段一

使用如下命令生成可执行程序linkbomb:

$ gcc -o linkbomb main.o phase1.o -no-pie

正确性验证:如下运行可执行程序linkbomb

$ ./linkbomb

应输出符合各阶段期望的字符串:

$ 232151503xx (已修改的情况下)

先执行一遍linkbomb 保证程序不会出现乱码

这里我们还没有修改,所以不会有结果

输入readelf -a phase1.o 查看elf文件内容

其中我们完成学号字符串的输出,找到对应参数g_data,其重定向类型是绝对地址(R_X86_64_32),且+了0x18,同时也是一个OBJECT-全局变量。因此我们需要找到对应的.data节在全文中的偏移量,从而将g_data的内容修改为学号字符串,完成phase1。

(R_X86_64_32)那里是5c,加上我们data中的60就是

5c+60=bc

从而确定在0xbc处插入我们需要插入的数据-学号字符串。

Ascii码的0-9是0x30-0x39

我的学号是23215150318

也就是32 33 32 31 35 31 35 30 33 31 38

接着输入hexedit phase1.o命令来修改phase1.o,并对phase1.o数据节中相应字节进行修改

修改完记得00结尾加保存ctrl+w,ctrl+x退出编辑

00结尾才能知道修改到的值

这是一个比较大的空间

我们找到0xbc的地方

这里显示的是b4,我们就挨个去算,4567,8 9 10 11

11位就是bb,12就是bc

我们就把32 33 32 31 35 31 35 30 33 31 38放进去,再00结尾保存

退出即可。

再验证一下有没有保存到

$ gcc -o linkbomb main.o phase1.o -no-pie

$ ./linkbomb

这样就过关了。

阶段二

使用readelf查看phase2.o并查找有关输出函数的内容。

输入readelf -a phase2.o 查看elf文件内容

可以发现COM未被赋初始值,COM表示g_myCharArray是一个未初始化的弱符号数组,大小Size为256,所以我们需要创建一个已初始化强符号的g_myCharArray来覆盖弱符号。需要打补丁phase2_patch.o

从中可以看到put函数的参数是g_myCharArray,其+0x5c,重定向类型也为绝对地址。

创建phase2_patch.c文件并写入0x5c个字节的"0"以及学号ASCII码。

使用"gcc -c phase2_patch.c"编译生成phase2_patch.o文件并链接:"gcc -o linkbomb2 main.o phase2.o phase2_patch.o -no-pie",最后运行程序

每个字符都发生了偏移。为了得到偏移量来反偏移得到字符串,实现学号的插入,为了方便计算输入的结果,我们编写一个程序来手动计算偏移量得出的结果,最终通过编辑好学号key,来计算be=%d输出计算结果,即正确的反偏移答案。

hack.c

使用"gcc -c hack.c"编译生成hack.o文件并链接

运行:gcc hack.c -o hack

gcc -o linkbomb2 main.o phase2.o phase2_patch.o -no-pie

./linkbomb2 > out

./hack < out

最终通过编辑好学号key,来计算be=%d输出计算结果,即正确的反偏移答案。

编译计算文件并链接上linkbomb2,将结果导出为out并使用out运行计算文件,得到的be值即为学号对应的反偏移量,修改patch文件中的字符串。

得到结果文件后再次编译链接运行linkbomb2

成功输出学号,这样就算过关了。

阶段三

链接 linkbomb3 执行:gcc -o linkbomb3 main.o phase3.o -no-pie

使用 objdump -d linkbomb3 反汇编查看汇编代码:

如果想要成功打印学号,应该是打印在后,所以包含puts语句的myFunc1方法在后面,并且接收一个参数,这个参数应该是学号;而myFunc2则是获取一个地址的值给到%rax寄存器。

可以看出,就是先调用myFunc2函数获取学号赋值给%rax,然后mov %rax,%rdi设置参数在调用myFunc1

所以我们注入的命令顺序为:

1、call myFunc2

2、Mov %rax,%rdi

3、Call myFunc1

使用 readelf -a phase3.o 查看 .text 节的偏移量:为0x40

使用 objdump -d phase3.o 查看 do_phase 填充代码地址

填充的起始地址是 0x40 + 0x31 = 0x71。

其中 call 指令是相对寻址,myFunc 函数的地址为

第一条指令call指令对应的机器码是e8 xx xx xx xx ,占 5 个字节,结束地址为 0x31 + 0x5 = 0x36,所以距离 myFunc2 函数地址的相对距离为 0x1b - 0x36 =-1b,也就是 e5 ff ff ff,

所以第一条 call 指令为 e8 e5 ff ff ff。

第二条指令mov %rax,%rdi,mov %rax,%rdi的机器码是为 48 89 c7

第三条指令为call指令对应的机器码是e8 xx xx xx xx ,占 5 个字节,加上第二条指令的 3 个字节,所以结束地址为 0x36 + 0x3 + 0x5 = 0x3e ,所以距离 myFunc1 函数地址的相对距离为 0x0 - 0x3e = c2 ff ff ff ,所以第三条指令为 e8 c2 ff ff ff 。

修改 phase3.o 的二进制,将构造的代码注入

然后执行 hexedit phase3.o 从 0x71 开始写入我们构造的代码

接着来查看是否修改

执行 objdump -d phase3.o查看 do_phase3 函数

可以看到修改成功

完成代码插入,现在需要完成学号赋值。回看myFunc2函数汇编,发现学号赋值处函数获取数据的内存地址,即为.data节。因此我们需要找到节头以及加数。图13中显示.data节节头为0x1a0,重新查看ELF发现.data加数是为0x5c,从而确定学号应当位于phase3.o的0x1a0+0x5c=0x1fc处,并且以"00"结尾进行插入。

readelf -a phase3.o

执行 hexedit phase3.o 从0x1fc修改成我们的学号

gcc -o linkbomb3 main.o phase3.o -no-pie

./linkbomb3

通过查阅之前讲过的第三章的知识,也算恶补了一下。

至此,阶段三结束。

实验总结

通过此实验,我掌握了符号解析、符号定义分类 、静态链接解析过程、符号表条目、重定位,还有的是关于地址的计算。基于ELF文件格式和程序链接过程的理解,修改给定二进制可重定位目标文件的数据内容、机器指令等部分。实验过程中,我有遇到了bug,但通过了查询资料(书都要翻烂了)、上百度搜问,最后自己独立解决了bug。通过完成此次实验,不仅收获了很多知识,而且还锻炼了我的动手能力。解决了问题,完成了实验,感觉收获满满的,也有一定的成就感。

相关推荐
Artintel2 个月前
[学习笔记]《CSAPP》深入理解计算机系统 - Chapter 6 存储器层次结构
笔记·学习·c·csapp
永恒,怎么可能4 个月前
【CSAPP】-cachelab实验
csapp
John_Snowww5 个月前
CSAPP Lab01——Data Lab完成思路
vscode·csapp·wsl2·cmu15213
念谨9 个月前
【目录】CSAPP的实验简介与解法总结(已包含Attack/Link/Architecture/Cache)
csapp·深入理解计算机系统·15213
Tmylyh1 年前
程序的机器级表示
汇编·操作系统·csapp
囚蕤1 年前
csapp-Machine-Level Representation of Program-review
csapp·machine-level
玛了个玛卡巴卡1 年前
csapp archlab PartC满分解答
csapp