计算机系统实验六:程序的链接

参考教材:计算机系统基础 第二版 袁春风 机械工业出版社
参考慕课:计算机系统基础(四):编程与调试实践 https://www.icourse163.org/learn/NJU-1449521162

计算机系统实验导航

实验一:环境安装 https://blog.csdn.net/weixin_46291251/article/details/122477054

实验二:数据的存储与运算 https://blog.csdn.net/weixin_46291251/article/details/122478255

实验三:程序的机器级表示 https://blog.csdn.net/weixin_46291251/article/details/122478979

实验四:二进制程序逆向工程 https://blog.csdn.net/weixin_46291251/article/details/122479554

实验五:缓冲区溢出攻击 https://blog.csdn.net/weixin_46291251/article/details/122479798

实验六:程序的链接 https://blog.csdn.net/weixin_46291251/article/details/122480049

实验源码: xxx

准备

实验内容:

1 链接与 ELF 实验的内容、方法和基本步骤;
2 程序链接的作用与过程、ELF 文件格式组成等知识的回顾与应用。

实验目标:

1 加深对程序链接中符号解析、重定位等基本概念、位置无关代码和 ELF 文件的基本组成等方面知识的理解和掌握;
2 掌握计算机系统思维,理解高级语言中数据、运算、过程调用和 I/O 操作等在计算机系统
中的实现方法,将程序设计、汇编语言、系统结构、操作系统、编译链接中的重要概念贯穿起来。能够对计算机系统复杂工程问题制定解决方案
3 掌握各种开源的编译调试工具,能够对分析优化程序设计,提高在代码调试、性能提升、软件移植和鲁棒性等方面的能力。

实验任务:

1 学习 MOOC 内容

https://www.icourse163.org/learn/NJU-1449521162
第七周 程序的链接
第 1 讲 链接与 ELF 实验:概述
第 2 讲 链接与 ELF 实验:静态数据与 ELF 数据节
第 3 讲 链接与 ELF 实验:指令与 ELF 代码节及课后实验

2 完成作业

2.1修改二进制可重定位目标文件“phase1.o”的数据节内容(不允许修改 其他节),使其与main.o链接后运行时输出自己的学号:

2.2实验内容:修改二进制可重定位目标文件“phase2.o”的代码节内容(不允许修改 其它节),使其与main.o链接后运行输出自己的学号:

phase1:静态数据对象与 ELF 数据节

第一步.

使用objdump工具获得目标文件的汇编代码,使用readelf工具获得其重定位记录。
首先对程序进行链接并执行,查看输出结果:
在这里插入图片描述

然后用objdump对phase1.o进行反汇编,查看输出结果:
分析反汇编后的文件:
在这里插入图片描述

选中的两行实现了对常数0x9a进行压栈操作。

然后用readelf -r 查看phase.o对应的信息

然后分析phase1.o中出现的重定位记录:

在这里插入图片描述

R_386_PC32PC绝对地址重定位方式下,重定位后的引用地址=符号定义地址-符号引用所在地址+重定位前引用处的初始值

第二步.

结合并分析汇编代码与重定位信息,定位输出函数的调用参数在目标 文件中的存储地址
使用readelf工具查看.data节中相应偏移量(0x29)处的字符串内容,并与未修改的phase1.o模块链接生成的程序输出的字符串比较,确定该字符串为修改的目标。

利用readelf -x .data phase1.o获得模块1指定节的内容:
在这里插入图片描述

上述在data节中对应0x9a偏移量地址对应的字符串与前面执行程序输出的字符串一致,可见输出字符串对应的地址确实是data节中的0x9a

第三步.

使用hexedit工具,对phase1.o模块的数据节中相应字节进行修改。

下面使用hexedit工具对目标模块phase1.o中输出字符串内容进行修改:

首先利用readeif -S phase1.o 查看data节的偏移量
在这里插入图片描述

由上图可知,data节在文件中的偏移量为0x60.
所以输出字符串在文件中的偏移量为0x60 + 0x9a = 0xfa

然后利用hexedit工具打开phase1.o模块
定位到偏移量为0xfa的字节处:
在这里插入图片描述

现在把输出字符串从第一个字节开始,依次替换为需要输出的学号对应的字符串,1对应的编码为31后面依次类推,输入完学号后,最后加上00作为字符串结束的标志。然后ctrl+x保存退出即可。
在这里插入图片描述

以上就完成了对phase1.o的修改。

第四步.

重新链接phase1.o模块和main.o模块,运行生成的可执行程序,验证修改是否完成了实验的目标。
在这里插入图片描述

验证了前面对字符串的修改,达到了实验目标。

phase2:指令与 ELF 代码节

第一步.

