CSAPP - LinkLab实验(阶段1-5)

news2024/11/24 14:41:27

LinkLab实验(阶段1-5)

官网:http://csapp.cs.cmu.edu/3e/labs.html

实验内容

每个实验阶段(共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

实验材料

  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

  1. 使用 readelf 查看 phase1.o,查找有关输出函数的内容

    执行 readelf -a phase1.o
    在这里插入图片描述
    我们可以看出 puts 函数的参数是 g_data ,其重定向类型是绝对地址( R_X86_64_32 ),其加数为 0x50 。我们只需要将 g_data 的内容修改为学号字符串,即可完成阶段一。

  2. 查看 g_data 符号所在节
    在这里插入图片描述

    OBJECT 说明 g_data 是一个全局变量,所以它应该在数据节 .data 中。

  3. 查看数据节在全文中的偏移量
    在这里插入图片描述

    所以 .data 节在全文的偏移量为 0x60

  4. 计算 g_data 在全文中的具体位置

    根据计算公式
    在这里插入图片描述

    可得 g_data 所在位置为 0x60+0x50=0xb0

  5. 使用 hexedit 修改 g_data 为学号并保存
    在这里插入图片描述

  6. 链接并查看输出结果

    执行 gcc -o linkbomb1 main.o phase1.o -no-pie

    执行 ./linkbomb1
    在这里插入图片描述

    成功输出学号。

阶段 2

  1. 使用 readelf 查看 phase2.o,查找有关输出函数的内容
    在这里插入图片描述

    从中可以看出 put 函数的参数是 g_myCharArray ,其加数为 0x50 ,重定向类型为绝对地址。

  2. 查看符号表
    在这里插入图片描述

    COM 表示 g_myCharArray 是一个未初始化的弱符号数组,其大小为 256 ,所以我们需要创建一个已初始化强符号的 g_myCharArray 来覆盖弱符号。

  3. 创建 phase2_match.c 文件
    在这里插入图片描述

    加数为 0x50 字节需要填充。

  4. 编译 phase2_match.c 并链接,运行程序

    编译:运行 gcc -c phase2_match.c 生成 phase2_match.o 目标文件。

    链接:运行 gcc -o linkbomb2 main.o phase2.o phase2_match.o -no-pie

    运行 ./linkbomb2
    在这里插入图片描述

    发现每个字符都被偏移了。为了方便我们编写一个程序来计算应该输入的结果,可手动计算偏移量得出结果。

  5. 编写 crack.c 文件计算反偏移的字符串
    在这里插入图片描述

  6. 修改 phase2_match.c 中的学号为基准值
    在这里插入图片描述

  7. 编译 crack.c ,链接 linkbomb2,将 linkbomb2 的结果导出为 out,使用 out 运行 crack。

    编译 crack.c :运行 gcc crack.c -o crack

    编译 phase2_match.c :运行 gcc -c phase2_match.c

    链接 linkbomb2 :运行 gcc -o linkbomb2 main.o phase2.o phase2_match.o -no-pie

    运行 linkbomb2 并将结果导出为 out :./linkbomb2 > out

    运行 crack 程序 : ./crack < out
    在这里插入图片描述

  8. 将结果覆盖 phase2_match.c 中的字符串
    在这里插入图片描述

  9. 编译链接运行 linkbomb2

    编译 phase2_match.c :运行 gcc -c phase2_match.c

    链接 linkbomb2 :运行 gcc -o linkbomb2 main.o phase2.o phase2_match.o -no-pie

    运行 linkbomb2 :运行 ./linkbomb2
    在这里插入图片描述

    成功输出学号。

阶段 3

  1. 链接 linkbomb3 了解程序运行流程

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

    使用 gdb 进行调试
    在这里插入图片描述

    发现程序流程并没有执行 puts 函数,而是执行了一个叫 do_phase3 的函数,所以我们需要查找可利用的代码,来完善 do_phase3 函数。

  2. 查看 linkbomb3 中可利用的代码

    使用 objdump -d linkbomb3 查看:
    在这里插入图片描述

    从中看出,myFunc2 函数的作用是从内存中取出某值放到 %rax 中,myFunc1 函数的作用是以 %rdi 为参数执行 puts 函数。所以我们的目标是在 do_phase3 中 call myFunc2 输出我们的学号。而我们可以修改的值在 myFunc1 ,所以我们的流程为:在 do_phase3 中按顺序写下

    call myFunc2
    mov %rax,%rdi
    call myFunc1
    

    然后找到 myFunc2 中的内存位置修改为学号。

  3. 查找源代码文本位置
    使用 readelf -a phase3.o 查看 .text 节的偏移量
    在这里插入图片描述
    使用 objdump -d phase3.o 查看 do_phase 填充代码地址
    在这里插入图片描述
    所以 90 填充的起始地址是 0x40 + 0x31 = 0x71。

  4. 构造写入代码
    我们要构造的代码为

    call myFunc2
    mov %rax,%rdi
    call myFunc1 
    

    其中 call 指令是相对寻址,myFunc 函数的地址为
    在这里插入图片描述
    第一条 call 指令为 e8 xx xx xx xx ,占 5 个字节,结束地址为 0x31 + 0x5 = 0x36,所以距离 myFunc2 函数地址的相对距离为 0x1b - 0x36 = e5 ff ff ff,所以第一条 call 指令为 e8 e5 ff ff ff。
    第二条指令为 48 89 c7
    第三条指令为 e8 xx xx xx xx ,占 5 个字节,加上第二条指令的 3 个字节,所以结束地址为 0x36 + 0x3 + 0x5 = 0x3e ,所以距离 myFunc1 函数地址的相对距离为 0x0 - 0x3e = c2 ff ff ff ,所以第三条指令为 e8 c2 ff ff ff 。

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

    执行 hexedit phase3.o 从 0x71 开始写入我们构造的代码
    在这里插入图片描述

  6. 查看是否修改
    执行 objdump -d phase3.o查看 do_phase3 函数:
    在这里插入图片描述
    成功修改源码。

  7. 查看全局符号,查找 myFunc2 获取的数据的内存地址
    执行 readelf -a phase3.o 查看重定位符号 在这里插入图片描述
    所以数据从 .data 节+ 0x50 的位置获取的。查看 .data 节的起始地址:
    在这里插入图片描述
    所以我们需要修改为学号的位置为 0x1a0 + 0x50 = 0x1f0 。

  8. 修改 phase3.o
    在这里插入图片描述

  9. 链接并运行
    执行 gcc -o linkbomb3 main.o phase3.o -no-pie在这里插入图片描述
    成功输出学号。

阶段 4

  1. 查看 phase4.o 的 elf 文件,查看异常块
    在这里插入图片描述
    发现 .text 的重定向节符号的偏移量都为 0 ,很明显不会出现多个符号覆盖同一地址的操作。所以这三个符号的偏移量缺失了。

  2. 查看 phase4.o 的汇编代码,查看留空位置。
    执行 objdump -d phase4.o
    在这里插入图片描述
    按文本位置,从上到下偏移量为 0x4 + 0x2 = 0x6 ,0xf + 0x2 = 0x11 ,0x18 + 0x1 = 0x19 。

  3. 查看重定向 .text 节初始地址,修改偏移量。
    在这里插入图片描述
    所以 .rela.text 的初始地址为 0x250。修改偏移量:
    在这里插入图片描述

  4. 查看修改
    在这里插入图片描述
    成功修改。

  5. 修改 puts 函数的参数为学号
    按文本顺序 .data + 0x0 的位置即参数位置。查看 .data 节的起始地址:在这里插入图片描述
    修改 phase4.o 文件在这里插入图片描述

  6. 链接并运行程序

    执行gcc -o linkbomb4 main.o phase4.o -no-pie在这里插入图片描述
    发现输出不全。

    我们使用 gdb 进行调试
    在这里插入图片描述
    发现 temp 的值为 0x4d 。并非 .data + 0x10 位置上的值。

    我们查看符号表:在这里插入图片描述
    发现 temp 的偏移量应该为 0x14 。

  7. 修改 phase4.o 将 .data + 0x14 位置的值修改为 0x00 。在这里插入图片描述

  8. 重新链接并运行

    执行 gcc -o linkbomb4 main.o phase4.o -no-pie在这里插入图片描述
    成功输出学号。

阶段 5

  1. 链接并调试 linkbomb5
    执行 gcc -o linkbomb5 main.o phase5.o -no-pie在这里插入图片描述
    查看值:在这里插入图片描述
    发现这里是一个假的字符串,我们查看上面 0x404030 地址的值:在这里插入图片描述
    发现这才是我们需要字符串。

  2. 查看两个数据的重定向信息在这里插入图片描述
    我们将两个偏移量交换。从上图可知重定向的初始地址为 0x340 。

  3. 修改 phase5.o 文件在这里插入图片描述

  4. 重新链接并运行

    执行 gcc -o linkbomb5 main.o phase5.o -no-pie在这里插入图片描述

  5. 查找数据地址,修改内容为学号在这里插入图片描述
    修改过后我们需要的字符串为 .data + 0x10 的位置,查看 .data 节初始地址:在这里插入图片描述
    所以数据存放位置为 0x90 + 0x10 = 0xa0。

  6. 修改 phase5.o 文件在这里插入图片描述

  7. 链接并运行程序

    执行 gcc -o linkbomb5 main.o phase5.o -no-pie在这里插入图片描述
    成功输出学号。

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

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

相关文章

丝滑!软件开发根本不需要会编码(看我10分钟应用上线)

目录 一、前言 二、低代码基础功能及搭建 设计组件丰富 连接数据源 工作流设计 三、低代码和敏捷开发如何协同工作&#xff1f; 一、前言 众所周知&#xff0c;开发一个大型的企业级系统&#xff0c;公司往往需要大量的人力做支持后盾&#xff0c;如需要需求分析师、数据库管理…

使用chatgpt过funcaptcha验证码1个人学习记录

funcaptcha 验证码1 记录 funcaptch 有好几种验证码 验证码1 验证码2 验证码3 … 好多好多 今日记录验证码一完成记录&#xff1a; 这种验证码貌似每几天就换动物了 现在发现如下几种 如何解决&#xff1f; 训练模型计算目标位置 下面是我训练的模型计算的结果&…

LeetCode912排序数组(快速排序机及其优化详解)

LeetCode912排序数组&#xff08;快速排序及其优化详解&#xff09; 文章目录 LeetCode912排序数组&#xff08;快速排序及其优化详解&#xff09;Abstract基本快速排序快速排序思路总结以及优化优化思路针对渐进有序数组针对相同元素较多的数组 Code参考文献 Abstract 我首先…

【Python 下载,Anaconda下载,环境变量配置,两个python不同版本使用环境变量配置切换】

我再下载Anaconda之前&#xff0c;自己安装了一个Python3.11.配置环境变量之后&#xff0c;查看python版本&#xff1a; 下载好Anaconda3之后&#xff0c;将环境变量提到之前的前面&#xff0c;再使用CMD,查看就是Anaconda自带的Python版本&#xff0c;该版本有就有很多的第三方…

大模型与人类的未来 | 基于认知神经科学的大模型论坛精彩回顾

导读 6 月 10 日&#xff0c;智源大会“基于认知神经科学的大模型论坛”召开&#xff0c;本次论坛邀请到了认知神经、脑科学领域非常有建树的专家&#xff0c;深度讨论大模型的能力与局限性&#xff0c;包括对未来人工智能发展方向的讨论。论坛主席是清华大学脑与智能实验室首席…

全网最牛最全Postman接口测试: postman设置接口关联,postman实现参数化

postman设置接口关联 在实际的接口测试中&#xff0c;后一个接口经常需要用到前一个接口返回的结果&#xff0c; 从而让后一个接口能正常执行&#xff0c;这个过程的实现称为关联。 在postman中实现关联操作的步骤如下&#xff1a; 1、利用postman获取上一个接口指定的返回值…

2023年5月青少年机器人技术等级考试理论综合试卷(五级)

青少年机器人技术等级考试理论综合试卷&#xff08;五级&#xff09; 分数&#xff1a; 100 题数&#xff1a; 30 一、 单选题(共 20 题&#xff0c; 每题 4 分&#xff0c; 共 80 分) 1.ESP32 for Arduino&#xff0c; 下列程序的运行结果是&#xff1f; &#xff08; &#x…

GAMES101笔记 Lecture05 光栅化1(Triangles)

目录 Perspective Projection(透视投影)Canonical Cube to Screen(从标准立方体到屏幕)What is a screen(什么是屏幕)? Rasterization: Drawing to Raster Displays(如何在光栅设备上画东西)Triangles - Fundamental Shape Primitives(三角形-基本形状的基元)Why triangles?&…

node从头到尾实现简单编译器

介绍 本文用node实现了一个简单的编译器mccompiler&#xff0c;主要用于学习&#xff0c;笔者能力和精力有限&#xff0c;如有不当&#xff0c;还请指出 原文地址&#xff1a;原文地址 项目地址&#xff1a;项目地址 本文涉及&#xff1a;编译器的词法分析&#xff0c;抽象语义…

应用程序传递数据给驱动和驱动操作LED灯

目录 1. 应用程序将数据传递给驱动 1.1. 函数分析 1.2. 编写驱动.c文件 1.3. 编写编译驱动的makefile文件 1.4. 执行make命令&#xff0c;并安装驱动&#xff0c;生成设备文件 1.5. 写应用层.c文件 1.6. 执行可执行文件验证 2. 驱动操作LED灯 2.1. 函数分析 2.2. 手册…

【C语言】第一个C语言项目——“猜数字”游戏(内附源码)

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello米娜桑&#xff0c;这里是君兮_&#xff0c;今天又抽空为大家更新我们的主线0基础C语言啦&#xff01;鉴于最近讲解了非常多的选择语句与循环语句&#xff0c;咱们今天就来讲讲两者结合的一个简单的实战应用。 同时…

Python Locust全过程使用代码详解

下方查看历史精选文章 重磅发布 - 自动化框架基础指南pdfv1.1大数据测试过程、策略及挑战 测试框架原理&#xff0c;构建成功的基石 在自动化测试工作之前&#xff0c;你应该知道的10条建议 在自动化测试中&#xff0c;重要的不是工具 Python locust 是一个基于 Python 的开源负…

MKS SERVO4257D 闭环步进电机_系列9 上位机通讯示例

第1部分 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口和RS485/CAN串行接口&#xff0c;支持MODBUS-RTU通讯协议&#xff0c;内置高效FOC矢量算法&#xff0c;采用高精度编码器&#xff0c;通过位置反馈&a…

视觉SLAM十四讲——ch13实践(设计SLAM系统)

视觉SLAM十四讲——ch13的实践操作及避坑 1. 实践操作前的准备工作2. 实践过程2.1 运行测试程序2.2 运行00数据集2.3 更改代码画出运动轨迹 3. 遇到的问题及解决办法3.1 cmake ..时出现的问题3.2 make时出现的问题3.3 头文件下红色报错 1. 实践操作前的准备工作 下载Kitti数据…

使用dat.gui更改three.js中的物体变量

一、dat.gui介绍 gui是一种JavaScript库&#xff0c;用于创建可视化控件和调试工具。它是dat.gui的简称。dat.gui是一个用于在Web应用程序中创建可定制GUI的JavaScript库。它可以轻松创建滑块、复选框、颜色选择器等控件&#xff0c;用户可以直接在GUI上进行交互和调整。dat.g…

一起来看看 K-verse LAND 销售活动中的合作伙伴给大家的祝福吧~

K-verse 是 The Sandbox 中的韩国内容主题空间&#xff0c;自去年 12 月首次推出以来&#xff0c;已吸引多家合作伙伴加入。此外&#xff0c;现有的合作伙伴公司和品牌正在积极准备以新的形式展示元宇宙内容。 这里有着许多可能性&#xff0c;K-verse LAND 销售活动是不是让你们…

Tomcat及项目部署

一、Tomcat是什么&#xff1f; Tomcat 是基于 Java 实现的⼀个开源免费, 也是被⼴泛使⽤的 HTTP 服务器。 二、下载安装 官⽅⽹站&#xff1a;https://tomcat.apache.org/ 选择其中的 zip 压缩包, 下载后解压缩即可. 解压缩的⽬录最好不要带 "中⽂" 或者 特殊符号…

vue-cli 如何修改默认环境变量名称

比如想要修改开发环境 NODE_ENV 的默认值 &#xff1f; 1. 新建文件 .env.development 2. 在 packjson.json 的 script 中添加一行代码 --mode [文件 env 后面的环境名称] "dev": "vue-cli-service serve --mode development", 3. 然后 npm run dev 环境变…

JavaScript ES12新特性有哪些?

文章目录 导文Promise.any()WeakRef 和 FinalizationRegistry数字分隔符String.prototype.replaceAll()Logical Assignment Operators数字类型的新增方法私有字段和方法 导文 JavaScript ES12&#xff08;也称为ECMAScript 2022&#xff09;是JavaScript的最新版本&#xff0c;…

如何解决报错:nginx error!

目录 Nginx报错问题 nginx error! The page you are looking for is not found. Website Administrator 解决方法 Nginx报错问题 当访问搭建好的Nginx服务网站时 有以下报错 nginx error! The page you are looking for is not found. Website Administrator Someth…