diff --git a/tests/test_simple_x64.py b/tests/test_simple_x64.py index 30cd68b..6baf4a8 100644 --- a/tests/test_simple_x64.py +++ b/tests/test_simple_x64.py @@ -12,6 +12,14 @@ if capstone: disassembleur = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64) disassembleur.detail = True +@pytest.fixture +def need_capstone(): + if capstone is None: + raise pytest.Skip("Capstone is not installed") + return True + +pytestmark = pytest.mark.usefixtures("need_capstone") + def disas(x): return list(disassembleur.disasm(x, 0)) @@ -264,6 +272,7 @@ def test_assembler(): CheckInstr(Add, must_fail=True)('RAX', 0xffffffff) + code = MultipleInstr() code += Nop() code += Rep + Nop() @@ -271,10 +280,10 @@ def test_assembler(): print(repr(code.get_code())) assert code.get_code() == "\x90\xf3\x90\xc3" -if capstone is None: - test_assembler = pytest.mark.skip("Capstone not installed")(test_assembler) - -# pytestmark = pytest.mark.skip("YOLO") +def test_simple_x64_raw_instruction(): + # Test the fake instruction "raw" + # By emetting a multi-char nop manually + CheckInstr(Raw, expected_result="nop word ptr [rax + rax]")("66 0F 1F 84 00 00 00 00 00") if __name__ == "__main__": test_assembler() diff --git a/tests/test_simple_x86.py b/tests/test_simple_x86.py index dd1bfa3..8cb1aae 100644 --- a/tests/test_simple_x86.py +++ b/tests/test_simple_x86.py @@ -13,6 +13,14 @@ if capstone: disassembleur = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32) disassembleur.detail = True +@pytest.fixture +def need_capstone(): + if capstone is None: + raise pytest.Skip("Capstone is not installed") + return True + +pytestmark = pytest.mark.usefixtures("need_capstone") + def disas(x): return list(disassembleur.disasm(x, 0)) @@ -38,6 +46,13 @@ class CheckInstr(object): print("{0} {1}".format(capres.mnemonic, capres.op_str)) if len(res) != len(capres.bytes): raise AssertionError("Not all bytes have been used by the disassembler") + + + if self.expected_result is not None: + if "{0} {1}".format(capres.mnemonic, capres.op_str) == self.expected_result: + return True + else: + raise AssertionError("Expected result <{0}> got <{1}>".format(self.expected_result, "{0} {1}".format(capres.mnemonic, capres.op_str))) self.compare_mnemo(capres) self.compare_args(args, capres) @@ -48,12 +63,6 @@ class CheckInstr(object): return True def compare_args(self, args, capres): - if self.expected_result is not None: - result = "{0} {1}".format(capres.mnemonic, capres.op_str) - if result != self.expected_result: - raise AssertionError("Bad expected result expect <{0}> got <{1}>".format(self.expected_result, result)) - return - capres_op = list(capres.operands) if len(args) != len(capres_op): raise AssertionError("Expected {0} operands got {1}".format(len(args), len(capres_op))) @@ -190,9 +199,9 @@ def test_assembler(): CheckInstr(x86.Test)('EAX', 'EAX') CheckInstr(x86.Test, expected_result="test edi, ecx")('ECX', 'EDI') - CheckInstr(x86.Test)(mem('[ECX + 0x100]'), 'ECX') + assert x86.Test(mem('[ECX + 0x100]'), 'ECX').get_code() == x86.Test('ECX', mem('[ECX + 0x100]')).get_code() assert Xchg('EAX', 'ECX').get_code() == Xchg('ECX', 'EAX').get_code() @@ -203,6 +212,11 @@ def test_assembler(): print(repr(code.get_code())) assert code.get_code() == "\x90\xf3\x90\xc3" +def test_simple_x64_raw_instruction(): + # Test the fake instruction "raw" + # By emetting a multi-char nop manually + CheckInstr(Raw, expected_result="nop word ptr [eax + eax]")("66 0F 1F 84 00 00 00 00 00") + if capstone is None: test_assembler = pytest.mark.skip("Capstone not installed")(test_assembler) diff --git a/windows/native_exec/simple_x64.py b/windows/native_exec/simple_x64.py index e6c64dd..5f7ce30 100644 --- a/windows/native_exec/simple_x64.py +++ b/windows/native_exec/simple_x64.py @@ -1059,6 +1059,16 @@ def JmpAt(addr): code += Jmp('RAX') return code +class Raw(Instruction): + """Output raw data""" + def __init__(self, *initial_args): + if len(initial_args) != 1: + raise ValueError("raw 'opcode' only accept one argument") + # Accept space + self.data = initial_args[0].replace(" ", "").decode("hex") + + def get_code(self): + return self.data class Label(object): def __init__(self, name): diff --git a/windows/native_exec/simple_x86.py b/windows/native_exec/simple_x86.py index 0fe5c97..716eb6c 100644 --- a/windows/native_exec/simple_x86.py +++ b/windows/native_exec/simple_x86.py @@ -858,7 +858,8 @@ class Raw(Instruction): def __init__(self, *initial_args): if len(initial_args) != 1: raise ValueError("raw 'opcode' only accept one argument") - self.data = initial_args[0].decode("hex") + # Accept space + self.data = initial_args[0].replace(" ", "").decode("hex") def get_code(self): return self.data