bomb lab phase_dufused
bomb lab을 다 깻지만 히든 스테이지가 있다고 하더라. 그래서 해보고자 했다.
phase로 시작하는 함수가 있나 찾아보는데 defused를 찾았다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
(gdb) disas phase
phase_1 phase_2 phase_3 phase_4 phase_5 phase_6 phase_defused phases.h
(gdb) disas phase
phase_1 phase_2 phase_3 phase_4 phase_5 phase_6 phase_defused phases.h
(gdb) disas phase
phase_1 phase_2 phase_3 phase_4 phase_5 phase_6 phase_defused phases.h
(gdb) disas phase
No symbol "phase" in current context.
(gdb) disas phase_defused
Dump of assembler code for function phase_defused:
0x00000000004015a3 <+0>: sub $0x78,%rsp
0x00000000004015a7 <+4>: mov %fs:0x28,%rax
0x00000000004015b0 <+13>: mov %rax,0x68(%rsp)
0x00000000004015b5 <+18>: xor %eax,%eax
0x00000000004015b7 <+20>: cmpl $0x6,0x2021ce(%rip) # 0x60378c <num_input_strings>
0x00000000004015be <+27>: jne 0x40161e <phase_defused+123>
0x00000000004015c0 <+29>: lea 0x10(%rsp),%r8
0x00000000004015c5 <+34>: lea 0xc(%rsp),%rcx
0x00000000004015ca <+39>: lea 0x8(%rsp),%rdx
0x00000000004015cf <+44>: mov $0x4025f9,%esi
0x00000000004015d4 <+49>: mov $0x603890,%edi
0x00000000004015d9 <+54>: callq 0x400bb0 <__isoc99_sscanf@plt>
0x00000000004015de <+59>: cmp $0x3,%eax
0x00000000004015e1 <+62>: jne 0x401614 <phase_defused+113>
0x00000000004015e3 <+64>: mov $0x402602,%esi
0x00000000004015e8 <+69>: lea 0x10(%rsp),%rdi
0x00000000004015ed <+74>: callq 0x40131d <strings_not_equal>
0x00000000004015f2 <+79>: test %eax,%eax
0x00000000004015f4 <+81>: jne 0x401614 <phase_defused+113>
0x00000000004015f6 <+83>: mov $0x4024d8,%edi
0x00000000004015fb <+88>: callq 0x400ae0 <puts@plt>
0x0000000000401600 <+93>: mov $0x402500,%edi
0x0000000000401605 <+98>: callq 0x400ae0 <puts@plt>
0x000000000040160a <+103>: mov $0x0,%eax
0x000000000040160f <+108>: callq 0x401234 <secret_phase>
0x0000000000401614 <+113>: mov $0x402538,%edi
0x0000000000401619 <+118>: callq 0x400ae0 <puts@plt>
0x000000000040161e <+123>: mov 0x68(%rsp),%rax
0x0000000000401623 <+128>: xor %fs:0x28,%rax
0x000000000040162c <+137>: je 0x401633 <phase_defused+144>
0x000000000040162e <+139>: callq 0x400b00 <__stack_chk_fail@plt>
0x0000000000401633 <+144>: add $0x78,%rsp
0x0000000000401637 <+148>: retq
End of assembler dump.
여기서 secret_phase를 부르는걸 알았다. 정확하게 어떻게 진입하는지 알기위해서 bomb.c를 봤더니 각 phase함수가 끝낼때마다. phase_defuse를 부르더라. 아 근데 진입조건찾는거부터 난관이다 진입조건을 체크해보니 전혀 모르겠다. 근데 주석으로 친절히 설명해놨다. num_input_strings 변수인데 아마 줄을 입력받을때 여기서 저장을 해놓지 않을까? 란 생각을 했다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
(gdb) disas read_line
Dump of assembler code for function read_line:
0x000000000040147d <+0>: sub $0x8,%rsp
0x0000000000401481 <+4>: mov $0x0,%eax
0x0000000000401486 <+9>: callq 0x4013db <skip>
0x000000000040148b <+14>: test %rax,%rax
0x000000000040148e <+17>: jne 0x4014fe <read_line+129>
0x0000000000401490 <+19>: mov 0x2022d9(%rip),%rax # 0x603770 <stdin@@GLIBC_2.2.5>
0x0000000000401497 <+26>: cmp %rax,0x2022f2(%rip) # 0x603790 <infile>
0x000000000040149e <+33>: jne 0x4014b4 <read_line+55>
0x00000000004014a0 <+35>: mov $0x4025b5,%edi
0x00000000004014a5 <+40>: callq 0x400ae0 <puts@plt>
0x00000000004014aa <+45>: mov $0x8,%edi
0x00000000004014af <+50>: callq 0x400be0 <exit@plt>
0x00000000004014b4 <+55>: mov $0x4025d3,%edi
0x00000000004014b9 <+60>: callq 0x400ab0 <getenv@plt>
0x00000000004014be <+65>: test %rax,%rax
0x00000000004014c1 <+68>: je 0x4014cd <read_line+80>
0x00000000004014c3 <+70>: mov $0x0,%edi
0x00000000004014c8 <+75>: callq 0x400be0 <exit@plt>
0x00000000004014cd <+80>: mov 0x20229c(%rip),%rax # 0x603770 <stdin@@GLIBC_2.2.5>
0x00000000004014d4 <+87>: mov %rax,0x2022b5(%rip) # 0x603790 <infile>
0x00000000004014db <+94>: mov $0x0,%eax
0x00000000004014e0 <+99>: callq 0x4013db <skip>
0x00000000004014e5 <+104>: test %rax,%rax
0x00000000004014e8 <+107>: jne 0x4014fe <read_line+129>
0x00000000004014ea <+109>: mov $0x4025b5,%edi
0x00000000004014ef <+114>: callq 0x400ae0 <puts@plt>
0x00000000004014f4 <+119>: mov $0x0,%edi
0x00000000004014f9 <+124>: callq 0x400be0 <exit@plt>
0x00000000004014fe <+129>: mov 0x202288(%rip),%esi # 0x60378c <num_input_strings>
0x0000000000401504 <+135>: movslq %esi,%rax
0x0000000000401507 <+138>: lea (%rax,%rax,4),%rdx
0x000000000040150b <+142>: shl $0x4,%rdx
0x000000000040150f <+146>: add $0x6037a0,%rdx
0x0000000000401516 <+153>: mov $0x0,%eax
0x000000000040151b <+158>: mov $0xffffffffffffffff,%rcx
0x0000000000401522 <+165>: mov %rdx,%rdi
0x0000000000401525 <+168>: repnz scas %es:(%rdi),%al
0x0000000000401527 <+170>: not %rcx
0x000000000040152a <+173>: sub $0x1,%rcx
0x000000000040152e <+177>: cmp $0x4e,%ecx
0x0000000000401531 <+180>: jle 0x401579 <read_line+252>
0x0000000000401533 <+182>: mov $0x4025de,%edi
0x0000000000401538 <+187>: callq 0x400ae0 <puts@plt>
0x000000000040153d <+192>: mov 0x202249(%rip),%eax # 0x60378c <num_input_strings>
---Type <return> to continue, or q <return> to quit---
0x0000000000401543 <+198>: lea 0x1(%rax),%edx
0x0000000000401546 <+201>: mov %edx,0x202240(%rip) # 0x60378c <num_input_strings>
0x000000000040154c <+207>: cltq
0x000000000040154e <+209>: imul $0x50,%rax,%rax
0x0000000000401552 <+213>: movabs $0x636e7572742a2a2a,%rdi
0x000000000040155c <+223>: mov %rdi,0x6037a0(%rax)
0x0000000000401563 <+230>: movabs $0x2a2a2a64657461,%rdi
0x000000000040156d <+240>: mov %rdi,0x6037a8(%rax)
0x0000000000401574 <+247>: callq 0x40141c <explode_bomb>
0x0000000000401579 <+252>: sub $0x1,%ecx
0x000000000040157c <+255>: movslq %ecx,%rcx
0x000000000040157f <+258>: movslq %esi,%rax
0x0000000000401582 <+261>: lea (%rax,%rax,4),%rax
0x0000000000401586 <+265>: shl $0x4,%rax
0x000000000040158a <+269>: movb $0x0,0x6037a0(%rcx,%rax,1)
0x0000000000401592 <+277>: lea 0x1(%rsi),%eax
0x0000000000401595 <+280>: mov %eax,0x2021f1(%rip) # 0x60378c <num_input_strings>
0x000000000040159b <+286>: mov %rdx,%rax
0x000000000040159e <+289>: add $0x8,%rsp
0x00000000004015a2 <+293>: retq
End of assembler dump.
코드는 읽지않았지만 주석을 보니 대충 그런것 같다.
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
32
33
34
35
36
37
38
39
(gdb) c
Continuing.
Phase 1 defused. How about the next one?
Breakpoint 1, 0x00000000004015b7 in phase_defused ()
(gdb) x/4wx 0x60378c
0x60378c <num_input_strings>: 0x00000002 0x00604260 0x00000000 0x00000000
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) n
Program not restarted.
(gdb) c
Continuing.
That's number 2. Keep going!
Breakpoint 1, 0x00000000004015b7 in phase_defused ()
(gdb) x/4wx 0x60378c
0x60378c <num_input_strings>: 0x00000003 0x006042600x00000000 0x00000000
(gdb) c
Continuing.
Halfway there!
Breakpoint 1, 0x00000000004015b7 in phase_defused ()
(gdb) x/4wx 0x60378c
0x60378c <num_input_strings>: 0x00000004 0x006042600x00000000 0x00000000
(gdb) c
Continuing.
So you got that one. Try this one.
Breakpoint 1, 0x00000000004015b7 in phase_defused ()
(gdb) x/4wx 0x60378c
0x60378c <num_input_strings>: 0x00000005 0x006042600x00000000 0x00000000
(gdb) c
Continuing.
Good work! On to the next...
Breakpoint 1, 0x00000000004015b7 in phase_defused ()
(gdb) x/4wx 0x60378c
0x60378c <num_input_strings>: 0x00000006 0x006042600x00000000 0x00000000
비교 부분을 break 처리하고 확인하니 줄이 입력될때마다 1씩 증가한다 따라서 phase6이 끝나면 진입한다. 그뒤에 sscnaf를 부르고 eax가 3개인지 봐서는 추가로 값을 입력 받는걸 처리하는것같다.
인자로 들어가는 고정 문자열을 뽑아봤다
1
2
3
4
(gdb) x/s 0x4025f9
0x4025f9: "%d %d %s"
(gdb) x/s 0x603890
0x603890 <input_strings+240>: "40 2"
phase_4의 정답 값이다 아마 이뒤에 %s를 넣고 여기에 대한 답을 원하는 듯하다.
1
2
(gdb) x/s 0x402602
0x402602: "DrEvil"
이를 phase_4 정답 뒤에 붙이면 될듯하다. 그러고 실행했더니 해당 문구가 떴다.
1
2
Curses, you've found the secret phase!
But finding it and solving it are quite different...
이제 secret_phase를 분석해보자.
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
(gdb) disas secret_phase
Dump of assembler code for function secret_phase:
0x0000000000401234 <+0>: push %rbx
0x0000000000401235 <+1>: callq 0x40147d <read_line>
0x000000000040123a <+6>: mov $0xa,%edx
0x000000000040123f <+11>: mov $0x0,%esi
0x0000000000401244 <+16>: mov %rax,%rdi
0x0000000000401247 <+19>: callq 0x400b90 <strtol@plt>
0x000000000040124c <+24>: mov %rax,%rbx
0x000000000040124f <+27>: lea -0x1(%rax),%eax
0x0000000000401252 <+30>: cmp $0x3e8,%eax
0x0000000000401257 <+35>: jbe 0x40125e <secret_phase+42>
0x0000000000401259 <+37>: callq 0x40141c <explode_bomb>
0x000000000040125e <+42>: mov %ebx,%esi
0x0000000000401260 <+44>: mov $0x603110,%edi
0x0000000000401265 <+49>: callq 0x4011f6 <fun7>
0x000000000040126a <+54>: test %eax,%eax
0x000000000040126c <+56>: je 0x401273 <secret_phase+63>
0x000000000040126e <+58>: callq 0x40141c <explode_bomb>
0x0000000000401273 <+63>: mov $0x4023e0,%edi
0x0000000000401278 <+68>: callq 0x400ae0 <puts@plt>
0x000000000040127d <+73>: callq 0x4015a3 <phase_defused>
0x0000000000401282 <+78>: pop %rbx
0x0000000000401283 <+79>: retq
End of assembler dump.
3e8+1 아니 근데 분석하려는데 계속 sigkill을 쏜다 왜이러지? 혹시 sol.txt에 값을 적어서 봐야하는가? 느낌상 해당 함수 실행시간에 시간제한이 있는것같다. break point를 걸고 확인하고 그뒤를 실행하면 프로그램이 터지는것같다. 따라서 값은 sol.txt에서 수정하면서 하기로했다. 아 근데 하고보니까 그냥 sol.txt에만 값을 적는것으로 충분한듯하다.
0x0000000000401252을 통과하기 위해 rax 값이 맞게 세팅을 해야하는거같다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
(gdb) disas strtol
strtol strtol@plt strtol_l.c strtold.c strtold_l.c strtoll
strtol.c strtol_l strtold strtold_l strtold_nan.c strtoll_l
(gdb) disas strtol@plt
No symbol "plt" in current context.
(gdb) disas strtol
Dump of assembler code for function __strtol:
0x00007ffff7a291c0 <+0>: mov 0x3a5c01(%rip),%rax # 0x7ffff7dcedc8
0x00007ffff7a291c7 <+7>: xor %ecx,%ecx
0x00007ffff7a291c9 <+9>: mov %fs:(%rax),%r8
0x00007ffff7a291cd <+13>: jmpq 0x7ffff7a29210 <__GI_____strtol_l_internal>
End of assembler dump.
(gdb) disas 0x400b90
Dump of assembler code for function strtol@plt:
0x0000000000400b90 <+0>: jmpq *0x2024f2(%rip) # 0x603088
0x0000000000400b96 <+6>: pushq $0xe
0x0000000000400b9b <+11>: jmpq 0x400aa0
End of assembler dump.
(gdb) disas 0x603088
Dump of assembler code for function _GLOBAL_OFFSET_TABLE_:
0x0000000000603000: sub %ch,(%rsi)
0x0000000000603002: (bad)
0x0000000000603003: add %al,(%rax)
0x0000000000603005: add %al,(%rax)
0x0000000000603007: add %dh,-0x1f(%rax)
0x000000000060300a: push %rdi
0x000000000060300c: (bad)
0x000000000060300d: jg 0x60300f
0x000000000060300f: add %ah,-0x82139(%rax)
0x0000000000603015: jg 0x603017
0x0000000000603017: add %dh,0x400a(%rsi)
0x000000000060301d: add %al,(%rax)
0x000000000060301f: add %al,%dh
0x0000000000603021: or 0x0(%rax),%al
0x0000000000603024: add %al,(%rax)
0x0000000000603026: add %al,(%rax)
0x0000000000603028: (bad)
0x0000000000603029: or 0x0(%rax),%al
0x000000000060302c: add %al,(%rax)
0x000000000060302e: add %al,(%rax)
0x0000000000603030: xor %cl,-0x5a(%rdx)
0x0000000000603033: idiv %edi
0x0000000000603035: jg 0x603037
0x0000000000603037: add %dh,%dh
0x0000000000603039: or 0x0(%rax),%al
0x000000000060303c: add %al,(%rax)
0x000000000060303e: add %al,(%rax)
0x0000000000603040: (bad)
0x0000000000603041: or 0x0(%rax),%eax
0x0000000000603044: add %al,(%rax)
0x0000000000603046: add %al,(%rax)
0x0000000000603048: (bad)
0x0000000000603049: or 0x0(%rax),%eax
0x000000000060304c: add %al,(%rax)
0x000000000060304e: add %al,(%rax)
0x0000000000603050: or %es:0x0(%rax),%eax
0x0000000000603054: add %al,(%rax)
0x0000000000603056: add %al,(%rax)
0x0000000000603058: or %ss:0x0(%rax),%eax
0x000000000060305c: add %al,(%rax)
0x000000000060305e: add %al,(%rax)
0x0000000000603060: mov $0x5a,%al
0x0000000000603062: movabs 0xa62b9000007ffff7,%al
0x000000000060306b: idiv %edi
---Type <return> to continue, or q <return> to quit---
0x000000000060306d: jg 0x60306f
0x000000000060306f: add %dl,0x2e(%rax)
0x0000000000603072: movabs %al,0x400b7600007ffff7
0x000000000060307b: add %al,(%rax)
0x000000000060307d: add %al,(%rax)
0x000000000060307f: add %al,0x400b(%rsi)
0x0000000000603085: add %al,(%rax)
0x0000000000603087: add %dl,0x400b(%rsi)
0x000000000060308d: add %al,(%rax)
0x000000000060308f: add %ah,0x400b(%rsi)
0x0000000000603095: add %al,(%rax)
0x0000000000603097: add %dl,0x5(%rax)
0x000000000060309a: cmpsb %es:(%rdi),%ds:(%rsi)
0x000000000060309b: idiv %edi
0x000000000060309d: jg 0x60309f
0x000000000060309f: add %al,%dh
0x00000000006030a1: or 0x0(%rax),%eax
0x00000000006030a4: add %al,(%rax)
0x00000000006030a6: add %al,(%rax)
0x00000000006030a8: movabs 0xe600007ffff7a62e,%al
0x00000000006030b1: or 0x0(%rax),%eax
0x00000000006030b4: add %al,(%rax)
0x00000000006030b6: add %al,(%rax)
0x00000000006030b8: testb $0x40,(%rbx)
0x00000000006030bb: add %al,(%rax)
0x00000000006030bd: add %al,(%rax)
0x00000000006030bf: add %al,(%rsi)
0x00000000006030c1: or $0x40,%al
0x00000000006030c3: add %al,(%rax)
0x00000000006030c5: add %al,(%rax)
0x00000000006030c7: add %dl,(%rsi)
0x00000000006030c9: or $0x40,%al
0x00000000006030cb: add %al,(%rax)
0x00000000006030cd: add %al,(%rax)
0x00000000006030cf: add %ah,(%rax)
0x00000000006030d1: rex.WB movabs 0x400c3600007ffff7,%rax
0x00000000006030db: add %al,(%rax)
0x00000000006030dd: add %al,(%rax)
0x00000000006030df: add %al,0xc(%rsi)
0x00000000006030e2: add %al,(%rax)
0x00000000006030e5: add %al,(%rax)
0x00000000006030e7: add %al,(%rax)
End of assembler dump.
솔직히 너무 답이없어서 포기하고 이부분 뒤의 rax 값을 보니 그냥 입력한 숫자가 그대로 들어가는 듯하다.따라서 그뒤의 검사를 하는 부분에 +1만 하면될듯하다. 3e8 은 1000이다 따라서 1001이하가 입력값 그후 fun7을 부른다. fun7을 부른 뒤의 어셈을 분석해보니 eax가 0이 되게하는게 목표이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(gdb) disas fun7
Dump of assembler code for function fun7:
0x00000000004011f6 <+0>: sub $0x8,%rsp
0x00000000004011fa <+4>: test %rdi,%rdi
0x00000000004011fd <+7>: je 0x40122a <fun7+52>
0x00000000004011ff <+9>: mov (%rdi),%edx
0x0000000000401201 <+11>: cmp %esi,%edx
0x0000000000401203 <+13>: jle 0x401212 <fun7+28>
0x0000000000401205 <+15>: mov 0x8(%rdi),%rdi
0x0000000000401209 <+19>: callq 0x4011f6 <fun7>
0x000000000040120e <+24>: add %eax,%eax
0x0000000000401210 <+26>: jmp 0x40122f <fun7+57>
0x0000000000401212 <+28>: mov $0x0,%eax
0x0000000000401217 <+33>: cmp %esi,%edx
0x0000000000401219 <+35>: je 0x40122f <fun7+57>
0x000000000040121b <+37>: mov 0x10(%rdi),%rdi
0x000000000040121f <+41>: callq 0x4011f6 <fun7>
0x0000000000401224 <+46>: lea 0x1(%rax,%rax,1),%eax
0x0000000000401228 <+50>: jmp 0x40122f <fun7+57>
0x000000000040122a <+52>: mov $0xffffffff,%eax
0x000000000040122f <+57>: add $0x8,%rsp
0x0000000000401233 <+61>: retq
End of assembler dump.
eax를 0으로 되게 하기 위해서 28줄로 옮기고 esi 를 edx와 같게 하면된다. esi = 입력값 *edi = 0x24
근데 보니까 0x0000000000401201을 통과하기위해서는 입력값을 edi의 값과 같게만 하면된다.
36
1
2
3
4
5
(gdb) c
Continuing.
Wow! You've defused the secret stage!
Congratulations! You've defused the bomb!
[Inferior 1 (process 4073) exited normally]