diff options
Diffstat (limited to 'example/jitter')
| -rw-r--r-- | example/jitter/unpack_upx.py | 48 | ||||
| -rw-r--r-- | example/jitter/x86_64.py | 94 |
2 files changed, 110 insertions, 32 deletions
diff --git a/example/jitter/unpack_upx.py b/example/jitter/unpack_upx.py index baa6f0bb..2527f0c4 100644 --- a/example/jitter/unpack_upx.py +++ b/example/jitter/unpack_upx.py @@ -1,9 +1,8 @@ from __future__ import print_function import os import logging -from pdb import pm -from miasm.loader import pe from miasm.analysis.sandbox import Sandbox_Win_x86_32 +from miasm.jitter.loader.pe import vm2pe from miasm.os_dep.common import get_win_str_a @@ -77,45 +76,30 @@ if options.verbose is True: print(sb.jitter.vm) -def update_binary(jitter): - sb.pe.Opthdr.AddressOfEntryPoint = sb.pe.virt2rva(jitter.pc) - logging.info('updating binary') - for s in sb.pe.SHList: - sdata = sb.jitter.vm.get_mem(sb.pe.rva2virt(s.addr), s.rawsize) - sb.pe.rva.set(s.addr, sdata) +def stop(jitter): + logging.info('OEP reached') # Stop execution jitter.run = False return False # Set callbacks -sb.jitter.add_breakpoint(end_offset, update_binary) +sb.jitter.add_breakpoint(end_offset, stop) # Run sb.run() -# Rebuild PE -# Alternative solution: miasm.jitter.loader.pe.vm2pe(sb.jitter, out_fname, -# libs=sb.libs, e_orig=sb.pe) -new_dll = [] - -sb.pe.SHList.align_sections(0x1000, 0x1000) -logging.info(repr(sb.pe.SHList)) - -sb.pe.DirRes = pe.DirRes(sb.pe) -sb.pe.DirImport.impdesc = None -logging.info(repr(sb.pe.DirImport.impdesc)) -new_dll = sb.libs.gen_new_lib(sb.pe) -logging.info(new_dll) -sb.pe.DirImport.impdesc = [] -sb.pe.DirImport.add_dlldesc(new_dll) -s_myimp = sb.pe.SHList.add_section(name="myimp", rawsize=len(sb.pe.DirImport)) -logging.info(repr(sb.pe.SHList)) -sb.pe.DirImport.set_rva(s_myimp.addr) - -# XXXX TODO -sb.pe.NThdr.optentries[pe.DIRECTORY_ENTRY_DELAY_IMPORT].rva = 0 - +# Construct the output filename bname, fname = os.path.split(options.filename) fname = os.path.join(bname, fname.replace('.', '_')) -open(fname + '_unupx.bin', 'wb').write(bytes(sb.pe)) +out_fname = fname + '_unupx.bin' + +# Rebuild the PE thanks to `vm2pe` +# +# vm2pe will: +# - set the new entry point to the current address (ie, the OEP) +# - dump each section from the virtual memory into the new PE +# - use `sb.libs` to generate a new import directory, and use it in the new PE +# - save the resulting PE in `out_fname` + +vm2pe(sb.jitter, out_fname, libs=sb.libs, e_orig=sb.pe) diff --git a/example/jitter/x86_64.py b/example/jitter/x86_64.py new file mode 100644 index 00000000..78d88c18 --- /dev/null +++ b/example/jitter/x86_64.py @@ -0,0 +1,94 @@ +from argparse import ArgumentParser +from pdb import pm +from miasm.jitter.csts import PAGE_READ, PAGE_WRITE, EXCEPT_SYSCALL +from miasm.analysis.machine import Machine + + +# Some syscalls often used by shellcodes +# See https://filippo.io/linux-syscall-table/ +SYSCALL = { + 0: "read", + 1: "write", + 2: "open", + 0x9: "mmap", + 0x27: "getpid", + 0x29: "socket", + 0x2a: "connect", + 0x2b: "accept", + 0x2c: "sendto", + 0x2d: "recvfrom", + 0x31: "bind", + 0x32: "listen", + 0x33: "getsockname", + 0x34: "getpeername", + 0x3b: "execve", + 0x3c: "exit", + 0x3d: "wait4", + 0x3e: "kill", + 0x57: "unlink", + 0x5a: "chmod", + 0x5b: "fchmod", + 0x5c: "chown" +} + + +def code_sentinelle(jitter): + jitter.run = False + jitter.pc = 0 + return True + + +def log_syscalls(jitter): + # For parameters, see + # https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux + # Example of how to implement some syscalls + if jitter.cpu.EAX == 1: + # Write + size_t = jitter.cpu.RDX + print("write(fd: {}, buf: {}, size_t: {})".format( + jitter.cpu.RDI, + jitter.vm.get_mem(jitter.cpu.RSI, size_t), + size_t + )) + # Return value is the size written + jitter.cpu.EAX = size_t + elif jitter.cpu.EAX == 0x3c: + # exit + print("Exit syscall - stopping the machine") + return False + else: + # Most syscalls are not implemented, it may create issues + if jitter.cpu.EAX in SYSCALL: + print("syscall {} - {} : Not Implemented".format(jitter.cpu.EAX, SYSCALL[jitter.cpu.EAX])) + else: + print("Unknown syscall {} : NotImplemented".format(jitter.cpu.EAX)) + jitter.cpu.set_exception(0) + jitter.cpu.EAX = 0 + return True + + +if __name__ == "__main__": + parser = ArgumentParser(description="x86 64 basic Jitter") + parser.add_argument("filename", help="x86 64 shellcode filename") + parser.add_argument("-j", "--jitter", + help="Jitter engine (default is 'gcc')", + default="gcc") + parser.add_argument("--verbose", "-v", action="store_true", + help="Verbose mode") + args = parser.parse_args() + + myjit = Machine("x86_64").jitter(args.jitter) + myjit.init_stack() + + with open(args.filename, 'rb') as f: + data = f.read() + run_addr = 0x40000000 + myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, data) + + if args.verbose: + myjit.set_trace_log() + myjit.push_uint64_t(0x1337beef) + myjit.add_breakpoint(0x1337beef, code_sentinelle) + # Add routine catching syscalls + myjit.add_exception_handler(EXCEPT_SYSCALL, log_syscalls) + myjit.run(run_addr) |