about summary refs log tree commit diff stats
path: root/miasm2/analysis
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--miasm2/analysis/machine.py13
-rw-r--r--miasm2/analysis/sandbox.py85
2 files changed, 97 insertions, 1 deletions
diff --git a/miasm2/analysis/machine.py b/miasm2/analysis/machine.py
index 7a6069c0..f361b412 100644
--- a/miasm2/analysis/machine.py
+++ b/miasm2/analysis/machine.py
@@ -12,7 +12,7 @@ class Machine(object):
 
     __available = ["arml", "armb", "armtl", "armtb", "sh4", "x86_16", "x86_32",
                    "x86_64", "msp430", "mips32b", "mips32l",
-                   "aarch64l", "aarch64b"]
+                   "aarch64l", "aarch64b", "ppc32b"]
 
 
     def __init__(self, machine_name):
@@ -162,6 +162,17 @@ class Machine(object):
             mn = arch.mn_mips32
             from miasm2.arch.mips32.ira import ir_a_mips32l as ira
             from miasm2.arch.mips32.sem import ir_mips32l as ir
+        elif machine_name == "ppc32b":
+            from miasm2.arch.ppc.disasm import dis_ppc32b as dis_engine
+            from miasm2.arch.ppc import arch
+            try:
+                from miasm2.arch.ppc import jit
+                jitter = jit.jitter_ppc32b
+            except ImportError:
+                pass
+            mn = arch.mn_ppc
+            from miasm2.arch.ppc.ira import ir_a_ppc32b as ira
+            from miasm2.arch.ppc.sem import ir_ppc32b as ir
         else:
             raise ValueError('Unknown machine: %s' % machine_name)
 
diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py
index 086473b0..5bdccddd 100644
--- a/miasm2/analysis/sandbox.py
+++ b/miasm2/analysis/sandbox.py
@@ -440,6 +440,14 @@ class Arch_aarch64b(Arch):
         self.jitter.stack_base = self.STACK_BASE
         self.jitter.init_stack()
 
+class Arch_ppc(Arch):
+    _ARCH_ = None
+
+class Arch_ppc32(Arch):
+    _ARCH_ = None
+
+class Arch_ppc32b(Arch_ppc32):
+    _ARCH_ = "ppc32b"
 
 class Sandbox_Win_x86_32(Sandbox, Arch_x86_32, OS_Win):
 
@@ -745,3 +753,80 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux):
         """
         prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv)
         super(self.__class__, self).call(prepare_cb, addr, *args)
+
+class Sandbox_Linux_ppc32b(Sandbox, Arch_ppc32b, OS_Linux):
+
+    STACK_SIZE = 0x10000
+    STACK_BASE = 0xbfce0000
+
+    # The glue between the kernel and the ELF ABI on Linux/PowerPC is
+    # implemented in glibc/sysdeps/powerpc/powerpc32/dl-start.S, so we
+    # have to play the role of ld.so here.
+    def __init__(self, *args, **kwargs):
+        super(Sandbox_Linux_ppc32b, self).__init__(*args, **kwargs)
+
+        # Init stack
+        self.jitter.stack_size = self.STACK_SIZE
+        self.jitter.stack_base = self.STACK_BASE
+        self.jitter.init_stack()
+        self.jitter.cpu.R1 -= 8
+
+        # Pre-stack some arguments
+        if self.options.mimic_env:
+            env_ptrs = []
+            for env in self.envp:
+                env += "\x00"
+                self.jitter.cpu.R1 -= len(env)
+                ptr = self.jitter.cpu.R1
+                self.jitter.vm.set_mem(ptr, env)
+                env_ptrs.append(ptr)
+            argv_ptrs = []
+            for arg in self.argv:
+                arg += "\x00"
+                self.jitter.cpu.R1 -= len(arg)
+                ptr = self.jitter.cpu.R1
+                self.jitter.vm.set_mem(ptr, arg)
+                argv_ptrs.append(ptr)
+
+            self.jitter.push_uint32_t(0)
+            for ptr in reversed(env_ptrs):
+                self.jitter.push_uint32_t(ptr)
+            self.jitter.cpu.R5 = self.jitter.cpu.R1	# envp
+            self.jitter.push_uint32_t(0)
+            for ptr in reversed(argv_ptrs):
+                self.jitter.push_uint32_t(ptr)
+            self.jitter.cpu.R4 = self.jitter.cpu.R1	# argv
+            self.jitter.cpu.R3 = len(self.argv)		# argc
+            self.jitter.push_uint32_t(self.jitter.cpu.R3)
+
+            self.jitter.cpu.R6 = 0			# auxp
+            self.jitter.cpu.R7 = 0			# termination function
+
+            # From the glibc, we should push a 0 here to distinguish a
+            # dynamically linked executable from a statically linked one.
+            # We actually do not do it and attempt to be somehow compatible
+            # with both types of executables.
+            #self.jitter.push_uint32_t(0)
+
+        self.jitter.cpu.LR = self.CALL_FINISH_ADDR
+
+        # Set the runtime guard
+        self.jitter.add_breakpoint(self.CALL_FINISH_ADDR,
+                                   self.__class__.code_sentinelle)
+
+    def run(self, addr=None):
+        """
+        If addr is not set, use entrypoint
+        """
+        if addr is None and self.options.address is None:
+            addr = self.entry_point
+        super(Sandbox_Linux_ppc32b, self).run(addr)
+
+    def call(self, addr, *args, **kwargs):
+        """
+        Direct call of the function at @addr, with arguments @args
+        @addr: address of the target function
+        @args: arguments
+        """
+        prepare_cb = kwargs.pop('prepare_cb', self.jitter.func_prepare_systemv)
+        super(self.__class__, self).call(prepare_cb, addr, *args)