about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.codespell_ignore1
-rw-r--r--README.md7
-rw-r--r--miasm/analysis/gdbserver.py4
-rw-r--r--miasm/arch/arm/arch.py58
-rw-r--r--miasm/arch/arm/regs.py65
-rw-r--r--miasm/arch/arm/sem.py242
-rw-r--r--miasm/arch/mep/sem.py2
-rw-r--r--miasm/arch/mips32/sem.py2
-rw-r--r--miasm/arch/ppc/sem.py18
-rw-r--r--miasm/arch/x86/arch.py2
-rw-r--r--miasm/expression/expression.py4
-rw-r--r--miasm/expression/simplifications_common.py7
-rw-r--r--miasm/ir/ir.py2
-rw-r--r--miasm/ir/symbexec.py2
-rw-r--r--miasm/ir/translators/z3_ir.py2
-rw-r--r--miasm/jitter/bn.h2
-rw-r--r--miasm/jitter/jitload.py11
-rw-r--r--miasm/loader/pe.py6
-rw-r--r--miasm/os_dep/common.py8
-rw-r--r--miasm/os_dep/linux/syscall.py2
-rw-r--r--miasm/os_dep/win_api_x86_32.py154
-rw-r--r--test/arch/arm/arch.py4
-rw-r--r--test/utils/testset.py2
23 files changed, 500 insertions, 107 deletions
diff --git a/.codespell_ignore b/.codespell_ignore
index a7423acd..5e7feec6 100644
--- a/.codespell_ignore
+++ b/.codespell_ignore
@@ -10,3 +10,4 @@ daa
 od
 blocs
 fpr
+seh
diff --git a/README.md b/README.md
index a4c55a20..f80d02a3 100644
--- a/README.md
+++ b/README.md
@@ -616,10 +616,3 @@ Books
 
 * [Practical Reverse Engineering: X86, X64, Arm, Windows Kernel, Reversing Tools, and Obfuscation](http://eu.wiley.com/WileyCDA/WileyTitle/productCd-1118787315,subjectCd-CSJ0.html): Introduction to Miasm (Chapter 5 "Obfuscation")
 * [BlackHat Python - Appendix](https://github.com/oreilly-japan/black-hat-python-jp-support/tree/master/appendix-A): Japan security book's samples
-
-
-Misc
-====
-
-* Man, does miasm has a link with rr0d?
-* Yes! crappy code and uggly documentation.
diff --git a/miasm/analysis/gdbserver.py b/miasm/analysis/gdbserver.py
index ac58cdad..b45e9f35 100644
--- a/miasm/analysis/gdbserver.py
+++ b/miasm/analysis/gdbserver.py
@@ -251,8 +251,8 @@ class GdbServer(object):
                     else:
                         raise NotImplementedError("Unknown Except")
                 elif isinstance(ret, debugging.DebugBreakpointTerminate):
-                    # Connexion should close, but keep it running as a TRAP
-                    # The connexion will be close on instance destruction
+                    # Connection should close, but keep it running as a TRAP
+                    # The connection will be close on instance destruction
                     print(ret)
                     self.status = b"S05"
                     self.send_queue.append(b"S05")
diff --git a/miasm/arch/arm/arch.py b/miasm/arch/arm/arch.py
index fbccd329..2b4476f0 100644
--- a/miasm/arch/arm/arch.py
+++ b/miasm/arch/arm/arch.py
@@ -1660,6 +1660,33 @@ bs_mr_name = bs_name(l=1, name=mr_name)
 bs_addi = bs(l=1, fname="add_imm")
 bs_rw = bs_mod_name(l=1, fname='rw', mn_mod=['W', ''])
 
+class armt_barrier_option(reg_noarg, arm_arg):
+    reg_info = barrier_info
+    parser = reg_info.parser
+
+    def decode(self, v):
+        v = v & self.lmask
+        if v not in self.reg_info.dct_expr:
+            return False
+        self.expr = self.reg_info.dct_expr[v]
+        return True
+
+    def encode(self):
+        if not self.expr in self.reg_info.dct_expr_inv:
+            log.debug("cannot encode reg %r", self.expr)
+            return False
+        self.value = self.reg_info.dct_expr_inv[self.expr]
+        if self.value > self.lmask:
+            log.debug("cannot encode field value %x %x",
+                      self.value, self.lmask)
+            return False
+        return True
+
+    def check_fbits(self, v):
+        return v & self.fmask == self.fbits
+
+barrier_option = bs(l=4, cls=(armt_barrier_option,))
+
 armop("mul", [bs('000000'), bs('0'), scc, rd, bs('0000'), rs, bs('1001'), rm], [rd, rm, rs])
 armop("umull", [bs('000010'), bs('0'), scc, rd, rdl, rs, bs('1001'), rm], [rdl, rd, rm, rs])
 armop("umlal", [bs('000010'), bs('1'), scc, rd, rdl, rs, bs('1001'), rm], [rdl, rd, rm, rs])
@@ -1709,7 +1736,8 @@ armop("rev16", [bs('01101011'), bs('1111'), rd, bs('1111'), bs('1011'), rm])
 
 armop("pld", [bs8(0xF5), bs_addi, bs_rw, bs('01'), mem_rn_imm, bs('1111'), imm12_off])
 
-armop("isb", [bs8(0xF5), bs8(0x7F), bs8(0xF0), bs8(0x6F)])
+armop("dsb", [bs('111101010111'), bs('1111'), bs('1111'), bs('0000'), bs('0100'), barrier_option])
+armop("isb", [bs('111101010111'), bs('1111'), bs('1111'), bs('0000'), bs('0110'), barrier_option])
 armop("nop", [bs8(0xE3), bs8(0x20), bs8(0xF0), bs8(0)])
 
 class arm_widthm1(arm_imm, m_arg):
@@ -2326,7 +2354,6 @@ class arm_sp(arm_reg):
     reg_info = gpregs_sp
     parser = reg_info.parser
 
-
 off5 = bs(l=5, cls=(arm_imm,), fname="off")
 off3 = bs(l=3, cls=(arm_imm,), fname="off")
 off8 = bs(l=8, cls=(arm_imm,), fname="off")
@@ -3230,33 +3257,6 @@ bs_deref_reg_reg = bs(l=4, cls=(armt_deref_reg_reg,))
 bs_deref_reg_reg_lsl_1 = bs(l=4, cls=(armt_deref_reg_reg_lsl_1,))
 
 
-class armt_barrier_option(reg_noarg, arm_arg):
-    reg_info = barrier_info
-    parser = reg_info.parser
-
-    def decode(self, v):
-        v = v & self.lmask
-        if v not in self.reg_info.dct_expr:
-            return False
-        self.expr = self.reg_info.dct_expr[v]
-        return True
-
-    def encode(self):
-        if not self.expr in self.reg_info.dct_expr_inv:
-            log.debug("cannot encode reg %r", self.expr)
-            return False
-        self.value = self.reg_info.dct_expr_inv[self.expr]
-        if self.value > self.lmask:
-            log.debug("cannot encode field value %x %x",
-                      self.value, self.lmask)
-            return False
-        return True
-
-    def check_fbits(self, v):
-        return v & self.fmask == self.fbits
-
-barrier_option = bs(l=4, cls=(armt_barrier_option,))
-
 armtop("adc", [bs('11110'),  imm12_1, bs('0'), bs('1010'), scc, rn_nosppc, bs('0'), imm12_3, rd_nosppc, imm12_8])
 armtop("adc", [bs('11101'),  bs('01'), bs('1010'), scc, rn_nosppc, bs('0'), imm5_3, rd_nosppc, imm5_2, imm_stype, rm_sh])
 armtop("bl", [bs('11110'), tsign, timm10H, bs('11'), tj1, bs('1'), tj2, timm11L])
diff --git a/miasm/arch/arm/regs.py b/miasm/arch/arm/regs.py
index 63caada3..2b24b0d5 100644
--- a/miasm/arch/arm/regs.py
+++ b/miasm/arch/arm/regs.py
@@ -2,7 +2,7 @@
 
 from builtins import range
 from miasm.expression.expression import *
-
+from miasm.core.cpu import gen_reg, gen_regs
 
 # GP
 
@@ -111,4 +111,67 @@ regs_init = {}
 for i, r in enumerate(all_regs_ids):
     regs_init[r] = all_regs_ids_init[i]
 
+coproc_reg_str = [
+                    "MIDR", "CTR", "TCMTR", "TLBTR", "MIDR", "MPIDR", "REVIDR",
+                    "ID_PFR0", "ID_PFR1", "ID_DFR0", "ID_AFR0", "ID_MMFR0", "ID_MMFR1", "ID_MMFR2", "ID_MMFR3",
+                    "ID_ISAR0", "ID_ISAR1", "ID_ISAR2", "ID_ISAR3", "ID_ISAR4", "ID_ISAR5",
+                    "CCSIDR", "CLIDR", "AIDR",
+                    "CSSELR",
+                    "VPIDR", "VMPIDR",
+                    "SCTLR", "ACTLR", "CPACR",
+                    "SCR", "SDER", "NSACR",
+                    "HSCTLR", "HACTLR",
+                    "HCR", "HDCR", "HCPTR", "HSTR", "HACR",
+                    "TTBR0", "TTBR1", "TTBCR",
+                    "HTCR", "VTCR",
+                    "DACR",
+                    "DFSR", "IFSR",
+                    "ADFSR", "AIFSR",
+                    "HADFSR", "HAIFSR",
+                    "HSR",
+                    "DFAR", "IFAR",
+                    "HDFAR", "HIFAR", "HPFAR",
+                    "ICIALLUIS", "BPIALLIS",
+                    "PAR",
+                    "ICIALLU", "ICIMVAU", "CP15ISB", "BPIALL", "BPIMVA",
+                    "DCIMVAC", "DCISW",
+                    "ATS1CPR", "ATS1CPW", "ATS1CUR", "ATS1CUW", "ATS12NSOPR", "ATS12NSOPW", "ATS12NSOUR", "ATS12NSOUW",
+                    "DCCMVAC", "DCCSW", "CP15DSB", "CP15DMB",
+                    "DCCMVAU",
+                    "DCCIMVAC", "DCCISW",
+                    "ATS1HR", "ATS1HW",
+                    "TLBIALLIS", "TLBIMVAIS", "TLBIASIDIS", "TLBIMVAAIS",
+                    "ITLBIALL", "ITLBIMVA", "ITLBIASID",
+                    "DTLBIALL", "DTLBIMVA", "DTLBIASID",
+                    "TLBIALL", "TLBIMVA", "TLBIASID", "TLBIMVAA",
+                    "TLBIALLHIS", "TLBIMVAHIS", "TLBIALLNSNHIS",
+                    "TLBIALLH", "TLBIMVAH", "TLBIALLNSNH",
+                    "PMCR", "PMCNTENSET", "PMCNTENCLR", "PMOVSR", "PMSWINC", "PMSELR", "PMCEID0", "PMCEID1",
+                    "PMCCNTR", "PMXEVTYPER", "PMXEVCNTR",
+                    "PMUSERENR", "PMINTENSET", "PMINTENCLR", "PMOVSSET", 
+                    "PRRR", "NMRR",
+                    "AMAIR0", "AMAIR1",
+                    "HMAIR0", "HMAIR1",
+                    "HAMAIR0", "HAMAIR1",
+                    "VBAR", "MVBAR",
+                    "ISR",
+                    "HVBAR",
+                    "FCSEIDR", "CONTEXTIDR", "TPIDRURW", "TPIDRURO", "TPIDRPRW",
+                    "HTPIDR",
+                    "CNTFRQ",
+                    "CNTKCTL",
+                    "CNTP_TVAL", "CNTP_CTL",
+                    "CNTV_TVAL", "CNTV_CTL",
+                    "CNTHCTL",
+                    "CNTHP_TVAL", "CNTHP_CTL"
+                ]
+coproc_reg_expr, coproc_reg_init, coproc_reg_info = gen_regs(coproc_reg_str, globals(), 32)
+
+all_regs_ids = all_regs_ids + coproc_reg_expr
+all_regs_ids_byname.update(dict([(x.name, x) for x in coproc_reg_expr]))
+all_regs_ids_init = all_regs_ids_init + coproc_reg_init
+
+for i, r in enumerate(coproc_reg_expr):
+    regs_init[r] = coproc_reg_init[i]
+
 regs_flt_expr = []
diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py
index 569a9a23..7d72b956 100644
--- a/miasm/arch/arm/sem.py
+++ b/miasm/arch/arm/sem.py
@@ -8,6 +8,219 @@ from miasm.arch.arm.regs import *
 
 from miasm.jitter.csts import EXCEPT_DIV_BY_ZERO, EXCEPT_INT_XX
 
+coproc_reg_dict = {
+        ("p15", "c0", 0, "c0", 0): MIDR,
+        ("p15", "c0", 0, "c0", 1): CTR,
+        ("p15", "c0", 0, "c0", 2): TCMTR,
+        ("p15", "c0", 0, "c0", 3): TLBTR,
+        ("p15", "c0", 0, "c0", 4): MIDR,
+        ("p15", "c0", 0, "c0", 5): MPIDR,
+        ("p15", "c0", 0, "c0", 6): REVIDR,
+        ("p15", "c0", 0, "c0", 7): MIDR,
+
+        ("p15", "c0", 0, "c1", 0): ID_PFR0,
+        ("p15", "c0", 0, "c1", 1): ID_PFR1,
+        ("p15", "c0", 0, "c1", 2): ID_DFR0,
+        ("p15", "c0", 0, "c1", 3): ID_AFR0,
+        ("p15", "c0", 0, "c1", 4): ID_MMFR0,
+        ("p15", "c0", 0, "c1", 5): ID_MMFR1,
+        ("p15", "c0", 0, "c1", 6): ID_MMFR2,
+        ("p15", "c0", 0, "c1", 7): ID_MMFR3,
+
+        ("p15", "c0", 0, "c2", 0): ID_ISAR0,
+        ("p15", "c0", 0, "c2", 1): ID_ISAR1,
+        ("p15", "c0", 0, "c2", 2): ID_ISAR2,
+        ("p15", "c0", 0, "c2", 3): ID_ISAR3,
+        ("p15", "c0", 0, "c2", 4): ID_ISAR4,
+        ("p15", "c0", 0, "c2", 5): ID_ISAR5,
+
+        ("p15", "c0", 1, "c0", 0): CCSIDR,
+        ("p15", "c0", 1, "c0", 1): CLIDR,
+        ("p15", "c0", 1, "c0", 7): AIDR,
+
+        ("p15", "c0", 2, "c0", 0): CSSELR,
+
+        ("p15", "c0", 4, "c0", 0): VPIDR,
+        ("p15", "c0", 4, "c0", 5): VMPIDR,
+
+        ("p15", "c1", 0, "c0", 0): SCTLR,
+        ("p15", "c1", 0, "c0", 1): ACTLR,
+        ("p15", "c1", 0, "c0", 2): CPACR,
+
+        ("p15", "c1", 0, "c1", 0): SCR,
+        ("p15", "c1", 0, "c1", 1): SDER,
+        ("p15", "c1", 0, "c1", 2): NSACR,
+
+        ("p15", "c1", 4, "c0", 0): HSCTLR,
+        ("p15", "c1", 4, "c0", 1): HACTLR,
+
+        ("p15", "c1", 4, "c1", 0): HCR,
+        ("p15", "c1", 4, "c1", 1): HDCR,
+        ("p15", "c1", 4, "c1", 2): HCPTR,
+        ("p15", "c1", 4, "c1", 3): HSTR,
+        ("p15", "c1", 4, "c1", 7): HACR,
+
+        # TODO: TTBRO/TTBR1 64-bit
+        ("p15", "c2", 0, "c0", 0): TTBR0,
+        ("p15", "c2", 0, "c0", 1): TTBR1,
+        ("p15", "c2", 0, "c0", 2): TTBCR,
+
+        ("p15", "c2", 4, "c0", 2): HTCR,
+
+        ("p15", "c2", 4, "c1", 2): VTCR,
+
+        # TODO: HTTBR, VTTBR
+
+        ("p15", "c3", 0, "c0", 0): DACR,
+
+        ("p15", "c5", 0, "c0", 0): DFSR,
+        ("p15", "c5", 0, "c0", 1): IFSR,
+
+        ("p15", "c5", 0, "c1", 0): ADFSR,
+        ("p15", "c5", 0, "c1", 1): AIFSR,
+
+        ("p15", "c5", 4, "c1", 0): HADFSR,
+        ("p15", "c5", 4, "c1", 1): HAIFSR,
+
+        ("p15", "c5", 4, "c2", 0): HSR,
+
+        ("p15", "c6", 0, "c1", 0): DFAR,
+        ("p15", "c6", 0, "c1", 2): IFAR,
+
+        ("p15", "c6", 4, "c0", 0): HDFAR,
+        ("p15", "c6", 4, "c0", 2): HIFAR,
+        ("p15", "c6", 4, "c0", 4): HPFAR,
+
+        ("p15", "c7", 0, "c1", 0): ICIALLUIS,
+        ("p15", "c7", 0, "c1", 6): BPIALLIS,
+
+        ("p15", "c7", 0, "c4", 0): PAR,
+
+        # TODO: PAR 64-bit
+
+        ("p15", "c7", 0, "c5", 0): ICIALLU,
+        ("p15", "c7", 0, "c5", 1): ICIMVAU,
+        ("p15", "c7", 0, "c5", 4): CP15ISB,
+        ("p15", "c7", 0, "c5", 6): BPIALL,
+        ("p15", "c7", 0, "c5", 7): BPIMVA,
+
+        ("p15", "c7", 0, "c6", 1): DCIMVAC,
+        ("p15", "c7", 0, "c6", 2): DCISW,
+
+        ("p15", "c7", 0, "c8", 0): ATS1CPR,
+        ("p15", "c7", 0, "c8", 1): ATS1CPW,
+        ("p15", "c7", 0, "c8", 2): ATS1CUR,
+        ("p15", "c7", 0, "c8", 3): ATS1CUW,
+        ("p15", "c7", 0, "c8", 4): ATS12NSOPR,
+        ("p15", "c7", 0, "c8", 5): ATS12NSOPW,
+        ("p15", "c7", 0, "c8", 6): ATS12NSOUR,
+        ("p15", "c7", 0, "c8", 7): ATS12NSOUW,
+
+        ("p15", "c7", 0, "c10", 1): DCCMVAC,
+        ("p15", "c7", 0, "c10", 2): DCCSW,
+        ("p15", "c7", 0, "c10", 4): CP15DSB,
+        ("p15", "c7", 0, "c10", 5): CP15DMB,
+
+        ("p15", "c7", 0, "c11", 1): DCCMVAU,
+
+        ("p15", "c7", 0, "c14", 1): DCCIMVAC,
+        ("p15", "c7", 0, "c14", 2): DCCISW,
+
+        ("p15", "c7", 4, "c8", 0): ATS1HR,
+        ("p15", "c7", 4, "c8", 1): ATS1HW,
+
+        ("p15", "c8", 0, "c3", 0): TLBIALLIS,
+        ("p15", "c8", 0, "c3", 1): TLBIMVAIS,
+        ("p15", "c8", 0, "c3", 2): TLBIASIDIS,
+        ("p15", "c8", 0, "c3", 3): TLBIMVAAIS,
+
+        ("p15", "c8", 0, "c5", 0): ITLBIALL,
+        ("p15", "c8", 0, "c5", 1): ITLBIMVA,
+        ("p15", "c8", 0, "c5", 2): ITLBIASID,
+
+        ("p15", "c8", 0, "c6", 0): DTLBIALL,
+        ("p15", "c8", 0, "c6", 1): DTLBIMVA,
+        ("p15", "c8", 0, "c6", 2): DTLBIASID,
+
+        ("p15", "c8", 0, "c7", 0): TLBIALL,
+        ("p15", "c8", 0, "c7", 1): TLBIMVA,
+        ("p15", "c8", 0, "c7", 2): TLBIASID,
+        ("p15", "c8", 0, "c7", 3): TLBIMVAA,
+
+        ("p15", "c8", 4, "c3", 0): TLBIALLHIS,
+        ("p15", "c8", 4, "c3", 1): TLBIMVAHIS,
+        ("p15", "c8", 4, "c3", 4): TLBIALLNSNHIS,
+
+        ("p15", "c8", 4, "c7", 0): TLBIALLH,
+        ("p15", "c8", 4, "c7", 1): TLBIMVAH,
+        ("p15", "c8", 4, "c7", 2): TLBIALLNSNH,
+
+        ("p15", "c9", 0, "c12", 0): PMCR,
+        ("p15", "c9", 0, "c12", 1): PMCNTENSET,
+        ("p15", "c9", 0, "c12", 2): PMCNTENCLR,
+        ("p15", "c9", 0, "c12", 3): PMOVSR,
+        ("p15", "c9", 0, "c12", 4): PMSWINC,
+        ("p15", "c9", 0, "c12", 5): PMSELR,
+        ("p15", "c9", 0, "c12", 6): PMCEID0,
+        ("p15", "c9", 0, "c12", 7): PMCEID1,
+
+        ("p15", "c9", 0, "c13", 0): PMCCNTR,
+        ("p15", "c9", 0, "c13", 1): PMXEVTYPER,
+        ("p15", "c9", 0, "c13", 2): PMXEVCNTR,
+
+        ("p15", "c9", 0, "c14", 0): PMUSERENR,
+        ("p15", "c9", 0, "c14", 1): PMINTENSET,
+        ("p15", "c9", 0, "c14", 2): PMINTENCLR,
+        ("p15", "c9", 0, "c14", 3): PMOVSSET,
+
+        ("p15", "c10", 0, "c2", 0): PRRR,   # ALIAS MAIR0
+        ("p15", "c10", 0, "c2", 1): NMRR,   # ALIAS MAIR1
+
+        ("p15", "c10", 0, "c3", 0): AMAIR0,
+        ("p15", "c10", 0, "c3", 1): AMAIR1,
+
+        ("p15", "c10", 4, "c2", 0): HMAIR0,
+        ("p15", "c10", 4, "c2", 1): HMAIR1,
+
+        ("p15", "c10", 4, "c3", 0): HAMAIR0,
+        ("p15", "c10", 4, "c3", 1): HAMAIR1,
+
+        ("p15", "c12", 0, "c0", 0): VBAR,
+        ("p15", "c12", 0, "c0", 1): MVBAR,
+
+        ("p15", "c12", 0, "c1", 0): ISR,
+
+        ("p15", "c12", 4, "c0", 0): HVBAR,
+
+        ("p15", "c13", 0, "c0", 0): FCSEIDR,
+        ("p15", "c13", 0, "c0", 1): CONTEXTIDR,
+        ("p15", "c13", 0, "c0", 2): TPIDRURW,
+        ("p15", "c13", 0, "c0", 3): TPIDRURO,
+        ("p15", "c13", 0, "c0", 4): TPIDRPRW,
+
+        ("p15", "c13", 4, "c0", 2): HTPIDR,
+
+        ("p15", "c14", 0, "c0", 0): CNTFRQ,
+        # TODO: CNTPCT 64-bit
+
+        ("p15", "c14", 0, "c1", 0): CNTKCTL,
+
+        ("p15", "c14", 0, "c2", 0): CNTP_TVAL,
+        ("p15", "c14", 0, "c2", 1): CNTP_CTL,
+
+        ("p15", "c14", 0, "c3", 0): CNTV_TVAL,
+        ("p15", "c14", 0, "c3", 1): CNTV_CTL,
+
+        # TODO: CNTVCT, CNTP_CVAL, CNTV_CVAL, CNTVOFF 64-bit
+
+        ("p15", "c14", 4, "c1", 0): CNTHCTL,
+
+        ("p15", "c14", 4, "c2", 0): CNTHP_TVAL,
+        ("p15", "c14", 4, "c2", 0): CNTHP_CTL
+
+        # TODO: CNTHP_CVAL 64-bit
+        }
+
 # liris.cnrs.fr/~mmrissa/lib/exe/fetch.php?media=armv7-a-r-manual.pdf
 EXCEPT_SOFT_BP = (1 << 1)
 
@@ -1319,6 +1532,10 @@ def dsb(ir, instr, a):
     e = []
     return e, []
 
+def isb(ir, instr, a):
+    # XXX TODO
+    e = []
+    return e, []
 
 def cpsie(ir, instr, a):
     # XXX TODO
@@ -1376,6 +1593,25 @@ def pkhtb(ir, instr, arg1, arg2, arg3):
     )
     return e, []
 
+def mrc(ir, insr, arg1, arg2, arg3, arg4, arg5, arg6):
+    e = []
+    sreg = (str(arg1), str(arg4), int(arg2), str(arg5), int(arg6))
+    if sreg in coproc_reg_dict:
+        e.append(ExprAssign(arg3, coproc_reg_dict[sreg]))
+    else:
+        raise NotImplementedError("Unknown coprocessor register: %s %s %d %s %d" % (str(arg1), str(arg4), int(arg2), str(arg5), int(arg6)))
+
+    return e, []
+
+def mcr(ir, insr, arg1, arg2, arg3, arg4, arg5, arg6):
+    e = []
+    sreg = (str(arg1), str(arg4), int(arg2), str(arg5), int(arg6))
+    if sreg in coproc_reg_dict:
+        e.append(ExprAssign(coproc_reg_dict[sreg], arg3))
+    else:
+        raise NotImplementedError("Unknown coprocessor register: %s %s %d %s %d" % (str(arg1), str(arg4), int(arg2), str(arg5), int(arg6)))
+
+    return e, []
 
 COND_EQ = 0
 COND_NE = 1
@@ -1574,6 +1810,9 @@ mnemo_condm1 = {'adds': add,
                 'bics': bics,
                 'mvns': mvns,
 
+                'mrc': mrc,
+                'mcr': mcr,
+
                 'mrs': mrs,
                 'msr': msr,
 
@@ -1629,6 +1868,7 @@ mnemo_nocond = {'lsr': lsr,
                 'tbh': tbh,
                 'nop': nop,
                 'dsb': dsb,
+                'isb': isb,
                 'cpsie': cpsie,
                 'cpsid': cpsid,
                 'wfe': wfe,
@@ -1774,7 +2014,7 @@ class ir_arml(IntermediateRepresentation):
             index += 1
             instr = block.lines[index]
 
-            # Add conditionnal jump to current irblock
+            # Add conditional jump to current irblock
             loc_do = self.loc_db.add_location()
             loc_next = self.get_next_loc_key(instr)
 
diff --git a/miasm/arch/mep/sem.py b/miasm/arch/mep/sem.py
index c1585d35..df484ab5 100644
--- a/miasm/arch/mep/sem.py
+++ b/miasm/arch/mep/sem.py
@@ -334,7 +334,7 @@ if False:
 def sltu3(r0, rn, rm_or_imm5):
     """SLTU3 - Set on less than (unsigned)."""
 
-    # if (Rn<Rm) R0<-1 else R0<-0 (Unigned)
+    # if (Rn<Rm) R0<-1 else R0<-0 (Unsigned)
     # if (Rn<ZeroExt(imm5)) R0<-1 else R0<-0(Unsigned)
     r0 = i32(1) if compute_u_inf(rn, rm_or_imm5) else i32(0)
 
diff --git a/miasm/arch/mips32/sem.py b/miasm/arch/mips32/sem.py
index 4986a307..9f935a5e 100644
--- a/miasm/arch/mips32/sem.py
+++ b/miasm/arch/mips32/sem.py
@@ -68,7 +68,7 @@ def lbu(arg1, arg2):
 
 @sbuild.parse
 def lh(arg1, arg2):
-    """A word is loaded into a register @arg1 from the 
+    """A word is loaded into a register @arg1 from the
     specified address @arg2."""
     arg1 = mem16[arg2.ptr].signExtend(32)
 
diff --git a/miasm/arch/ppc/sem.py b/miasm/arch/ppc/sem.py
index 61330fe1..7ca7e3e1 100644
--- a/miasm/arch/ppc/sem.py
+++ b/miasm/arch/ppc/sem.py
@@ -26,17 +26,17 @@ sr_dict = {
 }
 
 float_dict = {
-    0: FPR0, 1: FPR1, 2: FPR2, 3: FPR3, 4: FPR4, 5: FPR5, 6: FPR6, 7: FPR7, 8: FPR8, 
-    9: FPR9, 10: FPR10, 11: FPR11, 12: FPR12, 13: FPR13, 14: FPR14, 15: FPR15, 16: FPR16, 
-    17: FPR17, 18: FPR18, 19: FPR19, 20: FPR20, 21: FPR21, 22: FPR22, 23: FPR23, 24: FPR24, 
+    0: FPR0, 1: FPR1, 2: FPR2, 3: FPR3, 4: FPR4, 5: FPR5, 6: FPR6, 7: FPR7, 8: FPR8,
+    9: FPR9, 10: FPR10, 11: FPR11, 12: FPR12, 13: FPR13, 14: FPR14, 15: FPR15, 16: FPR16,
+    17: FPR17, 18: FPR18, 19: FPR19, 20: FPR20, 21: FPR21, 22: FPR22, 23: FPR23, 24: FPR24,
     25: FPR25, 26: FPR26, 27: FPR27, 28: FPR28, 29: FPR29, 30: FPR30, 31: FPR31
 }
 
 vex_dict = {
-    0: VR0, 1: VR1, 2: VR2, 3: VR3, 4: VR4, 5: VR5, 6: VR6, 7: VR7, 8: VR8, 
-    9: VR9, 10: VR10, 11: VR11, 12: VR12, 13: VR13, 14: VR14, 15: VR15, 16: VR16, 
-    17: VR17, 18: VR18, 19: VR19, 20: VR20, 21: VR21, 22: VR22, 23: VR23, 24: VR24, 
-    25: VR25, 26: VR26, 27: VR27, 28: VR28, 29: VR29, 30: VR30, 31: VR31,    
+    0: VR0, 1: VR1, 2: VR2, 3: VR3, 4: VR4, 5: VR5, 6: VR6, 7: VR7, 8: VR8,
+    9: VR9, 10: VR10, 11: VR11, 12: VR12, 13: VR13, 14: VR14, 15: VR15, 16: VR16,
+    17: VR17, 18: VR18, 19: VR19, 20: VR20, 21: VR21, 22: VR22, 23: VR23, 24: VR24,
+    25: VR25, 26: VR26, 27: VR27, 28: VR28, 29: VR29, 30: VR30, 31: VR31,
 }
 
 crf_dict = dict((ExprId("CR%d" % i, 4),
@@ -265,7 +265,7 @@ def mn_do_load(ir, instr, arg1, arg2, arg3=None):
         return  [], []
     elif instr.name[1] == 'V':
         print("Warning, instruction %s implemented as NOP" % instr)
-        return [], []    
+        return [], []
 
     size = {'B': 8, 'H': 16, 'W': 32}[instr.name[1]]
 
@@ -527,7 +527,7 @@ def mn_do_rfi(ir, instr):
     ret = [ ExprAssign(MSR, (MSR &
                           ~ExprInt(0b1111111101110011, 32) |
                           ExprCompose(SRR1[0:2], ExprInt(0, 2),
-                                      SRR1[4:7], ExprInt(0, 1), 
+                                      SRR1[4:7], ExprInt(0, 1),
                                       SRR1[8:16], ExprInt(0, 16)))),
             ExprAssign(PC, dest),
             ExprAssign(ir.IRDst, dest) ]
diff --git a/miasm/arch/x86/arch.py b/miasm/arch/x86/arch.py
index 725f3126..d1802045 100644
--- a/miasm/arch/x86/arch.py
+++ b/miasm/arch/x86/arch.py
@@ -547,7 +547,7 @@ class instruction_x86(instruction):
 
     def __str__(self):
         return self.to_string()
-      
+
     def to_string(self, loc_db=None):
         o = super(instruction_x86, self).to_string(loc_db)
         if self.additional_info.g1.value & 1:
diff --git a/miasm/expression/expression.py b/miasm/expression/expression.py
index ef05a2b6..c2bf5b8b 100644
--- a/miasm/expression/expression.py
+++ b/miasm/expression/expression.py
@@ -727,8 +727,8 @@ class Expr(object):
 
     def visit(self, callback):
         """
-        Apply callbak to all sub expression of @self
-        This function keeps a cache to avoid rerunning @callbak on common sub
+        Apply callback to all sub expression of @self
+        This function keeps a cache to avoid rerunning @callback on common sub
         expressions.
 
         @callback: fn(Expr) -> Expr
diff --git a/miasm/expression/simplifications_common.py b/miasm/expression/simplifications_common.py
index f12ccfcf..f68b8ed5 100644
--- a/miasm/expression/simplifications_common.py
+++ b/miasm/expression/simplifications_common.py
@@ -1081,6 +1081,13 @@ def simp_cmp_bijective_op(expr_simp, expr):
             args_a.remove(value)
             args_b.remove(value)
 
+    # a + b == a + b + c
+    if not args_a:
+        return ExprOp(TOK_EQUAL, ExprOp(op, *args_b), ExprInt(0, args_b[0].size))
+    # a + b + c == a + b
+    if not args_b:
+        return ExprOp(TOK_EQUAL, ExprOp(op, *args_a), ExprInt(0, args_a[0].size))
+    
     arg_a = ExprOp(op, *args_a)
     arg_b = ExprOp(op, *args_b)
     return ExprOp(TOK_EQUAL, arg_a, arg_b)
diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py
index 9b2e4ba0..3219b5fc 100644
--- a/miasm/ir/ir.py
+++ b/miasm/ir/ir.py
@@ -885,7 +885,7 @@ class IntermediateRepresentation(object):
         return irblock
 
     def is_pc_written(self, block):
-        """Return the first Assignblk of the @blockin which PC is written
+        """Return the first Assignblk of the @block in which PC is written
         @block: IRBlock instance"""
         all_pc = viewvalues(self.arch.pc)
         for assignblk in block:
diff --git a/miasm/ir/symbexec.py b/miasm/ir/symbexec.py
index 65ddde3b..8c6245b8 100644
--- a/miasm/ir/symbexec.py
+++ b/miasm/ir/symbexec.py
@@ -121,7 +121,7 @@ class MemArray(MutableMapping):
     content relatively to an integer offset from *base*.
 
     The value associated to a given offset is a description of the slice of a
-    stored expression. The slice size depends on the configutation of the
+    stored expression. The slice size depends on the configuration of the
     MemArray. For example, for a slice size of 8 bits, the assignment:
     - @32[EAX+0x10] = EBX
 
diff --git a/miasm/ir/translators/z3_ir.py b/miasm/ir/translators/z3_ir.py
index 6b706770..1a36e94e 100644
--- a/miasm/ir/translators/z3_ir.py
+++ b/miasm/ir/translators/z3_ir.py
@@ -15,7 +15,7 @@ log.addHandler(console_handler)
 log.setLevel(logging.WARNING)
 
 class Z3Mem(object):
-    """Memory abstration for TranslatorZ3. Memory elements are only accessed,
+    """Memory abstraction for TranslatorZ3. Memory elements are only accessed,
     never written. To give a concrete value for a given memory cell in a solver,
     add "mem32.get(address, size) == <value>" constraints to your equation.
     The endianness of memory accesses is handled accordingly to the "endianness"
diff --git a/miasm/jitter/bn.h b/miasm/jitter/bn.h
index 1aa6b432..8c4a8ba1 100644
--- a/miasm/jitter/bn.h
+++ b/miasm/jitter/bn.h
@@ -35,7 +35,7 @@ Code slightly modified to support ast generation calculus style from Expr.
 #include <assert.h>
 
 
-/* This macro defines the word size in bytes of the array that constitues the big-number data structure. */
+/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */
 #ifndef WORD_SIZE
   #define WORD_SIZE 4
 #endif
diff --git a/miasm/jitter/jitload.py b/miasm/jitter/jitload.py
index 68f9c40d..34690425 100644
--- a/miasm/jitter/jitload.py
+++ b/miasm/jitter/jitload.py
@@ -422,6 +422,17 @@ class Jitter(object):
         self.init_run(addr)
         return self.continue_run()
 
+    def run_until(self, addr):
+        """PRE: init_run.
+        Continue the run of the current session until iterator returns, run is
+        set to False or addr is reached.
+        Return the iterator value"""
+
+        def stop_exec(jitter):
+            jitter.remove_breakpoints_by_callback(stop_exec)
+            return False
+        self.add_breakpoint(addr, stop_exec)
+        return self.continue_run()
 
     def init_stack(self):
         self.vm.add_memory_page(
diff --git a/miasm/loader/pe.py b/miasm/loader/pe.py
index c402715a..2d257906 100644
--- a/miasm/loader/pe.py
+++ b/miasm/loader/pe.py
@@ -1326,7 +1326,7 @@ class DirRes(CStruct):
                     # data dir
                     off = entry.offsettodata
                     if not 0 <= off < len(raw):
-                        log.warn('bad resrouce entry')
+                        log.warn('bad resource entry')
                         continue
                     data = ResDataEntry.unpack(raw,
                                                off,
@@ -1340,7 +1340,7 @@ class DirRes(CStruct):
                     log.warn('warning recusif subdir')
                     continue
                 if not 0 <= off < len(self.parent_head.img_rva):
-                    log.warn('bad resrouce entry')
+                    log.warn('bad resource entry')
                     continue
                 subdir, length = ResDesc_e.unpack_l(raw,
                                                     off,
@@ -1352,7 +1352,7 @@ class DirRes(CStruct):
                                                      ResEntry,
                                                      nbr)
                 except RuntimeError:
-                    log.warn('bad resrouce entry')
+                    log.warn('bad resource entry')
                     continue
 
                 entry.subdir = subdir
diff --git a/miasm/os_dep/common.py b/miasm/os_dep/common.py
index 4a92ef2a..74100817 100644
--- a/miasm/os_dep/common.py
+++ b/miasm/os_dep/common.py
@@ -71,15 +71,15 @@ class heap(object):
         self.addr &= self.mask ^ (self.align - 1)
         return ret
 
-    def alloc(self, jitter, size, perm=PAGE_READ | PAGE_WRITE):
+    def alloc(self, jitter, size, perm=PAGE_READ | PAGE_WRITE, cmt=""):
         """
         @jitter: a jitter instance
         @size: the size to allocate
         @perm: permission flags (see vm_alloc doc)
         """
-        return self.vm_alloc(jitter.vm, size, perm)
+        return self.vm_alloc(jitter.vm, size, perm=perm, cmt=cmt)
 
-    def vm_alloc(self, vm, size, perm=PAGE_READ | PAGE_WRITE):
+    def vm_alloc(self, vm, size, perm=PAGE_READ | PAGE_WRITE, cmt=""):
         """
         @vm: a VmMngr instance
         @size: the size to allocate
@@ -91,7 +91,7 @@ class heap(object):
             addr,
             perm,
             b"\x00" * (size),
-            "Heap alloc by %s" % get_caller_name(2)
+            "Heap alloc by %s %s" % (get_caller_name(2), cmt)
         )
         return addr
 
diff --git a/miasm/os_dep/linux/syscall.py b/miasm/os_dep/linux/syscall.py
index 3b1275aa..acebe2cb 100644
--- a/miasm/os_dep/linux/syscall.py
+++ b/miasm/os_dep/linux/syscall.py
@@ -681,7 +681,7 @@ def sys_x86_64_connect(jitter, linux_env):
     log.debug("sys_connect(%x, %r, %x)", fd, raddr, addrlen)
 
     # Stub
-    # Always refuse the connexion
+    # Always refuse the connection
     jitter.cpu.RAX = -1
 
 
diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py
index e42f8006..46f5783c 100644
--- a/miasm/os_dep/win_api_x86_32.py
+++ b/miasm/os_dep/win_api_x86_32.py
@@ -157,6 +157,9 @@ class c_winobjs(object):
         self.cryptcontext_num = 0
         self.cryptcontext = {}
         self.phhash_crypt_md5 = 0x55555
+        # key used by EncodePointer and DecodePointer
+        # (kernel32)
+        self.ptr_encode_key = 0xabababab
         self.files_hwnd = {}
         self.windowlong_dw = 0x77700
         self.module_cur_hwnd = 0x88800
@@ -272,7 +275,7 @@ class mdl(object):
 
 def kernel32_HeapAlloc(jitter):
     ret_ad, args = jitter.func_args_stdcall(["heap", "flags", "size"])
-    alloc_addr = winobjs.heap.alloc(jitter, args.size)
+    alloc_addr = winobjs.heap.alloc(jitter, args.size, cmt=hex(ret_ad))
     jitter.func_ret_stdcall(ret_ad, alloc_addr)
 
 
@@ -420,6 +423,36 @@ def kernel32_CloseHandle(jitter):
     ret_ad, _ = jitter.func_args_stdcall(["hwnd"])
     jitter.func_ret_stdcall(ret_ad, 1)
 
+def kernel32_EncodePointer(jitter):
+    """
+        PVOID EncodePointer(
+            _In_ PVOID Ptr
+        );
+
+        Encoding globally available pointers helps protect them from being
+        exploited. The EncodePointer function obfuscates the pointer value
+        with a secret so that it cannot be predicted by an external agent.
+        The secret used by EncodePointer is different for each process.
+
+        A pointer must be decoded before it can be used.
+
+    """
+    ret, args = jitter.func_args_stdcall(1)
+    jitter.func_ret_stdcall(ret, args[0] ^ winobjs.ptr_encode_key)
+    return True
+
+def kernel32_DecodePointer(jitter):
+    """
+        PVOID DecodePointer(
+           PVOID Ptr
+        );
+
+        The function returns the decoded pointer.
+
+    """
+    ret, args = jitter.func_args_stdcall(1)
+    jitter.func_ret_stdcall(ret, args[0] ^ winobjs.ptr_encode_key)
+    return True
 
 def user32_GetForegroundWindow(jitter):
     ret_ad, _ = jitter.func_args_stdcall(0)
@@ -505,7 +538,7 @@ def advapi32_CryptHashData(jitter):
 
     data = jitter.vm.get_mem(args.pbdata, args.dwdatalen)
     log.debug('will hash %X', args.dwdatalen)
-    log.debug(repr(data[:10]) + "...")
+    log.debug(repr(data[:0x10]) + "...")
     winobjs.cryptcontext[args.hhash].h.update(data)
     jitter.func_ret_stdcall(ret_ad, 1)
 
@@ -518,12 +551,18 @@ def advapi32_CryptGetHashParam(jitter):
         raise ValueError("unknown crypt context")
 
     if args.param == 2:
+        # HP_HASHVAL
         # XXX todo: save h state?
         h = winobjs.cryptcontext[args.hhash].h.digest()
+        jitter.vm.set_mem(args.pbdata, h)
+        jitter.vm.set_u32(args.dwdatalen, len(h))
+    elif args.param == 4:
+        # HP_HASHSIZE
+        ret = winobjs.cryptcontext[args.hhash].h.digest_size
+        jitter.vm.set_u32(args.pbdata, ret)
+        jitter.vm.set_u32(args.dwdatalen, 4)
     else:
         raise ValueError('not impl', args.param)
-    jitter.vm.set_mem(args.pbdata, h)
-    jitter.vm.set_u32(args.dwdatalen, len(h))
 
     jitter.func_ret_stdcall(ret_ad, 1)
 
@@ -606,7 +645,7 @@ def kernel32_CreateFile(jitter, funcname, get_str):
                         h = open(sb_fname, 'r+b')
                         ret = winobjs.handle_pool.add(sb_fname, h)
                 else:
-                    log.warning("FILE %r DOES NOT EXIST!", fname)
+                    log.warning("FILE %r (%s) DOES NOT EXIST!", fname, sb_fname)
             elif args.dwcreationdisposition == 1:
                 # create new
                 if os.access(sb_fname, os.R_OK):
@@ -1114,21 +1153,22 @@ def kernel32_GetCommandLineW(jitter):
 def shell32_CommandLineToArgvW(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pcmd", "pnumargs"])
     cmd = get_win_str_w(jitter, args.pcmd)
+    if cmd.startswith('"') and cmd.endswith('"'):
+        cmd = cmd[1:-1]
     log.info("CommandLineToArgv %r", cmd)
     tks = cmd.split(' ')
     addr = winobjs.heap.alloc(jitter, len(cmd) * 2 + 4 * len(tks))
     addr_ret = winobjs.heap.alloc(jitter, 4 * (len(tks) + 1))
     o = 0
     for i, t in enumerate(tks):
-        jitter.set_win_str_w(addr + o, t)
+        set_win_str_w(jitter, addr + o, t)
         jitter.vm.set_u32(addr_ret + 4 * i, addr + o)
         o += len(t)*2 + 2
 
-    jitter.vm.set_u32(addr_ret + 4 * i, 0)
+    jitter.vm.set_u32(addr_ret + 4 * (i+1), 0)
     jitter.vm.set_u32(args.pnumargs, len(tks))
     jitter.func_ret_stdcall(ret_ad, addr_ret)
 
-
 def cryptdll_MD5Init(jitter):
     ret_ad, args = jitter.func_args_stdcall(["ad_ctx"])
     index = len(winobjs.cryptdll_md5_h)
@@ -1335,7 +1375,7 @@ def ntoskrnl_RtlGetVersion(jitter):
                     0x2,  # min vers
                     0x666,  # build nbr
                     0x2,   # platform id
-                    ) + jitter.set_win_str_w("Service pack 4")
+                    ) + encode_win_str_w("Service pack 4")
 
     jitter.vm.set_mem(args.ptr_version, s)
     jitter.func_ret_stdcall(ret_ad, 0)
@@ -1521,7 +1561,7 @@ def kernel32_lstrcpy(jitter):
 def msvcrt__mbscpy(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
     s2 = get_win_str_w(jitter, args.ptr_str2)
-    jitter.set_win_str_w(args.ptr_str1, s2)
+    set_win_str_w(jitter, args.ptr_str1, s2)
     jitter.func_ret_cdecl(ret_ad, args.ptr_str1)
 
 def msvcrt_wcscpy(jitter):
@@ -1535,7 +1575,7 @@ def kernel32_lstrcpyn(jitter):
     if len(s2) >= args.mlen:
         s2 = s2[:args.mlen - 1]
     log.info("Copy '%r'", s2)
-    jitter.set_win_str_a(args.ptr_str1, s2)
+    set_win_str_a(jitter, args.ptr_str1, s2)
     jitter.func_ret_stdcall(ret_ad, args.ptr_str1)
 
 
@@ -1637,7 +1677,8 @@ def kernel32_MultiByteToWideChar(jitter):
                                              "cchwidechar"])
     src = get_win_str_a(jitter, args.lpmultibytestr)
     l = len(src) + 1
