diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/analysis/dse.py | 94 | ||||
| -rwxr-xr-x | test/test_all.py | 17 | ||||
| -rw-r--r-- | test/utils/test.py | 9 | ||||
| -rw-r--r-- | test/utils/testset.py | 3 |
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) |