使用objdump工具获得phase2.o目标模块的汇编代码,使用readelf工具获得其重定位记录和符号表。
首先对程序进行链接,然后运行查看结果:
在这里插入图片描述

由以上结果可知,默认phase2不输出任何信息。

然乎利用objdump对phase2进行反汇编,并查看代码:
在这里插入图片描述

然乎利用readelf查看phase2中出现的重定位记录:
在这里插入图片描述

第二步.

分析汇编代码并结合重定位信息、符号表,推断phase2.o模块中各函数的功能作用,定位出其中负责输出的函数。
在获得了phase2.o目标模块的汇编代码和重定位记录知之后,进一步分析该模块中各个函数的功能。

首先在phase2.o代码节中找到包含有类似puts输出函数调用的函数
利用less工具查看反汇编代码phase2.o,利用其查找功能查找call指令出现的位置:
在这里插入图片描述

然后查找重定位表
在这里插入图片描述

发现其对应puts函数。
所以调用puts语句的函数即为输出字符串的函数这里是(00000061 :)
然后就可以在phase2模块的dophase函数中调用kfSvKnbh函数以实现字符串的输出

下面从符号表中获得目标函数在.text节中的偏移量(这里是0x61)
利用readelf查看phase2的符号表
在这里插入图片描述

可以看出这个函数对应编号为1的节,大小为48。
然后利用readelf查看得到编号为1的节是text节。
在这里插入图片描述

所以目标函数位于text节中偏移量为0x61的位置上。

kfSvKnbh函数具有LOCAL链接绑定属性,故调用该函数可通过相对于PC值的偏移量来进行跳转,不需要构造相应的重定位记录进行配合。

第三步.

构造调用输出函数的指令代码。
分析目标函数kfSvKnbh的执行逻辑:

在这里插入图片描述

查看第一个call语句的重定位记录可知其调用的是strcmp函数,strcmp函数比较传递给它的两个字符串参数的内容是否相同,如果相同的话将返回0,如不同则返回非0的一个数。

当存放于EAX寄存器中的、strcmp函数的返回值等于0,即两个字符串相同时,将执行jne跳转指令后的参数压栈指令和调用puts函数的另一call指令。这个call对应的就是puts输出函数,被输出的、传递给puts函数的参数字符串地址就是传递给kfSvKnbh函数的第二个参数。

综上所述:
为了正确调用ecRIvzPzKN函数完成学号字符串的输出,需要完成两个任务:
1.确保ecRIvzPzKN函数中传递给strcmp函数的两个参数字符串,在内容上相同。
2.结合重定位记录确定用于strcmp函数进行字符串比较的内置字符串在phase2.o中的存放位置,进一步获得字符串内容。

可以看到先压入栈的偏移量的位置对应一个重定位记录如下:
在这里插入图片描述

结合重定位记录确定内置字符串在phase2.o中的存放位置,进一步使用readelf工具输出模块中 .rodata节的内容:
在这里插入图片描述

获得其内容为“MSLuleX.” 
内置字符串地址 = .rodata节起始地址 + 引用处的初始值0x2

然后在栈中构造与内置字符串和学号字符串内容相同的局部字符串变量,并将其地址作为实参压入栈中 。
构造在do phase函数中,调用kfSvKnbh函数的机器指令代码
指令内容:在栈中构造和初始化两个字符串局部变量,使其内容相同于程序内置的比较字符串"MSLuleX"和待输出的学号字符串“123456789" 。

可以利用sub指令先分配两个字符串的存储空间,然后使用一组move指令对两个字符串的内容按照前面分析的结果进行设置。然后用push指令将两个字符串的地址作为参数压入栈中。并进一步使用call指令调用目标函数。
在这里插入图片描述

然后利用as工具进行汇编,再利用objdump进行反汇编并查看:
在这里插入图片描述

第五步.

使用上步构造的调用输出函数的指令代码,替换do_ _phase()函数体中的nop指令,以实现期望输出。

使用readelf工具及其“-S”命令行选项获得节头表,从中获得.text在phase2.o中偏移量为 0x34
在这里插入图片描述

进一步得到函数中插入指令代码的位置为:
0x34 + 0xcf = 0xc8 (0xcf是do_phase函数中第一个被替换的nop指令的偏移量)

使用hexedit将phase2.o文件中上述位置0xc8起始的字节内容(原为nop指令代码0x90) 替换为调用指令代码序列
在这里插入图片描述

然后使用调用输出函数的指令代码,替换do_phase()函数体中的nop指令,以获得期望输出。

最后重新链接、生成和运行程序,验证修改有效:
在这里插入图片描述

可见,成功完成了目标。

  • 11
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheney822

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值