-    set_win_str_w(jitter, args.lpwidecharstr, src)
+    if args.cchwidechar != 0:
+        set_win_str_w(jitter, args.lpwidecharstr, src)
     jitter.func_ret_stdcall(ret_ad, l)
 
 
@@ -2879,7 +2920,7 @@ class win32_find_data(object):
         for k, v in viewitems(kargs):
             setattr(self, k, v)
 
-    def toStruct(self):
+    def toStruct(self, encode_str=encode_win_str_w):
         s = struct.pack('=IQQQIIII',
                         self.fileattrib,
                         self.creationtime,
@@ -2889,10 +2930,10 @@ class win32_find_data(object):
                         self.filesizelow,
                         self.dwreserved0,
                         self.dwreserved1)
-        fname = self.cfilename.encode('utf-8') + b'\x00' * MAX_PATH
+        fname = encode_str(self.cfilename) + b'\x00' * MAX_PATH
         fname = fname[:MAX_PATH]
         s += fname
-        fname = self.alternamefilename.encode('utf-8') + b'\x00' * 14
+        fname = encode_str(self.alternamefilename) + b'\x00' * 14
         fname = fname[:14]
         s += fname
         return s
@@ -2929,33 +2970,66 @@ class find_data_mngr(object):
 
         return fname
 
