2021哈工大深入理解计算机系统Lab5(linklab)


实验目的

  • 理解链接的作用与工作步骤。
  • 掌握ELF结构与符号解析与重定位的工作过程。
  • 熟练使用Linux工具完成ELF分析与修改。

实验环境与工具

硬件环境

X64 CPU; 2.40 GHz; 716G

软件环境

Windows10 专业版;Vmware; Ubuntu 20.04

开发工具

gdb; objdump; readelf; hexedit


实验内容

LinkBomb程序框架

//main
#include <stdio.h>
#include "config.h"

void (*phase)(); /*初始化为0*/

int main(int argc, const char* argv[])
{
	if(phase){
		(*phase)();
	}
	else{
		printf("To run lab, please link the relevant object module with the main module.\n");
	}

	return 0;
}

在各个阶段,运行main.o与修改后的phase[i].o链接生成的可执行程序,使之输出个人学号。
  PS.以下各阶段中a0a1…a9表示学号,A0A1…A9表示学号各位数字对应的ASCII码(十六进制)

phase1:全局变量 ⇔ 数据节

  1. 输入objdump -dx phase1.o,得知输出字符串起始地址在.data节中偏移量为 0x1f字节的位置
    在这里插入图片描述

  2. 用该命令同样也可以知道.data节再目标文件的偏移为0x60字节(File off)
    在这里插入图片描述

  3. 使用hexedit打开phase1.o文件。找到偏移为(0x60 + 0x1f) 字节处。在这里插入图片描述

  4. 将main.o与未修改的phase1.o链接,执行生成的可执行程序,输出字符串为
    zqo3JlaZmWMP0uQQNyC3BL26RmpkbuRqnWZxH8FBJehIWz6Hl8uFa jtEVPTY nAapc W626N4xh9 Cav4y6RVljGNfDa0hhYlZ6Vo0tLqsES3 yGAajbwOMh3Rxd8Q4QouHqbZajkEhB6QB3wHt
    与3中找出的字符串内容相同,确定此处为需要修改的字符串位置。
    在这里插入图片描述

  5. 从此处开始修改内容为学号编码(后加0x00字节表示字符串结束)。在这里插入图片描述

  6. 将main.o与修改后的phase1.o链接。执行生成的可执行程序,输出学号。在这里插入图片描述

phase2:指令 ⇔ 代码节

  1. 使用objdump得出此处是传递的参数与MYID进行比较。根据比较结果分析下一步动作。在这里插入图片描述

  2. 此处为调用puts函数,其参数与output函数参数相同。在这里插入图片描述

  3. 因此在do_phase函数中,我们要先把一个参数值压入栈,然后再调用output函数。

  4. 调用output函数可以使用call+相对PC的偏移量。而参数的压栈需要查看调用do_phase函数时的寄存器状态与参数之间的关系。由下图只main函数中通过%eax调用phase函数(即phase2.o中的do_phase函数)。即%eax中存有do_phase函数的绝对地址。在这里插入图片描述

  5. 而在do_phase函数中刚开始并没有改变%eax的值。在这里插入图片描述

  6. 利用objdump查看lab2(main.o与未修改phase2.o链接生成)反汇编,得出do_phase函数与output函数之间的偏移为(0x1231 – 0x1265) = -0x34字节;同时也可以知道do_phase函数与.rodata节之间的偏移为(0x207c – 0x1265) = 0xe17字节.在这里插入图片描述
    在这里插入图片描述

  7. 在do_phase中先将.rodata地址压栈,然后再调用output函数。补全汇编代码应如下。在这里插入图片描述

  8. 利用readelf找出phase2.o中do_phase函数的位置,偏移量为(0x34 + 0x34) = 0x68字节.在这里插入图片描述
    在这里插入图片描述

  9. 找到并修改phase2.o如下:在这里插入图片描述

  10. 将main.o与修改后的phase.o链接,执行生成的可执行程序,输出学号。在这里插入图片描述

phase3:符号解析

  1. 利用objdump,分析do_phase反汇编得出cookie字符串的组成内容:(地址由低到高)
    0x69 0x6a 0x65 0x6d 0x79 0x7a 0x6f 0x70 0x78 0x6c 0x00(第十个没有用到)在这里插入图片描述

  2. 分析这段汇编代码可知,从地址为%ebp – 0x17的内存开始,取一个字节,然后把这个字节当作映射数组的索引,取出一个字符输出,下一次作为索引的字节的地址为上次作为索引的地址加一,与phase3.c的程序框架相照应。在此图中同样可以得知该数组索引的符号名为yuYibdBlfT在这里插入图片描述

  3. 此处为计数功能,当累计输出10个字符后输出回车,输出程序的关键部分结束。在这里插入图片描述

  4. 编写一个映射数组c文件,只需将cookie字符串的前十个字节作为索引,依次把自己的序号字符填入即可(其他位置任意)。如图(可以适当布局设计无关位置方便索引):在这里插入图片描述

  5. 编译汇编phase3_patch.c得到phase3_patch.o,与main.o和phase3.o一起链接生成可执行程序。执行该程序,输出学号。在这里插入图片描述

phase4:switch语句与重定位

  1. 第一步与阶段3的第一步相同,找到COOKIE字符串的组成内容:(地址由低到高):
    0x44 0x58 0x4a 0x42 0x59 0x47 0x4e 0x52 0x48 0x5a 0x00在这里插入图片描述

  2. 利用objdump生成反汇编文件phase4dx.txt,可以分析出来此处和阶段3相同,也是一个一个字符取出来进行操做。在这里插入图片描述

  3. 从这几句可以判断出%eax先减去了0x41后与0x19比较,根据比较结果以及减去0x41后的结果进行跳转。在这里插入图片描述

  4. 在这个文件中也可以查出.rodata节的偏移为0x184字节,大小为0x68字节。在这里插入图片描述

  5. 使用hexedit打开phase4.o,找到.rodata节的部分。将.rodata节中的数据(跳转表)存入新建的.rodata文档中。在这里插入图片描述
    在这里插入图片描述

  6. 根据我们的cookie值,以及刚刚的跳转表,可以得出跳转地址。在这里插入图片描述

  7. 我们只要将跳转表修改,使程序按照我们cookie的值选择地址跳转后,正好按顺序输出学号中的字符即可。

  8. 由下图可知每次根据跳转表跳转到某个地址后,会固定输出某个特定的字符。在这里插入图片描述

  9. 我们根据学号中的字符查询到跳转表中应该存储的地址(到时候重定位会把更改.rodata的值,故写此时的“绝对”地址即可),将需要更改的地方先存入rodata.txt文件中,下图以查询使程序输出1的地址示例:在这里插入图片描述
    在这里插入图片描述

   PS.修改之后的跳转表中0~5是为了方便索引无实际意义。空白位
  置包括索引位置表示原跳转表不必要更改。

  1. 按照rodata.txt中的内容修改phase4.o如下。在这里插入图片描述

  2. 将修改后的phase4.o与main.o链接生成可执行程序。执行该可执行程序,输出学号。在这里插入图片描述


结语

由于时间比较紧,就没有看phase5。之后如果有时间的话再把第五阶段发出来(并且如果会做的话😆😆😆)。欢迎各位朋友一起来提问讨论。

  • 13
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lgxo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值