diff options
| -rw-r--r-- | miasm2/arch/x86/arch.py | 44 | ||||
| -rw-r--r-- | miasm2/arch/x86/sem.py | 16 | ||||
| -rw-r--r-- | miasm2/core/bin_stream.py | 8 | ||||
| -rw-r--r-- | miasm2/core/graph.py | 35 | ||||
| -rw-r--r-- | miasm2/ir/translators/z3_ir.py | 4 | ||||
| -rw-r--r-- | test/arch/x86/arch.py | 7 |
6 files changed, 90 insertions, 24 deletions
diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py index 7f9d50e6..b625647e 100644 --- a/miasm2/arch/x86/arch.py +++ b/miasm2/arch/x86/arch.py @@ -470,7 +470,7 @@ class instruction_x86(instruction): return self.name in ['CALL'] def dstflow2label(self, loc_db): - if self.additional_info.g1.value & 6 and self.name in repeat_mn: + if self.additional_info.g1.value & 14 and self.name in repeat_mn: return expr = self.args[0] if not expr.is_int(): @@ -512,7 +512,7 @@ class instruction_x86(instruction): return self.name in ['CALL'] def getdstflow(self, loc_db): - if self.additional_info.g1.value & 6 and self.name in repeat_mn: + if self.additional_info.g1.value & 14 and self.name in repeat_mn: addr = int(self.offset) loc_key = loc_db.get_or_create_offset_location(addr) return [ExprLoc(loc_key, self.v_opmode())] @@ -549,7 +549,10 @@ class instruction_x86(instruction): if self.additional_info.g1.value & 2: if getattr(self.additional_info.prefixed, 'default', "") != "\xF2": o = "REPNE %s" % o - if self.additional_info.g1.value & 4: + if self.additional_info.g1.value & 8: + if getattr(self.additional_info.prefixed, 'default', "") != "\xF3": + o = "REP %s" % o + elif self.additional_info.g1.value & 4: if getattr(self.additional_info.prefixed, 'default', "") != "\xF3": o = "REPE %s" % o return o @@ -677,12 +680,15 @@ class mn_x86(cls_mn): if prefix == "LOCK": pref |= 1 text = new_s - elif prefix == "REPNE": + elif prefix == "REPNE" or prefix == "REPNZ": pref |= 2 text = new_s - elif prefix == "REPE": + elif prefix == "REPE" or prefix == "REPZ": pref |= 4 text = new_s + elif prefix == "REP": + pref |= 8 + text = new_s c = super(mn_x86, cls).fromstring(text, loc_db, mode) c.additional_info.g1.value = pref return c @@ -713,7 +719,7 @@ class mn_x86(cls_mn): elif c == '\xf2': pre_dis_info['g1'] = 2 elif c == '\xf3': - pre_dis_info['g1'] = 4 + pre_dis_info['g1'] = 12 elif c == '\x2e': pre_dis_info['g2'] = 1 @@ -728,20 +734,20 @@ class mn_x86(cls_mn): elif c == '\x65': pre_dis_info['g2'] = 6 - elif mode == 64 and c in '@ABCDEFGHIJKLMNO': - x = ord(c) - pre_dis_info['rex_p'] = 1 - pre_dis_info['rex_w'] = (x >> 3) & 1 - pre_dis_info['rex_r'] = (x >> 2) & 1 - pre_dis_info['rex_x'] = (x >> 1) & 1 - pre_dis_info['rex_b'] = (x >> 0) & 1 - offset += 1 - break else: - c = '' break pre_dis_info['prefix'] += c offset += 1 + if mode == 64 and c in '@ABCDEFGHIJKLMNO': + x = ord(c) + pre_dis_info['rex_p'] = 1 + pre_dis_info['rex_w'] = (x >> 3) & 1 + pre_dis_info['rex_r'] = (x >> 2) & 1 + pre_dis_info['rex_x'] = (x >> 1) & 1 + pre_dis_info['rex_b'] = (x >> 0) & 1 + offset += 1 + elif pre_dis_info.get('g1', None) == 12 and c in ['\xa6', '\xa7', '\xae', '\xaf']: + pre_dis_info['g1'] = 4 return pre_dis_info, v, mode, offset, offset - offset_o @classmethod @@ -856,7 +862,7 @@ class mn_x86(cls_mn): if hasattr(self, 'no_xmm_pref'): return None v = "\xf2" + v - if self.g1.value & 4: + if self.g1.value & 12: if hasattr(self, 'no_xmm_pref'): return None v = "\xf3" + v @@ -895,7 +901,7 @@ class mn_x86(cls_mn): out = [] for c, v in candidates: if (hasattr(c, 'no_xmm_pref') and - (c.g1.value & 2 or c.g1.value & 4 or c.opmode)): + (c.g1.value & 2 or c.g1.value & 4 or c.g1.value & 8 or c.opmode)): continue if hasattr(c, "fopmode") and v_opmode(c) != c.fopmode.mode: continue @@ -4607,6 +4613,8 @@ addop("maskmovdqu", [bs8(0x0f), bs8(0xf7), pref_66] + addop("emms", [bs8(0x0f), bs8(0x77)]) +addop("endbr64", [pref_f3, bs8(0x0f), bs8(0x1e), bs8(0xfa)]) +addop("endbr32", [pref_f3, bs8(0x0f), bs8(0x1e), bs8(0xfb)]) mn_x86.bintree = factor_one_bit(mn_x86.bintree) # mn_x86.bintree = factor_fields_all(mn_x86.bintree) diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 862240e5..b2ef5a43 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -1321,7 +1321,7 @@ def _tpl_eflags(tmp): def popfw(ir, instr): - tmp = ir.ExprMem(mRSP[instr.mode], 32) + tmp = ir.ExprMem(mRSP[instr.mode], 16) e = _tpl_eflags(tmp) e.append( m2_expr.ExprAssign(mRSP[instr.mode], mRSP[instr.mode] + m2_expr.ExprInt(2, mRSP[instr.mode].size))) @@ -4938,6 +4938,14 @@ def emms(ir, instr): # Implemented as a NOP return [], [] +def endbr64(ir, instr): + # Implemented as a NOP + return [], [] + +def endbr32(ir, instr): + # Implemented as a NOP + return [], [] + # Common value without too many option, 0x1fa0 STMXCSR_VALUE = 0x1fa0 def stmxcsr(ir, instr, dst): @@ -5584,6 +5592,8 @@ mnemo_func = {'mov': mov, "movmskpd": movmskpd, "stmxcsr": stmxcsr, "ldmxcsr": ldmxcsr, + "endbr64": endbr64, + "endbr32": endbr32, } @@ -5669,9 +5679,9 @@ class ir_x86_16(IntermediateRepresentation): # end condition if zf_val is None: c_cond = cond_dec - elif instr.additional_info.g1.value & 2: # REPNE + elif instr.additional_info.g1.value & 2: # REPNE and REPNZ c_cond = cond_dec | zf - elif instr.additional_info.g1.value & 4: # REP + elif instr.additional_info.g1.value & 12: # REPE, REP and REPZ c_cond = cond_dec | (zf ^ m2_expr.ExprInt(1, 1)) # gen while diff --git a/miasm2/core/bin_stream.py b/miasm2/core/bin_stream.py index 8bd59467..1dada90f 100644 --- a/miasm2/core/bin_stream.py +++ b/miasm2/core/bin_stream.py @@ -170,12 +170,16 @@ class bin_stream_str(bin_stream): def _getbytes(self, start, l=1): if start + l + self.shift > self.l: raise IOError("not enough bytes in str") + if start + self.shift < 0: + raise IOError("Negative offset") return super(bin_stream_str, self)._getbytes(start + self.shift, l) def readbs(self, l=1): if self.offset + l + self.shift > self.l: raise IOError("not enough bytes in str") + if self.offset + self.shift < 0: + raise IOError("Negative offset") self.offset += l return self.bin[self.offset - l + self.shift:self.offset + self.shift] @@ -210,6 +214,8 @@ class bin_stream_file(bin_stream): def readbs(self, l=1): if self.offset + l + self.shift > self.l: raise IOError("not enough bytes in file") + if self.offset + self.shift < 0: + raise IOError("Negative offset") return self.bin.read(l) def __str__(self): @@ -236,6 +242,8 @@ class bin_stream_container(bin_stream): def readbs(self, l=1): if self.offset + l > self.l: raise IOError("not enough bytes") + if self.offset < 0: + raise IOError("Negative offset") self.offset += l return self.bin.virt.get(self.offset - l, self.offset) diff --git a/miasm2/core/graph.py b/miasm2/core/graph.py index f61d1e67..e385b044 100644 --- a/miasm2/core/graph.py +++ b/miasm2/core/graph.py @@ -143,6 +143,14 @@ class DiGraph(object): return [x for x in self.heads_iter()] def find_path(self, src, dst, cycles_count=0, done=None): + """ + Searches for paths from @src to @dst + @src: loc_key of basic block from which it should start + @dst: loc_key of basic block where it should stop + @cycles_count: maximum number of times a basic block can be processed + @done: dictionary of already processed loc_keys, it's value is number of times it was processed + @out: list of paths from @src to @dst + """ if done is None: done = {} if dst in done and done[dst] > cycles_count: @@ -157,6 +165,33 @@ class DiGraph(object): if path and path[0] == src: out.append(path + [dst]) return out + + def find_path_from_src(self, src, dst, cycles_count=0, done=None): + """ + This function does the same as function find_path. + But it searches the paths from src to dst, not vice versa like find_path. + This approach might be more efficient in some cases. + @src: loc_key of basic block from which it should start + @dst: loc_key of basic block where it should stop + @cycles_count: maximum number of times a basic block can be processed + @done: dictionary of already processed loc_keys, it's value is number of times it was processed + @out: list of paths from @src to @dst + """ + + if done is None: + done = {} + if src == dst: + return [[src]] + if src in done and done[src] > cycles_count: + return [[]] + out = [] + for node in self.successors(src): + done_n = dict(done) + done_n[src] = done_n.get(src, 0) + 1 + for path in self.find_path_from_src(node, dst, cycles_count, done_n): + if path and path[len(path)-1] == dst: + out.append([src] + path) + return out def nodeid(self, node): """ diff --git a/miasm2/ir/translators/z3_ir.py b/miasm2/ir/translators/z3_ir.py index 2572ac74..204ee976 100644 --- a/miasm2/ir/translators/z3_ir.py +++ b/miasm2/ir/translators/z3_ir.py @@ -219,7 +219,7 @@ class TranslatorZ3(Translator): ) elif expr.op == "<s": res = z3.If( - z3.SLT(args[0], args[1]), + args[0] < args[1], z3.BitVecVal(1, 1), z3.BitVecVal(0, 1) ) @@ -231,7 +231,7 @@ class TranslatorZ3(Translator): ) elif expr.op == "<=s": res = z3.If( - z3.SLE(args[0], args[1]), + args[0] <= args[1], z3.BitVecVal(1, 1), z3.BitVecVal(0, 1) ) diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py index b866a325..d2204d77 100644 --- a/test/arch/x86/arch.py +++ b/test/arch/x86/arch.py @@ -2020,7 +2020,7 @@ reg_tests = [ "F2AE"), (m32, "00000000 REPE SCASB", "F3AE"), - (m32, "00000000 REPE LODSD", + (m32, "00000000 REP LODSD", "F3ad"), (m32, "00000000 RET", @@ -3093,6 +3093,11 @@ reg_tests = [ (m32, "00000000 EMMS", "0f77"), + + (m64, "00000000 ENDBR64", + "f30f1efa"), + (m32, "00000000 ENDBR32", + "f30f1efb"), ] |