about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/arch/x86/arch.py44
-rw-r--r--miasm2/arch/x86/sem.py16
-rw-r--r--miasm2/core/bin_stream.py8
-rw-r--r--miasm2/core/graph.py35
-rw-r--r--miasm2/ir/translators/z3_ir.py4
-rw-r--r--test/arch/x86/arch.py7
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"),
 ]