-
-def kernel32_FindFirstFileA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"])
-
-    filepattern = get_win_str_a(jitter, args.pfilepattern)
+def my_FindFirstFile(jitter, pfilepattern, pfindfiledata, get_win_str, encode_str):
+    filepattern = get_win_str(jitter, pfilepattern)
     h = winobjs.find_data.findfirst(filepattern)
 
     fname = winobjs.find_data.findnext(h)
     fdata = win32_find_data(cfilename=fname)
 
-    jitter.vm.set_mem(args.pfindfiledata, fdata.toStruct())
+    jitter.vm.set_mem(pfindfiledata, fdata.toStruct(encode_str=encode_str))
+    return h
+
+def kernel32_FindFirstFileA(jitter):
+    ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"])
+    h = my_FindFirstFile(jitter, args.pfilepattern, args.pfindfiledata,
+                           get_win_str_a, encode_win_str_a)
     jitter.func_ret_stdcall(ret_ad, h)
 
+def kernel32_FindFirstFileW(jitter):
+    ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"])
+    h = my_FindFirstFile(jitter, args.pfilepattern, args.pfindfiledata,
+                           get_win_str_w, encode_win_str_w)
+    jitter.func_ret_stdcall(ret_ad, h)
 
-def kernel32_FindNextFileA(jitter):
-    ret_ad, args = jitter.func_args_stdcall(["handle", "pfindfiledata"])
+def kernel32_FindFirstFileExA(jitter):
+    ret_ad, args = jitter.func_args_stdcall([
+        "lpFileName",
+        "fInfoLevelId",
+        "lpFindFileData",
+        "fSearchOp",
+        "lpSearchFilter",
+        "dwAdditionalFlags"])
+    h = my_FindFirstFile(jitter, args.lpFileName, args.lpFindFileData,
+                         get_win_str_a, encode_win_str_a)
+    jitter.func_ret_stdcall(ret_ad, h)
+
+def kernel32_FindFirstFileExW(jitter):
+    ret_ad, args = jitter.func_args_stdcall([
+        "lpFileName",
+        "fInfoLevelId",
+        "lpFindFileData",
+        "fSearchOp",
+        "lpSearchFilter",
+        "dwAdditionalFlags"])
+    h = my_FindFirstFile(jitter, args.lpFileName, args.lpFindFileData,
+                         get_win_str_w, encode_win_str_w)
+    jitter.func_ret_stdcall(ret_ad, h)
 
