about summary refs log tree commit diff stats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/analysis/dse.py94
-rwxr-xr-xtest/test_all.py17
-rw-r--r--test/utils/test.py9
-rw-r--r--test/utils/testset.py3
4 files changed, 120 insertions, 3 deletions
diff --git a/test/analysis/dse.py b/test/analysis/dse.py
new file mode 100644
index 00000000..59fc2b59
--- /dev/null
+++ b/test/analysis/dse.py
@@ -0,0 +1,94 @@
+import sys
+import os
+from pdb import pm
+
+from miasm2.core.cpu import ParseAst
+from miasm2.arch.x86.arch import mn_x86, base_expr, variable
+from miasm2.core import parse_asm
+from miasm2.expression.expression import *
+from miasm2.core import asmblock
+from elfesteem.strpatchwork import StrPatchwork
+from miasm2.analysis.machine import Machine
+from miasm2.jitter.csts import *
+from miasm2.analysis.dse import DSEEngine
+
+reg_and_id = dict(mn_x86.regs.all_regs_ids_byname)
+
+class DSE_test(object):
+    """Inspired from TEST/ARCH/X86
+
+    Test the symbolic execution correctly follow generated labels
+    """
+    TXT = '''
+    main:
+        SHL         EDX, CL
+        RET
+    '''
+
+    arch_name = "x86_32"
+    arch_attrib = 32
+    ret_addr = 0x1337beef
+
+    run_addr = 0x0
+
+    def __init__(self, jitter_engine):
+        self.machine = Machine(self.arch_name)
+        self.myjit = self.machine.jitter(jitter_engine)
+        self.myjit.init_stack()
+
+        self.myjit.jit.log_regs = False
+        self.myjit.jit.log_mn = False
+
+    def init_machine(self):
+        self.myjit.vm.add_memory_page(self.run_addr, PAGE_READ | PAGE_WRITE, self.assembly)
+        self.myjit.push_uint32_t(self.ret_addr)
+        self.myjit.add_breakpoint(self.ret_addr, lambda x:False)
+
+    def prepare(self):
+        self.myjit.cpu.ECX = 4
+        self.myjit.cpu.EDX = 5
+
+        self.dse = DSEEngine(self.machine)
+        self.dse.attach(self.myjit)
+
+    def __call__(self):
+        self.asm()
+        self.init_machine()
+        self.prepare()
+        self.run()
+        self.check()
+
+    def run(self):
+
+        self.myjit.init_run(self.run_addr)
+        self.myjit.continue_run()
+
+        assert(self.myjit.pc == self.ret_addr)
+
+    def asm(self):
+        blocks, symbol_pool = parse_asm.parse_txt(mn_x86, self.arch_attrib, self.TXT,
+                                                  symbol_pool=self.myjit.ir_arch.symbol_pool)
+
+
+        # fix shellcode addr
+        symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0)
+        s = StrPatchwork()
+        patches = asmblock.asm_resolve_final(mn_x86, blocks, symbol_pool)
+        for offset, raw in patches.items():
+            s[offset] = raw
+
+        s = str(s)
+        self.assembly = s
+
+    def check(self):
+        regs = self.dse.ir_arch.arch.regs
+        value = self.dse.eval_expr(regs.EDX)
+        # The expected value should contains '<<', showing it has been in the
+        # corresponding generated label
+        expected = ExprOp('<<', regs.EDX,
+                          ExprCompose(regs.ECX[0:8],
+                                      ExprInt(0x0, 24)) & ExprInt(0x1F, 32))
+        assert value == expected
+
+if __name__ == "__main__":
+    [test(*sys.argv[1:])() for test in [DSE_test]]
diff --git a/test/test_all.py b/test/test_all.py
index 94779898..d2c3e5e2 100755
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -278,6 +278,12 @@ testset += RegressionTest(["depgraph.py"], base_dir="analysis",
                                                      (14, 1), (15, 1))
                            ])
 testset += RegressionTest(["modularintervals.py"], base_dir="analysis")
+for jitter in ArchUnitTest.jitter_engines:
+    if jitter in blacklist.get(script, []):
+        continue
+    tags = [TAGS[jitter]] if jitter in TAGS else []
+    testset += RegressionTest(["dse.py", jitter], base_dir="analysis", tags=tags)
+
 testset += RegressionTest(["range.py"], base_dir="analysis",
                           tags=[TAGS["z3"]])
 
@@ -586,6 +592,17 @@ for options, nb_sol, tag in [([], 4, []),
                                  depends=[test_x86_32_if_reg],
                                  tags=tag)
 
+dse_crackme_out = Example.get_sample("dse_crackme.c")[:-2]
+dse_crackme = ExampleSymbolExec([Example.get_sample("dse_crackme.c"),
+                                 "-o", dse_crackme_out],
+                                products=[dse_crackme_out],
+                                executable="cc")
+testset += dse_crackme
+testset += ExampleSymbolExec(["dse_crackme.py", dse_crackme_out],
+                             depends=[dse_crackme],
+                             products=["test.txt"],
+                             tags=[TAGS["z3"]])
+
 ## Jitter
 class ExampleJitter(Example):
     """Jitter examples specificities:
diff --git a/test/utils/test.py b/test/utils/test.py
index e4f8888c..9e569a4b 100644
--- a/test/utils/test.py
+++ b/test/utils/test.py
@@ -2,22 +2,25 @@ class Test(object):
     "Stand for a test to run"
 
     def __init__(self, command_line, base_dir="", depends=None,
-                 products=None, tags=None):
+                 products=None, tags=None, executable=None):
         """Create a Test instance.
         @command_line: list of string standing for arguments to launch
         @base_dir: base directory for launch
         @depends: list of Test instance indicating dependencies
         @products: elements produced to remove after tests
         @tags: list of str indicating current test categories
+        @executable: if set, use this binary instead of Python
         """
         self.command_line = command_line
         self.base_dir = base_dir
         self.depends = depends if depends else []
         self.products = products if products else []
         self.tags = tags if tags else []
+        self.executable = executable
 
     def __repr__(self):
         displayed = ["command_line", "base_dir", "depends", "products", "tags"]
+        displayed.append("python" if not self.executable else self.executable)
         return "<Test " + \
             " ".join("%s=%s" % (n, getattr(self,n)) for n in displayed ) + ">"
 
@@ -29,4 +32,6 @@ class Test(object):
                     self.base_dir == test.base_dir,
                     self.depends == test.depends,
                     self.products == test.products,
-                    self.tags == test.tags])
+                    self.tags == test.tags,
+                    self.executable == test.executable,
+        ])
diff --git a/test/utils/testset.py b/test/utils/testset.py
index e1df01a4..29a4e5d0 100644
--- a/test/utils/testset.py
+++ b/test/utils/testset.py
@@ -153,7 +153,8 @@ class TestSet(object):
             os.chdir(test.base_dir)
 
             # Launch test
-            testpy = subprocess.Popen(([sys.executable] +
+            executable = test.executable if test.executable else sys.executable
+            testpy = subprocess.Popen(([executable] +
                                        init_args + test.command_line),
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE)