# ReadFile(eax, &esp+80, 0x50, &esp+8, 0) code += x86.Lea("EBX", x86.mem("[ESP + 0x80]")) code += x86.Push(0) code += x86.Push("EDI") code += x86.Push(0xF0) # Oops stack overflow code += x86.Push("EBX") code += x86.Push("EAX") # hConsoleInput code += x86.Call(call_import(imports["kernel32.dll"]["ReadFile"])) # GetStdHandle(STD_OUTPUT_HANDLE) code += x86.Push(STD_OUTPUT_HANDLE) code += x86.Call(call_import(imports["kernel32.dll"]["GetStdHandle"])) # WriteFile(eax, &esp+50, 0x50, &esp+8, 0) code += x86.Push(0) code += x86.Push("EDI") code += x86.Push(0x50) code += x86.Push("EBX") code += x86.Push("EAX") # hConsoleOutput code += x86.Call(call_import(imports["kernel32.dll"]["WriteFile"])) code += x86.Mov("ESP", "EBP") code += x86.Ret() padded_code = code.get_code() padded_code += x86.Nop().get_code() * (0x100 - len(padded_code)) section_text.content = tobytes(padded_code) builder = PE.Builder(binary32) builder.build_imports(True) builder.build() builder.write("pwn.exe") print("Generated pwn.exe")
def build_pe_executable(asm_code: bytearray, memory_layout: List[MemorySection], arch: Architecture) -> str: """ Uses LIEF to build a standalone binary. Upon success, return the path to the file generated """ if not is_x86_32(arch) and not is_x86_64(arch): raise ValueError("Unsupported architecture for PE generation") is_x64 = is_x86_64(arch) if is_x64: basename = "cemu-pe-amd64-{:s}".format(generate_random_string(5)) pe = PE.Binary(basename, PE.PE_TYPE.PE32_PLUS) else: basename = "cemu-pe-i386-{:s}".format(generate_random_string(5)) pe = PE.Binary(basename, PE.PE_TYPE.PE32) # adding sections sections = {} reladdr = 0x1000 for mem in memory_layout: name, base_address, size, permission = mem.name, mem.address, mem.size, mem.permission if name in (".stack", ): continue sect = PE.Section(name) if name == ".text": # .text section: copy our code and set the entrypoint to the # beginning VA sect.content = asm_code sect.virtual_address = reladdr sect.characteristics = parse_as_lief_pe_permission( permission, "code") sections["text"] = pe.add_section(sect, PE.SECTION_TYPES.TEXT) elif name == ".data": # .data is also sure to exist sect.content = b"\x00" sect.virtual_address = reladdr sect.characteristics = parse_as_lief_pe_permission( permission, "udata") sections["data"] = pe.add_section(sect, PE.SECTION_TYPES.DATA) reladdr += size # fixing pe header pe.header.add_characteristic(PE.HEADER_CHARACTERISTICS.EXECUTABLE_IMAGE) pe.header.add_characteristic(PE.HEADER_CHARACTERISTICS.DEBUG_STRIPPED) if is_x64: pe.header.add_characteristic( PE.HEADER_CHARACTERISTICS.LARGE_ADDRESS_AWARE) else: pe.header.add_characteristic( PE.HEADER_CHARACTERISTICS.CHARA_32BIT_MACHINE) # fixing pe optional header pe.optional_header.addressof_entrypoint = sections["text"].virtual_address pe.optional_header.major_operating_system_version = 0x04 pe.optional_header.minor_operating_system_version = 0x00 pe.optional_header.major_subsystem_version = 0x05 pe.optional_header.minor_subsystem_version = 0x02 pe.optional_header.major_linker_version = 0x02 pe.optional_header.minor_linker_version = 0x1e pe.optional_header.remove(PE.DLL_CHARACTERISTICS.NX_COMPAT) pe.optional_header.add(PE.DLL_CHARACTERISTICS.NO_SEH) # pe.add_library("ntdll.dll") #building exe to disk outfile = f"{tempfile.gettempdir()}{os.path.sep:s}{basename:s}.exe" builder = PE.Builder(pe) builder.build_imports(True) builder.build() builder.write(outfile) return outfile