+def my_FindNextFile(jitter, encode_str):
+    ret_ad, args = jitter.func_args_stdcall(["handle", "pfindfiledata"])
     fname = winobjs.find_data.findnext(args.handle)
     if fname is None:
+        winobjs.lastwin32error = 0x12 # ERROR_NO_MORE_FILES
         ret = 0
     else:
         ret = 1
         fdata = win32_find_data(cfilename=fname)
-        jitter.vm.set_mem(args.pfindfiledata, fdata.toStruct())
-
+        jitter.vm.set_mem(args.pfindfiledata, fdata.toStruct(encode_str=encode_str))
     jitter.func_ret_stdcall(ret_ad, ret)
 
+kernel32_FindNextFileA = lambda jitter: my_FindNextFile(jitter, encode_win_str_a)
+kernel32_FindNextFileW = lambda jitter: my_FindNextFile(jitter, encode_win_str_w)
 
 def kernel32_GetNativeSystemInfo(jitter):
     ret_ad, args = jitter.func_args_stdcall(["sys_ptr"])
@@ -3082,7 +3156,7 @@ class FLS(object):
         '''
         DWORD FlsAlloc(
           PFLS_CALLBACK_FUNCTION lpCallback
-        );    
+        );
         '''
         ret_ad, args = jitter.func_args_stdcall(["lpCallback"])
         index = len(self.slots)
