diff options
| author | Tek <tek@randhome.io> | 2020-03-28 13:46:00 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-28 13:46:00 +0100 |
| commit | 10f7fff0851ab8327b360a93948d95d38cb1e168 (patch) | |
| tree | 1a95ae7080614a232eb32dca3978726b94d84945 | |
| parent | a040288c541f3b2d05fe1ce50f4c30a22572a3fb (diff) | |
| download | miasm-10f7fff0851ab8327b360a93948d95d38cb1e168.tar.gz miasm-10f7fff0851ab8327b360a93948d95d38cb1e168.zip | |
Implements EXCEPT_SYSCALL (#1163)
* Implements EXCEPT_SYSCALL * Improves example and remove EXCEPT_PRIV_INSN call from syscall * fixes exceptions to raise or remove EXCEPTION_SYSCALL with linux x86_64
| -rw-r--r-- | example/jitter/x86_64.py | 94 | ||||
| -rw-r--r-- | miasm/arch/x86/sem.py | 5 | ||||
| -rw-r--r-- | miasm/jitter/csts.py | 1 | ||||
| -rw-r--r-- | miasm/os_dep/linux/syscall.py | 11 |
4 files changed, 103 insertions, 8 deletions
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) diff --git a/miasm/arch/x86/sem.py b/miasm/arch/x86/sem.py index cf3539e2..fdb4efd6 100644 --- a/miasm/arch/x86/sem.py +++ b/miasm/arch/x86/sem.py @@ -28,7 +28,8 @@ from miasm.arch.x86.arch import mn_x86, repeat_mn, replace_regs from miasm.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock from miasm.core.sembuilder import SemBuilder from miasm.jitter.csts import EXCEPT_DIV_BY_ZERO, EXCEPT_ILLEGAL_INSN, \ - EXCEPT_PRIV_INSN, EXCEPT_SOFT_BP, EXCEPT_INT_XX, EXCEPT_INT_1 + EXCEPT_PRIV_INSN, EXCEPT_SOFT_BP, EXCEPT_INT_XX, EXCEPT_INT_1, \ + EXCEPT_SYSCALL import math import struct @@ -3408,7 +3409,7 @@ def l_sysenter(_, instr): def l_syscall(_, instr): e = [] e.append(m2_expr.ExprAssign(exception_flags, - m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) + m2_expr.ExprInt(EXCEPT_SYSCALL, 32))) return e, [] # XXX diff --git a/miasm/jitter/csts.py b/miasm/jitter/csts.py index 6d40fe0d..3829ed98 100644 --- a/miasm/jitter/csts.py +++ b/miasm/jitter/csts.py @@ -9,6 +9,7 @@ EXCEPT_CODE_AUTOMOD = (1 << 0) EXCEPT_SOFT_BP = (1 << 1) EXCEPT_INT_XX = (1 << 2) EXCEPT_SPR_ACCESS = (1 << 3) +EXCEPT_SYSCALL = (1 << 4) EXCEPT_BREAKPOINT_MEMORY = (1 << 10) # Deprecated EXCEPT_BREAKPOINT_INTERN = EXCEPT_BREAKPOINT_MEMORY diff --git a/miasm/os_dep/linux/syscall.py b/miasm/os_dep/linux/syscall.py index fc6bbd8a..3b612f74 100644 --- a/miasm/os_dep/linux/syscall.py +++ b/miasm/os_dep/linux/syscall.py @@ -5,7 +5,7 @@ import logging import struct import termios -from miasm.jitter.csts import EXCEPT_PRIV_INSN, EXCEPT_INT_XX +from miasm.jitter.csts import EXCEPT_INT_XX, EXCEPT_SYSCALL from miasm.core.utils import pck64 log = logging.getLogger('syscalls') @@ -979,7 +979,7 @@ syscall_callbacks_arml = { } def syscall_x86_64_exception_handler(linux_env, syscall_callbacks, jitter): - """Call to actually handle an EXCEPT_PRIV_INSN exception + """Call to actually handle an EXCEPT_SYSCALL exception In the case of an error raised by a SYSCALL, call the corresponding syscall_callbacks @linux_env: LinuxEnvironment_x86_64 instance @@ -1002,14 +1002,14 @@ def syscall_x86_64_exception_handler(linux_env, syscall_callbacks, jitter): # Clean exception and move pc to the next instruction, to let the jitter # continue - jitter.cpu.set_exception(jitter.cpu.get_exception() ^ EXCEPT_PRIV_INSN) + jitter.cpu.set_exception(jitter.cpu.get_exception() ^ EXCEPT_SYSCALL) jitter.pc += cur_instr.l return True def syscall_x86_32_exception_handler(linux_env, syscall_callbacks, jitter): - """Call to actually handle an EXCEPT_PRIV_INSN exception + """Call to actually handle an EXCEPT_INT_XX exception In the case of an error raised by a SYSCALL, call the corresponding syscall_callbacks @linux_env: LinuxEnvironment_x86_32 instance @@ -1078,7 +1078,7 @@ def enable_syscall_handling(jitter, linux_env, syscall_callbacks): if arch_name == "x8664": handler = syscall_x86_64_exception_handler handler = functools.partial(handler, linux_env, syscall_callbacks) - jitter.add_exception_handler(EXCEPT_PRIV_INSN, handler) + jitter.add_exception_handler(EXCEPT_SYSCALL, handler) elif arch_name == "x8632": handler = syscall_x86_32_exception_handler handler = functools.partial(handler, linux_env, syscall_callbacks) @@ -1089,4 +1089,3 @@ def enable_syscall_handling(jitter, linux_env, syscall_callbacks): jitter.add_exception_handler(EXCEPT_INT_XX, handler) else: raise ValueError("No syscall handler implemented for %s" % arch_name) - |