Some checks failed
sm-rpc / build (Debug, aarch64-linux-gnu) (push) Failing after 13m15s
sm-rpc / build (Release, mipsel-linux-gnu) (push) Failing after 13m1s
sm-rpc / build (Release, host.gcc) (push) Failing after 13m14s
sm-rpc / build (Release, arm-linux-gnueabihf) (push) Failing after 13m35s
sm-rpc / build (Release, aarch64-linux-gnu) (push) Failing after 13m56s
sm-rpc / build (Debug, mipsel-linux-gnu) (push) Failing after 14m22s
sm-rpc / build (Debug, host.gcc) (push) Failing after 14m49s
sm-rpc / build (Debug, arm-linux-gnueabihf) (push) Failing after 15m13s
2154 lines
96 KiB
Python
2154 lines
96 KiB
Python
#
|
|
# Gil Dabah 2006
|
|
# Tests for diStorm3
|
|
#
|
|
|
|
import os
|
|
import random
|
|
import struct
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
import ctypes
|
|
|
|
import distorm3
|
|
from distorm3._generated import Registers, Mnemonics
|
|
|
|
# We require YASM assembler to work.
|
|
# Set YASM_PATH envar to its full binary path.
|
|
YASM_PATH = os.environ.get("YASM_PATH", "yasm")
|
|
|
|
REG_NONE = 255
|
|
|
|
class _Registers(object):
|
|
def __init__(self):
|
|
for index, name in enumerate(distorm3.Registers):
|
|
if name:
|
|
setattr(_Registers, name, index)
|
|
|
|
Regs = _Registers()
|
|
fbin = []
|
|
|
|
def Assemble(text, mode):
|
|
lines = text.replace("\n", "\r\n")
|
|
lines = ("bits %d\r\n" % mode) + lines
|
|
asm_name = ""
|
|
with tempfile.NamedTemporaryFile(suffix=".asm", prefix="distorm3-test-", mode="wb+", delete=False) as asm_file:
|
|
asm_file.write(lines.encode())
|
|
asm_file.flush() # Doesn't work instantly on windows. :(
|
|
asm_name = asm_file.name
|
|
asm_file.close()
|
|
out_name = asm_name + ".out"
|
|
cmd = [YASM_PATH, "-m%s" % ("amd64" if mode == 64 else "x86"), asm_name, "-o%s" % out_name]
|
|
subprocess.check_call(cmd, shell=(sys.platform == "win32"))
|
|
with open(out_name, "rb") as out_file:
|
|
s = out_file.read()
|
|
os.unlink(out_name)
|
|
if len(asm_name):
|
|
os.unlink(asm_name)
|
|
return s
|
|
|
|
class Test(unittest.TestCase):
|
|
def __init__(self):
|
|
unittest.TestCase.__init__(self, "test_dummy")
|
|
def test_dummy(self):
|
|
self.fail("dummy")
|
|
|
|
class InstBin(Test):
|
|
def __init__(self, bin, mode, features, address):
|
|
Test.__init__(self)
|
|
try:
|
|
bin = bin.decode("hex")
|
|
except:
|
|
bin = bytes.fromhex(bin)
|
|
#fbin[mode].write(bin)
|
|
self.insts = distorm3.Decompose(address, bin, mode, features)
|
|
self.inst = self.insts[0]
|
|
def check_valid(self, instsNo = 1):
|
|
self.assertNotEqual(self.inst.rawFlags, 65535)
|
|
self.assertEqual(len(self.insts), instsNo)
|
|
def check_invalid(self):
|
|
self.assertEqual(self.inst.rawFlags, 65535)
|
|
def check_mnemonic(self, mnemonic, instNo = 0):
|
|
self.assertNotEqual(self.inst.rawFlags, 65535)
|
|
self.assertEqual(self.insts[instNo].mnemonic, mnemonic)
|
|
|
|
class Inst(Test):
|
|
def __init__(self, instText, mode, instNo, features):
|
|
Test.__init__(self)
|
|
modeSize = [16, 32, 64][mode]
|
|
bin = Assemble(instText, modeSize)
|
|
#print map(lambda x: hex(ord(x)), bin)
|
|
#fbin[mode].write(bin)
|
|
self.insts = distorm3.Decompose(0, bin, mode, features)
|
|
self.inst = self.insts[instNo]
|
|
|
|
def check_mnemonic(self, mnemonic):
|
|
self.assertEqual(self.inst.mnemonic, mnemonic)
|
|
|
|
def check_imm(self, n, val, sz):
|
|
self.assertEqual(self.inst.operands[n].type, distorm3.OPERAND_IMMEDIATE)
|
|
self.assertEqual(self.inst.operands[n].size, sz)
|
|
self.assertEqual(self.inst.operands[n].value, val)
|
|
|
|
def check_reg(self, n, idx, sz):
|
|
self.assertEqual(self.inst.operands[n].type, distorm3.OPERAND_REGISTER)
|
|
self.assertEqual(self.inst.operands[n].index, idx)
|
|
self.assertEqual(self.inst.operands[n].size, sz)
|
|
|
|
def check_pc(self, val, sz):
|
|
self.assertEqual(self.inst.operands[0].type, distorm3.OPERAND_IMMEDIATE)
|
|
self.assertEqual(self.inst.operands[0].size, sz)
|
|
self.assertEqual(self.inst.operands[0].value, val)
|
|
|
|
def check_disp(self, n, val, dispSize, derefSize):
|
|
self.assertEqual(self.inst.operands[n].type, distorm3.OPERAND_MEMORY)
|
|
self.assertEqual(self.inst.operands[n].dispSize, dispSize)
|
|
self.assertEqual(self.inst.operands[n].size, derefSize)
|
|
self.assertEqual(self.inst.operands[n].disp, val)
|
|
|
|
def check_abs_disp(self, n, val, dispSize, derefSize):
|
|
self.assertEqual(self.inst.operands[n].type, distorm3.OPERAND_ABSOLUTE_ADDRESS)
|
|
self.assertEqual(self.inst.operands[n].dispSize, dispSize)
|
|
self.assertEqual(self.inst.operands[n].size, derefSize)
|
|
self.assertEqual(self.inst.operands[n].disp, val)
|
|
|
|
def check_simple_deref(self, n, idx, derefSize):
|
|
""" Checks whether a (simple) memory dereference type is used, size of deref is in ops.size.
|
|
Displacement is ignored in this check. """
|
|
self.assertEqual(self.inst.operands[n].type, distorm3.OPERAND_MEMORY)
|
|
self.assertEqual(self.inst.operands[n].size, derefSize)
|
|
self.assertEqual(self.inst.operands[n].index, idx)
|
|
|
|
def check_deref(self, n, idx, base, derefSize):
|
|
""" Checks whether a memory dereference type is used, size of deref is in ops.size.
|
|
Base registers is in inst.base.
|
|
Displacement is ignored in this check. """
|
|
self.assertEqual(self.inst.operands[n].type, distorm3.OPERAND_MEMORY)
|
|
self.assertEqual(self.inst.operands[n].size, derefSize)
|
|
self.assertEqual(self.inst.operands[n].index, idx)
|
|
self.assertEqual(self.inst.operands[n].base, base)
|
|
|
|
def check_type_size(self, n, t, sz):
|
|
self.assertEqual(self.inst.operands[n].type, t)
|
|
self.assertEqual(self.inst.operands[n].size, sz)
|
|
|
|
def check_addr_size(self, sz):
|
|
self.assertEqual({0: 16, 1: 32, 2: 64}[(self.inst.rawFlags >> 10) & 3], sz)
|
|
|
|
def I16(instText, instNo = 0, features = 0):
|
|
return Inst(instText, distorm3.Decode16Bits, instNo, features)
|
|
|
|
def IB16(bin, features = 0, address = 0):
|
|
return InstBin(bin, distorm3.Decode16Bits, features, address)
|
|
|
|
def I32(instText, features = 0):
|
|
return Inst(instText, distorm3.Decode32Bits, 0, features)
|
|
|
|
def IB32(bin, features = 0, address = 0):
|
|
return InstBin(bin, distorm3.Decode32Bits, features, address)
|
|
|
|
def I64(instText, features = 0):
|
|
return Inst(instText, distorm3.Decode64Bits, 0, features)
|
|
|
|
def IB64(bin, features = 0, address = 0):
|
|
return InstBin(bin, distorm3.Decode64Bits, features, address)
|
|
|
|
def ABS64(x):
|
|
return x
|
|
#return struct.unpack("q", struct.pack("Q", x))[0]
|
|
|
|
class TestMode16(unittest.TestCase):
|
|
Derefs = ["BX + SI", "BX + DI", "BP + SI", "BP + DI", "SI", "DI", "BP", "BX"]
|
|
DerefsInfo = [(Regs.BX, Regs.SI), (Regs.BX, Regs.DI), (Regs.BP, Regs.SI), (Regs.BP, Regs.DI),
|
|
(Regs.SI,), (Regs.DI,), (Regs.BP,), (Regs.BX,)]
|
|
def test_none(self):
|
|
self.assertFalse(len(I16("cbw").inst.operands) > 0)
|
|
def test_imm8(self):
|
|
I16("int 0x55").check_imm(0, 0x55, 8)
|
|
def test_imm16(self):
|
|
I16("ret 0x1122").check_imm(0, 0x1122, 16)
|
|
def test_seimm32(self):
|
|
I16("mov ax, 0xff80").check_imm(1, 0xff80, 16)
|
|
self.assertTrue(str(IB16("BA8080").inst).find("0x8080") != -1)
|
|
def test_imm_full(self):
|
|
I16("push 0x1234").check_imm(0, 0x1234, 16)
|
|
def test_imm_aadm(self):
|
|
I16("aam").check_imm(0, 0xa, 8)
|
|
I16("aam 0x15").check_imm(0, 0x15, 8)
|
|
I16("aad").check_imm(0, 0xa, 8)
|
|
I16("aad 0x51").check_imm(0, 0x51, 8)
|
|
def test_seimm(self):
|
|
I16("push 5").check_imm(0, 0x5, 8)
|
|
a = I16("push -6")
|
|
self.assertTrue(str(a.inst).find("-0x6") != -1)
|
|
self.assertEqual(a.inst.size, 2)
|
|
a.check_type_size(0, distorm3.OPERAND_IMMEDIATE, 8)
|
|
self.assertFalse(ABS64(a.inst.operands[0].value) != -6)
|
|
a = I16("db 0x66\n push -5")
|
|
self.assertEqual(a.inst.size, 3)
|
|
a.check_type_size(0, distorm3.OPERAND_IMMEDIATE, 32)
|
|
self.assertFalse(ABS64(a.inst.operands[0].value) != -5)
|
|
def test_imm16_1_imm8_2(self):
|
|
a = I16("enter 0x1234, 0x40")
|
|
a.check_imm(0, 0x1234, 16)
|
|
a.check_imm(1, 0x40, 8)
|
|
def test_imm8_1_imm8_2(self):
|
|
a = I16("extrq xmm0, 0x55, 0xff")
|
|
a.check_imm(1, 0x55, 8)
|
|
a.check_imm(2, 0xff, 8)
|
|
def test_reg8(self):
|
|
I16("inc dh").check_reg(0, Regs.DH, 8)
|
|
def test_reg16(self):
|
|
I16("arpl ax, bp").check_reg(1, Regs.BP, 16)
|
|
def test_reg_full(self):
|
|
I16("dec di").check_reg(0, Regs.DI, 16)
|
|
def test_reg32(self):
|
|
I16("movmskps ebx, xmm6").check_reg(0, Regs.EBX, 32)
|
|
def test_reg32_64(self):
|
|
I16("cvttsd2si esp, xmm3").check_reg(0, Regs.ESP, 32)
|
|
def test_freg32_64_rm(self):
|
|
I16("mov cr0, eax").check_reg(1, Regs.EAX, 32)
|
|
def test_rm8(self):
|
|
I16("seto dh").check_reg(0, Regs.DH, 8)
|
|
def test_rm16(self):
|
|
I16("str di").check_reg(0, Regs.DI, 16)
|
|
def test_rm_full(self):
|
|
I16("push bp").check_reg(0, Regs.BP, 16)
|
|
def test_rm32_64(self):
|
|
I16("movd xmm0, ebx").check_reg(1, Regs.EBX, 32)
|
|
def test_fpum16(self):
|
|
I16("fiadd word [bx]").check_simple_deref(0, Regs.BX, 16)
|
|
def test_fpum32(self):
|
|
I16("fisttp dword [si]").check_simple_deref(0, Regs.SI, 32)
|
|
def test_fpum64(self):
|
|
I16("fadd qword [esp]").check_simple_deref(0, Regs.ESP, 64)
|
|
def test_fpum80(self):
|
|
I16("fbld [eax]").check_simple_deref(0, Regs.EAX, 80)
|
|
def test_r32_m8(self):
|
|
I16("pinsrb xmm4, eax, 0x55").check_reg(1, Regs.EAX, 32)
|
|
I16("pinsrb xmm4, [bx], 0x55").check_simple_deref(1, Regs.BX, 8)
|
|
def test_r32_m16(self):
|
|
I16("pinsrw xmm4, edi, 0x55").check_reg(1, Regs.EDI, 32)
|
|
I16("pinsrw xmm1, word [si], 0x55").check_simple_deref(1, Regs.SI, 16)
|
|
def test_r32_64_m8(self):
|
|
I16("pextrb eax, xmm4, 0xaa").check_reg(0, Regs.EAX, 32)
|
|
I16("pextrb [bx], xmm2, 0xaa").check_simple_deref(0, Regs.BX, 8)
|
|
def test_r32_64_m16(self):
|
|
I16("pextrw esp, xmm7, 0x11").check_reg(0, Regs.ESP, 32)
|
|
I16("pextrw [bp], xmm0, 0xbb").check_simple_deref(0, Regs.BP, 16)
|
|
def test_rfull_m16(self):
|
|
I16("smsw ax").check_reg(0, Regs.AX, 16)
|
|
I16("smsw [bx]").check_simple_deref(0, Regs.BX, 16)
|
|
def test_creg(self):
|
|
I16("mov esp, cr3").check_reg(1, Regs.CR3, 32)
|
|
#I16("mov esp, cr8").check_reg(1, Regs.CR8, 32)
|
|
def test_dreg(self):
|
|
I16("mov edi, dr7").check_reg(1, Regs.DR7, 32)
|
|
def test_sreg(self):
|
|
I16("mov ax, ds").check_reg(1, Regs.DS, 16)
|
|
I16("mov ax, cs").check_reg(1, Regs.CS, 16)
|
|
def test_seg(self):
|
|
I16("push fs").check_reg(0, Regs.FS, 16)
|
|
I16("db 0x66\n push es").check_reg(0, Regs.ES, 16)
|
|
def test_acc8(self):
|
|
I16("in al, 0x60").check_reg(0, Regs.AL, 8)
|
|
def test_acc_full(self):
|
|
I16("add ax, 0x100").check_reg(0, Regs.AX, 16)
|
|
def test_acc_full_not64(self):
|
|
I16("out 0x64, ax").check_reg(1, Regs.AX, 16)
|
|
def test_mem16_full(self):
|
|
I16("call far [bp]").check_simple_deref(0, Regs.BP, 16)
|
|
def test_ptr16_full(self):
|
|
a = I16("jmp 0xffff:0x1234").inst
|
|
self.assertEqual(a.size, 5)
|
|
self.assertEqual(a.operands[0].type, distorm3.OPERAND_FAR_MEMORY)
|
|
self.assertEqual(a.operands[0].size, 16)
|
|
self.assertEqual(a.operands[0].seg, 0xffff)
|
|
self.assertEqual(a.operands[0].off, 0x1234)
|
|
def test_mem16_3264(self):
|
|
I16("sgdt [bx]").check_simple_deref(0, Regs.BX, 32)
|
|
def test_relcb(self):
|
|
a = I16("db 0xe9\ndw 0x00")
|
|
a.check_pc(3, 16)
|
|
a = I16("db 0xe2\ndb 0x50")
|
|
a.check_pc(0x52, 8)
|
|
a = I16("db 0xe2\ndb 0xfd")
|
|
a.check_pc(-1, 8)
|
|
a = I16("db 0x67\ndb 0xe2\ndb 0xf0")
|
|
a.check_pc(-0xd, 8)
|
|
def test_relc_full(self):
|
|
a = I16("jmp 0x100")
|
|
self.assertEqual(a.inst.size, 3)
|
|
a.check_type_size(0, distorm3.OPERAND_IMMEDIATE, 16)
|
|
def test_mem(self):
|
|
I16("lea ax, [bx]").check_simple_deref(1, Regs.BX, 0)
|
|
def test_mem32(self):
|
|
I16("movntss [ebx], xmm5").check_simple_deref(0, Regs.EBX, 32)
|
|
def test_mem32_64(self):
|
|
I16("movnti [ebx], eax").check_simple_deref(0, Regs.EBX, 32)
|
|
def test_mem64(self):
|
|
I16("movlps [edi], xmm7").check_simple_deref(0, Regs.EDI, 64)
|
|
def test_mem128(self):
|
|
I16("movntps [eax], xmm3").check_simple_deref(0, Regs.EAX, 128)
|
|
def test_mem64_128(self):
|
|
I16("cmpxchg8b [edx]").check_simple_deref(0, Regs.EDX, 64)
|
|
def test_moffs8(self):
|
|
I16("mov al, [0x1234]").check_abs_disp(1, 0x1234, 16, 8)
|
|
I16("mov [dword 0x11112222], al").check_abs_disp(0, 0x11112222, 32, 8)
|
|
def test_moff_full(self):
|
|
I16("mov [0x8765], ax").check_abs_disp(0, 0x8765, 16, 16)
|
|
I16("mov ax, [dword 0x11112222]").check_abs_disp(1, 0x11112222, 32, 16)
|
|
def test_const1(self):
|
|
I16("shl si, 1").check_imm(1, 1, 8)
|
|
def test_regcl(self):
|
|
I16("rcl bp, cl").check_reg(1, Regs.CL, 8)
|
|
def test_ib_rb(self):
|
|
I16("mov dl, 0x88").check_reg(0, Regs.DL, 8)
|
|
def test_ib_r_dw_qw(self):
|
|
I16("bswap ecx").check_reg(0, Regs.ECX, 32)
|
|
def test_ib_r_full(self):
|
|
I16("inc si").check_reg(0, Regs.SI, 16)
|
|
def test_regi_esi(self):
|
|
I16("lodsb").check_simple_deref(1, Regs.SI, 8)
|
|
I16("cmpsw").check_simple_deref(0, Regs.SI, 16)
|
|
I16("lodsd").check_simple_deref(1, Regs.SI, 32)
|
|
def test_regi_edi(self):
|
|
I16("movsb").check_simple_deref(0, Regs.DI, 8)
|
|
I16("scasw").check_simple_deref(0, Regs.DI, 16)
|
|
I16("stosd").check_simple_deref(0, Regs.DI, 32)
|
|
def test_regi_ebxal(self):
|
|
a = I16("xlatb")
|
|
a.check_type_size(0, distorm3.OPERAND_MEMORY, 8)
|
|
self.assertFalse(a.inst.operands[0].index != Regs.AL)
|
|
self.assertFalse(a.inst.operands[0].base != Regs.BX)
|
|
def test_regi_eax(self):
|
|
I16("vmrun [ax]").check_simple_deref(0, Regs.AX, 16)
|
|
def test_regdx(self):
|
|
I16("in ax, dx").check_reg(1, Regs.DX, 16)
|
|
def test_regecx(self):
|
|
I16("invlpga [eax], ecx").check_reg(1, Regs.ECX, 32)
|
|
def test_fpu_si(self):
|
|
I16("fxch st4").check_reg(0, Regs.ST4, 32)
|
|
def test_fpu_ssi(self):
|
|
a = I16("fcmovnbe st0, st3")
|
|
a.check_reg(0, Regs.ST0, 32)
|
|
a.check_reg(1, Regs.ST3, 32)
|
|
def test_fpu_sis(self):
|
|
a = I16("fadd st3, st0")
|
|
a.check_reg(0, Regs.ST3, 32)
|
|
a.check_reg(1, Regs.ST0, 32)
|
|
def test_mm(self):
|
|
I16("pand mm0, mm7").check_reg(0, Regs.MM0, 64)
|
|
def test_mm_rm(self):
|
|
I16("psllw mm0, 0x55").check_reg(0, Regs.MM0, 64)
|
|
def test_mm32(self):
|
|
I16("punpcklbw mm1, [si]").check_simple_deref(1, Regs.SI, 32)
|
|
def test_mm64(self):
|
|
I16("packsswb mm3, [bx]").check_simple_deref(1, Regs.BX, 64)
|
|
def test_xmm(self):
|
|
I16("orps xmm5, xmm4").check_reg(0, Regs.XMM5, 128)
|
|
def test_xmm_rm(self):
|
|
I16("psrlw xmm6, 0x12").check_reg(0, Regs.XMM6, 128)
|
|
def test_xmm16(self):
|
|
I16("pmovsxbq xmm3, [bp]").check_simple_deref(1, Regs.BP, 16)
|
|
def test_xmm32(self):
|
|
I16("pmovsxwq xmm5, [di]").check_simple_deref(1, Regs.DI, 32)
|
|
def test_xmm64(self):
|
|
I16("roundsd xmm6, [si], 0x55").check_simple_deref(1, Regs.SI, 64)
|
|
def test_xmm128(self):
|
|
I16("roundpd xmm7, [bx], 0xaa").check_simple_deref(1, Regs.BX, 128)
|
|
def test_regxmm0(self):
|
|
I16("blendvpd xmm1, xmm3, xmm0").check_reg(2, Regs.XMM0, 128)
|
|
def test_disp_only(self):
|
|
a = I16("add [0x1234], bx")
|
|
a.check_type_size(0, distorm3.OPERAND_ABSOLUTE_ADDRESS, 16)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 16)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x1234)
|
|
def test_modrm(self):
|
|
texts = ["ADD [%s], AX" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I16(i[1])
|
|
if len(self.DerefsInfo[i[0]]) == 2:
|
|
a.check_deref(0, self.DerefsInfo[i[0]][1], self.DerefsInfo[i[0]][0], 16)
|
|
else:
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]][0], 16)
|
|
def test_modrm_disp8(self):
|
|
texts = ["ADD [%s + 0x55], AX" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I16(i[1])
|
|
if len(self.DerefsInfo[i[0]]) == 2:
|
|
a.check_deref(0, self.DerefsInfo[i[0]][1], self.DerefsInfo[i[0]][0], 16)
|
|
else:
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]][0], 16)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 8)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x55)
|
|
def test_modrm_disp16(self):
|
|
texts = ["ADD [%s + 0x3322], AX" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I16(i[1])
|
|
if len(self.DerefsInfo[i[0]]) == 2:
|
|
a.check_deref(0, self.DerefsInfo[i[0]][1], self.DerefsInfo[i[0]][0], 16)
|
|
else:
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]][0], 16)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 16)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x3322)
|
|
|
|
class TestMode32(unittest.TestCase):
|
|
Derefs = ["EAX", "ECX", "EDX", "EBX", "EBP", "ESI", "EDI"]
|
|
DerefsInfo = [Regs.EAX, Regs.ECX, Regs.EDX, Regs.EBX, Regs.EBP, Regs.ESI, Regs.EDI]
|
|
def test_none(self):
|
|
self.assertFalse(len(I32("cdq").inst.operands) > 0)
|
|
def test_imm8(self):
|
|
I32("int 0x55").check_imm(0, 0x55, 8)
|
|
def test_imm16(self):
|
|
I32("ret 0x1122").check_imm(0, 0x1122, 16)
|
|
def test_seimm32(self):
|
|
I32("mov eax, 0xff112233").check_imm(1, 0xff112233, 32)
|
|
self.assertTrue(str(IB32("BA5F6038CE").inst).find("0xce38605f") != -1)
|
|
def test_imm_full(self):
|
|
I32("push 0x12345678").check_imm(0, 0x12345678, 32)
|
|
def test_imm_aadm(self):
|
|
I32("aam").check_imm(0, 0xa, 8)
|
|
I32("aam 0x15").check_imm(0, 0x15, 8)
|
|
I32("aad").check_imm(0, 0xa, 8)
|
|
I32("aad 0x51").check_imm(0, 0x51, 8)
|
|
def test_seimm(self):
|
|
I32("push 6").check_imm(0, 0x6, 8)
|
|
a = I32("push -7")
|
|
self.assertEqual(a.inst.size, 2)
|
|
self.assertTrue(str(a.inst).find("-0x7") != -1)
|
|
a.check_type_size(0, distorm3.OPERAND_IMMEDIATE, 8)
|
|
self.assertFalse(ABS64(a.inst.operands[0].value) != -7)
|
|
a = I32("db 0x66\n push -5")
|
|
self.assertEqual(a.inst.size, 3)
|
|
a.check_type_size(0, distorm3.OPERAND_IMMEDIATE, 16)
|
|
self.assertFalse(ABS64(a.inst.operands[0].value) != -5)
|
|
def test_imm16_1_imm8_2(self):
|
|
a = I32("enter 0x1234, 0x40")
|
|
a.check_imm(0, 0x1234, 16)
|
|
a.check_imm(1, 0x40, 8)
|
|
def test_imm8_1_imm8_2(self):
|
|
a = I32("extrq xmm0, 0x55, 0xff")
|
|
a.check_imm(1, 0x55, 8)
|
|
a.check_imm(2, 0xff, 8)
|
|
def test_reg8(self):
|
|
I32("inc dh").check_reg(0, Regs.DH, 8)
|
|
def test_reg16(self):
|
|
I32("arpl ax, bp").check_reg(1, Regs.BP, 16)
|
|
def test_reg_full(self):
|
|
I32("dec edi").check_reg(0, Regs.EDI, 32)
|
|
def test_reg32(self):
|
|
I32("movmskps ebx, xmm6").check_reg(0, Regs.EBX, 32)
|
|
def test_reg32_64(self):
|
|
I32("cvttsd2si esp, xmm3").check_reg(0, Regs.ESP, 32)
|
|
def test_freg32_64_rm(self):
|
|
I32("mov cr0, eax").check_reg(1, Regs.EAX, 32)
|
|
def test_rm8(self):
|
|
I32("seto dh").check_reg(0, Regs.DH, 8)
|
|
def test_rm16(self):
|
|
I32("verr di").check_reg(0, Regs.DI, 16)
|
|
def test_rm_full(self):
|
|
I32("push ebp").check_reg(0, Regs.EBP, 32)
|
|
def test_rm32_64(self):
|
|
I32("movd xmm0, ebx").check_reg(1, Regs.EBX, 32)
|
|
def test_fpum16(self):
|
|
I32("fiadd word [ebx]").check_simple_deref(0, Regs.EBX, 16)
|
|
def test_fpum32(self):
|
|
I32("fisttp dword [esi]").check_simple_deref(0, Regs.ESI, 32)
|
|
def test_fpum64(self):
|
|
I32("fadd qword [esp]").check_simple_deref(0, Regs.ESP, 64)
|
|
def test_fpum80(self):
|
|
I32("fbld [eax]").check_simple_deref(0, Regs.EAX, 80)
|
|
def test_r32_m8(self):
|
|
I32("pinsrb xmm4, eax, 0x55").check_reg(1, Regs.EAX, 32)
|
|
I32("pinsrb xmm4, [ebx], 0x55").check_simple_deref(1, Regs.EBX, 8)
|
|
def test_r32_m16(self):
|
|
I32("pinsrw xmm4, edi, 0x55").check_reg(1, Regs.EDI, 32)
|
|
I32("pinsrw xmm1, word [esi], 0x55").check_simple_deref(1, Regs.ESI, 16)
|
|
def test_r32_64_m8(self):
|
|
I32("pextrb eax, xmm4, 0xaa").check_reg(0, Regs.EAX, 32)
|
|
I32("pextrb [ebx], xmm2, 0xaa").check_simple_deref(0, Regs.EBX, 8)
|
|
def test_r32_64_m16(self):
|
|
I32("pextrw esp, xmm7, 0x11").check_reg(0, Regs.ESP, 32)
|
|
I32("pextrw [ebp], xmm0, 0xbb").check_simple_deref(0, Regs.EBP, 16)
|
|
def test_rfull_m16(self):
|
|
I32("smsw eax").check_reg(0, Regs.EAX, 32)
|
|
I32("smsw [ebx]").check_simple_deref(0, Regs.EBX, 16)
|
|
def test_creg(self):
|
|
I32("mov esp, cr3").check_reg(1, Regs.CR3, 32)
|
|
def test_dreg(self):
|
|
I32("mov edi, dr7").check_reg(1, Regs.DR7, 32)
|
|
def test_sreg(self):
|
|
I32("mov ax, ds").check_reg(1, Regs.DS, 16)
|
|
I32("mov ax, cs").check_reg(1, Regs.CS, 16)
|
|
def test_seg(self):
|
|
I32("push ss").check_reg(0, Regs.SS, 16)
|
|
I32("db 0x66\n push ds").check_reg(0, Regs.DS, 16)
|
|
def test_acc8(self):
|
|
I32("in al, 0x60").check_reg(0, Regs.AL, 8)
|
|
def test_acc_full(self):
|
|
I32("add eax, 0x100").check_reg(0, Regs.EAX, 32)
|
|
def test_acc_full_not64(self):
|
|
I32("out 0x64, eax").check_reg(1, Regs.EAX, 32)
|
|
def test_mem16_full(self):
|
|
I32("call far [ebp]").check_simple_deref(0, Regs.EBP, 32)
|
|
def test_ptr16_full(self):
|
|
a = I32("jmp 0xffff:0x12345678").inst
|
|
self.assertEqual(a.size, 7)
|
|
self.assertEqual(a.operands[0].type, distorm3.OPERAND_FAR_MEMORY)
|
|
self.assertEqual(a.operands[0].size, 32)
|
|
self.assertEqual(a.operands[0].seg, 0xffff)
|
|
self.assertEqual(a.operands[0].off, 0x12345678)
|
|
def test_mem16_3264(self):
|
|
I32("sgdt [ebx]").check_simple_deref(0, Regs.EBX, 32)
|
|
def test_relcb(self):
|
|
a = I32("db 0xe9\ndd 0x00")
|
|
a.check_pc(5, 32)
|
|
a = I32("db 0xe2\ndb 0x50")
|
|
a.check_pc(0x52, 8)
|
|
a = I32("db 0xe2\ndb 0xfd")
|
|
a.check_pc(-1, 8)
|
|
a = I32("db 0x67\ndb 0xe2\ndb 0xf0")
|
|
a.check_pc(-0xd, 8)
|
|
def test_relc_full(self):
|
|
a = I32("jmp 0x100")
|
|
self.assertEqual(a.inst.size, 5)
|
|
a.check_type_size(0, distorm3.OPERAND_IMMEDIATE, 32)
|
|
def test_mem(self):
|
|
I32("lea ax, [ebx]").check_simple_deref(1, Regs.EBX, 0)
|
|
def test_mem32(self):
|
|
I32("movntss [ebx], xmm5").check_simple_deref(0, Regs.EBX, 32)
|
|
def test_mem32_64(self):
|
|
I32("movnti [edi], eax").check_simple_deref(0, Regs.EDI, 32)
|
|
def test_mem64(self):
|
|
I32("movlps [edi], xmm7").check_simple_deref(0, Regs.EDI, 64)
|
|
def test_mem128(self):
|
|
I32("movntps [eax], xmm3").check_simple_deref(0, Regs.EAX, 128)
|
|
def test_mem64_128(self):
|
|
I32("cmpxchg8b [edx]").check_simple_deref(0, Regs.EDX, 64)
|
|
def test_moffs8(self):
|
|
I32("mov al, [word 0x5678]").check_abs_disp(1, 0x5678, 16, 8)
|
|
I32("mov [0x11112222], al").check_abs_disp(0, 0x11112222, 32, 8)
|
|
def test_moff_full(self):
|
|
I32("mov [word 0x4321], eax").check_abs_disp(0, 0x4321, 16, 32)
|
|
I32("mov eax, [0x11112222]").check_abs_disp(1, 0x11112222, 32, 32)
|
|
def test_const1(self):
|
|
I32("shl esi, 1").check_imm(1, 1, 8)
|
|
def test_regcl(self):
|
|
I32("rcl ebp, cl").check_reg(1, Regs.CL, 8)
|
|
def test_ib_rb(self):
|
|
I32("mov dl, 0x88").check_reg(0, Regs.DL, 8)
|
|
def test_ib_r_dw_qw(self):
|
|
I32("bswap ecx").check_reg(0, Regs.ECX, 32)
|
|
def test_ib_r_full(self):
|
|
I32("inc esi").check_reg(0, Regs.ESI, 32)
|
|
def test_regi_esi(self):
|
|
I32("lodsb").check_simple_deref(1, Regs.ESI, 8)
|
|
I32("cmpsw").check_simple_deref(0, Regs.ESI, 16)
|
|
I32("lodsd").check_simple_deref(1, Regs.ESI, 32)
|
|
def test_regi_edi(self):
|
|
I32("movsb").check_simple_deref(0, Regs.EDI, 8)
|
|
I32("scasw").check_simple_deref(0, Regs.EDI, 16)
|
|
I32("stosd").check_simple_deref(0, Regs.EDI, 32)
|
|
def test_regi_ebxal(self):
|
|
a = I32("xlatb")
|
|
a.check_type_size(0, distorm3.OPERAND_MEMORY, 8)
|
|
self.assertFalse(a.inst.operands[0].index != Regs.AL)
|
|
self.assertFalse(a.inst.operands[0].base != Regs.EBX)
|
|
def test_regi_eax(self):
|
|
I32("vmrun [eax]").check_simple_deref(0, Regs.EAX, 32)
|
|
def test_regdx(self):
|
|
I32("in eax, dx").check_reg(1, Regs.DX, 16)
|
|
def test_regecx(self):
|
|
I32("invlpga [eax], ecx").check_reg(1, Regs.ECX, 32)
|
|
def test_fpu_si(self):
|
|
I32("fxch st4").check_reg(0, Regs.ST4, 32)
|
|
def test_fpu_ssi(self):
|
|
a = I32("fcmovnbe st0, st3")
|
|
a.check_reg(0, Regs.ST0, 32)
|
|
a.check_reg(1, Regs.ST3, 32)
|
|
def test_fpu_sis(self):
|
|
a = I32("fadd st3, st0")
|
|
a.check_reg(0, Regs.ST3, 32)
|
|
a.check_reg(1, Regs.ST0, 32)
|
|
def test_mm(self):
|
|
I32("pand mm0, mm7").check_reg(0, Regs.MM0, 64)
|
|
def test_mm_rm(self):
|
|
I32("psllw mm0, 0x55").check_reg(0, Regs.MM0, 64)
|
|
def test_mm32(self):
|
|
I32("punpcklbw mm1, [esi]").check_simple_deref(1, Regs.ESI, 32)
|
|
def test_mm64(self):
|
|
I32("packsswb mm3, [ebx]").check_simple_deref(1, Regs.EBX, 64)
|
|
def test_xmm(self):
|
|
I32("orps xmm5, xmm4").check_reg(0, Regs.XMM5, 128)
|
|
def test_xmm_rm(self):
|
|
I32("psrlw xmm6, 0x12").check_reg(0, Regs.XMM6, 128)
|
|
def test_xmm16(self):
|
|
I32("pmovsxbq xmm3, [ebp]").check_simple_deref(1, Regs.EBP, 16)
|
|
def test_xmm32(self):
|
|
I32("pmovsxwq xmm5, [edi]").check_simple_deref(1, Regs.EDI, 32)
|
|
def test_xmm64(self):
|
|
I32("roundsd xmm6, [esi], 0x55").check_simple_deref(1, Regs.ESI, 64)
|
|
def test_xmm128(self):
|
|
I32("roundpd xmm7, [ebx], 0xaa").check_simple_deref(1, Regs.EBX, 128)
|
|
def test_regxmm0(self):
|
|
I32("blendvpd xmm1, xmm3, xmm0").check_reg(2, Regs.XMM0, 128)
|
|
def test_cr8(self):
|
|
I32("db 0xf0\n mov cr0, eax").check_reg(0, Regs.CR8, 32)
|
|
def test_disp_only(self):
|
|
a = I32("add [0x12345678], ebx")
|
|
a.check_type_size(0, distorm3.OPERAND_ABSOLUTE_ADDRESS, 32)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x12345678)
|
|
def test_modrm(self):
|
|
texts = ["ADD [%s], EDI" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I32(i[1])
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]], 32)
|
|
def test_modrm_disp8(self):
|
|
texts = ["ADD [%s + 0x55], ESI" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I32(i[1])
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]], 32)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 8)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x55)
|
|
def test_modrm_disp32(self):
|
|
texts = ["ADD [%s + 0x33221144], EDX" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I32(i[1])
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]], 32)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x33221144)
|
|
def test_base_ebp(self):
|
|
a = I32("mov [ebp+0x55], eax")
|
|
a.check_simple_deref(0, Regs.EBP, 32)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 8)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x55)
|
|
a = I32("mov [ebp+0x55+eax], eax")
|
|
a.check_deref(0, Regs.EAX, Regs.EBP, 32)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 8)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x55)
|
|
a = I32("mov [ebp+0x55443322], eax")
|
|
a.check_simple_deref(0, Regs.EBP, 32)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x55443322)
|
|
Bases = ["EAX", "ECX", "EDX", "EBX", "ESP", "ESI", "EDI"]
|
|
BasesInfo = [Regs.EAX, Regs.ECX, Regs.EDX, Regs.EBX, Regs.ESP, Regs.ESI, Regs.EDI]
|
|
Indices = ["EAX", "ECX", "EDX", "EBX", "EBP", "ESI", "EDI"]
|
|
IndicesInfo = [Regs.EAX, Regs.ECX, Regs.EDX, Regs.EBX, Regs.EBP, Regs.ESI, Regs.EDI]
|
|
def test_bases(self):
|
|
for i in enumerate(self.Bases):
|
|
a = I32("cmp ebp, [%s]" % (i[1]))
|
|
a.check_simple_deref(1, self.BasesInfo[i[0]], 32)
|
|
def test_bases_disp32(self):
|
|
for i in enumerate(self.Bases):
|
|
a = I32("cmp ebp, [%s+0x12345678]" % (i[1]))
|
|
a.check_simple_deref(1, self.BasesInfo[i[0]], 32)
|
|
self.assertFalse(a.inst.operands[1].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[1].disp != 0x12345678)
|
|
def test_scales(self):
|
|
for i in enumerate(self.Indices):
|
|
# A scale of 2 causes the scale to be omitted and changed from reg*2 to reg+reg.
|
|
for s in [4, 8]:
|
|
a = I32("and bp, [%s*%d]" % (i[1], s))
|
|
a.check_deref(1, self.IndicesInfo[i[0]], None, 16)
|
|
self.assertFalse(a.inst.operands[1].scale != s)
|
|
def test_sib(self):
|
|
for i in enumerate(self.Indices):
|
|
for j in enumerate(self.Bases):
|
|
for s in [1, 2, 4, 8]:
|
|
a = I32("or bp, [%s*%d + %s]" % (i[1], s, j[1]))
|
|
a.check_deref(1, self.IndicesInfo[i[0]], self.BasesInfo[j[0]], 16)
|
|
if s != 1:
|
|
self.assertFalse(a.inst.operands[1].scale != s)
|
|
def test_sib_disp8(self):
|
|
for i in enumerate(self.Indices):
|
|
for j in enumerate(self.Bases):
|
|
for s in [1, 2, 4, 8]:
|
|
a = I32("xor al, [%s*%d + %s + 0x55]" % (i[1], s, j[1]))
|
|
a.check_deref(1, self.IndicesInfo[i[0]], self.BasesInfo[j[0]], 8)
|
|
self.assertFalse(a.inst.operands[1].dispSize != 8)
|
|
self.assertFalse(a.inst.operands[1].disp != 0x55)
|
|
if s != 1:
|
|
self.assertFalse(a.inst.operands[1].scale != s)
|
|
def test_sib_disp32(self):
|
|
for i in enumerate(self.Indices):
|
|
for j in enumerate(self.Bases):
|
|
for s in [1, 2, 4, 8]:
|
|
a = I32("sub ebp, [%s*%d + %s + 0x55aabbcc]" % (i[1], s, j[1]))
|
|
a.check_deref(1, self.IndicesInfo[i[0]], self.BasesInfo[j[0]], 32)
|
|
self.assertFalse(a.inst.operands[1].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[1].disp != 0x55aabbcc)
|
|
if s != 1:
|
|
self.assertFalse(a.inst.operands[1].scale != s)
|
|
|
|
class TestMode64(unittest.TestCase):
|
|
Derefs = ["RAX", "RCX", "RDX", "RBX", "RBP", "RSI", "RDI"]
|
|
DerefsInfo = [Regs.RAX, Regs.RCX, Regs.RDX, Regs.RBX, Regs.RBP, Regs.RSI, Regs.RDI]
|
|
def test_none(self):
|
|
self.assertFalse(len(I64("cdq").inst.operands) > 0)
|
|
def test_imm8(self):
|
|
I64("int 0x55").check_imm(0, 0x55, 8)
|
|
def test_imm16(self):
|
|
I64("ret 0x1122").check_imm(0, 0x1122, 16)
|
|
def test_seimm32(self):
|
|
I64("mov eax, 0xff112233").check_imm(1, -15654349, 32)
|
|
self.assertTrue(str(IB64("BA5F6038CE").inst).find("0xce38605f") != -1)
|
|
def test_imm_full(self):
|
|
I64("push 0x12345678").check_imm(0, 0x12345678, 32)
|
|
I64("mov rax, 0x1234567812345678").check_imm(1, 0x1234567812345678, 64)
|
|
def test_imm_aadm(self):
|
|
#I64("aam").check_imm(0, 0xa, 8)
|
|
#I64("aam 0x15").check_imm(0, 0x15, 8)
|
|
#I64("aad").check_imm(0, 0xa, 8)
|
|
#I64("aad 0x51").check_imm(0, 0x51, 8)
|
|
pass
|
|
def test_seimm(self):
|
|
I64("push 6").check_imm(0, 0x6, 8)
|
|
a = I64("push -7")
|
|
self.assertEqual(a.inst.size, 2)
|
|
self.assertTrue(str(a.inst).find("-0x7") != -1)
|
|
a.check_type_size(0, distorm3.OPERAND_IMMEDIATE, 8)
|
|
self.assertFalse(ABS64(a.inst.operands[0].value) != -7)
|
|
def test_imm16_1_imm8_2(self):
|
|
a = I64("enter 0x1234, 0x40")
|
|
a.check_imm(0, 0x1234, 16)
|
|
a.check_imm(1, 0x40, 8)
|
|
def test_imm8_1_imm8_2(self):
|
|
a = I64("extrq xmm0, 0x55, 0xff")
|
|
a.check_imm(1, 0x55, 8)
|
|
a.check_imm(2, 0xff, 8)
|
|
def test_reg8(self):
|
|
I64("inc dh").check_reg(0, Regs.DH, 8)
|
|
def test_reg_full(self):
|
|
I64("dec rdi").check_reg(0, Regs.RDI, 64)
|
|
I64("cmp r15, r14").check_reg(0, Regs.R15, 64)
|
|
I64("cmp r8d, r9d").check_reg(0, Regs.R8D, 32)
|
|
I64("cmp r9w, r8w").check_reg(0, Regs.R9W, 16)
|
|
def test_reg32(self):
|
|
I64("movmskps ebx, xmm6").check_reg(0, Regs.EBX, 32)
|
|
I64("movmskps r11d, xmm6").check_reg(0, Regs.R11D, 32)
|
|
def test_reg32_64(self):
|
|
I64("cvttsd2si rsp, xmm3").check_reg(0, Regs.RSP, 64)
|
|
I64("cvttsd2si r14, xmm3").check_reg(0, Regs.R14, 64)
|
|
def test_freg32_64_rm(self):
|
|
I64("mov cr0, rax").check_reg(1, Regs.RAX, 64)
|
|
I64("mov cr0, r14").check_reg(1, Regs.R14, 64)
|
|
def test_rm8(self):
|
|
I64("seto dh").check_reg(0, Regs.DH, 8)
|
|
def test_rm16(self):
|
|
I64("verr di").check_reg(0, Regs.DI, 16)
|
|
I64("verr r8w").check_reg(0, Regs.R8W, 16)
|
|
def test_rm_full(self):
|
|
I64("push rbp").check_reg(0, Regs.RBP, 64)
|
|
def test_rm32_64(self):
|
|
I64("movq xmm0, rdx").check_reg(1, Regs.RDX, 64)
|
|
I64("movq xmm0, r10").check_reg(1, Regs.R10, 64)
|
|
I64("cvtsi2sd xmm0, rdx").check_reg(1, Regs.RDX, 64)
|
|
I64("vmread rax, rax").check_reg(1, Regs.RAX, 64)
|
|
def test_rm16_32(self):
|
|
I64("movsxd rax, eax").check_reg(1, Regs.EAX, 32)
|
|
I64("movzx rax, ax").check_reg(1, Regs.AX, 16)
|
|
def test_fpum16(self):
|
|
I64("fiadd word [rbx]").check_simple_deref(0, Regs.RBX, 16)
|
|
def test_fpum32(self):
|
|
I64("fisttp dword [rsi]").check_simple_deref(0, Regs.RSI, 32)
|
|
def test_fpum64(self):
|
|
I64("fadd qword [rsp]").check_simple_deref(0, Regs.RSP, 64)
|
|
def test_fpum80(self):
|
|
I64("fbld [rax]").check_simple_deref(0, Regs.RAX, 80)
|
|
def test_r32_m8(self):
|
|
I64("pinsrb xmm4, eax, 0x55").check_reg(1, Regs.EAX, 32)
|
|
I64("pinsrb xmm4, [rbx], 0x55").check_simple_deref(1, Regs.RBX, 8)
|
|
def test_r32_m16(self):
|
|
I64("pinsrw xmm4, edi, 0x55").check_reg(1, Regs.EDI, 32)
|
|
I64("pinsrw xmm1, word [rsi], 0x55").check_simple_deref(1, Regs.RSI, 16)
|
|
I64("pinsrw xmm1, r8d, 0x55").check_reg(1, Regs.R8D, 32)
|
|
def test_r32_64_m8(self):
|
|
I64("pextrb eax, xmm4, 0xaa").check_reg(0, Regs.EAX, 32)
|
|
I64("pextrb [rbx], xmm2, 0xaa").check_simple_deref(0, Regs.RBX, 8)
|
|
def test_r32_64_m16(self):
|
|
I64("pextrw esp, xmm7, 0x11").check_reg(0, Regs.ESP, 32)
|
|
I64("pextrw [rbp], xmm0, 0xbb").check_simple_deref(0, Regs.RBP, 16)
|
|
def test_rfull_m16(self):
|
|
I64("smsw eax").check_reg(0, Regs.EAX, 32)
|
|
I64("smsw [rbx]").check_simple_deref(0, Regs.RBX, 16)
|
|
def test_creg(self):
|
|
I64("mov rsp, cr3").check_reg(1, Regs.CR3, 64)
|
|
I64("mov cr8, rdx").check_reg(0, Regs.CR8, 64)
|
|
def test_dreg(self):
|
|
I64("mov rdi, dr7").check_reg(1, Regs.DR7, 64)
|
|
def test_sreg(self):
|
|
I64("mov ax, fs").check_reg(1, Regs.FS, 16)
|
|
I64("mov ax, cs").check_reg(1, Regs.CS, 16)
|
|
def test_seg(self):
|
|
I64("push gs").check_reg(0, Regs.GS, 16)
|
|
def test_acc8(self):
|
|
I64("in al, 0x60").check_reg(0, Regs.AL, 8)
|
|
def test_acc_full(self):
|
|
I64("add rax, 0x100").check_reg(0, Regs.RAX, 64)
|
|
def test_acc_full_not64(self):
|
|
I64("out 0x64, eax").check_reg(1, Regs.EAX, 32)
|
|
I64("db 0x48\nout 0x64, eax").check_reg(1, Regs.EAX, 32)
|
|
def test_mem16_full(self):
|
|
I64("call far [rbp]").check_simple_deref(0, Regs.RBP, 32)
|
|
I64("db 0x48\n call far [rbp]").check_simple_deref(0, Regs.RBP, 64)
|
|
def test_mem16_3264(self):
|
|
I64("sgdt [rbx]").check_simple_deref(0, Regs.RBX, 64)
|
|
def test_relcb(self):
|
|
a = I64("db 0xe9\ndd 0x00")
|
|
a.check_pc(5, 32)
|
|
a = I64("db 0xe2\ndb 0x50")
|
|
a.check_pc(0x52, 8)
|
|
a = I64("db 0xe2\ndb 0xfd")
|
|
a.check_pc(-1, 8)
|
|
a = I64("db 0x67\ndb 0xe2\ndb 0xf0")
|
|
a.check_pc(-0xd, 8)
|
|
def test_relc_full(self):
|
|
a = I64("jmp 0x100")
|
|
self.assertEqual(a.inst.size, 5)
|
|
a.check_type_size(0, distorm3.OPERAND_IMMEDIATE, 32)
|
|
def test_mem(self):
|
|
I64("lea ax, [rbx]").check_simple_deref(1, Regs.RBX, 0)
|
|
def test_mem32(self):
|
|
I64("movntss [rbx], xmm5").check_simple_deref(0, Regs.RBX, 32)
|
|
def test_mem32_64(self):
|
|
I64("movnti [rdi], eax").check_simple_deref(0, Regs.RDI, 32)
|
|
I64("movnti [rbp], rax").check_simple_deref(0, Regs.RBP, 64)
|
|
def test_mem64(self):
|
|
I64("movlps [rdi], xmm7").check_simple_deref(0, Regs.RDI, 64)
|
|
def test_mem128(self):
|
|
I64("movntps [rax], xmm3").check_simple_deref(0, Regs.RAX, 128)
|
|
def test_mem64_128(self):
|
|
I64("cmpxchg8b [rdx]").check_simple_deref(0, Regs.RDX, 64)
|
|
I64("cmpxchg16b [rbx]").check_simple_deref(0, Regs.RBX, 128)
|
|
def test_moffs8(self):
|
|
I64("mov al, [dword 0x12345678]").check_abs_disp(1, 0x12345678, 32, 8)
|
|
I64("mov [qword 0xaaaabbbbccccdddd], al").check_abs_disp(0, 0xaaaabbbbccccdddd, 64, 8)
|
|
def test_moff_full(self):
|
|
I64("mov [dword 0xaaaabbbb], rax").check_abs_disp(0, 0xffffffffaaaabbbb, 32, 64)
|
|
I64("mov rax, [qword 0xaaaabbbbccccdddd]").check_abs_disp(1, 0xaaaabbbbccccdddd, 64, 64)
|
|
def test_const1(self):
|
|
I64("shl rsi, 1").check_imm(1, 1, 8)
|
|
def test_regcl(self):
|
|
I64("rcl rbp, cl").check_reg(1, Regs.CL, 8)
|
|
def test_ib_rb(self):
|
|
I64("mov dl, 0x88").check_reg(0, Regs.DL, 8)
|
|
I64("mov spl, 0x88").check_reg(0, Regs.SPL, 8)
|
|
I64("mov r10b, 0x88").check_reg(0, Regs.R10B, 8)
|
|
def test_ib_r_dw_qw(self):
|
|
I64("bswap rcx").check_reg(0, Regs.RCX, 64)
|
|
I64("bswap r10").check_reg(0, Regs.R10, 64)
|
|
I64("push r10").check_reg(0, Regs.R10, 64)
|
|
def test_ib_r_full(self):
|
|
I64("inc rsi").check_reg(0, Regs.RSI, 64)
|
|
I64("inc r9").check_reg(0, Regs.R9, 64)
|
|
I64("push r10w").check_reg(0, Regs.R10W, 16)
|
|
I64("xchg r10d, eax").check_reg(0, Regs.R10D, 32)
|
|
def test_regi_esi(self):
|
|
I64("lodsb").check_simple_deref(1, Regs.RSI, 8)
|
|
I64("cmpsw").check_simple_deref(0, Regs.RSI, 16)
|
|
I64("lodsd").check_simple_deref(1, Regs.RSI, 32)
|
|
I64("lodsq").check_simple_deref(1, Regs.RSI, 64)
|
|
def test_regi_edi(self):
|
|
I64("movsb").check_simple_deref(0, Regs.RDI, 8)
|
|
I64("scasw").check_simple_deref(0, Regs.RDI, 16)
|
|
I64("stosd").check_simple_deref(0, Regs.RDI, 32)
|
|
I64("stosq").check_simple_deref(0, Regs.RDI, 64)
|
|
def test_regi_ebxal(self):
|
|
a = I64("xlatb")
|
|
a.check_type_size(0, distorm3.OPERAND_MEMORY, 8)
|
|
self.assertFalse(a.inst.operands[0].index != Regs.AL)
|
|
self.assertFalse(a.inst.operands[0].base != Regs.RBX)
|
|
def test_regi_eax(self):
|
|
I64("vmrun [rax]").check_simple_deref(0, Regs.RAX, 64)
|
|
def test_regdx(self):
|
|
#I64("in eax, dx").check_reg(1, Regs.DX, 16)
|
|
pass
|
|
def test_regecx(self):
|
|
I64("invlpga [rax], ecx").check_reg(1, Regs.ECX, 32)
|
|
def test_fpu_si(self):
|
|
I64("fxch st4").check_reg(0, Regs.ST4, 32)
|
|
def test_fpu_ssi(self):
|
|
a = I64("fcmovnbe st0, st3")
|
|
a.check_reg(0, Regs.ST0, 32)
|
|
a.check_reg(1, Regs.ST3, 32)
|
|
def test_fpu_sis(self):
|
|
a = I64("fadd st3, st0")
|
|
a.check_reg(0, Regs.ST3, 32)
|
|
a.check_reg(1, Regs.ST0, 32)
|
|
def test_mm(self):
|
|
I64("pand mm0, mm7").check_reg(0, Regs.MM0, 64)
|
|
def test_mm_rm(self):
|
|
I64("psllw mm0, 0x55").check_reg(0, Regs.MM0, 64)
|
|
def test_mm32(self):
|
|
I64("punpcklbw mm1, [rsi]").check_simple_deref(1, Regs.RSI, 32)
|
|
def test_mm64(self):
|
|
I64("packsswb mm3, [rbx]").check_simple_deref(1, Regs.RBX, 64)
|
|
def test_xmm(self):
|
|
I64("orps xmm5, xmm4").check_reg(0, Regs.XMM5, 128)
|
|
I64("orps xmm15, xmm4").check_reg(0, Regs.XMM15, 128)
|
|
def test_xmm_rm(self):
|
|
I64("psrlw xmm6, 0x12").check_reg(0, Regs.XMM6, 128)
|
|
I64("psrlw xmm13, 0x12").check_reg(0, Regs.XMM13, 128)
|
|
def test_xmm16(self):
|
|
I64("pmovsxbq xmm3, [rbp]").check_simple_deref(1, Regs.RBP, 16)
|
|
def test_xmm32(self):
|
|
I64("pmovsxwq xmm5, [rdi]").check_simple_deref(1, Regs.RDI, 32)
|
|
def test_xmm64(self):
|
|
I64("roundsd xmm6, [rsi], 0x55").check_simple_deref(1, Regs.RSI, 64)
|
|
def test_xmm128(self):
|
|
I64("roundpd xmm7, [rbx], 0xaa").check_simple_deref(1, Regs.RBX, 128)
|
|
I64("roundpd xmm7, xmm15, 0xaa").check_reg(1, Regs.XMM15, 128)
|
|
def test_regxmm0(self):
|
|
I64("blendvpd xmm1, xmm3, xmm0").check_reg(2, Regs.XMM0, 128)
|
|
def test_disp_only(self):
|
|
a = I64("add [0x12345678], rbx")
|
|
a.check_type_size(0, distorm3.OPERAND_ABSOLUTE_ADDRESS, 64)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x12345678)
|
|
def test_modrm(self):
|
|
texts = ["ADD [%s], RDI" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I64(i[1])
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]], 64)
|
|
def test_modrm_disp8(self):
|
|
texts = ["ADD [%s + 0x55], RSI" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I64(i[1])
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]], 64)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 8)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x55)
|
|
def test_modrm_disp32(self):
|
|
texts = ["ADD [%s + 0x33221144], RDX" % i for i in self.Derefs]
|
|
for i in enumerate(texts):
|
|
a = I64(i[1])
|
|
a.check_simple_deref(0, self.DerefsInfo[i[0]], 64)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x33221144)
|
|
def test_base_rbp(self):
|
|
a = I64("mov [rbp+0x55], eax")
|
|
a.check_simple_deref(0, Regs.RBP, 32)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 8)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x55)
|
|
a = I64("mov [rbp+0x55443322], eax")
|
|
a.check_simple_deref(0, Regs.RBP, 32)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x55443322)
|
|
def test_base_rip(self):
|
|
a = I64("mov [rip+0x12345678], rdx")
|
|
a.check_simple_deref(0, Regs.RIP, 64)
|
|
self.assertFalse(a.inst.operands[0].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[0].disp != 0x12345678)
|
|
def test_reg8_rex(self):
|
|
I64("mov sil, al").check_reg(0, Regs.SIL, 8)
|
|
I64("inc bpl").check_reg(0, Regs.BPL, 8)
|
|
def test_imm64(self):
|
|
I64("mov rax, 0x1234567890abcdef").check_imm(1, 0x1234567890abcdef, 64)
|
|
def test_reg64(self):
|
|
I64("movsxd r10, eax").check_reg(0, Regs.R10, 64)
|
|
def test_rm16_32_2(self):
|
|
#MOVZXD RAX, [RAX]
|
|
I64("db 0x63\n db 0x00").check_simple_deref(1, Regs.RAX, 32)
|
|
#MOVZXDW RAX, [RAX]
|
|
#I64("db 0x66\n db 0x63\n db 0x00").check_simple_deref(1, Regs.RAX, 16)
|
|
#MOVZXD RAX, EAX
|
|
I64("db 0x63\n db 0xc0").check_reg(1, Regs.EAX, 32)
|
|
#MOVZXDW RAX, AX
|
|
#I64("db 0x66\n db 0x63\n db 0xc0").check_reg(1, Regs.AX, 16)
|
|
#MOVZXDW RAX, R8W
|
|
#I64("db 0x66\n db 0x41\n db 0x63\n db 0xc0").check_reg(1, Regs.R8W, 16)
|
|
Bases = ["RAX", "RCX", "RDX", "RBX", "RSP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"]
|
|
BasesInfo = [Regs.RAX, Regs.RCX, Regs.RDX, Regs.RBX, Regs.RSP, Regs.RSI, Regs.RDI, Regs.R8, Regs.R9, Regs.R10, Regs.R11, Regs.R12, Regs.R13, Regs.R14, Regs.R15]
|
|
Indices = ["RAX", "RCX", "RDX", "RBX", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"]
|
|
IndicesInfo = [Regs.RAX, Regs.RCX, Regs.RDX, Regs.RBX, Regs.RBP, Regs.RSI, Regs.RDI, Regs.R8, Regs.R9, Regs.R10, Regs.R11, Regs.R12, Regs.R13, Regs.R14, Regs.R15]
|
|
def test_bases(self):
|
|
for i in enumerate(self.Bases):
|
|
a = I64("cmp rbp, [%s]" % (i[1]))
|
|
a.check_simple_deref(1, self.BasesInfo[i[0]], 64)
|
|
def test_bases_disp32(self):
|
|
for i in enumerate(self.Bases):
|
|
a = I64("cmp rbp, [%s+0x12345678]" % (i[1]))
|
|
a.check_simple_deref(1, self.BasesInfo[i[0]], 64)
|
|
self.assertFalse(a.inst.operands[1].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[1].disp != 0x12345678)
|
|
def test_scales(self):
|
|
for i in enumerate(self.Indices):
|
|
# A scale of 2 causes the scale to be omitted and changed from reg*2 to reg+reg.
|
|
for s in [4, 8]:
|
|
a = I64("and rbp, [%s*%d]" % (i[1], s))
|
|
a.check_deref(1, self.IndicesInfo[i[0]], None, 64)
|
|
self.assertFalse(a.inst.operands[1].scale != s)
|
|
def test_sib(self):
|
|
for i in enumerate(self.Indices):
|
|
for j in enumerate(self.Bases):
|
|
for s in [1, 2, 4, 8]:
|
|
a = I64("or rbp, [%s*%d + %s]" % (i[1], s, j[1]))
|
|
a.check_deref(1, self.IndicesInfo[i[0]], self.BasesInfo[j[0]], 64)
|
|
if s != 1:
|
|
self.assertFalse(a.inst.operands[1].scale != s)
|
|
def test_sib_disp8(self):
|
|
for i in enumerate(self.Indices):
|
|
for j in enumerate(self.Bases):
|
|
for s in [1, 2, 4, 8]:
|
|
a = I64("xor al, [%s*%d + %s + 0x55]" % (i[1], s, j[1]))
|
|
a.check_deref(1, self.IndicesInfo[i[0]], self.BasesInfo[j[0]], 8)
|
|
self.assertFalse(a.inst.operands[1].dispSize != 8)
|
|
self.assertFalse(a.inst.operands[1].disp != 0x55)
|
|
if s != 1:
|
|
self.assertFalse(a.inst.operands[1].scale != s)
|
|
def test_sib_disp32(self):
|
|
for i in enumerate(self.Indices):
|
|
for j in enumerate(self.Bases):
|
|
for s in [1, 2, 4, 8]:
|
|
a = I64("sub rdx, [%s*%d + %s + 0x55aabbcc]" % (i[1], s, j[1]))
|
|
a.check_deref(1, self.IndicesInfo[i[0]], self.BasesInfo[j[0]], 64)
|
|
self.assertFalse(a.inst.operands[1].dispSize != 32)
|
|
self.assertFalse(a.inst.operands[1].disp != 0x55aabbcc)
|
|
if s != 1:
|
|
self.assertFalse(a.inst.operands[1].scale != s)
|
|
def test_base32(self):
|
|
I64("mov eax, [ebx]").check_simple_deref(1, Regs.EBX, 32)
|
|
|
|
class TestInstTable(unittest.TestCase):
|
|
""" Check that locate_inst algorithm covers all opcode-length (ol)
|
|
for the varying sizes of opcodes.
|
|
The bad tests should not find an instruction, so they should fail on purpose,
|
|
to see we don't crash the diassembler.
|
|
Also test for some end-cases with nop and wait. """
|
|
def test_c7_opcode(self):
|
|
IB32("c7f8aaaaaaaa").check_mnemonic("XBEGIN")
|
|
IB64("c7f8aaaaaaaa").check_mnemonic("XBEGIN")
|
|
IB32("C7C108000000").check_mnemonic("MOV")
|
|
IB64("C7C108000000").check_mnemonic("MOV")
|
|
IB64("48C7C000000000").check_mnemonic("MOV")
|
|
def test_tx(self):
|
|
IB64("0f01d5").check_mnemonic("XEND")
|
|
IB64("c6f8bb").check_mnemonic("XABORT")
|
|
IB64("c7f800000000").check_mnemonic("XBEGIN")
|
|
def test_fuzz_9b_and_c7(self):
|
|
for i in range(10000):
|
|
s = "%02x%02x" % (i & 0xff, random.randint(0, 255))
|
|
IB32("9b%sffffffff" % s)
|
|
IB32("c7%sffffffff" % s)
|
|
def test_ol1(self):
|
|
IB32("00c0").check_mnemonic("ADD")
|
|
def test_ol13(self):
|
|
IB32("80c055").check_mnemonic("ADD")
|
|
def test_ol1d(self):
|
|
IB32("d900").check_mnemonic("FLD")
|
|
IB32("d9c8").check_mnemonic("FXCH")
|
|
IB32("d9e1").check_mnemonic("FABS")
|
|
def test_ol2(self):
|
|
IB32("0f06").check_mnemonic("CLTS")
|
|
def test_ol23(self):
|
|
IB32("0fbae055").check_mnemonic("BT")
|
|
def test_ol2d(self):
|
|
IB32("0f01e0").check_mnemonic("SMSW")
|
|
IB32("0f0130").check_mnemonic("LMSW")
|
|
IB32("0f01c9").check_mnemonic("MWAIT")
|
|
def test_ol3(self):
|
|
IB32("0f380000").check_mnemonic("PSHUFB")
|
|
def test_ol1_bad(self):
|
|
# There is no undefined instruction in the root, except a prefix, oh well.
|
|
pass
|
|
def test_ol13_bad(self):
|
|
IB32("f780").check_invalid()
|
|
def test_ol1d_bad(self):
|
|
IB32("d908").check_invalid()
|
|
IB32("d9d1").check_invalid()
|
|
IB32("d9ef").check_invalid()
|
|
def test_ol2_bad(self):
|
|
IB32("0fff").check_invalid()
|
|
def test_ol23_bad(self):
|
|
IB32("0f0dff").check_invalid()
|
|
def test_ol2d_bad(self):
|
|
IB32("0f0128").check_invalid()
|
|
IB32("0f01cc").check_invalid()
|
|
def test_ol3_bad(self):
|
|
IB32("0f0fff").check_invalid()
|
|
def test_index63(self):
|
|
# Test arpl, since it has a special treatment for 32/64 bits.
|
|
a = IB32("63c0")
|
|
a.check_mnemonic("ARPL")
|
|
a = IB64("63c0")
|
|
a.check_mnemonic("MOVSXD")
|
|
def test_index90(self):
|
|
# If nop is prefixed with f3, it is pause then. If it is prefixed with rex, it might be xchg.
|
|
IB32("90").check_mnemonic("NOP")
|
|
IB64("90").check_mnemonic("NOP")
|
|
IB64("4890").check_mnemonic("NOP")
|
|
IB64("4190").check_mnemonic("XCHG")
|
|
IB64("f390").check_mnemonic("PAUSE")
|
|
def test_wait(self):
|
|
# Wait instruction is very tricky. It might be coalesced with the next bytes.
|
|
# If the next bytes are 'waitable', otherwise it is a standalone instruction.
|
|
IB32("9b90").check_mnemonic("WAIT", 0) # nop isn't waitable.
|
|
IB32("9bdfe0").check_mnemonic("FSTSW") # waitable stsw
|
|
IB32("dfe0").check_mnemonic("FNSTSW") # non-waitable stsw
|
|
IB32("9b00c0").check_mnemonic("WAIT") # add isn't waitable
|
|
IB32("9bd930").check_mnemonic("FSTENV") # waitable fstenv
|
|
IB32("9b66dbe3").check_mnemonic("WAIT") # prefix breaks waiting
|
|
def test_3dnow(self):
|
|
IB32("0f0fc00d").check_mnemonic("PI2FD")
|
|
IB32("0f0d00").check_mnemonic("PREFETCH")
|
|
def test_mandatory(self):
|
|
IB32("f30f10c0").check_mnemonic("MOVSS")
|
|
IB32("660f10c0").check_mnemonic("MOVUPD")
|
|
IB32("660f71d055").check_mnemonic("PSRLW")
|
|
IB32("660ffec0").check_mnemonic("PADDD")
|
|
IB32("f20f10c0").check_mnemonic("MOVSD")
|
|
IB32("f20f11c0").check_mnemonic("MOVSD")
|
|
IB32("660f3800c0").check_mnemonic("PSHUFB")
|
|
IB32("f20f38f0c0").check_mnemonic("CRC32")
|
|
IB32("660fc730").check_mnemonic("VMCLEAR")
|
|
IB32("f30fc730").check_mnemonic("VMXON")
|
|
def test_vex(self):
|
|
I32("vaddpd ymm1, ymm2, ymm2").check_mnemonic("VADDPD") # pre encoding: 66, 0f, 58
|
|
I32("vaddps ymm1, ymm2, ymm2").check_mnemonic("VADDPS") # pre encoding: 0f, 58
|
|
I32("vaddsd xmm1, xmm2, qword [eax]").check_mnemonic("VADDSD") # pre encoding: f2, 0f, 58
|
|
I32("vaddss xmm1, xmm2, dword [eax]").check_mnemonic("VADDSS") # pre encoding: f3, 0f, 58
|
|
I32("vmovsd xmm1, xmm2, xmm3").check_mnemonic("VMOVSD") # pre encoding: f2, 0f, 10
|
|
I32("vmovsd xmm1, qword [eax]").check_mnemonic("VMOVSD") # pre encoding: f2 0f 10 - but VEX.vvvv is not encoded!
|
|
# Since in a VEX prefix you can encode the virtual prefix, we got three ways to get to 0xf 0x38
|
|
# So see that both work well.
|
|
IB32("c4e279dbc2").check_mnemonic("VAESIMC") # pre encoding: 66, 0f, 38, db, virtual prefix is 0f 38
|
|
IB32("c4e17938dbc2").check_mnemonic("VAESIMC") # the virtual prefix is only 0f
|
|
IB32("c5f938dbc2").check_mnemonic("VAESIMC") # the virtual prefix is only 0f, but short VEX
|
|
# Same test as earlier, but for 0xf 0x3a, though this instruction doesn't have a short form.
|
|
IB32("c4e3710dc255").check_mnemonic("VBLENDPD") # pre encoding: 66, 0f, 3a, 0d, virtual prefix is 0f 3a
|
|
IB32("c4e1713a0dc255").check_mnemonic("VBLENDPD") # pre encoding: 66, 0f, 3a, 0d, virtual prefix is 0f
|
|
I32("vldmxcsr dword [eax]").check_mnemonic("VLDMXCSR")
|
|
I32("vzeroupper").check_mnemonic("VZEROUPPER")
|
|
I32("vzeroall").check_mnemonic("VZEROALL")
|
|
I32("vpslld xmm1, xmm2, xmm3").check_mnemonic("VPSLLD")
|
|
def test_vex_special(self):
|
|
# VVVV encoded, where there is not such an encoding for the VAESIMC instruction.
|
|
IB32("c4e271dbca").check_invalid()
|
|
IB32("c4e2791800").check_mnemonic("VBROADCASTSS") # just to make sure this instruction is fine.
|
|
IB32("c4e279ff00").check_invalid() # pre encoding: 66, 0f, 38, ff
|
|
IB32("c4e179ff00").check_invalid() # pre encoding: 66, 0f, 38, ff, mmmmm = 1
|
|
IB32("c4e379ff00").check_invalid() # pre encoding: 66, 0f, 38, ff, mmmmm = 3
|
|
IB32("c4e4791800").check_invalid() # pre encoding: 66, 0f, 38, 18, mmmmm = 4
|
|
IB32("c5f8ae10").check_mnemonic("VLDMXCSR") # pre encoding: 0f, ae /02
|
|
IB32("c4c178ae10").check_mnemonic("VLDMXCSR") # longer form of 0f, ae /02
|
|
IB32("c4c179ae10").check_invalid() # longer form of 0f, ae /02, invalid pp=1
|
|
IB32("c4c17aae10").check_invalid() # longer form of 0f, ae /02, invalid pp=2
|
|
IB32("c4c17bae10").check_invalid() # longer form of 0f, ae /02, invalid pp=3
|
|
IB32("c4c17877").check_mnemonic("VZEROUPPER") # longer form of 0f, 77
|
|
IB32("c4c17c77").check_mnemonic("VZEROALL") # longer form of 0f, 77
|
|
IB32("c4c97c77").check_invalid() # longer form of 0f, 77, invalid mmmmm
|
|
def test_crc32(self):
|
|
I32("crc32 eax, al").check_reg(0, Regs.EAX, 32)
|
|
def test_lzcnt(self):
|
|
# This is the only instruction that has a mandatory prefix and can have ALSO a valid operand size prefix!
|
|
I32("lzcnt ax, bx").check_reg(0, Regs.AX, 16)
|
|
I32("lzcnt eax, ebx").check_reg(0, Regs.EAX, 32)
|
|
I64("lzcnt rax, rbx").check_reg(0, Regs.RAX, 64)
|
|
|
|
class TestAVXOperands(unittest.TestCase):
|
|
def test_rm32(self):
|
|
#I16("vextractps eax, xmm2, 3").check_reg(0, Regs.EAX, 32)
|
|
I32("vextractps eax, xmm2, 3").check_reg(0, Regs.EAX, 32)
|
|
I64("vextractps eax, xmm2, 3").check_reg(0, Regs.EAX, 32)
|
|
def test_reg32_64_m8(self):
|
|
#I16("vpextrb eax, xmm2, 3").check_reg(0, Regs.EAX, 32)
|
|
I32("vpextrb eax, xmm2, 3").check_reg(0, Regs.EAX, 32)
|
|
I64("vpextrb eax, xmm2, 3").check_reg(0, Regs.EAX, 32)
|
|
I64("vpextrb rax, xmm2, 3").check_reg(0, Regs.RAX, 64)
|
|
I32("vpextrb [ebx], xmm2, 3").check_simple_deref(0, Regs.EBX, 8)
|
|
I64("vpextrb [rbx], xmm2, 3").check_simple_deref(0, Regs.RBX, 8)
|
|
def test_reg32_64_m16(self):
|
|
I32("vpextrw eax, xmm2, 3").check_reg(0, Regs.EAX, 32)
|
|
I64("vpextrw rax, xmm2, 3").check_reg(0, Regs.RAX, 64)
|
|
I64("vpextrw rax, xmm2, 3").check_reg(0, Regs.RAX, 64)
|
|
I32("vpextrw [ebx], xmm2, 3").check_simple_deref(0, Regs.EBX, 16)
|
|
I64("vpextrw [rbx], xmm2, 3").check_simple_deref(0, Regs.RBX, 16)
|
|
def test_wreg32_64_WITH_wxmm32_64(self):
|
|
a = I32("vcvtss2si eax, xmm1")
|
|
a.check_reg(0, Regs.EAX, 32)
|
|
a.check_reg(1, Regs.XMM1, 128)
|
|
a = I64("vcvtss2si rax, [rbx]")
|
|
a.check_reg(0, Regs.RAX, 64)
|
|
a.check_simple_deref(1, Regs.RBX, 64)
|
|
a = I64("vcvtss2si eax, [rbx]")
|
|
a.check_reg(0, Regs.EAX, 32)
|
|
a.check_simple_deref(1, Regs.RBX, 32)
|
|
def test_vxmm(self):
|
|
I32("vaddsd xmm1, xmm2, xmm3").check_reg(1, Regs.XMM2, 128)
|
|
I64("vaddsd xmm2, xmm3, xmm4").check_reg(1, Regs.XMM3, 128)
|
|
def test_xmm_imm(self):
|
|
I32("vpblendvb xmm1, xmm2, xmm3, xmm4").check_reg(3, Regs.XMM4, 128)
|
|
# Force XMM15, but high bit is ignored in 32bits.
|
|
self.assertFalse(IB32("c4e3694ccbf0").inst.operands[3].index != Regs.XMM7)
|
|
I64("vpblendvb xmm1, xmm2, xmm3, xmm15").check_reg(3, Regs.XMM15, 128)
|
|
def test_yxmm(self):
|
|
I32("vaddsubpd ymm2, ymm4, ymm6").check_reg(0, Regs.YMM2, 256)
|
|
I32("vaddsubpd xmm7, xmm4, xmm6").check_reg(0, Regs.XMM7, 128)
|
|
I64("vaddsubpd ymm12, ymm4, ymm6").check_reg(0, Regs.YMM12, 256)
|
|
I64("vaddsubpd xmm14, xmm4, xmm6").check_reg(0, Regs.XMM14, 128)
|
|
def test_yxmm_imm(self):
|
|
I32("vblendvpd xmm1, xmm2, xmm3, xmm4").check_reg(3, Regs.XMM4, 128)
|
|
I32("vblendvpd ymm1, ymm2, ymm3, ymm4").check_reg(3, Regs.YMM4, 256)
|
|
# Force YMM15, but high bit is ignored in 32bits.
|
|
self.assertFalse(IB32("c4e36d4bcbf0").inst.operands[3].index != Regs.YMM7)
|
|
I64("vblendvpd xmm1, xmm2, xmm3, xmm14").check_reg(3, Regs.XMM14, 128)
|
|
I64("vblendvpd ymm1, ymm2, ymm3, ymm9").check_reg(3, Regs.YMM9, 256)
|
|
def test_ymm(self):
|
|
I32("vbroadcastsd ymm5, [eax]").check_reg(0, Regs.YMM5, 256)
|
|
I64("vbroadcastsd ymm13, [rax]").check_reg(0, Regs.YMM13, 256)
|
|
def test_ymm256(self):
|
|
I32("vperm2f128 ymm2, ymm4, [eax], 0x55").check_simple_deref(2, Regs.EAX, 256)
|
|
I64("vperm2f128 ymm2, ymm14, [rax], 0x55").check_simple_deref(2, Regs.RAX, 256)
|
|
def test_vymm(self):
|
|
I32("vinsertf128 ymm1, ymm4, xmm4, 0xaa").check_reg(1, Regs.YMM4, 256)
|
|
I64("vinsertf128 ymm1, ymm15, xmm4, 0xaa").check_reg(1, Regs.YMM15, 256)
|
|
def test_vyxmm(self):
|
|
I32("vmaxpd xmm1, xmm2, xmm3").check_reg(1, Regs.XMM2, 128)
|
|
I32("vmaxpd ymm1, ymm2, ymm3").check_reg(1, Regs.YMM2, 256)
|
|
I64("vmaxpd xmm1, xmm12, xmm3").check_reg(1, Regs.XMM12, 128)
|
|
I64("vmaxpd ymm1, ymm12, ymm3").check_reg(1, Regs.YMM12, 256)
|
|
def test_yxmm64_256(self):
|
|
I32("vmovddup xmm1, xmm2").check_reg(1, Regs.XMM2, 128)
|
|
I32("vmovddup ymm1, ymm2").check_reg(1, Regs.YMM2, 256)
|
|
I32("vmovddup xmm1, [ecx]").check_simple_deref(1, Regs.ECX, 64)
|
|
I32("vmovddup ymm1, [ebx]").check_simple_deref(1, Regs.EBX, 256)
|
|
I64("vmovddup xmm1, xmm12").check_reg(1, Regs.XMM12, 128)
|
|
I64("vmovddup ymm1, ymm12").check_reg(1, Regs.YMM12, 256)
|
|
I64("vmovddup xmm1, [rcx]").check_simple_deref(1, Regs.RCX, 64)
|
|
I64("vmovddup ymm1, [rbx]").check_simple_deref(1, Regs.RBX, 256)
|
|
def test_yxmm128_256(self):
|
|
I32("vandnpd xmm1, xmm2, xmm3").check_reg(2, Regs.XMM3, 128)
|
|
I32("vandnpd ymm1, ymm2, ymm3").check_reg(2, Regs.YMM3, 256)
|
|
I32("vandnpd xmm1, xmm2, [edi]").check_simple_deref(2, Regs.EDI, 128)
|
|
I32("vandnpd ymm1, ymm2, [esi]").check_simple_deref(2, Regs.ESI, 256)
|
|
I64("vandnpd xmm1, xmm2, xmm13").check_reg(2, Regs.XMM13, 128)
|
|
I64("vandnpd ymm1, ymm2, ymm13").check_reg(2, Regs.YMM13, 256)
|
|
I64("vandnpd xmm1, xmm2, [rdi]").check_simple_deref(2, Regs.RDI, 128)
|
|
I64("vandnpd ymm1, ymm2, [rsi]").check_simple_deref(2, Regs.RSI, 256)
|
|
def test_lxmm64_128(self):
|
|
I32("vcvtdq2pd xmm1, xmm2").check_reg(1, Regs.XMM2, 128)
|
|
I32("vcvtdq2pd xmm1, [eax]").check_simple_deref(1, Regs.EAX, 64)
|
|
I32("vcvtdq2pd ymm1, [ebx]").check_simple_deref(1, Regs.EBX, 128)
|
|
I64("vcvtdq2pd xmm1, xmm12").check_reg(1, Regs.XMM12, 128)
|
|
I64("vcvtdq2pd xmm1, [rax]").check_simple_deref(1, Regs.RAX, 64)
|
|
I64("vcvtdq2pd ymm1, [rbx]").check_simple_deref(1, Regs.RBX, 128)
|
|
def test_lmem128_256(self):
|
|
I32("vlddqu xmm1, [eax]").check_simple_deref(1, Regs.EAX, 128)
|
|
I32("vlddqu ymm1, [eax]").check_simple_deref(1, Regs.EAX, 256)
|
|
I64("vlddqu xmm1, [r14]").check_simple_deref(1, Regs.R14, 128)
|
|
I64("vlddqu ymm1, [r13]").check_simple_deref(1, Regs.R13, 256)
|
|
|
|
class TestMisc(unittest.TestCase):
|
|
def test_lods(self):
|
|
a = I16("lodsb")
|
|
a.check_reg(0, Regs.AL, 8)
|
|
a.check_simple_deref(1, Regs.SI, 8)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("lodsw")
|
|
a.check_reg(0, Regs.AX, 16)
|
|
a.check_simple_deref(1, Regs.ESI, 16)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("lodsd")
|
|
a.check_reg(0, Regs.EAX, 32)
|
|
a.check_simple_deref(1, Regs.ESI, 32)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I64("lodsq")
|
|
a.check_reg(0, Regs.RAX, 64)
|
|
a.check_simple_deref(1, Regs.RSI, 64)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
a = I16("db 0x2e\nlodsb")
|
|
a.check_reg(0, Regs.AL, 8)
|
|
a.check_simple_deref(1, Regs.SI, 8)
|
|
self.assertEqual(a.inst.segment, Regs.CS)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
a = I32("db 0x2e\nlodsw")
|
|
a.check_reg(0, Regs.AX, 16)
|
|
a.check_simple_deref(1, Regs.ESI, 16)
|
|
self.assertEqual(a.inst.segment, Regs.CS)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
a = I32("db 0x2e\nlodsd")
|
|
a.check_reg(0, Regs.EAX, 32)
|
|
a.check_simple_deref(1, Regs.ESI, 32)
|
|
self.assertEqual(a.inst.segment, Regs.CS)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
a = I64("db 0x65\nlodsq")
|
|
a.check_reg(0, Regs.RAX, 64)
|
|
a.check_simple_deref(1, Regs.RSI, 64)
|
|
self.assertEqual(a.inst.segment, Regs.GS)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
def test_stos(self):
|
|
a = I16("stosb")
|
|
a.check_simple_deref(0, Regs.DI, 8)
|
|
a.check_reg(1, Regs.AL, 8)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("stosw")
|
|
a.check_simple_deref(0, Regs.EDI, 16)
|
|
a.check_reg(1, Regs.AX, 16)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("stosd")
|
|
a.check_simple_deref(0, Regs.EDI, 32)
|
|
a.check_reg(1, Regs.EAX, 32)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I64("stosq")
|
|
a.check_simple_deref(0, Regs.RDI, 64)
|
|
a.check_reg(1, Regs.RAX, 64)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
a = I16("db 0x2e\nstosb")
|
|
a.check_simple_deref(0, Regs.DI, 8)
|
|
a.check_reg(1, Regs.AL, 8)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, Regs.ES)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("db 0x2e\nstosw")
|
|
a.check_simple_deref(0, Regs.EDI, 16)
|
|
a.check_reg(1, Regs.AX, 16)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, Regs.ES)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("db 0x2e\nstosd")
|
|
a.check_simple_deref(0, Regs.EDI, 32)
|
|
a.check_reg(1, Regs.EAX, 32)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, Regs.ES)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I64("db 0x65\nstosq")
|
|
a.check_simple_deref(0, Regs.RDI, 64)
|
|
a.check_reg(1, Regs.RAX, 64)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, REG_NONE)
|
|
def test_scas(self):
|
|
a = I16("scasb")
|
|
a.check_simple_deref(0, Regs.DI, 8)
|
|
a.check_reg(1, Regs.AL, 8)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("scasw")
|
|
a.check_simple_deref(0, Regs.EDI, 16)
|
|
a.check_reg(1, Regs.AX, 16)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("scasd")
|
|
a.check_simple_deref(0, Regs.EDI, 32)
|
|
a.check_reg(1, Regs.EAX, 32)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I64("scasq")
|
|
a.check_simple_deref(0, Regs.RDI, 64)
|
|
a.check_reg(1, Regs.RAX, 64)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
a = I16("db 0x2e\nscasb")
|
|
a.check_simple_deref(0, Regs.DI, 8)
|
|
a.check_reg(1, Regs.AL, 8)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, Regs.ES)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("db 0x2e\nscasw")
|
|
a.check_simple_deref(0, Regs.EDI, 16)
|
|
a.check_reg(1, Regs.AX, 16)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, Regs.ES)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("db 0x2e\nscasd")
|
|
a.check_simple_deref(0, Regs.EDI, 32)
|
|
a.check_reg(1, Regs.EAX, 32)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, Regs.ES)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I64("db 0x65\nscasq")
|
|
a.check_simple_deref(0, Regs.RDI, 64)
|
|
a.check_reg(1, Regs.RAX, 64)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, REG_NONE)
|
|
def test_cmps(self):
|
|
a = I64("cmpsd")
|
|
a.check_simple_deref(0, Regs.RSI, 32)
|
|
a.check_simple_deref(1, Regs.RDI, 32)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 0)
|
|
self.assertEqual(a.inst.segment, REG_NONE)
|
|
a = I16("db 0x2e\ncmpsb")
|
|
a.check_simple_deref(0, Regs.SI, 8)
|
|
a.check_simple_deref(1, Regs.DI, 8)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 0)
|
|
self.assertEqual(a.inst.segment, Regs.CS)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
def test_movs(self):
|
|
a = I32("movsd")
|
|
a.check_simple_deref(0, Regs.EDI, 32)
|
|
a.check_simple_deref(1, Regs.ESI, 32)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 0)
|
|
self.assertEqual(a.inst.segment, Regs.DS)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
a = I32("db 0x2e\nmovsw")
|
|
a.check_simple_deref(0, Regs.EDI, 16)
|
|
a.check_simple_deref(1, Regs.ESI, 16)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 0)
|
|
self.assertEqual(a.inst.segment, Regs.CS)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
def test_ins(self):
|
|
a = I32("db 0x65\ninsw")
|
|
a.check_simple_deref(0, Regs.EDI, 16)
|
|
a.check_reg(1, Regs.DX, 16)
|
|
self.assertEqual(a.inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(a.inst.segment, Regs.ES)
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
def test_outs(self):
|
|
a = I64("db 0x65\noutsd")
|
|
a.check_reg(0, Regs.DX, 16)
|
|
a.check_simple_deref(1, Regs.RSI, 32)
|
|
self.assertEqual(a.inst.segment, Regs.GS)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
def test_branch_hints(self):
|
|
self.assertFalse("FLAG_HINT_TAKEN" not in I32("db 0x3e\n jnz 0x50").inst.flags)
|
|
self.assertFalse("FLAG_HINT_NOT_TAKEN" not in I32("db 0x2e\n jp 0x55").inst.flags)
|
|
self.assertFalse("FLAG_HINT_NOT_TAKEN" not in I32("db 0x2e\n jo 0x55000").inst.flags)
|
|
self.assertFalse(I32("db 0x2e\n loop 0x55").inst.rawFlags & 0x1f, 0)
|
|
def test_mnemonic_by_vexw(self):
|
|
I32("vmovd xmm1, eax").check_mnemonic("VMOVD")
|
|
I64("vmovd xmm1, eax").check_reg(1, Regs.EAX, 32)
|
|
a = I64("vmovq xmm1, rax")
|
|
a.check_mnemonic("VMOVQ")
|
|
a.check_reg(1, Regs.RAX, 64)
|
|
def test_vexl_ignored(self):
|
|
I32("vaesdeclast xmm1, xmm2, xmm3").check_reg(0, Regs.XMM1, 128)
|
|
IB32("c4e26ddfcb").check_mnemonic("VAESDECLAST")
|
|
IB64("c4e26ddfcb").check_mnemonic("VAESDECLAST")
|
|
def test_vexl_needed(self):
|
|
I32("vinsertf128 ymm1, ymm2, xmm4, 0x42").check_mnemonic("VINSERTF128")
|
|
IB32("c4e36918cc42").check_invalid() # Without VEX.L.
|
|
IB64("c4e36918cc42").check_invalid() # Without VEX.L.
|
|
def test_force_reg0(self):
|
|
I32("extrq xmm1, 0x55, 0x66").check_mnemonic("EXTRQ")
|
|
I64("extrq xmm14, 0x55, 0x66").check_reg(0, Regs.XMM14, 128)
|
|
def test_pause(self):
|
|
self.assertEqual(I16("pause").inst.size, 2)
|
|
self.assertEqual(I32("pause").inst.size, 2)
|
|
self.assertEqual(I64("pause").inst.size, 2)
|
|
def test_nop(self):
|
|
self.assertEqual(I16("db 0x90").inst.size, 1)
|
|
self.assertEqual(I32("db 0x90").inst.size, 1)
|
|
self.assertEqual(I64("db 0x90").inst.size, 1)
|
|
self.assertEqual(I64("db 0x48, 0x90").inst.size, 2)
|
|
# XCHG R8D, EAX
|
|
a = I64("db 0x41, 0x90")
|
|
a.check_reg(0, Regs.R8D, 32)
|
|
a.check_reg(1, Regs.EAX, 32)
|
|
# XCHG R8, RAX
|
|
a = I64("db 0x49, 0x90")
|
|
a.check_reg(0, Regs.R8, 64)
|
|
a.check_reg(1, Regs.RAX, 64)
|
|
a = I64("db 0x4f, 0x90")
|
|
a.check_reg(0, Regs.R8, 64)
|
|
a.check_reg(1, Regs.RAX, 64)
|
|
def test_3dnow(self):
|
|
I32("pfadd mm4, [eax]").check_reg(0, Regs.MM4, 64)
|
|
I32("pfsub mm5, [eax]").check_reg(0, Regs.MM5, 64)
|
|
I32("pfrcpit1 mm1, [ebx]").check_mnemonic("PFRCPIT1")
|
|
I64("pavgusb mm1, mm2").check_mnemonic("PAVGUSB")
|
|
def test_all_segs(self):
|
|
I16("push fs").check_reg(0, Regs.FS, 16)
|
|
I16("push gs").check_reg(0, Regs.GS, 16)
|
|
I16("push ds").check_reg(0, Regs.DS, 16)
|
|
I16("push cs").check_reg(0, Regs.CS, 16)
|
|
I16("push ds").check_reg(0, Regs.DS, 16)
|
|
I16("push es").check_reg(0, Regs.ES, 16)
|
|
def test_op4(self):
|
|
a = I32("insertq xmm2, xmm1, 0x55, 0xaa")
|
|
a.check_reg(0, Regs.XMM2, 128)
|
|
a.check_reg(1, Regs.XMM1, 128)
|
|
a.check_type_size(2, distorm3.OPERAND_IMMEDIATE, 8)
|
|
self.assertEqual(a.inst.operands[2].value, 0x55)
|
|
a.check_type_size(3, distorm3.OPERAND_IMMEDIATE, 8)
|
|
self.assertEqual(a.inst.operands[3].value, 0xaa)
|
|
def test_pseudo_cmp(self):
|
|
I32("cmpps xmm2, xmm3, 0x7")
|
|
I64("cmpps xmm2, xmm4, 0x2")
|
|
def test_jmp_counters(self):
|
|
I16("jcxz 0x100")
|
|
I32("jecxz 0x100")
|
|
I64("jrcxz 0x100")
|
|
def test_natives(self):
|
|
self.assertEqual(I16("pusha").inst.size, 1)
|
|
self.assertEqual(I16("pushad").inst.size, 2)
|
|
self.assertEqual(I32("pusha").inst.size, 1)
|
|
self.assertEqual(I32("pushaw").inst.size, 2)
|
|
self.assertEqual(I16("CBW").inst.size, 1)
|
|
self.assertEqual(I32("CWDE").inst.size, 1)
|
|
self.assertEqual(I64("CDQE").inst.size, 2)
|
|
def test_modrm_based(self):
|
|
I32("movhlps xmm0, xmm1")
|
|
I32("movhps xmm0, [eax]")
|
|
I64("movhlps xmm0, xmm1")
|
|
I64("movhps xmm0, [eax]")
|
|
I64("movhlps xmm0, xmm1")
|
|
I64("movlps xmm0, [eax]")
|
|
def test_wait(self):
|
|
self.assertEqual(I16("wait").inst.size, 1)
|
|
def test_include_wait(self):
|
|
self.assertEqual(I16("db 0x9b\n db 0xd9\n db 0x30").inst.size, 3)
|
|
def test_loopxx_counters_size(self):
|
|
a = I16("loopz 0x50")
|
|
a.check_type_size(0,distorm3.OPERAND_IMMEDIATE, 8)
|
|
a.check_addr_size(16)
|
|
a = I32("loopz 0x50")
|
|
a.check_type_size(0,distorm3.OPERAND_IMMEDIATE, 8)
|
|
a.check_addr_size(32)
|
|
a = I64("loopz 0x50")
|
|
a.check_type_size(0,distorm3.OPERAND_IMMEDIATE, 8)
|
|
a.check_addr_size(64)
|
|
a = I16("db 0x67\n loopz 0x50")
|
|
a.check_type_size(0,distorm3.OPERAND_IMMEDIATE, 8)
|
|
a.check_addr_size(32)
|
|
a = I32("db 0x67\n loopz 0x50")
|
|
a.check_type_size(0,distorm3.OPERAND_IMMEDIATE, 8)
|
|
a.check_addr_size(16)
|
|
a = I64("db 0x67\n loopnz 0x50")
|
|
a.check_type_size(0,distorm3.OPERAND_IMMEDIATE, 8)
|
|
a.check_addr_size(32)
|
|
def test_privileged(self):
|
|
self.assertFalse(IB32("90").inst.privileged)
|
|
self.assertTrue(I32("iret").inst.privileged)
|
|
|
|
def _hexlify(data):
|
|
s = ""
|
|
if type(data[0]) == str: # Python 2.x
|
|
for i in data:
|
|
s += "%02x" % ord(i)
|
|
else:
|
|
for i in data: # Python 3.x
|
|
s += "%02x" % i
|
|
return s
|
|
|
|
class TestMisc2(unittest.TestCase):
|
|
def test_binary(self):
|
|
# Generate 128kb of random bytes.
|
|
# Disasm them, extract the returned hex,
|
|
# And see that it matches the input.
|
|
# This checks no bytes are skipped.
|
|
data = "".join(["%02x" % random.randint(0, 255) for i in range(1 << 17)])
|
|
insts = IB16(data).insts
|
|
output = "".join([_hexlify(i.instructionBytes) for i in insts])
|
|
self.assertTrue(data == output)
|
|
insts = IB32(data).insts
|
|
output = "".join([_hexlify(i.instructionBytes) for i in insts])
|
|
self.assertTrue(data == output)
|
|
insts = IB64(data).insts
|
|
output = "".join([_hexlify(i.instructionBytes) for i in insts])
|
|
self.assertTrue(data == output)
|
|
def test_longest_mnemonic(self):
|
|
# The longest mnemonic is VAESKEYGENASSIST and check it's null terminated.
|
|
self.assertEqual(I32("VAESKEYGENASSIST xmm1, xmm2, 7").inst.mnemonic, "VAESKEYGENASSIST")
|
|
|
|
class TestPrefixes(unittest.TestCase):
|
|
Derefs16 = ["BX + SI", "BX + DI", "BP + SI", "BP + DI", "SI", "DI", "BP", "BX"]
|
|
Derefs32 = ["EAX", "ECX", "EDX", "EBX", "EBP", "ESI", "EDI"]
|
|
Bases = ["EAX", "ECX", "EDX", "EBX", "ESP", "ESI", "EDI"]
|
|
def test_without_seg(self):
|
|
self.assertEqual(I64("and [rip+0X5247], ch").inst.segment, REG_NONE)
|
|
self.assertEqual(I32("mov eax, [ebp*4]").inst.segment, Regs.DS)
|
|
self.assertEqual(I32("mov eax, [eax*4+ebp]").inst.segment, Regs.SS)
|
|
def test_default_seg16(self):
|
|
a = I16("mov [ds:0x1234], ax")
|
|
self.assertEqual(a.inst.segment, Regs.DS)
|
|
self.assertEqual(a.inst.isSegmentDefault, 1)
|
|
a = I16("mov [cs:0x1234], ax")
|
|
self.assertEqual(a.inst.segment, Regs.CS)
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
def test_default_seg16_all(self):
|
|
for i in ["ADD [ds:%s], AX" % i for i in self.Derefs16]:
|
|
a = I16(i)
|
|
self.assertEqual(a.inst.segment, Regs.DS)
|
|
if i[8:10] == "BP":
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
else:
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
# Test with disp8
|
|
for i in ["ADD [ds:%s + 0x55], AX" % i for i in self.Derefs16]:
|
|
a = I16(i)
|
|
self.assertEqual(a.inst.segment, Regs.DS)
|
|
if i[8:10] == "BP":
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
else:
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
def test_default_seg32(self):
|
|
self.assertEqual(I32("mov [ds:0x12345678], eax").inst.segment, Regs.DS)
|
|
self.assertEqual(I32("mov [cs:0x12345678], eax").inst.segment, Regs.CS)
|
|
texts = ["ADD [ds:%s], EAX" % i for i in self.Derefs32]
|
|
for i in enumerate(texts):
|
|
a = I32(i[1])
|
|
self.assertEqual(a.inst.segment, Regs.DS)
|
|
if self.Derefs32[i[0]] == "EBP":
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
else:
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
# Test with disp8
|
|
texts = ["ADD [ds:%s + 0x55], EAX" % i for i in self.Derefs32]
|
|
for i in enumerate(texts):
|
|
a = I32(i[1])
|
|
self.assertEqual(a.inst.segment, Regs.DS)
|
|
if self.Derefs32[i[0]] == "EBP":
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
else:
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
def test_sib(self):
|
|
for i in enumerate(self.Derefs32):
|
|
for j in enumerate(self.Bases):
|
|
for s in [1, 2, 4, 8]:
|
|
a = I32("cmp ebp, [ds:%s*%d + %s]" % (i[1], s, j[1]))
|
|
a2 = I32("cmp ebp, [ds:%s*%d + %s + 0x55]" % (i[1], s, j[1]))
|
|
self.assertEqual(a.inst.segment, Regs.DS)
|
|
self.assertEqual(a2.inst.segment, Regs.DS)
|
|
if (j[1] == "EBP" or j[1] == "ESP"):
|
|
self.assertEqual(a.inst.isSegmentDefault, False)
|
|
self.assertEqual(a2.inst.isSegmentDefault, False)
|
|
else:
|
|
self.assertEqual(a.inst.isSegmentDefault, True)
|
|
self.assertEqual(a2.inst.isSegmentDefault, True)
|
|
|
|
def test_seg64(self):
|
|
self.assertEqual(I64("mov [gs:rip+0x12345678], eax").inst.segment, Regs.GS)
|
|
self.assertEqual(I64("mov [fs:0x12345678], eax").inst.segment, Regs.FS)
|
|
def test_lock(self):
|
|
self.assertFalse("FLAG_LOCK" not in I32("lock inc dword [eax]").inst.flags)
|
|
def test_repnz(self):
|
|
self.assertFalse("FLAG_REPNZ" not in I32("repnz scasb").inst.flags)
|
|
def test_rep(self):
|
|
self.assertFalse("FLAG_REP" not in I32("rep movsb").inst.flags)
|
|
def test_reps(self):
|
|
""" Scas and cmps have different repZ prefix. """
|
|
self.assertTrue(str(I32("rep scasb").inst).find("REPZ") != -1)
|
|
self.assertTrue(str(I32("rep cmpsd").inst).find("REPZ") != -1)
|
|
self.assertTrue(str(I32("rep stosb").inst).find("REP") != -1)
|
|
self.assertTrue(str(I32("rep stosb").inst).find("REPZ") == -1)
|
|
self.assertTrue(str(I16("repnz scasb").inst).find("REPNZ") != -1)
|
|
self.assertTrue(str(I32("repnz cmpsd").inst).find("REPNZ") != -1)
|
|
self.assertTrue(str(I64("repnz stosb").inst).find("REPNZ") != -1)
|
|
def test_stos(self):
|
|
""" STOS instruction is treated specially with certain prefixes, check all such cases. """
|
|
# 16 bits
|
|
self.assertEqual(str(IB16("aa").inst), "STOSB")
|
|
self.assertEqual(str(IB16("ab").inst), "STOSW")
|
|
self.assertEqual(str(IB16("66ab").inst), "STOSD")
|
|
self.assertEqual(str(IB16("67ab").inst), "STOS [EDI], AX")
|
|
self.assertEqual(str(IB16("6766ab").inst), "STOS [EDI], EAX")
|
|
self.assertEqual(str(IB16("2eab").inst), "STOSW") # 1st op cannot be prefixed by segment!
|
|
self.assertEqual(str(IB16("f3ab").inst), "REP STOSW")
|
|
self.assertEqual(str(IB16("f2ab").inst), "REPNZ STOSW")
|
|
# 32 bits
|
|
self.assertEqual(str(IB32("aa").inst), "STOSB")
|
|
self.assertEqual(str(IB32("ab").inst), "STOSD")
|
|
self.assertEqual(str(IB32("66ab").inst), "STOSW")
|
|
self.assertEqual(str(IB32("67ab").inst), "STOS [DI], EAX")
|
|
self.assertEqual(str(IB32("6766ab").inst), "STOS [DI], AX")
|
|
self.assertEqual(str(IB32("2eab").inst), "STOSD") # 1st op cannot be prefixed by segment!
|
|
self.assertEqual(str(IB32("f3ab").inst), "REP STOSD")
|
|
self.assertEqual(str(IB32("f2ab").inst), "REPNZ STOSD")
|
|
# 64 bits
|
|
self.assertEqual(str(IB64("aa").inst), "STOSB")
|
|
self.assertEqual(str(IB64("ab").inst), "STOSD")
|
|
self.assertEqual(str(IB64("48ab").inst), "STOSQ")
|
|
self.assertEqual(str(IB64("66ab").inst), "STOSW")
|
|
self.assertEqual(str(IB64("67ab").inst), "STOS [EDI], EAX")
|
|
self.assertEqual(str(IB64("6766ab").inst), "STOS [EDI], AX")
|
|
self.assertEqual(str(IB64("2eab").inst), "STOSD") # 1st op cannot be prefixed by segment!
|
|
self.assertEqual(str(IB64("2e48ab").inst), "STOSQ") # 1st op cannot be prefixed by segment!
|
|
self.assertEqual(str(IB64("f3ab").inst), "REP STOSD")
|
|
self.assertEqual(str(IB64("f348ab").inst), "REP STOSQ")
|
|
self.assertEqual(str(IB64("f2ab").inst), "REPNZ STOSD")
|
|
self.assertEqual(str(IB64("f248ab").inst), "REPNZ STOSQ")
|
|
def test_scas(self):
|
|
""" SCAS instruction is treated specially with certain prefixes, check all such cases. """
|
|
# 16 bits
|
|
self.assertEqual(str(IB16("ae").inst), "SCASB")
|
|
self.assertEqual(str(IB16("af").inst), "SCASW")
|
|
self.assertEqual(str(IB16("66af").inst), "SCASD")
|
|
self.assertEqual(str(IB16("67af").inst), "SCAS [EDI], AX")
|
|
self.assertEqual(str(IB16("6766af").inst), "SCAS [EDI], EAX")
|
|
self.assertEqual(str(IB16("2eaf").inst), "SCASW") # 1st op cannot be prefixed by segment!
|
|
self.assertEqual(str(IB16("f3af").inst), "REPZ SCASW")
|
|
self.assertEqual(str(IB16("f2af").inst), "REPNZ SCASW")
|
|
# 32 bits
|
|
self.assertEqual(str(IB32("ae").inst), "SCASB")
|
|
self.assertEqual(str(IB32("af").inst), "SCASD")
|
|
self.assertEqual(str(IB32("66af").inst), "SCASW")
|
|
self.assertEqual(str(IB32("67af").inst), "SCAS [DI], EAX")
|
|
self.assertEqual(str(IB32("6766af").inst), "SCAS [DI], AX")
|
|
self.assertEqual(str(IB32("2eaf").inst), "SCASD") # 1st op cannot be prefixed by segment!
|
|
self.assertEqual(str(IB32("f3af").inst), "REPZ SCASD")
|
|
self.assertEqual(str(IB32("f2af").inst), "REPNZ SCASD")
|
|
# 64 bits
|
|
self.assertEqual(str(IB64("ae").inst), "SCASB")
|
|
self.assertEqual(str(IB64("af").inst), "SCASD")
|
|
self.assertEqual(str(IB64("48af").inst), "SCASQ")
|
|
self.assertEqual(str(IB64("66af").inst), "SCASW")
|
|
self.assertEqual(str(IB64("67af").inst), "SCAS [EDI], EAX")
|
|
self.assertEqual(str(IB64("6766af").inst), "SCAS [EDI], AX")
|
|
self.assertEqual(str(IB64("2eaf").inst), "SCASD") # 1st op cannot be prefixed by segment!
|
|
self.assertEqual(str(IB64("2e48af").inst), "SCASQ") # 1st op cannot be prefixed by segment!
|
|
self.assertEqual(str(IB64("f3af").inst), "REPZ SCASD")
|
|
self.assertEqual(str(IB64("f348af").inst), "REPZ SCASQ")
|
|
self.assertEqual(str(IB64("f2af").inst), "REPNZ SCASD")
|
|
self.assertEqual(str(IB64("f248af").inst), "REPNZ SCASQ")
|
|
def test_lods(self):
|
|
""" LODS instruction is treated specially with certain prefixes, check all such cases. """
|
|
# 16 bits
|
|
self.assertEqual(str(IB16("ac").inst), "LODSB")
|
|
self.assertEqual(str(IB16("ad").inst), "LODSW")
|
|
self.assertEqual(str(IB16("66ad").inst), "LODSD")
|
|
self.assertEqual(str(IB16("67ad").inst), "LODS AX, [ESI]")
|
|
self.assertEqual(str(IB16("6766ad").inst), "LODS EAX, [ESI]")
|
|
self.assertEqual(str(IB16("64ad").inst), "LODS AX, [FS:SI]")
|
|
self.assertEqual(str(IB16("f364ad").inst), "REP LODS AX, [FS:SI]")
|
|
self.assertEqual(str(IB16("f264ad").inst), "REPNZ LODS AX, [FS:SI]")
|
|
# 32 bits
|
|
self.assertEqual(str(IB32("ac").inst), "LODSB")
|
|
self.assertEqual(str(IB32("66ad").inst), "LODSW")
|
|
self.assertEqual(str(IB32("ad").inst), "LODSD")
|
|
self.assertEqual(str(IB32("f3ac").inst), "REP LODSB")
|
|
self.assertEqual(str(IB32("66f3ad").inst), "REP LODSW")
|
|
self.assertEqual(str(IB32("f3ad").inst), "REP LODSD")
|
|
self.assertEqual(str(IB32("65ad").inst), "LODS EAX, [GS:ESI]")
|
|
self.assertEqual(str(IB32("f365ad").inst), "REP LODS EAX, [GS:ESI]")
|
|
self.assertEqual(str(IB32("f36567ad").inst), "REP LODS EAX, [GS:SI]")
|
|
self.assertEqual(str(IB32("f3656766ad").inst), "REP LODS AX, [GS:SI]")
|
|
self.assertEqual(str(IB32("6667f365ad").inst), "REP LODS AX, [GS:SI]")
|
|
self.assertEqual(str(IB32("67f3ac").inst), "REP LODS AL, [SI]")
|
|
self.assertEqual(str(IB32("67f2ac").inst), "REPNZ LODS AL, [SI]")
|
|
# 64 bits
|
|
self.assertEqual(str(IB64("ac").inst), "LODSB")
|
|
self.assertEqual(str(IB64("66ad").inst), "LODSW")
|
|
self.assertEqual(str(IB64("ad").inst), "LODSD")
|
|
self.assertEqual(str(IB64("48ad").inst), "LODSQ")
|
|
self.assertEqual(str(IB64("f3ac").inst), "REP LODSB")
|
|
self.assertEqual(str(IB64("66f3ad").inst), "REP LODSW")
|
|
self.assertEqual(str(IB64("f3ad").inst), "REP LODSD")
|
|
self.assertEqual(str(IB64("65ad").inst), "LODS EAX, [GS:RSI]")
|
|
self.assertEqual(str(IB64("f365ad").inst), "REP LODS EAX, [GS:RSI]")
|
|
self.assertEqual(str(IB64("f36567ad").inst), "REP LODS EAX, [GS:ESI]")
|
|
self.assertEqual(str(IB64("f3656766ad").inst), "REP LODS AX, [GS:ESI]")
|
|
self.assertEqual(str(IB64("6667f365ad").inst), "REP LODS AX, [GS:ESI]")
|
|
self.assertEqual(str(IB64("6667f265ad").inst), "REPNZ LODS AX, [GS:ESI]")
|
|
self.assertEqual(str(IB64("67f3ac").inst), "REP LODS AL, [ESI]")
|
|
def test_movs(self):
|
|
""" MOVS instruction is treated specially with certain prefixes, check all such cases. """
|
|
# 16 bits
|
|
self.assertEqual(str(IB16("a4").inst), "MOVSB")
|
|
self.assertEqual(str(IB16("66a5").inst), "MOVSD")
|
|
self.assertEqual(str(IB16("a5").inst), "MOVSW")
|
|
self.assertEqual(str(IB16("f3a5").inst), "REP MOVSW")
|
|
self.assertEqual(str(IB16("66f3a5").inst), "REP MOVSD")
|
|
self.assertEqual(str(IB16("f366a5").inst), "REP MOVSD")
|
|
self.assertEqual(str(IB16("f3a5").inst), "REP MOVSW")
|
|
self.assertEqual(str(IB16("65a5").inst), "MOVS WORD [ES:DI], [GS:SI]")
|
|
self.assertEqual(str(IB16("f365a5").inst), "REP MOVS WORD [ES:DI], [GS:SI]")
|
|
self.assertEqual(str(IB16("f36567a5").inst), "REP MOVS WORD [ES:EDI], [GS:ESI]")
|
|
self.assertEqual(str(IB16("f3656766a5").inst), "REP MOVS DWORD [ES:EDI], [GS:ESI]")
|
|
self.assertEqual(str(IB16("6667f365a5").inst), "REP MOVS DWORD [ES:EDI], [GS:ESI]")
|
|
self.assertEqual(str(IB16("6667f3a4").inst), "REP MOVS BYTE [ES:EDI], [DS:ESI]")
|
|
self.assertEqual(str(IB16("6667f2a4").inst), "REPNZ MOVS BYTE [ES:EDI], [DS:ESI]")
|
|
# 32 bits
|
|
self.assertEqual(str(IB32("a4").inst), "MOVSB")
|
|
self.assertEqual(str(IB32("66a5").inst), "MOVSW")
|
|
self.assertEqual(str(IB32("a5").inst), "MOVSD")
|
|
self.assertEqual(str(IB32("f3a5").inst), "REP MOVSD")
|
|
self.assertEqual(str(IB32("66f3a5").inst), "REP MOVSW")
|
|
self.assertEqual(str(IB32("f366a5").inst), "REP MOVSW")
|
|
self.assertEqual(str(IB32("f3a5").inst), "REP MOVSD")
|
|
self.assertEqual(str(IB32("f2a5").inst), "REPNZ MOVSD")
|
|
self.assertEqual(str(IB32("65a5").inst), "MOVS DWORD [ES:EDI], [GS:ESI]")
|
|
self.assertEqual(str(IB32("f365a5").inst), "REP MOVS DWORD [ES:EDI], [GS:ESI]")
|
|
self.assertEqual(str(IB32("f36567a5").inst), "REP MOVS DWORD [ES:DI], [GS:SI]")
|
|
self.assertEqual(str(IB32("f3656766a5").inst), "REP MOVS WORD [ES:DI], [GS:SI]")
|
|
self.assertEqual(str(IB32("6667f365a5").inst), "REP MOVS WORD [ES:DI], [GS:SI]")
|
|
self.assertEqual(str(IB32("6667f3a4").inst), "REP MOVS BYTE [ES:DI], [DS:SI]")
|
|
self.assertEqual(str(IB32("6667f2a4").inst), "REPNZ MOVS BYTE [ES:DI], [DS:SI]")
|
|
# 64 bits
|
|
self.assertEqual(str(IB64("a4").inst), "MOVSB")
|
|
self.assertEqual(str(IB64("66a5").inst), "MOVSW")
|
|
self.assertEqual(str(IB64("a5").inst), "MOVSD")
|
|
self.assertEqual(str(IB64("48a5").inst), "MOVSQ")
|
|
self.assertEqual(str(IB64("4fa5").inst), "MOVSQ") # Set all REX bits, still MOVSQ.
|
|
self.assertEqual(str(IB64("f3a5").inst), "REP MOVSD")
|
|
self.assertEqual(str(IB64("f348a5").inst), "REP MOVSQ")
|
|
self.assertEqual(str(IB64("f248a5").inst), "REPNZ MOVSQ")
|
|
self.assertEqual(str(IB64("66f3a5").inst), "REP MOVSW")
|
|
self.assertEqual(str(IB64("f366a5").inst), "REP MOVSW")
|
|
self.assertEqual(str(IB64("f3a5").inst), "REP MOVSD")
|
|
self.assertEqual(str(IB64("65a5").inst), "MOVS DWORD [RDI], [GS:RSI]")
|
|
self.assertEqual(str(IB64("6548a5").inst), "MOVS QWORD [RDI], [GS:RSI]")
|
|
self.assertEqual(str(IB64("f365a5").inst), "REP MOVS DWORD [RDI], [GS:RSI]")
|
|
self.assertEqual(str(IB64("f367a5").inst), "REP MOVS DWORD [EDI], [ESI]")
|
|
self.assertEqual(str(IB64("f3656766a5").inst), "REP MOVS WORD [EDI], [GS:ESI]")
|
|
self.assertEqual(str(IB64("6667f365a5").inst), "REP MOVS WORD [EDI], [GS:ESI]")
|
|
self.assertEqual(str(IB64("6667f36548a5").inst), "REP MOVS QWORD [EDI], [GS:ESI]")
|
|
self.assertEqual(str(IB64("6667f3a4").inst), "REP MOVS BYTE [EDI], [ESI]")
|
|
def test_cmps(self):
|
|
""" CMPS instruction is treated specially with certain prefixes, check all such cases. """
|
|
# 16 bits
|
|
self.assertEqual(str(IB16("a6").inst), "CMPSB")
|
|
self.assertEqual(str(IB16("66a7").inst), "CMPSD")
|
|
self.assertEqual(str(IB16("a7").inst), "CMPSW")
|
|
self.assertEqual(str(IB16("f3a7").inst), "REPZ CMPSW")
|
|
self.assertEqual(str(IB16("66f3a7").inst), "REPZ CMPSD")
|
|
self.assertEqual(str(IB16("f366a7").inst), "REPZ CMPSD")
|
|
self.assertEqual(str(IB16("f3a7").inst), "REPZ CMPSW")
|
|
self.assertEqual(str(IB16("65a7").inst), "CMPS WORD [GS:SI], [ES:DI]")
|
|
self.assertEqual(str(IB16("f365a7").inst), "REPZ CMPS WORD [GS:SI], [ES:DI]")
|
|
self.assertEqual(str(IB16("f36567a7").inst), "REPZ CMPS WORD [GS:ESI], [ES:EDI]")
|
|
self.assertEqual(str(IB16("f3656766a7").inst), "REPZ CMPS DWORD [GS:ESI], [ES:EDI]")
|
|
self.assertEqual(str(IB16("6667f365a7").inst), "REPZ CMPS DWORD [GS:ESI], [ES:EDI]")
|
|
self.assertEqual(str(IB16("6667f3a6").inst), "REPZ CMPS BYTE [DS:ESI], [ES:EDI]")
|
|
self.assertEqual(str(IB16("6667f2a6").inst), "REPNZ CMPS BYTE [DS:ESI], [ES:EDI]")
|
|
# 32 bits
|
|
self.assertEqual(str(IB32("a6").inst), "CMPSB")
|
|
self.assertEqual(str(IB32("66a7").inst), "CMPSW")
|
|
self.assertEqual(str(IB32("a7").inst), "CMPSD")
|
|
self.assertEqual(str(IB32("f3a7").inst), "REPZ CMPSD")
|
|
self.assertEqual(str(IB32("66f3a7").inst), "REPZ CMPSW")
|
|
self.assertEqual(str(IB32("f366a7").inst), "REPZ CMPSW")
|
|
self.assertEqual(str(IB32("f3a7").inst), "REPZ CMPSD")
|
|
self.assertEqual(str(IB32("f2a7").inst), "REPNZ CMPSD")
|
|
self.assertEqual(str(IB32("65a7").inst), "CMPS DWORD [GS:ESI], [ES:EDI]")
|
|
self.assertEqual(str(IB32("f365a7").inst), "REPZ CMPS DWORD [GS:ESI], [ES:EDI]")
|
|
self.assertEqual(str(IB32("f36567a7").inst), "REPZ CMPS DWORD [GS:SI], [ES:DI]")
|
|
self.assertEqual(str(IB32("f3656766a7").inst), "REPZ CMPS WORD [GS:SI], [ES:DI]")
|
|
self.assertEqual(str(IB32("6667f365a7").inst), "REPZ CMPS WORD [GS:SI], [ES:DI]")
|
|
self.assertEqual(str(IB32("6667f3a6").inst), "REPZ CMPS BYTE [DS:SI], [ES:DI]")
|
|
self.assertEqual(str(IB32("6667f2a6").inst), "REPNZ CMPS BYTE [DS:SI], [ES:DI]")
|
|
# 64 bits
|
|
self.assertEqual(str(IB64("a6").inst), "CMPSB")
|
|
self.assertEqual(str(IB64("66a7").inst), "CMPSW")
|
|
self.assertEqual(str(IB64("a7").inst), "CMPSD")
|
|
self.assertEqual(str(IB64("48a7").inst), "CMPSQ")
|
|
self.assertEqual(str(IB64("4fa7").inst), "CMPSQ") # Set all REX bits, still CMPSQ.
|
|
self.assertEqual(str(IB64("f3a7").inst), "REPZ CMPSD")
|
|
self.assertEqual(str(IB64("f348a7").inst), "REPZ CMPSQ")
|
|
self.assertEqual(str(IB64("f248a7").inst), "REPNZ CMPSQ")
|
|
self.assertEqual(str(IB64("66f3a7").inst), "REPZ CMPSW")
|
|
self.assertEqual(str(IB64("f366a7").inst), "REPZ CMPSW")
|
|
self.assertEqual(str(IB64("f3a7").inst), "REPZ CMPSD")
|
|
self.assertEqual(str(IB64("65a7").inst), "CMPS DWORD [GS:RSI], [RDI]")
|
|
self.assertEqual(str(IB64("6548a7").inst), "CMPS QWORD [GS:RSI], [RDI]")
|
|
self.assertEqual(str(IB64("f365a7").inst), "REPZ CMPS DWORD [GS:RSI], [RDI]")
|
|
self.assertEqual(str(IB64("f367a7").inst), "REPZ CMPS DWORD [ESI], [EDI]")
|
|
self.assertEqual(str(IB64("f3656766a7").inst), "REPZ CMPS WORD [GS:ESI], [EDI]")
|
|
self.assertEqual(str(IB64("6667f365a7").inst), "REPZ CMPS WORD [GS:ESI], [EDI]")
|
|
self.assertEqual(str(IB64("6667f36548a7").inst), "REPZ CMPS QWORD [GS:ESI], [EDI]")
|
|
self.assertEqual(str(IB64("6667f3a6").inst), "REPZ CMPS BYTE [ESI], [EDI]")
|
|
def test_segment_override(self):
|
|
self.assertEqual(I32("mov eax, [cs:eax]").inst.segment, Regs.CS)
|
|
self.assertEqual(I32("mov eax, [ds:eax]").inst.segment, Regs.DS)
|
|
self.assertEqual(I32("mov eax, [es:eax]").inst.segment, Regs.ES)
|
|
self.assertEqual(I32("mov eax, [ss:eax]").inst.segment, Regs.SS)
|
|
self.assertEqual(I32("mov eax, [fs:eax]").inst.segment, Regs.FS)
|
|
self.assertEqual(I32("mov eax, [gs:eax]").inst.segment, Regs.GS)
|
|
def test_unused_normal(self):
|
|
self.assertEqual(IB64("4090").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("6790").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("6690").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("f290").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("f090").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("f3c3").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("64c3").inst.unusedPrefixesMask, 1)
|
|
def test_unused_doubles(self):
|
|
self.assertEqual(IB64("404090").inst.unusedPrefixesMask, 3)
|
|
self.assertEqual(IB64("676790").inst.unusedPrefixesMask, 3)
|
|
self.assertEqual(IB64("666690").inst.unusedPrefixesMask, 3)
|
|
self.assertEqual(IB64("f2f290").inst.unusedPrefixesMask, 3)
|
|
self.assertEqual(IB64("f0f090").inst.unusedPrefixesMask, 3)
|
|
self.assertEqual(IB64("f3f3c3").inst.unusedPrefixesMask, 3)
|
|
self.assertEqual(IB64("642ec3").inst.unusedPrefixesMask, 3)
|
|
def test_unused_sequences(self):
|
|
self.assertEqual(len(IB64("66"*15).insts), 15)
|
|
r = int(random.random() * 14)
|
|
self.assertEqual(IB64("66"*r + "90").inst.unusedPrefixesMask, (1 << r) - 1)
|
|
def test_rexw_66(self):
|
|
self.assertEqual(IB64("6648ffc0").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("6640ffc0").inst.unusedPrefixesMask, 2)
|
|
self.assertEqual(IB64("48660f10c0").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("664f0f10c0").inst.unusedPrefixesMask, 0)
|
|
def test_last_segment(self):
|
|
""" Only last segment is used as a prefix.
|
|
Check tricky 64 bits too for default overrides. """
|
|
self.assertEqual(IB32("2e260000").inst.segment, Regs.ES)
|
|
self.assertEqual(IB32("2e260000").inst.unusedPrefixesMask, 1)
|
|
self.assertEqual(IB64("2e650000").inst.segment, Regs.GS)
|
|
self.assertEqual(IB64("652e0000").inst.segment, REG_NONE)
|
|
self.assertEqual(IB64("652e0000").inst.unusedPrefixesMask, 3)
|
|
|
|
class TestInvalid(unittest.TestCase):
|
|
def align(self):
|
|
for i in range(15):
|
|
IB32("90")
|
|
def test_filter_mem(self):
|
|
#cmpxchg8b eax
|
|
IB32("0fc7c8")
|
|
self.align()
|
|
def test_drop_prefixes(self):
|
|
# Drop prefixes when we encountered an instruction that couldn't be decoded.
|
|
IB32("666764ffff")
|
|
self.align()
|
|
def test_zzz_must_be_last_drop_prefixes(self):
|
|
# Drop prefixes when the last byte in stream is a prefix.
|
|
IB32("66")
|
|
def test_CR4_regression(self):
|
|
# Regression test to validate CR4 isn't used as invalid default segment (-1 maps to CR4) in 64 bits.
|
|
self.assertEqual(str(IB64("f20f104c1860").inst), "MOVSD XMM1, [RAX+RBX+0x60]")
|
|
self.assertEqual(str(IB64("4883241e00").inst), "AND QWORD [RSI+RBX], 0x0")
|
|
def test_undefined_byte00(self):
|
|
# This is a regression test for the decomposer wrapper.
|
|
a = ""
|
|
insts = IB32("c300").insts
|
|
for i in insts:
|
|
a += str(i)
|
|
insts = IB32("33c0" * 2000 + "90", 0, 0x4000).insts
|
|
self.assertEqual(insts[-1].mnemonic, "NOP")
|
|
self.assertEqual(insts[-1].instructionBytes, b"\x90")
|
|
self.assertEqual(insts[-1].address, 0x4000 + 2000 * 2)
|
|
self.assertEqual(insts[1000].mnemonic, "XOR")
|
|
self.assertEqual(insts[1000].instructionBytes, b"\x33\xc0")
|
|
self.assertEqual(insts[1000].address, 0x4000 + 1000 * 2)
|
|
def test_prefix_regression(self):
|
|
# We had a temporary code with a prefix length bug that wouldn't return an instruction.
|
|
# So make sure we get an instruction where stream ends with last code byte.
|
|
self.assertEqual(IB32("66af").insts[0].mnemonic, "SCAS")
|
|
|
|
class TestFeatures(unittest.TestCase):
|
|
def test_addr16(self):
|
|
#I16("mov [-4], bx", 0, DF_MAXIMUM_ADDR16).check_disp(0, 0xfffc, 16, 16)
|
|
pass
|
|
def test_add32(self):
|
|
pass
|
|
def test_fc(self):
|
|
pairs = [
|
|
(["INT 5", "db 0xf1", "INT 3", "INTO", "UD2"], distorm3.FlowControl.INT),
|
|
(["CALL 0x50", "CALL FAR [ebx]"], distorm3.FlowControl.CALL),
|
|
(["RET", "IRET", "RETF"], distorm3.FlowControl.RET),
|
|
(["HLT"], distorm3.FlowControl.HLT),
|
|
(["SYSCALL", "SYSENTER", "SYSRET", "SYSEXIT"], distorm3.FlowControl.SYS),
|
|
(["JMP 0x50", "JMP FAR [ebx]"], distorm3.FlowControl.UNC_BRANCH),
|
|
(["JCXZ 0x50", "JO 0x50", "JNO 0x50", "JB 0x50", "JAE 0x50",
|
|
"JZ 0x50", "JNZ 0x50", "JBE 0x50", "JA 0x50", "JS 0x50",
|
|
"JNS 0x50", "JP 0x50", "JNP 0x50", "JL 0x50", "JGE 0x50",
|
|
"JLE 0x50", "JG 0x50", "LOOP 0x50", "LOOPZ 0x50", "LOOPNZ 0x50"], distorm3.FlowControl.CND_BRANCH)
|
|
]
|
|
for i in pairs:
|
|
for j in i[0]:
|
|
a = I32(j + "\nnop", distorm3.DF_STOP_ON_FLOW_CONTROL)
|
|
self.assertEqual(len(a.insts), 1)
|
|
self.assertEqual(a.inst.meta & 0xf, i[1])
|
|
a = I32("push eax\nnop\n" + j, distorm3.DF_RETURN_FC_ONLY)
|
|
self.assertEqual(len(a.insts), 1)
|
|
a = I32("nop\nxor eax, eax\n" + j + "\ninc eax", distorm3.DF_RETURN_FC_ONLY | distorm3.DF_STOP_ON_FLOW_CONTROL)
|
|
self.assertEqual(len(a.insts), 1)
|
|
def test_filter(self):
|
|
a = IB32("33c0907e00" * 5, distorm3.DF_RETURN_FC_ONLY).insts
|
|
self.assertEqual(len(a), 5)
|
|
self.assertEqual(a[0].mnemonic[0], "J")
|
|
self.assertEqual(a[0].address, 3)
|
|
self.assertEqual(a[1].address, 8)
|
|
self.assertEqual(a[2].address, 13)
|
|
self.assertEqual(a[3].address, 18)
|
|
self.assertEqual(a[4].address, 23)
|
|
def test_stop_on_privileged(self):
|
|
a = I32("nop\niret\nret", distorm3.DF_STOP_ON_PRIVILEGED)
|
|
self.assertEqual(len(a.insts), 2)
|
|
a = I64("mov eax, ebx\nnop\ncli\nnop", distorm3.DF_STOP_ON_PRIVILEGED)
|
|
self.assertEqual(len(a.insts), 3)
|
|
def test_step_byte(self):
|
|
a = IB32("90b833c3eb48", distorm3.DF_SINGLE_BYTE_STEP).insts
|
|
self.assertEqual(a[0].address, 0)
|
|
self.assertEqual(a[0].mnemonic, "NOP")
|
|
self.assertEqual(a[0].size, 1)
|
|
self.assertEqual(a[1].address, 1)
|
|
self.assertEqual(a[1].mnemonic, "MOV")
|
|
self.assertEqual(a[1].size, 5)
|
|
self.assertEqual(a[2].address, 2)
|
|
self.assertEqual(a[2].mnemonic, "XOR")
|
|
self.assertEqual(a[2].size, 2)
|
|
self.assertEqual(a[3].address, 3)
|
|
self.assertEqual(a[3].mnemonic, "RET")
|
|
self.assertEqual(a[3].size, 1)
|
|
self.assertEqual(a[4].address, 4)
|
|
self.assertEqual(a[4].mnemonic, "JMP")
|
|
self.assertEqual(a[4].size, 2)
|
|
self.assertEqual(a[5].address, 5)
|
|
self.assertEqual(a[5].mnemonic, "DEC")
|
|
self.assertEqual(a[5].size, 1)
|
|
def test_eflags_on(self):
|
|
a = IB32("33c04890", distorm3.DF_FILL_EFLAGS).insts
|
|
# XOR
|
|
self.assertEqual(a[0].modifiedFlags, distorm3.D_SF | distorm3.D_ZF | distorm3.D_PF)
|
|
self.assertEqual(a[0].testedFlags, 0)
|
|
self.assertEqual(a[0].undefinedFlags, distorm3.D_AF)
|
|
# INC
|
|
self.assertEqual(a[1].modifiedFlags, distorm3.D_OF | distorm3.D_SF | distorm3.D_ZF | distorm3.D_AF | distorm3.D_PF)
|
|
self.assertEqual(a[1].testedFlags, 0)
|
|
self.assertEqual(a[1].undefinedFlags, 0)
|
|
# NOP
|
|
self.assertEqual(a[2].modifiedFlags, 0)
|
|
self.assertEqual(a[2].testedFlags, 0)
|
|
self.assertEqual(a[2].undefinedFlags, 0)
|
|
def test_eflags_off(self):
|
|
a = IB32("33c04890").insts
|
|
# XOR
|
|
self.assertEqual(a[0].modifiedFlags, 0)
|
|
self.assertEqual(a[0].testedFlags, 0)
|
|
self.assertEqual(a[0].undefinedFlags, 0)
|
|
# INC
|
|
self.assertEqual(a[1].modifiedFlags, 0)
|
|
self.assertEqual(a[1].testedFlags, 0)
|
|
self.assertEqual(a[1].undefinedFlags, 0)
|
|
# NOP
|
|
self.assertEqual(a[2].modifiedFlags, 0)
|
|
self.assertEqual(a[2].testedFlags, 0)
|
|
self.assertEqual(a[2].undefinedFlags, 0)
|
|
def test_stop_undecodable(self):
|
|
self.assertEqual(len(IB16("909033c0ffff90", distorm3.DF_STOP_ON_UNDECODEABLE).insts), 4)
|
|
self.assertEqual(len(IB32("909033c090ffff90", distorm3.DF_STOP_ON_UNDECODEABLE).insts), 5)
|
|
self.assertEqual(len(IB64("909033c09090ffff9090", distorm3.DF_STOP_ON_UNDECODEABLE).insts), 6)
|
|
|
|
class TestAPI(unittest.TestCase):
|
|
def direct_decompose(self, code, codeOffset, dt, features, maxInstructions):
|
|
codeLen = len(code)
|
|
code_buf = ctypes.create_string_buffer(code)
|
|
p_code = ctypes.byref(code_buf)
|
|
result = (distorm3._DInst * maxInstructions)()
|
|
p_result = ctypes.byref(result)
|
|
usedInstructionsCount = ctypes.c_uint(0)
|
|
codeInfo = distorm3._CodeInfo(distorm3._OffsetType(codeOffset), distorm3._OffsetType(0), distorm3._OffsetType(0), ctypes.cast(p_code, ctypes.c_char_p), codeLen, dt, features)
|
|
status = distorm3.internal_decompose(ctypes.byref(codeInfo), ctypes.byref(result), maxInstructions, ctypes.byref(usedInstructionsCount))
|
|
return (status, usedInstructionsCount.value, result)
|
|
def test_out_buf(self):
|
|
s, count, results = self.direct_decompose(b"\x90\x90", 0, distorm3.Decode32Bits, 0, 0)
|
|
self.assertEqual(s, distorm3.DECRES_INPUTERR)
|
|
s, count, results = self.direct_decompose(b"\x90\x90", 0, distorm3.Decode32Bits, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_MEMORYERR)
|
|
self.assertEqual(count, 1)
|
|
s, count, results = self.direct_decompose(b"\x90\x90", 0, distorm3.Decode32Bits, 0, 2)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 2)
|
|
def test_0_len(self):
|
|
s, count, results = self.direct_decompose(b"", 0, distorm3.Decode32Bits, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
s, count, results = self.direct_decompose(b"", 0x1234, distorm3.Decode64Bits, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
def test_bad_features(self):
|
|
s, count, results = self.direct_decompose(b"\x90", 0, distorm3.Decode32Bits, distorm3.DF_MAXIMUM_ADDR16 | distorm3.DF_MAXIMUM_ADDR32, 1)
|
|
self.assertEqual(s, distorm3.DECRES_INPUTERR)
|
|
def test_bad_decoding_type(self):
|
|
s, count, results = self.direct_decompose(b"\x90", 0, -1, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_INPUTERR)
|
|
s, count, results = self.direct_decompose(b"\x90", 0, 3, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_INPUTERR)
|
|
def test_single_out_buf(self):
|
|
s, count, results = self.direct_decompose(b"\x66\x90", 0, distorm3.Decode32Bits, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(Mnemonics.get(results[0].opcode, ""), "NOP")
|
|
s, count, results = self.direct_decompose(b"\x66\x67", 0, distorm3.Decode32Bits, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_MEMORYERR)
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(results[0].imm.byte, 0x66)
|
|
s, count, results = self.direct_decompose(b"\x66\x67", 0, distorm3.Decode32Bits, 0, 2)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 2)
|
|
self.assertEqual(results[0].imm.byte, 0x66)
|
|
self.assertEqual(results[1].imm.byte, 0x67)
|
|
s, count, results = self.direct_decompose(b"\x66\x67", 0, distorm3.Decode32Bits, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_MEMORYERR)
|
|
self.assertEqual(count, 1)
|
|
def test_drop_skip(self):
|
|
s, count, results = self.direct_decompose(b"\x05\x00\x01", 0, distorm3.Decode32Bits, 0, 1) # Skips 05, then returns add [ecx], al
|
|
self.assertEqual(s, distorm3.DECRES_MEMORYERR)
|
|
self.assertEqual(count, 1)
|
|
s, count, results = self.direct_decompose(b"\x05\x00\x01", 0, distorm3.Decode32Bits, 0, 2)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 2)
|
|
s, count, results = self.direct_decompose(b"\xc4\x01", 0, distorm3.Decode32Bits, 0, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(Mnemonics.get(results[0].opcode, ""), "LES")
|
|
s, count, results = self.direct_decompose(b"\xc5\xc5", 0, distorm3.Decode32Bits, 0, 2)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 2)
|
|
self.assertEqual(results[0].imm.byte, 0xc5)
|
|
self.assertEqual(results[1].imm.byte, 0xc5)
|
|
s, count, results = self.direct_decompose(b"\xc5\xc5\xc5", 0, distorm3.Decode32Bits, 0, 3)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 3)
|
|
self.assertEqual(results[0].imm.byte, 0xc5)
|
|
self.assertEqual(results[1].imm.byte, 0xc5)
|
|
self.assertEqual(results[2].imm.byte, 0xc5)
|
|
def test_fc(self):
|
|
s, count, results = self.direct_decompose(b"\x90", 0, distorm3.Decode32Bits, distorm3.DF_RETURN_FC_ONLY, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 0)
|
|
s, count, results = self.direct_decompose(b"\x90\x75\x00", 0, distorm3.Decode32Bits, distorm3.DF_RETURN_FC_ONLY, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 1)
|
|
def test_single_step(self):
|
|
s, count, results = self.direct_decompose(b"\x33\xff\xc0", 0, distorm3.Decode32Bits, distorm3.DF_SINGLE_BYTE_STEP, 1)
|
|
self.assertEqual(s, distorm3.DECRES_MEMORYERR)
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(Mnemonics.get(results[0].opcode, ""), "XOR")
|
|
s, count, results = self.direct_decompose(b"\x33\xff\xc0", 0, distorm3.Decode32Bits, distorm3.DF_SINGLE_BYTE_STEP, 2)
|
|
self.assertEqual(s, distorm3.DECRES_MEMORYERR)
|
|
self.assertEqual(count, 2)
|
|
self.assertEqual(Mnemonics.get(results[0].opcode, ""), "XOR")
|
|
self.assertEqual(Mnemonics.get(results[1].opcode, ""), "INC")
|
|
s, count, results = self.direct_decompose(b"\x33\xff\xc0", 0, distorm3.Decode32Bits, distorm3.DF_SINGLE_BYTE_STEP, 3)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 3)
|
|
self.assertEqual(Mnemonics.get(results[0].opcode, ""), "XOR")
|
|
self.assertEqual(Mnemonics.get(results[1].opcode, ""), "INC")
|
|
self.assertEqual(results[2].imm.byte, 0xc0)
|
|
def test_fc_and_single_step(self):
|
|
s, count, results = self.direct_decompose(b"\x33\xc3", 0, distorm3.Decode32Bits, distorm3.DF_SINGLE_BYTE_STEP | distorm3.DF_RETURN_FC_ONLY, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(Mnemonics.get(results[0].opcode, ""), "RET")
|
|
def test_fc_dropped(self):
|
|
s, count, results = self.direct_decompose(b"\x33\xc3", 0, distorm3.Decode64Bits, distorm3.DF_RETURN_FC_ONLY, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 0)
|
|
s, count, results = self.direct_decompose(b"\x66\x67\x90\xc3", 0, distorm3.Decode64Bits, distorm3.DF_RETURN_FC_ONLY, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 1)
|
|
s, count, results = self.direct_decompose(b"\x66\x67", 0, distorm3.Decode64Bits, distorm3.DF_RETURN_FC_ONLY, 1)
|
|
self.assertEqual(s, distorm3.DECRES_SUCCESS)
|
|
self.assertEqual(count, 0)
|
|
|
|
def GetNewSuite(className):
|
|
suite = unittest.TestSuite()
|
|
suite.addTest(unittest.makeSuite(className))
|
|
return suite
|
|
|
|
def initfiles():
|
|
for i in ["bin16", "bin32", "bin64"]:
|
|
fbin.append(open("build\\linux\\"+i, "wb"))
|
|
|
|
if "pytest" in sys.modules:
|
|
print("pytest isn't supported; this file uses Python's unittest, run: ./test_distorm3.py")
|
|
sys.exit(-1)
|
|
|
|
if __name__ == "__main__":
|
|
random.seed()
|
|
#initfiles() # Used to emit the bytes of the tests - useful for code coverage input.
|
|
suite = unittest.TestSuite()
|
|
suite.addTest(GetNewSuite(TestMode16))
|
|
suite.addTest(GetNewSuite(TestMode32))
|
|
suite.addTest(GetNewSuite(TestMode64))
|
|
suite.addTest(GetNewSuite(TestInstTable))
|
|
suite.addTest(GetNewSuite(TestAVXOperands))
|
|
suite.addTest(GetNewSuite(TestMisc))
|
|
suite.addTest(GetNewSuite(TestMisc2))
|
|
suite.addTest(GetNewSuite(TestPrefixes))
|
|
suite.addTest(GetNewSuite(TestInvalid))
|
|
suite.addTest(GetNewSuite(TestFeatures))
|
|
suite.addTest(GetNewSuite(TestAPI))
|
|
result = unittest.TextTestRunner(verbosity=1).run(suite)
|
|
if result.wasSuccessful():
|
|
exit(0)
|
|
else:
|
|
exit(1)
|