@@ -3099,7 +3173,7 @@ class FLS(object):
         ret_ad, args = jitter.func_args_stdcall(["dwFlsIndex", "lpFlsData"])
         self.slots[args.dwFlsIndex] = args.lpFlsData
         jitter.func_ret_stdcall(ret_ad, 1)
-        
+
     def kernel32_FlsGetValue(self, jitter):
         '''
         PVOID FlsGetValue(
@@ -3107,8 +3181,8 @@ class FLS(object):
         );
         '''
         ret_ad, args = jitter.func_args_stdcall(["dwFlsIndex"])
-        jitter.func_ret_stdcall(ret_ad, self.slots[args.dwFlsIndex])        
-        
+        jitter.func_ret_stdcall(ret_ad, self.slots[args.dwFlsIndex])
+
 fls = FLS()
 
 
@@ -3131,15 +3205,15 @@ def kernel32_GetStdHandle(jitter):
     HANDLE WINAPI GetStdHandle(
       _In_ DWORD nStdHandle
     );
-    
-    STD_INPUT_HANDLE (DWORD)-10 	
+
+    STD_INPUT_HANDLE (DWORD)-10
     The standard input device. Initially, this is the console input buffer, CONIN$.
 
-    STD_OUTPUT_HANDLE (DWORD)-11 	
+    STD_OUTPUT_HANDLE (DWORD)-11
     The standard output device. Initially, this is the active console screen buffer, CONOUT$.
 
