【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
2. 实验工具
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
2. gdb调试器和objdump反汇编指令
3. 笔记本

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

实验工具
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。通过完成此次实验,不仅收获了很多知识,而且还锻炼了我的动手能力。解决了问题,完成了实验,感觉收获满满的,也有一定的成就感。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/40823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32F1+HAL库+FreeTOTS学习2——STM32移植FreeRTOS

STM32F1HAL库FreeTOTS学习2——STM32移植FreeRTOS 获取FreeRTOS源码创建工程窥探源码移植 上期我们认识了FreeRTOS&#xff0c;对FreeRTOS有了个初步的认识&#xff0c;这一期我们来上手移植FreeRTOS到STM32上。 获取FreeRTOS源码 进入官网&#xff1a;https://www.freertos.o…

故障转移处理器的工作原理

将故障的sink降级到故障池中&#xff0c;并在池中为它们分配一个冷却器&#xff0c;在重试之前&#xff0c;故障时间会增加&#xff0c;当sink成功发送event后&#xff0c;它将恢复到活跃池中。sink具有与之相关的优先级&#xff0c;数值越大&#xff0c;优先级越高。如果在发送…

Frrouting快速入门——OSPF组网(一)

FRR简介 FRR是FRRouting的简称&#xff0c;是一个开源的路由交换软件套件。其作者源自老牌项目quaga的成员&#xff0c;也可以算是quaga的新版本。 使用时一般查看此文档&#xff1a;https://docs.frrouting.org/projects/dev-guide/en/latest/index.html FRR支持的协议众多…

网络爬虫(一)深度优先爬虫与广度优先爬虫

1. 深度优先爬虫&#xff1a;深度优先爬虫是一种以深度为优先的爬虫算法。它从一个起始点开始&#xff0c;先访问一个链接&#xff0c;然后再访问该链接下的链接&#xff0c;一直深入地访问直到无法再继续深入为止。然后回溯到上一个链接&#xff0c;再继续深入访问下一个未被访…

AOP切面、动态代理

目录 一、用切面做的是怎么声明切面的&#xff1f;&#xff08;切面是怎么用的&#xff1f;&#xff09; 二、切点是怎么定义的&#xff1f; 三、说一下面向切面编程&#xff1f; 四、AOP是怎么实现的&#xff1f; 五、说一下动态代理&#xff1f; 一、用切面做的是怎么声明切面…

promise.all和promise.race的区别

Promise.all和Promise.race是JavaScript中Promise API的两个重要方法&#xff0c;它们在处理多个Promise对象时表现出不同的行为。以下是它们之间的主要区别&#xff1a; 1. 功能和行为 Promise.all&#xff1a; 功能&#xff1a;接收一个包含多个Promise的数组&#x…

【leetcode--逆波兰表达式】

今天学逆波兰表达式撰写还顺便复习了一下二叉树的前中后序遍历&#xff1a; 前序遍历&#xff1a;根左右 中序遍历&#xff1a;左根右 后序遍历&#xff1a;左右根 本题两个要点&#xff1a; a.判断字符串中的元素是数字还是字符串 因为Python 中没有一个函数可以判断一个字…

138. 完美数(卡码网周赛第二十四期(23年腾讯音乐笔试真题))

138. 完美数&#xff08;卡码网周赛第二十四期&#xff08;23年腾讯音乐笔试真题&#xff09;&#xff09; 题目描述 小红定义一个数为“完美数”&#xff0c;当且仅当该数仅有一个非零数字。例如 5000, 4, 1, 10, 200 都是完美数。 小红拿到了一个大小为 n&#xff08;2 <…

HarmonyOS APP应用开发项目- MCA助手(Day02持续更新中~)

简言&#xff1a; gitee地址&#xff1a;https://gitee.com/whltaoin_admin/money-controller-app.git端云一体化开发在线文档&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/agc-harmonyos-clouddev-view-0000001700053733-V5注&#xff1a;…

Laravel为什么会成为最优雅的PHP框架

