about summary refs log tree commit diff stats
path: root/example
diff options
context:
space:
mode:
Diffstat (limited to 'example')
-rw-r--r--example/disasm/full.py12
-rw-r--r--example/ida/graph_ir.py11
-rw-r--r--example/jitter/unpack_upx.py48
-rw-r--r--example/jitter/x86_64.py94
-rw-r--r--example/samples/x86_32_automod_2.S25
5 files changed, 141 insertions, 49 deletions
diff --git a/example/disasm/full.py b/example/disasm/full.py
index d4fae867..57263a6f 100644
--- a/example/disasm/full.py
+++ b/example/disasm/full.py
@@ -10,8 +10,7 @@ from miasm.core.asmblock import log_asmblock, AsmCFG
 from miasm.core.interval import interval
 from miasm.analysis.machine import Machine
 from miasm.analysis.data_flow import \
-    DiGraphDefUse, ReachingDefinitions, \
-    replace_stack_vars, load_from_int, del_unused_edges
+    DiGraphDefUse, ReachingDefinitions, load_from_int
 from miasm.expression.simplifications import expr_simp
 from miasm.analysis.ssa import SSADiGraph
 from miasm.ir.ir import AssignBlock, IRBlock
@@ -65,10 +64,6 @@ parser.add_argument('-p', "--ssa", action="store_true",
                     help="Generate the ssa form in  'ssa.dot'.")
 parser.add_argument('-x', "--propagexpr", action="store_true",
                     help="Do Expression propagation.")
-parser.add_argument('-y', "--stack2var", action="store_true",
-                    help="*Try* to do transform stack accesses into variables. "
-                    "Use only with --propagexpr option. "
-                    "WARNING: not reliable, may fail.")
 parser.add_argument('-e', "--loadint", action="store_true",
                     help="Load integers from binary in fixed memory lookup.")
 parser.add_argument('-j', "--calldontmodstack", action="store_true",
@@ -309,16 +304,11 @@ if args.propagexpr:
             ssa = self.do_simplify_loop(ssa, head)
             ircfg = self.ssa_to_unssa(ssa, head)
 
-            if args.stack2var:
-                replace_stack_vars(self.ir_arch, ircfg)
-
             ircfg_simplifier = IRCFGSimplifierCommon(self.ir_arch)
             ircfg_simplifier.deadremoval.add_expr_to_original_expr(ssa.ssa_variable_to_expr)
             ircfg_simplifier.simplify(ircfg, head)
             return ircfg
 
-
-
     head = list(entry_points)[0]
     simplifier = CustomIRCFGSimplifierSSA(ir_arch_a)
     ircfg = simplifier.simplify(ircfg_a, head)
diff --git a/example/ida/graph_ir.py b/example/ida/graph_ir.py
index c011b4c3..082fabd7 100644
--- a/example/ida/graph_ir.py
+++ b/example/ida/graph_ir.py
@@ -125,11 +125,11 @@ class GraphMiasmIR(idaapi.GraphViewer):
     def OnRefresh(self):
         self.Clear()
         addr_id = {}
-        for irblock in viewvalues(self.ircfg.blocks):
+        for (loc_key, irblock) in viewitems(self.ircfg.blocks):
             id_irblock = self.AddNode(color_irblock(irblock, self.ircfg))
-            addr_id[irblock] = id_irblock
+            addr_id[loc_key] = id_irblock
 
-        for irblock in viewvalues(self.ircfg.blocks):
+        for (loc_key, irblock) in viewitems(self.ircfg.blocks):
             if not irblock:
                 continue
             all_dst = self.ircfg.dst_trackback(irblock)
@@ -138,9 +138,8 @@ class GraphMiasmIR(idaapi.GraphViewer):
                     continue
                 if not dst.loc_key in self.ircfg.blocks:
                     continue
-                dst_block = self.ircfg.blocks[dst.loc_key]
-                node1 = addr_id[irblock]
-                node2 = addr_id[dst_block]
+                node1 = addr_id[loc_key]
+                node2 = addr_id[dst.loc_key]
                 self.AddEdge(node1, node2)
         return True
 
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)
diff --git a/example/samples/x86_32_automod_2.S b/example/samples/x86_32_automod_2.S
new file mode 100644
index 00000000..832e253f
--- /dev/null
+++ b/example/samples/x86_32_automod_2.S
@@ -0,0 +1,25 @@
+main:
+	MOV     EAX, 0
+	MOV     ECX, 0x3
+block1:
+	DEC     ECX
+block2:
+	INC     EAX
+tmp:
+	DEC     ECX
+	JNZ     block2
+	; Modify block1
+	MOV     BYTE PTR [block1], 0x90
+	; Modify block2
+	MOV     BYTE PTR [block2], 0x90
+	MOV     BYTE PTR [tmp], 0x90
+	MOV     ECX, 4
+	MOV     EBX, EAX
+	XOR     EAX, EAX
+	CMP     EBX, 2
+	JZ      block2
+	CMP     EBX, 0
+	JZ      ok
+	INT     0x3
+ok:
+	RET