diff options
| -rw-r--r-- | example/jitter/run_with_linuxenv.py | 2 | ||||
| -rw-r--r-- | miasm/arch/x86/arch.py | 19 | ||||
| -rw-r--r-- | miasm/arch/x86/sem.py | 42 | ||||
| -rw-r--r-- | miasm/expression/simplifications.py | 2 | ||||
| -rw-r--r-- | miasm/expression/simplifications_common.py | 32 | ||||
| -rw-r--r-- | miasm/jitter/emulatedsymbexec.py | 30 | ||||
| -rw-r--r-- | miasm/jitter/op_semantics.c | 35 | ||||
| -rw-r--r-- | miasm/jitter/vm_mngr.h | 6 | ||||
| -rw-r--r-- | miasm/os_dep/linux/environment.py | 76 | ||||
| -rw-r--r-- | test/arch/x86/arch.py | 20 | ||||
| -rw-r--r-- | test/expression/simplifications.py | 5 |
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]), |