PHP作为一种广泛应用的服务器端脚本语言&#xff0c;拥有着丰富的Web开发框架。其中&#xff0c;Laravel凭借其简洁优雅的语法、强大的功能集、优秀的文档与社区支持以及高度可扩展性&#xff0c;成为了许多开发者心目中的首选框架。本文将深入探讨Laravel为何能够在众多PHP框架…

【Sping Boot2】笔记

Spring Boot 2入门 如何创建一个Spring Boot的Web例子&#xff1f;1.如何创建一个Spring Boot项目1.1 使用Maven构建一个Spring Boot 2项目1.1.1创建Maven工程注&#xff1a;Maven项目结构&#xff1a; 1.1.2引入SpingBoot相关依赖依赖注意事项&#xff1a; 1.1.3创建主类1.1.4…

VIM介绍

VIM&#xff08;Vi IMproved&#xff09;是一种高度可配置的文本编辑器&#xff0c;用于有效地创建和更改任何类型的文本。它是从 vi 编辑器发展而来的&#xff0c;后者最初是 UNIX 系统上的一个文本编辑器。VIM 以其键盘驱动的界面和强大的文本处理能力而闻名&#xff0c;是许…

Python学习之小游戏--坦克大作战

今天跟视频学习了Python实现坦克大作战小游戏&#xff0c;挺有意思的&#xff0c;一起来玩吧~ 按空格发射子弹&#xff0c;上下左右键实现移动&#xff0c;ESC键无限复活。 import pygame,time,random from pygame.sprite import Sprite SCREEN_WIDTH800 SCREEN_HEIGHT500 BG…

Vue3中为Ant Design Vue中Modal.confirm自定义内容

在一次业务开发时代码时&#xff0c;碰到了一种既想要Modal.confirm样式&#xff0c;又想要定制其content内容的情况。 大部分情况下&#xff0c;使用Modal.method()这种方式时&#xff0c;可能content内容固定都是字符串&#xff0c;那如果想要做更高级的交互怎么办&#xff…

用Docker搭建分布式 Redis 的方法

使用 Docker 搭建一个分布式的 Redis 集群可以帮助你快速部署和管理多个 Redis 实例。一个典型的 Redis 集群包括多个主从节点&#xff0c;通过分片来实现数据的分布式存储与高可用性。 以下是使用 Docker 搭建分布式 Redis 集群的详细步骤&#xff1a; 前提条件 安装 Docke…

【Git-驯化】一文学会git配置用户信息,git config用法细节

【Git-驯化】一文学会git配置用户信息&#xff0c;git config用法细节 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档…

通过 url 下载文件的浏览器插件

大多数情况下访问 url 就会开始下载文件&#xff0c;但是由于文件格式等原因&#xff0c;下载可能不会开始或者失败&#xff0c;这时可以使用一些浏览器插件&#xff0c;例如 https://chromewebstore.google.com/detail/download-file-%E4%B8%8B%E8%BD%BD%E6%96%87%E4%BB%B6/do…

Sourcecodester Fantastic Blog CMS v1.0 SQL 注入漏洞(CVE-2022-28512)

前言 CVE-2022-28512 是一个存在于 Sourcecodester Fantastic Blog CMS v1.0 中的 SQL 注入漏洞。攻击者可以通过 "/fantasticblog/single.php" 中的 id 参数注入恶意 SQL 查询&#xff0c;从而获得对数据库的未经授权的访问和控制。 漏洞详细信息 漏洞描述: 该漏…

2024 年第十四届 APMCM 亚太地区大学生数学建模竞赛赛题浅析

一图流&#xff1a; 赛题编号 赛题名称 涉及学科 所需模型 赛题复杂度 赛题难度 主要挑战 A 飞行器外形的优化问题 航空航天工程&#xff0c;数学&#xff0c;物理 几何模型&#xff0c;空气动力学模型&#xff0c;优化算法 高 高 精确计算飞行器表面积和体积&…

工具发送formdata请求 Multipartfile 接收

1.需求&#xff1a; 接收到 (Multipartfile file 文件 》使用工具转发到别的请求&#xff0c;将文件传到别的接口 主要代码&#xff1a; InputStreamResource inputstreamResource new InputstreamResource(file.getInputstream(), file.getoriginalfilename());MultiReso…