计算机系统基础实训四-LinkLab实验

实验目的与要求

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

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

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

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

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

实验原理与内容

每个实验阶段(共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, …)提交供评分。 

实验设备与软件环境

Linux Ubuntu 18.04 64-bit

笔记本电脑

VMware虚拟机

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

Phase 1

先运行一遍

为了方便生成phase1.s文件

使用objdump -rd phase1.o查看elf文件内容,找到输出的.data 节中偏移量为32的位置。

使用readelf -a phase1.o命令查看phase1.o的ELF数据,

即在0x60+c=0x6c处,用hexedit phase1.o命令修改phase1.o找到0x6c处,修改0x6c+1的值为学号十六进制ASCII码。然后以ASCII码”00”结束字符。

修改的十六进制是:32 33 32 31 35 31 35 30 35 34 31

编译重新运行,正确输出学号

Phase2

反汇编phase2,发现有两部分构成

Func函数主要是对数组做一些处理,处理之后返回给phase2函数

readelf -a phase2.o命令查看phase2.o的符号表

有个COM未被赋初始值,是个弱符号,根据文档提示打个补丁phase2_patch.o。里面的内容应该是cahr类型的大小为256的g_myCharArray变量的初始化,

得出偏移量为0xc

创建phase2_patch.c文件,创建一个g_myCharArray(弱符号),偏移量是0xb(12)所以前12个无用填0

采用两种方法

方法一:随机输入两个数35 35,发现打印出来的是/0,于是一个个慢慢推出来

方法二:先在phase2_patch.c填充大小为256个0

依次输入 gcc -c phase2_patch.c、gcc -no-pie main.o phase2.o phase2_patch.c、./a.out

因为我的学号是11位数,所以取最前面的11位“<=>?@ABCDEF”根据ASCII得到16进制的值

因此往phase2_patch.c填充偏移量12个0以及所得出来的字符:

\X26\X26\X24\X22\X25\X20\X23\X1D\X21\X1F\X1B

发现后面的框框不美观,于是在ASCII码找到null字符进行终止

Phase3

先进行反汇编

Fun1输出函数,fun2是获取data数据,因此要将他们做一个结合调用

将所写的函数进行反汇编得到

得到text的地址码为:e8 00 00 00 48 89 c7 e8 00 00 00 00

打印文件格式:readelf -a phase3.o

找到偏移字段

查看反汇编

因此,在第60+D的位置可以看到<do_phase3>的地址55 48 89 e5,在后面添加test的地址码

保存并退出,将其编译进.s文件

查看phase3.s,命令为:vim phase3.s

写进func2里的偏移:1b(myfunc2头)-36(第一个callq)=FFE5

写进func1里的偏移:0(myfunc1头)-3E(第二个callq)=FFC2

将他写进 phase3.o中

再次反汇编,命令

查看phase3.s文件

尝试编译输出,发现全都是XXXXX....

进入字符集,命令:readelf -a phase3.o

找到data字段,位置是01a0

找到位置加上偏移量,后移一位就是我们要修改的值:01A0+C=01AC+1=01AD

保存并退出ctrl+x,重新运行

Phase4

查看phase4.o文件ELF数据,命令:readelf -a phase4.o

要修改上面全为0的偏移量

从↓可以看出

一个是变量:g_myCharArray

一个是变量:temp

还有一个:puts函数

且g_myCharArray是位于.data节中偏移量为0(即value值)处

temp是位于.data节中偏移量为0x14(即value值)处编译查看汇编代码

编译查看汇编代码:

截图避免待会需要,用objdump -d phase4.o查看汇编代码

观察可得
偏移量是要使变量和函数到这里

即0x6、0x11、0x19
0x18是call指令,所以它对应的是call puts函数。
要把这里的值设置为19

输入命令:Hexedit phase4.0,查看一下.rela.text段的开始是250

经过我的分析
偏移量、信息、是符号名称+加数的加数

这个是“第一组”的,以此类推可以找到”puts组”的位置,”FC FF FF FF FF FF FF”是-4的补码也验证了我们的计算

修改此处的偏移量为19

重新查看phase4.o文件的ELF数据

可以发现改对了
重新编译查看汇编代码

会发现变成了<puts@pIt>

现在还有两个偏移量要修改

这两个是数据,看下面是这两个变量的值

.data段在

一个在.data+0处,一个在.data+0x10处

前面有提到.data+0是g_myCharArray,那.data+0x10是temp

修改为学号

现在就要改对应的偏移量
可以看出0x6和0x11处

根据思考,0x11应该放学号数组,因为要赋值给%rdi传递给puts函数打印,0x6应该放temp
回到上面已经发现”.data+10”(temp)组偏移量是这里,修改为6

“.data+0”组偏移量是这里,修改为11

readelf -a phase4.o查看,修改正确

但是值有点错误

还有一个值没有修改

这里可以看出temp是一个位于.data节中偏移量为0x14处的。

从这里可以看出上面的.data+10并不是真的temp的值,而是.symtab里的value才是它的偏移量。

这里就是.data节偏移量为0x14处,改为”00”

保存退出重新运行,结果正确

Phase 5

编译查看汇编代码

查看一下ELF数据,命令:readelf -a phase5.o

这两个换换就好

找到偏移量,互换即可

这里可以看出g_myCharArray是一个位于.data节中偏移量为0x10处的。
.data在0x90处

g_myCharArray在0x90+0x10=0xA0处,修改为学号

编译运行,结果正确

实验总结

通过此实验,我掌握了符号解析、符号定义分类、静态链接解析过程、符号表条目、重定位、动态链接、静态库的缺点、位置无关代码、数据和代码调用,还有的是关于地址的计算。基于ELF文件格式和程序链接过程的理解,修改给定二进制可重定位目标文件的数据内容、机器指令、重定位记录等部分。实验过程中,我遇到了一些困难和bug,但通过查询资料、搜索和自己思考,最后独立解决了问题。通过完成此次实验,不仅收获了许多知识,而且还锻炼了动手能力和解决问题的能力。解决问题,完成实验,感觉收获很多,也有一定的成就感。

  • 29
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值