diff options
31 files changed, 348 insertions, 57 deletions
diff --git a/.codespell_ignore b/.codespell_ignore index 8eab9f6f..06b8df87 100644 --- a/.codespell_ignore +++ b/.codespell_ignore @@ -5,3 +5,5 @@ mye iff nto rela +daa +od diff --git a/example/elfesteem/test_pe.py b/example/elfesteem/test_pe.py deleted file mode 100644 index 543cbea5..00000000 --- a/example/elfesteem/test_pe.py +++ /dev/null @@ -1,31 +0,0 @@ -#! /usr/bin/env python - -import miasm.loader.pe as pe -from miasm.loader.pe_init import PE -import rlcompleter -import readline -import pdb -import sys -from pprint import pprint as pp -readline.parse_and_bind("tab: complete") - - -e_ = PE() -mysh = b"\xc3" -s_text = e_.SHList.add_section( - name="text", addr=0x1000, rawsize=0x1000, data=mysh) -e_.Opthdr.AddressOfEntryPoint = s_text.addr -new_dll = [({"name": "kernel32.dll", - "firstthunk": s_text.addr + 0x100}, - ["CreateFileA", "SetFilePointer", "WriteFile", "CloseHandle"] - ), - ({"name": "USER32.dll", - "firstthunk": None}, - ["SetDlgItemInt", "GetMenu", "HideCaret"] - ) - ] -e_.DirImport.add_dlldesc(new_dll) - -s_myimp = e_.SHList.add_section(name="myimp", rawsize=0x1000) -e_.DirImport.set_rva(s_myimp.addr) -open('uu.bin', 'wb').write(bytes(e_)) 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/example/loader/build_pe.py b/example/loader/build_pe.py new file mode 100644 index 00000000..6baeb645 --- /dev/null +++ b/example/loader/build_pe.py @@ -0,0 +1,33 @@ +#! /usr/bin/env python + +from miasm.loader.pe_init import PE + +# Build an empty PE object +pe_object = PE() + +# Add a section with a just a "RET" +payload = b"\xc3" +s_text = pe_object.SHList.add_section( + name="text", addr=0x1000, rawsize=0x1000, data=payload +) + +# Set the entry point on this instruction +pe_object.Opthdr.AddressOfEntryPoint = s_text.addr + +# Add some imports +new_dll = [ + ({"name": "kernel32.dll", + "firstthunk": s_text.addr + 0x100}, + ["CreateFileA", "SetFilePointer", "WriteFile", "CloseHandle"] + ), + ({"name": "USER32.dll", + "firstthunk": None}, + ["SetDlgItemInt", "GetMenu", "HideCaret"] + ) +] +pe_object.DirImport.add_dlldesc(new_dll) +s_myimp = pe_object.SHList.add_section(name="myimp", rawsize=0x1000) +pe_object.DirImport.set_rva(s_myimp.addr) + +# Rebuild the PE and dump it to a file +open('fresh_pe.exe', 'wb').write(bytes(pe_object)) diff --git a/example/elfesteem/minidump_to_pe.py b/example/loader/minidump_to_pe.py index 30a95325..30a95325 100644 --- a/example/elfesteem/minidump_to_pe.py +++ b/example/loader/minidump_to_pe.py diff --git a/miasm/analysis/data_flow.py b/miasm/analysis/data_flow.py index c86bece5..be0e4528 100644 --- a/miasm/analysis/data_flow.py +++ b/miasm/analysis/data_flow.py @@ -185,7 +185,7 @@ class DiGraphDefUse(DiGraph): self._edge_attr[(src, dst)] = edge_label def add_data_edge(self, src, dst): - """Adds an edge representing a data dependencie + """Adds an edge representing a data dependency and sets the label accordingly""" self.add_uniq_labeled_edge(src, dst, ATTR_DEP) diff --git a/miasm/analysis/depgraph.py b/miasm/analysis/depgraph.py index 219a32ee..80e94c7f 100644 --- a/miasm/analysis/depgraph.py +++ b/miasm/analysis/depgraph.py @@ -357,7 +357,7 @@ class DependencyResultImplicit(DependencyResult): conds = z3.Or(*out) else: # Ex: expr: lblgen1, expected: 0x1234 - # -> Avoid unconsistent solution lblgen1 = 0x1234 + # -> Avoid inconsistent solution lblgen1 = 0x1234 conds = translator.from_expr(self.unsat_expr) return conds diff --git a/miasm/arch/mep/arch.py b/miasm/arch/mep/arch.py index 171f5fab..8a9f60fd 100644 --- a/miasm/arch/mep/arch.py +++ b/miasm/arch/mep/arch.py @@ -293,7 +293,7 @@ class mn_mep(cls_mn): """ # Define variables that stores information used to disassemble & assemble - # Notes: - theses variables are mandatory + # Notes: - these variables are mandatory # - they could be moved to the cls_mn class num = 0 # holds the number of mnemonics 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/core/graph.py b/miasm/core/graph.py index f585379b..01f580a3 100644 --- a/miasm/core/graph.py +++ b/miasm/core/graph.py @@ -978,7 +978,7 @@ class MatchGraph(DiGraph): """ # Partial solution: nodes corrects, edges between these nodes corrects # A partial solution is a dictionary MatchGraphJoker -> @graph's node - todo = list() # Dictionnaries containing partial solution + todo = list() # Dictionaries containing partial solution done = list() # Already computed partial solutions # Elect first candidates diff --git a/miasm/expression/expression.py b/miasm/expression/expression.py index 6c54b9a2..6f171d93 100644 --- a/miasm/expression/expression.py +++ b/miasm/expression/expression.py @@ -279,6 +279,11 @@ class Expr(object): def __ne__(self, other): return not self.__eq__(other) + def __lt__(self, other): + weight1 = EXPR_ORDER_DICT[self.__class__] + weight2 = EXPR_ORDER_DICT[other.__class__] + return weight1 < weight2 + def __add__(self, other): return ExprOp('+', self, other) 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/ir/ir.py b/miasm/ir/ir.py index eb9857b1..372b712a 100644 --- a/miasm/ir/ir.py +++ b/miasm/ir/ir.py @@ -831,7 +831,7 @@ class IntermediateRepresentation(object): def add_block(self, block, gen_pc_updt=False): """ DEPRECATED function - Use add_block instead of add_block + Use add_asmblock_to_ircfg instead of add_block """ warnings.warn("""DEPRECATION WARNING ircfg is now out of IntermediateRepresentation @@ -844,7 +844,7 @@ class IntermediateRepresentation(object): def add_bloc(self, block, gen_pc_updt=False): """ DEPRECATED function - Use add_block instead of add_block + Use add_asmblock_to_ircfg instead of add_bloc """ self.add_block(block, gen_pc_updt) diff --git a/miasm/jitter/codegen.py b/miasm/jitter/codegen.py index 792feae0..abbf65d2 100644 --- a/miasm/jitter/codegen.py +++ b/miasm/jitter/codegen.py @@ -187,7 +187,7 @@ class CGen(object): def add_local_var(self, dst_var, dst_index, expr): """ - Add local variable used to store temporay result + Add local variable used to store temporary result @dst_var: dictionary of Expr -> local_var_expr @dst_index : dictionary of size -> local var count @expr: Expression source diff --git a/miasm/jitter/emulatedsymbexec.py b/miasm/jitter/emulatedsymbexec.py index cf5e3036..aacfba9f 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/llvmconvert.py b/miasm/jitter/llvmconvert.py index d0e0407b..c4467411 100644 --- a/miasm/jitter/llvmconvert.py +++ b/miasm/jitter/llvmconvert.py @@ -1720,7 +1720,7 @@ class LLVMFunction(object): self.gen_bad_block(asmblock) return - # Create basic blocks (for label branchs) + # Create basic blocks (for label branches) entry_bbl, builder = self.entry_bbl, self.builder for instr in asmblock.lines: lbl = self.llvm_context.ir_arch.loc_db.get_or_create_offset_location(instr.offset) 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..35a648a5 100644 --- a/miasm/jitter/vm_mngr.h +++ b/miasm/jitter/vm_mngr.h @@ -35,14 +35,16 @@ #ifdef __APPLE__ #define __BYTE_ORDER __BYTE_ORDER__ +#define __BIG_ENDIAN BIG_ENDIAN +#define __LITTLE_ENDIAN LITTLE_ENDIAN #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/loader/elf_init.py b/miasm/loader/elf_init.py index 36c4cfaf..786d030b 100644 --- a/miasm/loader/elf_init.py +++ b/miasm/loader/elf_init.py @@ -104,6 +104,8 @@ class WRel64(StructWrapper): wrapped._fields.append(("type", "u32")) def get_sym(self): + if not hasattr(self.parent.linksection, 'symtab'): + return None return self.parent.linksection.symtab[self.cstr.info >> 32].name def get_type(self): 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/miasm/os_dep/linux/syscall.py b/miasm/os_dep/linux/syscall.py index 1edf72c4..353d61cf 100644 --- a/miasm/os_dep/linux/syscall.py +++ b/miasm/os_dep/linux/syscall.py @@ -6,6 +6,7 @@ import struct import termios from miasm.jitter.csts import EXCEPT_PRIV_INSN, EXCEPT_INT_XX +from miasm.core.utils import pck64 log = logging.getLogger('syscalls') hnd = logging.StreamHandler() @@ -347,6 +348,18 @@ def sys_x86_64_arch_prctl(jitter, linux_env): 0x1002: "ARCH_SET_FS", 0x1003: "ARCH_GET_FS", 0x1004: "ARCH_GET_GS", + 0x1011: "ARCH_GET_CPUID", + 0x1012: "ARCH_SET_CPUID", + 0x2001: "ARCH_MAP_VDSO_X32", + 0x2002: "ARCH_MAP_VDSO_32", + 0x2003: "ARCH_MAP_VDSO_64", + 0x3001: "ARCH_CET_STATUS", + 0x3002: "ARCH_CET_DISABLE", + 0x3003: "ARCH_CET_LOCK", + 0x3004: "ARCH_CET_EXEC", + 0x3005: "ARCH_CET_ALLOC_SHSTK", + 0x3006: "ARCH_CET_PUSH_SHSTK", + 0x3007: "ARCH_CET_LEGACY_BITMAP", } code = jitter.cpu.RDI rcode = code_name[code] @@ -355,6 +368,9 @@ def sys_x86_64_arch_prctl(jitter, linux_env): if code == 0x1002: jitter.cpu.set_segm_base(jitter.cpu.FS, addr) + elif code == 0x3001: + # CET status (disabled) + jitter.cpu.set_mem(addr, pck64(0)) else: raise RuntimeError("Not implemented") jitter.cpu.RAX = 0 diff --git a/optional_requirements.txt b/optional_requirements.txt index d6a28948..88d09170 100644 --- a/optional_requirements.txt +++ b/optional_requirements.txt @@ -1,2 +1,3 @@ pycparser z3-solver==4.5.1.0 +llvmlite==0.26.0 diff --git a/requirements.txt b/requirements.txt index 135ca071..eb542916 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ pyparsing future -llvmlite==0.26.0 diff --git a/setup.py b/setup.py index 2767c33d..e8ea7b3a 100755..100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,7 @@ from __future__ import print_function from distutils.core import setup, Extension from distutils.util import get_platform +from distutils.sysconfig import get_python_lib, get_config_vars import io import os import platform @@ -10,6 +11,13 @@ from shutil import copy2 import sys is_win = platform.system() == "Windows" +is_mac = platform.system() == "Darwin" + +def set_extension_compile_args(extension): + rel_lib_path = extension.name.replace('.', '/') + abs_lib_path = os.path.join(get_python_lib(), rel_lib_path) + lib_name = abs_lib_path + '.so' + extension.extra_link_args = [ '-Wl,-install_name,' + lib_name] def buil_all(): packages=[ @@ -139,6 +147,11 @@ def buil_all(): # Force setuptools to use whatever msvc version installed os.environ['MSSdk'] = '1' os.environ['DISTUTILS_USE_SDK'] = '1' + elif is_mac: + for extension in ext_modules_all: + set_extension_compile_args(extension) + cfg_vars = get_config_vars() + cfg_vars['LDSHARED'] = cfg_vars['LDSHARED'].replace('-bundle', '-dynamiclib') print("building") build_ok = False diff --git a/test/arch/mep/asm/test_asm.py b/test/arch/mep/asm/test_asm.py index 7762669a..e8b8afb9 100644 --- a/test/arch/mep/asm/test_asm.py +++ b/test/arch/mep/asm/test_asm.py @@ -22,12 +22,12 @@ class TestMisc(object): for mn_str, mn_hex in unit_tests: print("-" * 49) # Tests separation - # Dissassemble + # Disassemble mn_bin = decode_hex(mn_hex) mn = mn_mep.dis(mn_bin, "b") print("dis: %s -> %s" % (mn_hex.rjust(20), str(mn).rjust(20))) - assert(str(mn) == mn_str) # dissassemble assertion + assert(str(mn) == mn_str) # disassemble assertion # Assemble and return all possible candidates instr = mn_mep.fromstring(str(mn), "b") diff --git a/test/arch/mep/asm/test_major_opcode_4.py b/test/arch/mep/asm/test_major_opcode_4.py index a6f57ac2..fd466b62 100644 --- a/test/arch/mep/asm/test_major_opcode_4.py +++ b/test/arch/mep/asm/test_major_opcode_4.py @@ -107,7 +107,7 @@ class TestMajor4(object): check_instruction("LBU $4, 0x22($TP)", "4ca2", multi=2) # Note: the following instruction can not be easily manipulated due to # expressions simplifications performed by miasm at assembly and - # dissassembly, i.e. ExprMem($TP + 0) is simplified into ExprMem($TP) + # disassembly, i.e. ExprMem($TP + 0) is simplified into ExprMem($TP) #check_instruction("LBU $6, 0x0($TP)", "4e80", multi=2) check_instruction("LBU $7, 0x3C($TP)", "4fbc", multi=2) check_instruction("LBU $2, 0x4($TP)", "4a84", multi=2) 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]), diff --git a/test/test_all.py b/test/test_all.py index 6d4ee0a5..ce223211 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -697,6 +697,18 @@ for script in [["basic_op.py"], ]: testset += ExampleExpression(script) +## Loader +class ExampleLoader(Example): + """Loader examples specificities: + - script path begins with "loader/" + """ + example_dir = "loader" + + +testset += ExampleLoader(["build_pe.py"], products=["fresh_pe.exe"]) +# A sample is required, so "minidump_to_pe.py" is disabled for now + + ## Symbolic Execution class ExampleSymbolExec(Example): """Symbol Exec examples specificities: |