about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/jitter/run_with_linuxenv.py2
-rw-r--r--miasm/arch/x86/arch.py19
-rw-r--r--miasm/arch/x86/sem.py42
-rw-r--r--miasm/expression/simplifications.py2
-rw-r--r--miasm/expression/simplifications_common.py32
-rw-r--r--miasm/jitter/emulatedsymbexec.py30
-rw-r--r--miasm/jitter/op_semantics.c35
-rw-r--r--miasm/jitter/vm_mngr.h6
-rw-r--r--miasm/os_dep/linux/environment.py76
-rw-r--r--test/arch/x86/arch.py20
-rw-r--r--test/expression/simplifications.py5
11 files changed, 255 insertions, 14 deletions
diff --git a/example/jitter/run_with_linuxenv.py b/example/jitter/run_with_linuxenv.py
index f981d2dd..9b17b172 100644
--- a/example/jitter/run_with_linuxenv.py
+++ b/example/jitter/run_with_linuxenv.py
@@ -78,7 +78,7 @@ elf_phdr_header = next(
 # Prepare the desired environment
 argv = [args.target.encode()] + [arg.encode() for arg in args.extra_args]
 if args.flags:
-    argv += ["-%s" % args.flags]
+    argv += [("-%s" % args.flags).encode()]
 envp = {b"PATH": b"/usr/local/bin", b"USER": linux_env.user_name}
 auxv = environment.AuxVec(
     elf_base_addr + elf_phdr_header.vaddr,
diff --git a/miasm/arch/x86/arch.py b/miasm/arch/x86/arch.py
index a82fac02..3053301a 100644
--- a/miasm/arch/x86/arch.py
+++ b/miasm/arch/x86/arch.py
@@ -3212,6 +3212,14 @@ class bs_mem(object):
         self.value = v
         return v != 0b11
 
+class bs_reg(object):
+    def encode(self):
+        return self.value == 0b11
+
+    def decode(self, v):
+        self.value = v
+        return v == 0b11
+
 d_imm64 = bs(l=0, fname="imm64")
 
 d_eax = bs(l=0, cls=(bs_eax, ), fname='eax')
@@ -3239,6 +3247,7 @@ msegoff = bs(l=16, cls=(bs_msegoff,), fname="mseg")
 movoff = bs(l=0, cls=(bs_movoff,), fname="off")
 mod = bs(l=2, fname="mod")
 mod_mem = bs(l=2, cls=(bs_mem,), fname="mod")
+mod_reg = bs(l=2, cls=(bs_reg,), fname="mod")
 
 rmreg = bs(l=3, cls=(x86_rm_reg, ), order =1, fname = "reg")
 reg = bs(l=3, cls=(x86_reg, ), order =1, fname = "reg")
@@ -3721,7 +3730,7 @@ addop("lgs", [bs8(0x0f), bs8(0xb5)] + rmmod(rmreg, rm_arg_x=rm_mem, modrm=mod_me
 addop("lgdt", [bs8(0x0f), bs8(0x01)] + rmmod(d2, modrm=mod_mem))
 addop("lidt", [bs8(0x0f), bs8(0x01)] + rmmod(d3, modrm=mod_mem))
 
-addop("lfence", [bs8(0x0f), bs8(0xae), bs8(0xe8)])
+addop("lfence", [bs8(0x0f), bs8(0xae), bs8(0xe8), no_xmm_pref])
 addop("mfence", [bs8(0x0f), bs8(0xae), bs8(0xf0)])
 addop("sfence", [bs8(0x0f), bs8(0xae), bs8(0xf8)])
 
@@ -4620,6 +4629,14 @@ addop("maskmovdqu", [bs8(0x0f), bs8(0xf7), pref_66] +
 
 addop("emms", [bs8(0x0f), bs8(0x77)])
 
+addop("incssp", [pref_f3, bs8(0x0f), bs8(0xae)] + rmmod(d5))
+addop("rdssp", [pref_f3, bs8(0x0f), bs8(0x1e)] + rmmod(d1, modrm=mod_reg))
+addop("saveprevssp", [pref_f3, bs8(0x0f), bs8(0x01), bs8(0xea)])
+addop("rstorssp", [pref_f3, bs8(0x0f), bs8(0x01)] + rmmod(d5, rm_arg_xmm, modrm=mod_mem))
+addop("wrss", [bs8(0x0f), bs8(0x38), bs8(0xf6)] + rmmod(rmreg, rm_arg), [rm_arg, rmreg])
+addop("wruss", [pref_66, bs8(0x0f), bs8(0x38), bs8(0xf5)] + rmmod(rmreg, rm_arg), [rm_arg, rmreg])
+addop("setssbsy", [pref_f3, bs8(0x0f), bs8(0x01), bs8(0xe8)])
+addop("clrssbsy", [pref_f3, bs8(0x0f), bs8(0xae)] + rmmod(d6, rm_arg_xmm))
 addop("endbr64", [pref_f3, bs8(0x0f), bs8(0x1e), bs8(0xfa)])
 addop("endbr32", [pref_f3, bs8(0x0f), bs8(0x1e), bs8(0xfb)])
 
diff --git a/miasm/arch/x86/sem.py b/miasm/arch/x86/sem.py
index b924c44f..1af9359e 100644
--- a/miasm/arch/x86/sem.py
+++ b/miasm/arch/x86/sem.py
@@ -4981,6 +4981,38 @@ def emms(ir, instr):
     # Implemented as a NOP
     return [], []
 
+def incssp(ir, instr, dst):
+    # Implemented as a NOP
+    return [], []
+
+def rdssp(ir, instr, dst):
+    # Implemented as a NOP
+    return [], []
+
+def saveprevssp(ir, instr):
+    # Implemented as a NOP
+    return [], []
+
+def rstorssp(ir, instr, dst):
+    # Implemented as a NOP
+    return [], []
+
+def wrss(ir, instr, src, dst):
+    # Implemented as a NOP
+    return [], []
+
+def wruss(ir, instr, src, dst):
+    # Implemented as a NOP
+    return [], []
+
+def setssbsy(ir, instr):
+    # Implemented as a NOP
+    return [], []
+
+def clrssbsy(ir, instr, dst):
+    # Implemented as a NOP
+    return [], []
+
 def endbr64(ir, instr):
     # Implemented as a NOP
     return [], []
@@ -5635,6 +5667,16 @@ mnemo_func = {'mov': mov,
               "movmskpd": movmskpd,
               "stmxcsr": stmxcsr,
               "ldmxcsr": ldmxcsr,
+
+              # CET (Control-flow Enforcement Technology)
+              "incssp": incssp,
+              "rdssp": rdssp,
+              "saveprevssp": saveprevssp,
+              "rstorssp": rstorssp,
+              "wrss": wrss,
+              "wruss": wruss,
+              "setssbsy": setssbsy,
+              "clrssbsy": clrssbsy,
               "endbr64": endbr64,
               "endbr32": endbr32,
               }
diff --git a/miasm/expression/simplifications.py b/miasm/expression/simplifications.py
index 585a9c6b..8f63ab91 100644
--- a/miasm/expression/simplifications.py
+++ b/miasm/expression/simplifications.py
@@ -58,7 +58,7 @@ class ExpressionSimplifier(object):
             simplifications_common.simp_test_signext_inf,
             simplifications_common.simp_test_zeroext_inf,
             simplifications_common.simp_cond_inf_eq_unsigned_zero,
-
+            simplifications_common.simp_compose_and_mask,
         ],
 
         m2_expr.ExprSlice: [
diff --git a/miasm/expression/simplifications_common.py b/miasm/expression/simplifications_common.py
index cda9c5e2..69d56997 100644
--- a/miasm/expression/simplifications_common.py
+++ b/miasm/expression/simplifications_common.py
@@ -607,7 +607,6 @@ def simp_compose(e_s, expr):
         return ExprCond(cond, arg1, arg2)
     return ExprCompose(*args)
 
-
 def simp_cond(_, expr):
     """
     Common simplifications on ExprCond.
@@ -1554,3 +1553,34 @@ def simp_add_multiple(_, expr):
     if len(out) == 1:
         return out[0]
     return ExprOp('+', *out)
+
+def simp_compose_and_mask(_, expr):
+    """
+    {X 0 8, Y 8 32} & 0xFF => zeroExt(X)
+    {X 0 8, Y 8 16, Z 16 32} & 0xFFFF => {X 0 8, Y 8 16, 0x0 16 32}
+    {X 0 8, 0x123456 8 32} & 0xFFFFFF => {X 0 8, 0x1234 8 24, 0x0 24 32}
+    """
+    if not expr.is_op('&'):
+        return expr
+    # handle the case where arg2 = arg1.mask
+    if len(expr.args) != 2:
+        return expr
+    arg1, arg2 = expr.args
+    if not arg1.is_compose():
+        return expr
+    if not arg2.is_int():
+        return expr
+    int2 = int(arg2)
+    if (int2 + 1) & int2 != 0:
+        return expr
+    mask_size = int2.bit_length() + 7 // 8
+    out = []
+    for offset, arg in arg1.iter_args():
+        if offset == mask_size:
+            return ExprCompose(*out).zeroExtend(expr.size)
+        elif mask_size > offset and mask_size < offset+arg.size and arg.is_int():
+            out.append(ExprSlice(arg, 0, mask_size-offset))
+            return ExprCompose(*out).zeroExtend(expr.size)
+        else:
+            out.append(arg)
+    return expr
diff --git a/miasm/jitter/emulatedsymbexec.py b/miasm/jitter/emulatedsymbexec.py
index 4355c0b9..35986fb9 100644
--- a/miasm/jitter/emulatedsymbexec.py
+++ b/miasm/jitter/emulatedsymbexec.py
@@ -19,6 +19,36 @@ class EmulatedSymbExec(SymbolicExecutionEngine):
             2: 0x00000209,
             3: 0x078bf9ff
         },
+        2: {
+            0: 0,
+            1: 0,
+            2: 0,
+            3: 0
+        },
+        4: {
+            0: 0,
+            1: 0,
+            2: 0,
+            3: 0
+        },
+        7: {
+            0: 0,
+            1: (1 << 0) | (1 << 3),
+            2: 0,
+            3: 0
+        },
+        0x80000000: {
+            0: 0x80000008,
+            1: 0,
+            2: 0,
+            3: 0
+        },
+        0x80000001: {
+            0: 0,
+            1: 0,
+            2: (1 << 0) | (1 << 8),
+            3: (1 << 11) | (1 << 29),
+        },
     }
 
     def __init__(self, cpu, vm, *args, **kwargs):
diff --git a/miasm/jitter/op_semantics.c b/miasm/jitter/op_semantics.c
index 79dcdcf4..6725ae64 100644
--- a/miasm/jitter/op_semantics.c
+++ b/miasm/jitter/op_semantics.c
@@ -380,6 +380,41 @@ unsigned int x86_cpuid(unsigned int a, unsigned int reg_num)
 			return 0x00000000;
 		}
 	}
+	// Extended Function CPUID Information
+	else if (a == 0x80000000){
+		switch(reg_num){
+		case 0:
+			// Pentium 4 Processor supporting Hyper-Threading
+			// Technology to Intel Xeon Processor 5100 Series
+			return 0x80000008;
+		case 1:
+			return 0x00000000;
+		case 2:
+			return 0x00000000;
+		case 3:
+			return 0x00000000;
+		}
+	}
+	else if (a == 0x80000001){
+		switch(reg_num){
+		case 0:
+			// Extended Processor Signature and Extended Feature
+			// Bits
+			return 0x00000000;
+		case 1:
+			return 0x00000000;
+		case 2:
+			return (/* LAHF-SAHF */ 1 << 0)
+			| (/* LZCNT */ 0 << 5)
+			| (/* PREFETCHW */ 1 << 8);
+		case 3:
+			return (/* SYSCALL/SYSRET */ 1 << 11)
+			| (/* Execute Disable Bit available */ 0 << 20)
+			| (/* 1-GByte pages available */ 0 << 26)
+			| (/* RDTSCP and IA32_TSC_AUX available */ 0 << 27)
+			| (/* Intel ® 64 Architecture available */ 1 << 29);
+		}
+	}
 	else{
 		fprintf(stderr, "WARNING not implemented x86_cpuid index %X!\n", a);
 		exit(EXIT_FAILURE);
diff --git a/miasm/jitter/vm_mngr.h b/miasm/jitter/vm_mngr.h
index 913d06f8..e7d0c123 100644
--- a/miasm/jitter/vm_mngr.h
+++ b/miasm/jitter/vm_mngr.h
@@ -35,14 +35,18 @@
 
 #ifdef __APPLE__
 #define __BYTE_ORDER __BYTE_ORDER__
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN '>'
+#define __LITTLE_ENDIAN '<'
+#endif
 #elif defined(__NetBSD__) || defined(__OpenBSD__)
 #define __BYTE_ORDER _BYTE_ORDER
 #define __BIG_ENDIAN _BIG_ENDIAN
 #define __LITTLE_ENDIAN _LITTLE_ENDIAN
 #elif defined(_WIN32) || defined(_WIN64)
+#define __BYTE_ORDER __LITTLE_ENDIAN
 #define __BIG_ENDIAN '>'
 #define __LITTLE_ENDIAN '<'
-#define __BYTE_ORDER __LITTLE_ENDIAN
 #endif
 
 
diff --git a/miasm/os_dep/linux/environment.py b/miasm/os_dep/linux/environment.py
index 8826abb7..42e45dd3 100644
--- a/miasm/os_dep/linux/environment.py
+++ b/miasm/os_dep/linux/environment.py
@@ -1,7 +1,9 @@
 from __future__ import print_function
 from collections import namedtuple
 import functools
+import logging
 import os
+import re
 import struct
 import termios
 
@@ -11,6 +13,8 @@ from miasm.core.interval import interval
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 
 
+REGEXP_T = type(re.compile(''))
+
 StatInfo = namedtuple("StatInfo", [
     "st_dev", "st_ino", "st_nlink", "st_mode", "st_uid", "st_gid", "st_rdev",
     "st_size", "st_blksize", "st_blocks", "st_atime", "st_atimensec",
@@ -21,6 +25,11 @@ StatFSInfo = namedtuple("StatFSInfo", [
     "f_ffree", "f_fsid", "f_namelen", "f_frsize", "f_flags", "f_spare",
 ])
 
+log = logging.getLogger("environment")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.WARNING)
 
 class FileDescriptor(object):
     """Stand for a file descriptor on a system
@@ -206,24 +215,73 @@ class FileSystem(object):
 
     def resolve_path(self, path, follow_link=True):
         """Resolve @path to the corresponding sandboxed path"""
+
+        # path_bytes is used for Python 2 / Python 3 compatibility
+        path_bytes = not isinstance(path, str)
+        path_sep = os.path.sep.encode() if path_bytes else os.path.sep
+
+        if path_bytes:
+            def _convert(subpath):
+                if not isinstance(subpath, str):
+                    return subpath
+                return subpath.encode()
+            def _convert_re(expr):
+                if isinstance(expr.pattern, str):
+                    try:
+                        return re.compile(
+                            expr.pattern.encode(),
+                            flags=expr.flags & ~re.UNICODE
+                        )
+                    except UnicodeEncodeError:
+                        # Will never match
+                        log.warning(
+                            'Cannot convert regexp to bytes %r %r',
+                            expr.pattern,
+                            expr.flags,
+                            exc_info=True,
+                        )
+                        return re.compile(b'$X')
+                return expr
+        else:
+            def _convert(subpath):
+                if not isinstance(subpath, str):
+                    return subpath.decode()
+                return subpath
+            def _convert_re(expr):
+                if not isinstance(expr.pattern, str):
+                    try:
+                        return re.compile(
+                            expr.pattern.decode(),
+                            flags=expr.flags & re.UNICODE
+                        )
+                    except UnicodeDecodeError:
+                        # Will never match
+                        log.warning(
+                            'Cannot convert regexp to str %r %r',
+                            expr.pattern,
+                            expr.flags,
+                            exc_info=True,
+                        )
+                        return re.compile('$X')
+                return expr
+
         # Remove '../', etc.
         path = os.path.normpath(path)
 
         # Passthrough
         for passthrough in self.passthrough:
-            if hasattr(passthrough, "match"):
-                if passthrough.match(path):
+            if isinstance(passthrough, REGEXP_T):
+                if _convert_re(passthrough).match(path):
                     return path
-            elif passthrough == path:
+            elif _convert(passthrough) == path:
                 return path
 
-        # Remove leading '/' if any (multiple '//' are handled by 'abspath'
-        if path.startswith(os.path.sep):
-            path = path[1:]
+        # Remove leading '/' if any
+        path = path.lstrip(path_sep)
 
-        base_path = os.path.abspath(self.base_path)
+        base_path = os.path.abspath(_convert(self.base_path))
         out_path = os.path.join(base_path, path)
-        assert out_path.startswith(base_path + os.path.sep)
+        assert out_path.startswith(base_path + path_sep)
         if os.path.islink(out_path):
             link_target = os.readlink(out_path)
             # Link can be absolute or relative -> absolute
@@ -463,7 +521,7 @@ class LinuxEnvironment(object):
         if not isinstance(fdesc, FileDescriptorDirectory):
             raise RuntimeError("Not implemented")
 
-        out = ""
+        out = b""
         # fdesc.listdir continues from where it stopped
         for name in fdesc.listdir():
             d_ino = 1 # Not the real one
diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py
index 202ecac5..68a14036 100644
--- a/test/arch/x86/arch.py
+++ b/test/arch/x86/arch.py
@@ -3097,6 +3097,26 @@ reg_tests = [
     (m32, "00000000    EMMS",
      "0f77"),
 
+    (m64, "00000000    INCSSP     RAX",
+     "f3480faee8"),
+    (m64, "00000000    INCSSP     EAX",
+     "f30faee8"),
+    (m64, "00000000    RDSSP      EAX",
+     "f30f1ec8"),
+    (m64, "00000000    RDSSP      RAX",
+     "f3480f1ec8"),
+    (m64, "00000000    SAVEPREVSSP",
+     "f30f01ea"),
+    (m64, "00000000    RSTORSSP   XMMWORD PTR [RAX]",
+     "f30f0128"),
+    (m64, "00000000    WRSS       QWORD PTR [0x1234], RDX",
+     "480f38f6142534120000"),
+    (m64, "00000000    WRUSS      DWORD PTR [EAX], EAX",
+     "67660f38f500"),
+    (m64, "00000000    SETSSBSY",
+     "f30f01e8"),
+    (m64, "00000000    CLRSSBSY   XMMWORD PTR [RAX]",
+     "f30fae30"),
     (m64, "00000000    ENDBR64",
      "f30f1efa"),
     (m32, "00000000    ENDBR32",
diff --git a/test/expression/simplifications.py b/test/expression/simplifications.py
index 1a22c43d..e0b666da 100644
--- a/test/expression/simplifications.py
+++ b/test/expression/simplifications.py
@@ -192,6 +192,11 @@ to_test = [(ExprInt(1, 32) - ExprInt(1, 32), ExprInt(0, 32)),
             ExprOp('&', a, ExprInt(0x0FFFFFFF, 32))),
            (ExprOp('<<', ExprOp('>>', a, ExprInt(0x4, 32)), ExprInt(0x4, 32)),
             ExprOp('&', a, ExprInt(0xFFFFFFF0, 32))),
+
+           (ExprCompose(ExprId("a", 8), ExprId("b", 24)) & ExprInt(0xFF, 32), ExprCompose(ExprId("a", 8), ExprInt(0x0, 24))),
+           (ExprCompose(ExprId("a", 8), ExprInt(0x12, 8), ExprId("b", 16)) & ExprInt(0xFFFF, 32), ExprCompose(ExprId("a", 8), ExprInt(0x12, 24))),
+           (ExprCompose(ExprId("a", 8), ExprInt(0x1234, 16), ExprId("b", 8)) & ExprInt(0xFFFF, 32), ExprCompose(ExprId("a", 8), ExprInt(0x34, 24))),
+
            (a[:32], a),
            (a[:8][:8], a[:8]),
            (a[:16][:8], a[:8]),