mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Fix simple_x64 REX for python3
This commit is contained in:
@@ -8,6 +8,8 @@ import windows.native_exec.simple_x64 as x64
|
||||
from windows.native_exec.simple_x64 import *
|
||||
del Test # Prevent pytest warning
|
||||
|
||||
from windows.pycompat import int_types
|
||||
|
||||
if capstone:
|
||||
disassembleur = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64)
|
||||
disassembleur.detail = True
|
||||
@@ -27,8 +29,6 @@ def disas(x):
|
||||
mnemonic_name_exception = {'movabs': 'mov'}
|
||||
|
||||
|
||||
|
||||
|
||||
class CheckInstr(object):
|
||||
def __init__(self, instr_to_test, expected_result=None, immediat_accepted=None, must_fail=None, debug=False):
|
||||
self.instr_to_test = instr_to_test
|
||||
@@ -87,7 +87,7 @@ class CheckInstr(object):
|
||||
raise AssertionError("Expected args {0} operands got {1}".format(op_args, capres_op))
|
||||
if op_args.lower() != capres.reg_name(cap_op.reg).lower():
|
||||
raise AssertionError("Expected register <{0}> got {1}".format(op_args.lower(), capres.reg_name(cap_op.reg).lower()))
|
||||
elif isinstance(op_args, (int, long)):
|
||||
elif isinstance(op_args, int_types):
|
||||
if (op_args != cap_op.imm) and not (self.immediat_accepted and self.immediat_accepted == cap_op.imm):
|
||||
raise AssertionError("Expected Immediat <{0}> got {1}".format(op_args, cap_op.imm))
|
||||
elif isinstance(op_args, mem_access):
|
||||
@@ -272,13 +272,18 @@ def test_assembler():
|
||||
CheckInstr(Add, must_fail=True)('RAX', 0xffffffff)
|
||||
|
||||
|
||||
# Test some prefix / REP
|
||||
assert (x64.Rep + x64.Nop()).get_code() == b"\xf3\x90"
|
||||
assert (x64.GSPrefix + x64.Nop()).get_code() == b"\x65\x90"
|
||||
assert (x64.OperandSizeOverride + x64.Nop()).get_code() == b"\x66\x90"
|
||||
assert (x64.Repne + x64.Nop()).get_code() == b"\xf2\x90"
|
||||
|
||||
code = MultipleInstr()
|
||||
code += Nop()
|
||||
code += Rep + Nop()
|
||||
code += Ret()
|
||||
print(repr(code.get_code()))
|
||||
assert code.get_code() == "\x90\xf3\x90\xc3"
|
||||
assert code.get_code() == b"\x90\xf3\x90\xc3"
|
||||
|
||||
def test_simple_x64_raw_instruction():
|
||||
# Test the fake instruction "raw"
|
||||
@@ -296,8 +301,14 @@ def test_x64_multiple_instr_add_instr_and_str():
|
||||
res += "ret; ret; label :offset_3; ret"
|
||||
res += x64.Nop()
|
||||
res += x64.Label(":offset_5")
|
||||
assert res.get_code() == "\x90\xc3\xc3\xc3\x90"
|
||||
assert res.get_code() == b"\x90\xc3\xc3\xc3\x90"
|
||||
assert res.labels == {":offset_3": 3, ":offset_5": 5}
|
||||
|
||||
def test_x64_instr_multiply():
|
||||
res = x64.MultipleInstr()
|
||||
res += (x64.Nop() * 5)
|
||||
res += x64.Ret()
|
||||
assert res.get_code() == b"\x90\x90\x90\x90\x90\xc3"
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_assembler()
|
||||
|
||||
@@ -9,6 +9,8 @@ import windows.native_exec.simple_x86 as x86
|
||||
from windows.native_exec.simple_x86 import *
|
||||
del Test # Prevent pytest warning
|
||||
|
||||
from windows.pycompat import int_types
|
||||
|
||||
VERBOSE = False
|
||||
|
||||
if capstone:
|
||||
@@ -77,7 +79,7 @@ class CheckInstr(object):
|
||||
raise AssertionError("Expected args {0} operands got {1}".format(op_args, capres_op))
|
||||
if op_args.lower() != capres.reg_name(cap_op.reg).lower():
|
||||
raise AssertionError("Expected register <{0}> got {1}".format(op_args.lower(), capres.reg_name(cap_op.reg).lower()))
|
||||
elif isinstance(op_args, (int, long)):
|
||||
elif isinstance(op_args, int_types):
|
||||
if (op_args != cap_op.imm) and not (self.immediat_accepted and self.immediat_accepted == cap_op.imm):
|
||||
raise AssertionError("Expected Immediat <{0}> got {1}".format(op_args, cap_op.imm))
|
||||
elif isinstance(op_args, mem_access):
|
||||
@@ -226,7 +228,7 @@ def test_assembler():
|
||||
code += Rep + Nop()
|
||||
code += Ret()
|
||||
print(repr(code.get_code()))
|
||||
assert code.get_code() == "\x90\xf3\x90\xc3"
|
||||
assert code.get_code() == b"\x90\xf3\x90\xc3"
|
||||
|
||||
def test_simple_x64_raw_instruction():
|
||||
# Test the fake instruction "raw"
|
||||
@@ -239,9 +241,15 @@ def test_x86_multiple_instr_add_instr_and_str():
|
||||
res += "ret; ret; label :offset_3; ret"
|
||||
res += x86.Nop()
|
||||
res += x86.Label(":offset_5")
|
||||
assert res.get_code() == "\x90\xc3\xc3\xc3\x90"
|
||||
assert res.get_code() == b"\x90\xc3\xc3\xc3\x90"
|
||||
assert res.labels == {":offset_3": 3, ":offset_5": 5}
|
||||
|
||||
def test_x86_instr_multiply():
|
||||
res = x86.MultipleInstr()
|
||||
res += (x86.Nop() * 5)
|
||||
res += x86.Ret()
|
||||
assert res.get_code() == b"\x90\x90\x90\x90\x90\xc3"
|
||||
|
||||
if capstone is None:
|
||||
test_assembler = pytest.mark.skip("Capstone not installed")(test_assembler)
|
||||
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
import sys
|
||||
import collections
|
||||
import struct
|
||||
import binascii
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
||||
# py3
|
||||
is_py3 = (sys.version_info.major >= 3)
|
||||
if is_py3:
|
||||
basestring = str
|
||||
int_types = int
|
||||
else:
|
||||
int_types = (int, long)
|
||||
|
||||
class BitArray(object):
|
||||
def __init__(self, size, bits):
|
||||
self.size = size
|
||||
@@ -73,6 +84,16 @@ class BitArray(object):
|
||||
def copy(self):
|
||||
return type(self)(self.size, self.array)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, BitArray):
|
||||
return NotImplemented
|
||||
return self.array == other.array
|
||||
|
||||
def __ne__(self, other):
|
||||
if not isinstance(other, BitArray):
|
||||
return NotImplemented
|
||||
return self.array != other.array
|
||||
|
||||
|
||||
# Prefix
|
||||
class Prefix(object):
|
||||
@@ -84,9 +105,15 @@ class Prefix(object):
|
||||
def __add__(self, other):
|
||||
return type(self)(other)
|
||||
|
||||
def get_code_py3(self):
|
||||
return bytes([self.PREFIX_VALUE]) + self.next.get_code()
|
||||
|
||||
def get_code(self):
|
||||
return chr(self.PREFIX_VALUE) + self.next.get_code()
|
||||
|
||||
if is_py3:
|
||||
get_code = get_code_py3
|
||||
|
||||
|
||||
def create_prefix(name, value):
|
||||
prefix_type = type(name + "Type", (Prefix,), {'PREFIX_VALUE': value})
|
||||
@@ -763,6 +790,9 @@ class Instruction(object):
|
||||
default_rex = BitArray.from_int(8, 0x40)
|
||||
|
||||
def __init__(self, *initial_args):
|
||||
# if (type(self) is Push):
|
||||
# import pdb;pdb.set_trace()
|
||||
|
||||
for type_encoding in self.encoding:
|
||||
args = list(initial_args)
|
||||
res = []
|
||||
@@ -783,7 +813,7 @@ class Instruction(object):
|
||||
continue
|
||||
self.prefix = prefix
|
||||
self.value = sum(res, BitArray(0, ""))
|
||||
if str(full_rex.dump()) != "\x40":
|
||||
if full_rex != self.default_rex:
|
||||
self.value = full_rex + self.value
|
||||
return
|
||||
raise ValueError("Cannot encode <{0} {1}>:(".format(type(self).__name__, initial_args))
|
||||
@@ -792,8 +822,15 @@ class Instruction(object):
|
||||
prefix_opcode = b"".join(chr(p.PREFIX_VALUE) for p in self.prefix)
|
||||
return prefix_opcode + bytes(self.value.dump())
|
||||
|
||||
def get_code_py3(self):
|
||||
prefix_opcode = b"".join(bytes([p.PREFIX_VALUE]) for p in self.prefix)
|
||||
return prefix_opcode + bytes(self.value.dump())
|
||||
|
||||
if is_py3:
|
||||
get_code = get_code_py3
|
||||
|
||||
def __mul__(self, value):
|
||||
if not isinstance(value, (int, long)):
|
||||
if not isinstance(value, int_types):
|
||||
return NotImplemented
|
||||
res = MultipleInstr()
|
||||
for i in range(value):
|
||||
@@ -1071,7 +1108,7 @@ class Raw(Instruction):
|
||||
if len(initial_args) != 1:
|
||||
raise ValueError("raw 'opcode' only accept one argument")
|
||||
# Accept space
|
||||
self.data = initial_args[0].replace(" ", "").decode("hex")
|
||||
self.data = binascii.unhexlify(initial_args[0].replace(" ", ""))
|
||||
|
||||
def get_code(self):
|
||||
return self.data
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import sys
|
||||
import collections
|
||||
import struct
|
||||
import binascii
|
||||
|
||||
# py3
|
||||
is_py3 = (sys.version_info.major >= 3)
|
||||
if is_py3:
|
||||
basestring = str
|
||||
int_types = int
|
||||
else:
|
||||
int_types = (int, long)
|
||||
|
||||
class BitArray(object):
|
||||
def __init__(self, size, bits):
|
||||
@@ -633,7 +637,7 @@ class Instruction(object):
|
||||
# return res
|
||||
|
||||
def __mul__(self, value):
|
||||
if not isinstance(value, (int, long)):
|
||||
if not isinstance(value, int_types):
|
||||
return NotImplemented
|
||||
res = MultipleInstr()
|
||||
for i in range(value):
|
||||
@@ -910,7 +914,7 @@ class Raw(Instruction):
|
||||
if len(initial_args) != 1:
|
||||
raise ValueError("raw 'opcode' only accept one argument")
|
||||
# Accept space
|
||||
self.data = initial_args[0].replace(" ", "").decode("hex")
|
||||
self.data = binascii.unhexlify(initial_args[0].replace(" ", ""))
|
||||
|
||||
def get_code(self):
|
||||
return self.data
|
||||
|
||||
@@ -54,7 +54,6 @@ class PipeConnection(object): # Cannot inherit: crash the interpreter
|
||||
gdef.PIPE_UNLIMITED_INSTANCES, cls.BUFFER_SIZE, cls.BUFFER_SIZE,
|
||||
gdef.NMPWAIT_WAIT_FOREVER, security_attributes
|
||||
)
|
||||
import pdb;pdb.set_trace()
|
||||
return cls.from_handle(pipehandle, name=addr, server=True)
|
||||
|
||||
@classmethod
|
||||
|
||||
Reference in New Issue
Block a user