diff options
| -rw-r--r-- | example/jitter/unpack_upx.py | 48 | ||||
| -rw-r--r-- | miasm/arch/mips32/arch.py | 13 | ||||
| -rw-r--r-- | miasm/arch/mips32/sem.py | 78 | ||||
| -rw-r--r-- | miasm/arch/ppc/sem.py | 16 | ||||
| -rw-r--r-- | miasm/expression/expression.py | 2 | ||||
| -rw-r--r-- | miasm/jitter/jitcore.py | 5 | ||||
| -rw-r--r-- | test/arch/mips32/arch.py | 17 |
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"), ] |