-    STD_ERROR_HANDLE (DWORD)-12 	
-    The standard error device. Initially, this is the active console screen buffer, CONOUT$.    
+    STD_ERROR_HANDLE (DWORD)-12
+    The standard error device. Initially, this is the active console screen buffer, CONOUT$.
     '''
     ret_ad, args = jitter.func_args_stdcall(["nStdHandle"])
     jitter.func_ret_stdcall(ret_ad, {
@@ -3148,7 +3222,7 @@ def kernel32_GetStdHandle(jitter):
         STD_INPUT_HANDLE: 3,
     }[args.nStdHandle])
 
-    
+
 FILE_TYPE_UNKNOWN = 0x0000
 FILE_TYPE_CHAR = 0x0002
 
@@ -3228,13 +3302,13 @@ def kernel32_IsProcessorFeaturePresent(jitter):
         17: False,
     }[args.ProcessorFeature])
 
-    
+
 def kernel32_GetACP(jitter):
     '''
     UINT GetACP();
     '''
     ret_ad, args = jitter.func_args_stdcall([])
-    # Windows-1252: Latin 1 / Western European  Superset of ISO-8859-1 (without C1 controls). 
+    # Windows-1252: Latin 1 / Western European  Superset of ISO-8859-1 (without C1 controls).
     jitter.func_ret_stdcall(ret_ad, 1252)
 
 
@@ -3259,7 +3333,7 @@ def kernel32_IsValidCodePage(jitter):
     );
     '''
     ret_ad, args = jitter.func_args_stdcall(["CodePage"])
-    jitter.func_ret_stdcall(ret_ad, args.CodePage in VALID_CODE_PAGES)    
+    jitter.func_ret_stdcall(ret_ad, args.CodePage in VALID_CODE_PAGES)
 
 
 def kernel32_GetCPInfo(jitter):
@@ -3272,8 +3346,8 @@ def kernel32_GetCPInfo(jitter):
     ret_ad, args = jitter.func_args_stdcall(["CodePage", "lpCPInfo"])
     assert args.CodePage == 1252
     # ref: http://www.rensselaer.org/dept/cis/software/g77-mingw32/include/winnls.h
-    #define MAX_LEADBYTES 	12
+    #define MAX_LEADBYTES       12
     #define MAX_DEFAULTCHAR	2
     jitter.vm.set_mem(args.lpCPInfo, struct.pack('<I', 0x1) + b'??' + b'\x00' * 12)
     jitter.func_ret_stdcall(ret_ad, 1)
-    
+
diff --git a/test/arch/arm/arch.py b/test/arch/arm/arch.py
index 5aa619ea..55b9a9c2 100644
--- a/test/arch/arm/arch.py
+++ b/test/arch/arm/arch.py
@@ -233,6 +233,10 @@ reg_tests_arm = [
     ('XXXXXXXX    PKHTB      R1, R2, R3 ASR 0x20',
      '531082e6'),
 
+    ('XXXXXXXX    MRC        p15, 0x0, R0, c1, c1, 0x0',
+     '110f11ee'),
+    ('XXXXXXXX    MCR        p15, 0x0, R8, c2, c0, 0x0',
+     '108f02ee'),
 
 ]
 ts = time.time()
diff --git a/test/utils/testset.py b/test/utils/testset.py
index eee0e6f7..2bdb7450 100644
--- a/test/utils/testset.py
+++ b/test/utils/testset.py
@@ -203,7 +203,7 @@ class TestSet(object):
             try:
                 os.remove(product)
             except OSError:
-                print("Cleanning error: Unable to remove %s" % product)
+                print("Cleaning error: Unable to remove %s" % product)
 
     def add_additional_args(self, args):
         """Add arguments to used on the test command line