about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/jitter/unpack_upx.py48
-rw-r--r--miasm/arch/mips32/arch.py13
-rw-r--r--miasm/arch/mips32/sem.py78
-rw-r--r--miasm/arch/ppc/sem.py16
-rw-r--r--miasm/expression/expression.py2
-rw-r--r--miasm/jitter/jitcore.py5
-rw-r--r--test/arch/mips32/arch.py17
7 files changed, 126 insertions, 53 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/miasm/arch/mips32/arch.py b/miasm/arch/mips32/arch.py
index f1e52585..dcdfb707 100644
--- a/miasm/arch/mips32/arch.py
+++ b/miasm/arch/mips32/arch.py
@@ -47,8 +47,8 @@ class additional_info(object):
         self.except_on_instr = False
 
 br_0 = ['B', 'J', 'JR', 'BAL', 'JAL', 'JALR']
-br_1 = ['BGEZ', 'BLTZ', 'BGTZ', 'BLEZ', 'BC1T', 'BC1F']
-br_2 = ['BEQ', 'BEQL', 'BNE']
+br_1 = ['BGEZ', 'BLTZ', 'BGTZ', 'BGTZL', 'BLEZ', 'BLEZL', 'BC1T', 'BC1TL', 'BC1F', 'BC1FL']
+br_2 = ['BEQ', 'BEQL', 'BNE', 'BNEL']
 
 
 class instruction_mips32(cpu.instruction):
@@ -669,13 +669,18 @@ mips32op("mfhi",    [cpu.bs('000000'), cpu.bs('0000000000'), rd,
 mips32op("b",       [cpu.bs('000100'), cpu.bs('00000'), cpu.bs('00000'), soff],
          alias = True)
 mips32op("bne",     [cpu.bs('000101'), rs, rt, soff])
+mips32op("bnel",    [cpu.bs('010101'), rs, rt, soff])
+
 mips32op("beq",     [cpu.bs('000100'), rs, rt, soff])
+mips32op("beql",    [cpu.bs('010100'), rs, rt, soff])
 
 mips32op("blez",    [cpu.bs('000110'), rs, cpu.bs('00000'), soff])
+mips32op("blezl",   [cpu.bs('010110'), rs, cpu.bs('00000'), soff])
 
 mips32op("bcc",     [cpu.bs('000001'), rs, bs_bcc, soff])
 
 mips32op("bgtz",    [cpu.bs('000111'), rs, cpu.bs('00000'), soff])
+mips32op("bgtzl",   [cpu.bs('010111'), rs, cpu.bs('00000'), soff])
 mips32op("bal",     [cpu.bs('000001'), cpu.bs('00000'), cpu.bs('10001'), soff],
          alias = True)
 
@@ -716,8 +721,12 @@ mips32op("c",       [cpu.bs('010001'), bs_fmt, ft, fs, fcc, cpu.bs('0'),
 
 mips32op("bc1t",    [cpu.bs('010001'), cpu.bs('01000'), fcc, cpu.bs('0'),
                      cpu.bs('1'), soff])
+mips32op("bc1tl",    [cpu.bs('010001'), cpu.bs('01000'), fcc, cpu.bs('1'),
+                     cpu.bs('1'), soff])
 mips32op("bc1f",    [cpu.bs('010001'), cpu.bs('01000'), fcc, cpu.bs('0'),
                      cpu.bs('0'), soff])
+mips32op("bc1fl",    [cpu.bs('010001'), cpu.bs('01000'), fcc, cpu.bs('1'),
+                     cpu.bs('0'), soff])
 
 mips32op("swc1",    [cpu.bs('111001'), base, ft, s16imm_noarg], [ft, base])
 
diff --git a/miasm/arch/mips32/sem.py b/miasm/arch/mips32/sem.py
index 5fc491a7..903be3be 100644
--- a/miasm/arch/mips32/sem.py
+++ b/miasm/arch/mips32/sem.py
@@ -67,6 +67,12 @@ def lbu(arg1, arg2):
     arg1 = mem8[arg2.ptr].zeroExtend(32)
 
 @sbuild.parse
+def lh(arg1, arg2):
+    """A word is loaded into a register @arg1 from the 
+    specified address @arg2."""
+    arg1 = mem16[arg2.ptr].signExtend(32)
+
+@sbuild.parse
 def lhu(arg1, arg2):
     """A word is loaded (unsigned extended) into a register @arg1 from the
     specified address @arg2."""
@@ -85,6 +91,13 @@ def beq(arg1, arg2, arg3):
     ir.IRDst = dst
 
 @sbuild.parse
+def beql(arg1, arg2, arg3):
+    "Branches on @arg3 if the quantities of two registers @arg1, @arg2 are eq"
+    dst = arg3 if ExprOp(m2_expr.TOK_EQUAL, arg1, arg2) else ExprLoc(ir.get_next_delay_loc_key(instr), ir.IRDst.size)
+    PC = dst
+    ir.IRDst = dst
+
+@sbuild.parse
 def bgez(arg1, arg2):
     """Branches on @arg2 if the quantities of register @arg1 is greater than or
     equal to zero"""
@@ -93,6 +106,14 @@ def bgez(arg1, arg2):
     ir.IRDst = dst
 
 @sbuild.parse
+def bgezl(arg1, arg2):
+    """Branches on @arg2 if the quantities of register @arg1 is greater than or
+    equal to zero"""
+    dst = ExprLoc(ir.get_next_delay_loc_key(instr), ir.IRDst.size) if ExprOp(m2_expr.TOK_INF_SIGNED, arg1, ExprInt(0, arg1.size)) else arg2
+    PC = dst
+    ir.IRDst = dst
+
+@sbuild.parse
 def bne(arg1, arg2, arg3):
     """Branches on @arg3 if the quantities of two registers @arg1, @arg2 are NOT
     equal"""
@@ -101,6 +122,14 @@ def bne(arg1, arg2, arg3):
     ir.IRDst = dst
 
 @sbuild.parse
+def bnel(arg1, arg2, arg3):
+    """Branches on @arg3 if the quantities of two registers @arg1, @arg2 are NOT
+    equal"""
+    dst = ExprLoc(ir.get_next_delay_loc_key(instr), ir.IRDst.size) if ExprOp(m2_expr.TOK_EQUAL, arg1, arg2) else arg3
+    PC = dst
+    ir.IRDst = dst
+
+@sbuild.parse
 def lui(arg1, arg2):
     """The immediate value @arg2 is shifted left 16 bits and stored in the
     register @arg1. The lower 16 bits are zeroes."""
@@ -248,6 +277,13 @@ def bltz(arg1, arg2):
     ir.IRDst = dst_o
 
 @sbuild.parse
+def bltzl(arg1, arg2):
+    """Branches on @arg2 if the register @arg1 is less than zero"""
+    dst_o = arg2 if ExprOp(m2_expr.TOK_INF_SIGNED, arg1, ExprInt(0, arg1.size)) else ExprLoc(ir.get_next_delay_loc_key(instr), ir.IRDst.size)
+    PC = dst_o
+    ir.IRDst = dst_o
+
+@sbuild.parse
 def blez(arg1, arg2):
     """Branches on @arg2 if the register @arg1 is less than or equal to zero"""
     cond = ExprOp(m2_expr.TOK_INF_EQUAL_SIGNED, arg1, ExprInt(0, arg1.size))
@@ -256,6 +292,14 @@ def blez(arg1, arg2):
     ir.IRDst = dst_o
 
 @sbuild.parse
+def blezl(arg1, arg2):
+    """Branches on @arg2 if the register @arg1 is less than or equal to zero"""
+    cond = ExprOp(m2_expr.TOK_INF_EQUAL_SIGNED, arg1, ExprInt(0, arg1.size))
+    dst_o = arg2 if cond else ExprLoc(ir.get_next_delay_loc_key(instr), ir.IRDst.size)
+    PC = dst_o
+    ir.IRDst = dst_o
+
+@sbuild.parse
 def bgtz(arg1, arg2):
     """Branches on @arg2 if the register @arg1 is greater than zero"""
     cond =  ExprOp(m2_expr.TOK_INF_EQUAL_SIGNED, arg1, ExprInt(0, arg1.size))
@@ -264,6 +308,14 @@ def bgtz(arg1, arg2):
     ir.IRDst = dst_o
 
 @sbuild.parse
+def bgtzl(arg1, arg2):
+    """Branches on @arg2 if the register @arg1 is greater than zero"""
+    cond =  ExprOp(m2_expr.TOK_INF_EQUAL_SIGNED, arg1, ExprInt(0, arg1.size))
+    dst_o = ExprLoc(ir.get_next_delay_loc_key(instr), ir.IRDst.size) if cond else arg2
+    PC = dst_o
+    ir.IRDst = dst_o
+
+@sbuild.parse
 def wsbh(arg1, arg2):
     arg1 = ExprCompose(arg2[8:16], arg2[0:8], arg2[24:32], arg2[16:24])
 
@@ -327,12 +379,12 @@ def ins(ir, instr, a, b, c, d):
 
     my_slices = []
     if pos != 0:
-        my_slices.append((a[:pos], 0, pos))
+        my_slices.append(a[:pos])
     if l != 0:
-        my_slices.append((b[:l], pos, pos+l))
+        my_slices.append(b[:l])
     if pos + l != 32:
-        my_slices.append((a[pos+l:], pos+l, 32))
-    r = m2_expr.ExprCompose(my_slices)
+        my_slices.append(a[pos+l:])
+    r = m2_expr.ExprCompose(*my_slices)
     e.append(m2_expr.ExprAssign(a, r))
     return e, []
 
@@ -364,12 +416,24 @@ def bc1t(arg1, arg2):
     ir.IRDst = dst_o
 
 @sbuild.parse
+def bc1tl(arg1, arg2):
+    dst_o = arg2 if arg1 else ExprLoc(ir.get_next_delay_loc_key(instr), ir.IRDst.size)
+    PC = dst_o
+    ir.IRDst = dst_o
+
+@sbuild.parse
 def bc1f(arg1, arg2):
     dst_o = ExprLoc(ir.get_next_break_loc_key(instr), ir.IRDst.size) if arg1 else arg2
     PC = dst_o
     ir.IRDst = dst_o
 
 @sbuild.parse
+def bc1fl(arg1, arg2):
+    dst_o = ExprLoc(ir.get_next_delay_loc_key(instr), ir.IRDst.size) if arg1 else arg2
+    PC = dst_o
+    ir.IRDst = dst_o
+
+@sbuild.parse
 def cvt_d_w(arg1, arg2):
     # TODO XXX
     arg1 = 'flt_d_w'(arg2)
@@ -424,7 +488,6 @@ def ei(arg1):
 def ehb(arg1):
     "NOP"
 
-
 def teq(ir, instr, arg1, arg2):
     e = []
 
@@ -473,7 +536,7 @@ mnemo_func.update({
         'subu': l_sub,
         'xor': l_xor,
         'xori': l_xor,
-        'teq': teq,
+        'teq': teq
 })
 
 def get_mnemo_expr(ir, instr, *args):
@@ -511,6 +574,9 @@ class ir_mips32l(IntermediateRepresentation):
     def get_next_break_loc_key(self, instr):
         return self.loc_db.get_or_create_offset_location(instr.offset  + 8)
 
+    def get_next_delay_loc_key(self, instr):
+        return self.loc_db.get_or_create_offset_location(instr.offset + 16)
+
 class ir_mips32b(ir_mips32l):
     def __init__(self, loc_db=None):
         self.addrsize = 32
diff --git a/miasm/arch/ppc/sem.py b/miasm/arch/ppc/sem.py
index 670555d0..61330fe1 100644
--- a/miasm/arch/ppc/sem.py
+++ b/miasm/arch/ppc/sem.py
@@ -248,8 +248,8 @@ def mn_do_exts(ir, instr, ra, rs):
 
 def byte_swap(expr):
     nbytes = expr.size // 8
-    bytes = [ expr[i*8:i*8+8] for i in range(nbytes - 1, -1, -1) ]
-    return ExprCompose(bytes)
+    lbytes = [ expr[i*8:i*8+8] for i in range(nbytes - 1, -1, -1) ]
+    return ExprCompose(*lbytes)
 
 def mn_do_load(ir, instr, arg1, arg2, arg3=None):
     assert instr.name[0] == 'L'
@@ -320,7 +320,7 @@ def mn_do_load(ir, instr, arg1, arg2, arg3=None):
 
 def mn_do_lmw(ir, instr, rd, src):
     ret = []
-    address = int(src)
+    address = src.ptr
     ri = int(rd.name[1:],10)
     i = 0
     while ri <= 31:
@@ -602,7 +602,7 @@ def mn_do_srw(ir, instr, ra, rs, rb):
 
 def mn_do_stmw(ir, instr, rs, dest):
     ret = []
-    address = int(dest)
+    address = dest.ptr
     ri = int(rs.name[1:],10)
     i = 0
     while ri <= 31:
@@ -675,8 +675,8 @@ def mn_do_store(ir, instr, arg1, arg2, arg3=None):
         ret.append(ExprAssign(ir.IRDst, loc_next))
         dont = flags + [ ExprAssign(CR0_EQ, ExprInt(0,1)),
                          ExprAssign(ir.IRDst, loc_next) ]
-        additional_ir = [ IRBlock(loc_do, [ AssignBlock(ret) ]),
-                          IRBlock(loc_dont, [ AssignBlock(dont) ]) ]
+        additional_ir = [ IRBlock(loc_do.loc_key, [ AssignBlock(ret) ]),
+                          IRBlock(loc_dont.loc_key, [ AssignBlock(dont) ]) ]
         ret = [ ExprAssign(reserve, ExprInt(0, 1)),
                 ExprAssign(ir.IRDst, ExprCond(reserve, loc_do, loc_dont)) ]
 
@@ -958,9 +958,9 @@ class ir_ppc32b(IntermediateRepresentation):
             instr_ir, extra_ir = mn_do_store(self, instr, *args)
         elif instr.name[0:4] == 'SUBF':
             if instr.name[0:5] == 'SUBFZ':
-                last_arg = ExprInt(0)
+                last_arg = ExprInt(0, 32)
             elif instr.name[0:5] == 'SUBFM':
-                last_arg = ExprInt(0xFFFFFFFF)
+                last_arg = ExprInt(0xFFFFFFFF, 32)
             else:
                 last_arg = args[2]
             instr_ir, extra_ir = mn_do_sub(self, instr, args[0], args[1],
diff --git a/miasm/expression/expression.py b/miasm/expression/expression.py
index 18fcb77a..ef05a2b6 100644
--- a/miasm/expression/expression.py
+++ b/miasm/expression/expression.py
@@ -373,7 +373,7 @@ class ExprVisitorCallbackTopToBottom(ExprVisitorBase):
     """
     Rebuild expression by visiting sub-expressions
     Call @callback on each sub-expression
-    if @Ā¢allback return non None value, replace current node with this value
+    if @callback return non None value, replace current node with this value
     Else, continue visit of sub-expressions
     """
     def __init__(self, callback):
diff --git a/miasm/jitter/jitcore.py b/miasm/jitter/jitcore.py
index cff01f9b..cc531cf5 100644
--- a/miasm/jitter/jitcore.py
+++ b/miasm/jitter/jitcore.py
@@ -198,10 +198,7 @@ class JitCore(object):
         """
 
         mem_range = interval()
-
-        for block in blocks:
-            mem_range += interval([(block.ad_min, block.ad_max - 1)])
-
+        mem_range = interval([(block.ad_min, block.ad_max - 1) for block in blocks])
         return mem_range
 
     def __updt_jitcode_mem_range(self, vm):
diff --git a/test/arch/mips32/arch.py b/test/arch/mips32/arch.py
index e5e8cff6..e14eda8a 100644
--- a/test/arch/mips32/arch.py
+++ b/test/arch/mips32/arch.py
@@ -214,6 +214,23 @@ reg_tests_mips32 = [
 
     ("XXXXXXXX    LDC1       F22, 0xFFFF9148(V0)",
      "D4569148"),
+
+    ("XXXXXXXX    BEQL       S0, V0, 0x124",
+     "52020048"),
+    ("XXXXXXXX    BGEZL      T3, 0x24",
+     "05630008"),
+    ("XXXXXXXX    BNEL       A0, ZERO, 0x2C",
+     "5480000A"),
+    ("XXXXXXXX    BLTZL      S6, 0x5C",
+     "06C20016"),
+    ("XXXXXXXX    BLEZL      V1, 0x80",
+     "5860001F"),
+    ("XXXXXXXX    BGTZL      S4, 0x14",
+     "5E800004"),
+    ("XXXXXXXX    BC1FL      FCC0, 0x24",
+     "45020008"),
+    ("XXXXXXXX    BC1TL      FCC0, 0xB8",
+     "4503002D"),
 ]