mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
227 lines
7.1 KiB
Python
227 lines
7.1 KiB
Python
import struct
|
|
import sys
|
|
|
|
this_module = sys.modules[__name__]
|
|
|
|
def add_instruction(name, instruction):
|
|
setattr(this_module, name, instruction)
|
|
|
|
reg_order = ['EAX', 'ECX', 'EDX', 'EBX', 'ESP', 'EBP', 'ESI', 'EDI']
|
|
reg_opcode = {v : format(i, "03b") for i, v in enumerate(reg_order)}
|
|
|
|
|
|
class X86Instruction(object):
|
|
mnemo = ""
|
|
code = ""
|
|
biding = 0
|
|
|
|
def __init__(self, *bind_values):
|
|
if len(bind_values) != self.biding:
|
|
raise ValueError("{0} expect {1} values got {2}".format(self.__class__.__name__, self.biding, len(bind_values)))
|
|
self.bind_values = bind_values
|
|
for i, v in enumerate(bind_values):
|
|
if not isinstance(v, (int, long)):
|
|
raise ValueError("{0} bindings must be 'int' got '{1}' instead".format(self.__class__.__name__, type(v).__name__))
|
|
if not 0 <= v <= 0xffffffff:
|
|
raise ValueError("{0} bindings must be between 0 and 0xffffffff".format(self.__class__.__name__))
|
|
|
|
def get_unbinded_code(self):
|
|
return self.code.replace(" ", "").decode('hex')
|
|
|
|
def get_code(self):
|
|
code = self.get_unbinded_code()
|
|
for i in range(self.biding):
|
|
code = code.replace((str(i + 1) * 8).decode('hex'), struct.pack("<I", self.bind_values[i]))
|
|
return code
|
|
|
|
def get_mnemo(self):
|
|
return self.mnemo.format(*(hex(v) for v in self.bind_values))
|
|
|
|
|
|
class Ret(X86Instruction):
|
|
mnemo = "ret"
|
|
code = "C3"
|
|
|
|
class Int3(X86Instruction):
|
|
mnemo = "int3"
|
|
code = "CC"
|
|
|
|
|
|
class SimpleRegInstructionGenerator(object):
|
|
name = ""
|
|
instruction_bits = ''
|
|
|
|
|
|
class OneBindX86Instruction(X86Instruction):
|
|
biding = 1
|
|
|
|
|
|
class Push_X(OneBindX86Instruction):
|
|
mnemo = "push {0}"
|
|
code = "68 11 11 11 11"
|
|
|
|
|
|
def generate_simple_reg_instruction(instr_cls):
|
|
for reg_name, reg_bits in reg_opcode.items():
|
|
class SimpleRegInstruction(X86Instruction):
|
|
mnemo = "{0} {1}".format(instr_cls.mnemo, reg_name)
|
|
code = format(int(instr_cls.instruction_bits + reg_bits, 2), 'x')
|
|
|
|
SimpleRegInstruction.__name__ = "{0}_{1}".format(instr_cls.name, reg_name)
|
|
add_instruction(SimpleRegInstruction.__name__, SimpleRegInstruction)
|
|
|
|
|
|
class Push_Reg(object):
|
|
name = 'Push'
|
|
mnemo = "push"
|
|
instruction_bits = '01010'
|
|
|
|
generate_simple_reg_instruction(Push_Reg)
|
|
|
|
class Pop_Reg(object):
|
|
name = 'Pop'
|
|
mnemo = "pop"
|
|
instruction_bits = '01011'
|
|
|
|
generate_simple_reg_instruction(Pop_Reg)
|
|
|
|
class Call_Reg(object):
|
|
name = 'Call'
|
|
mnemo = "call"
|
|
instruction_bits = '1111111111010'
|
|
|
|
generate_simple_reg_instruction(Call_Reg)
|
|
|
|
|
|
|
|
def generate_reg_instruction_onebind(instr_cls):
|
|
for reg_name, reg_bits in reg_opcode.items():
|
|
class OneBindRegInstruction(OneBindX86Instruction):
|
|
mnemo = instr_cls.mnemo.format(reg_name)
|
|
code = chr(int(instr_cls.instruction_bits + reg_bits, 2)).encode('hex') + '11 11 11 11' # the biding
|
|
|
|
OneBindRegInstruction.__name__ = instr_cls.name.format(reg_name)
|
|
add_instruction(OneBindRegInstruction.__name__, OneBindRegInstruction)
|
|
|
|
class Mov_Reg_X(object):
|
|
name = 'Mov_{0}_X'
|
|
mnemo = 'mov {0}, {{0}}'
|
|
instruction_bits = '10111'
|
|
|
|
generate_reg_instruction_onebind(Mov_Reg_X)
|
|
|
|
def get_immediat_modr_byte(register_bits):
|
|
"Generate a modr-reg-r/m indicating a register and an immediat"
|
|
str_bits = "11000{0}".format(register_bits)
|
|
return chr(int(str_bits, 2)).encode('hex')
|
|
|
|
def generate_reg_immediat_modr(instr_cls):
|
|
for reg_name, reg_bits in reg_opcode.items():
|
|
class Reg_MEM_Instruction(OneBindX86Instruction):
|
|
mnemo = instr_cls.mnemo.format(reg_name)
|
|
code = instr_cls.instruction_bits + get_immediat_modr_byte(reg_bits) + '11 11 11 11' # the biding
|
|
|
|
Reg_MEM_Instruction.__name__ = instr_cls.name.format(reg_name)
|
|
add_instruction(Reg_MEM_Instruction.__name__, Reg_MEM_Instruction)
|
|
|
|
class Add_Reg_X(object):
|
|
name = 'Add_{0}_X'
|
|
mnemo = 'add {0}, {{0}}'
|
|
instruction_bits = '81'
|
|
|
|
generate_reg_immediat_modr(Add_Reg_X)
|
|
|
|
|
|
def get_simple_modr_byte(register_bits):
|
|
"Generate a simple modr-reg-r/m for a displacement only mode"
|
|
str_bits = "00{0}101".format(register_bits)
|
|
return chr(int(str_bits, 2)).encode('hex')
|
|
|
|
|
|
def generate_reg_modr(instr_cls):
|
|
for reg_name, reg_bits in reg_opcode.items():
|
|
class Reg_MEM_Instruction(OneBindX86Instruction):
|
|
mnemo = instr_cls.mnemo.format(reg_name)
|
|
code = instr_cls.instruction_bits + get_simple_modr_byte(reg_bits) + '11 11 11 11' # the biding
|
|
|
|
Reg_MEM_Instruction.__name__ = instr_cls.name.format(reg_name)
|
|
add_instruction(Reg_MEM_Instruction.__name__, Reg_MEM_Instruction)
|
|
|
|
|
|
|
|
|
|
class Mov_Reg_DX(object):
|
|
name = 'Mov_{0}_DX'
|
|
mnemo = 'mov {0}, [{{0}}]'
|
|
instruction_bits = '8B'
|
|
|
|
generate_reg_modr(Mov_Reg_DX)
|
|
|
|
class Mov_DX_Reg(object):
|
|
name = 'Mov_DX_{0}'
|
|
mnemo = 'mov [{{0}}], {0}'
|
|
instruction_bits = '89'
|
|
|
|
generate_reg_modr(Mov_DX_Reg)
|
|
|
|
|
|
|
|
def generate_reg_reg_modr_byte(reg_dst_bits, reg_src_bits):
|
|
return "11{0}{1}".format(reg_src_bits, reg_dst_bits)
|
|
|
|
def generate_reg_reg_modr(instr_cls):
|
|
for reg_src_name, reg_src_bits in reg_opcode.items():
|
|
for reg_dst_name, reg_dst_bits in reg_opcode.items():
|
|
class Reg_Reg_instruction(X86Instruction):
|
|
mnemo = "{0} {1},{2}".format(instr_cls.mnemo, reg_dst_name, reg_src_name)
|
|
modr_code = format(int(generate_reg_reg_modr_byte(reg_dst_bits, reg_src_bits) , 2), 'x')
|
|
code = instr_cls.instruction_bits + modr_code
|
|
Reg_Reg_instruction.__name__ = "{0}_{1}_{2}".format(instr_cls.name, reg_dst_name, reg_src_name)
|
|
add_instruction(Reg_Reg_instruction.__name__, Reg_Reg_instruction)
|
|
|
|
class Test_Reg_Reg(object):
|
|
mnemo = "tst"
|
|
name = "Tst"
|
|
instruction_bits = "85"
|
|
|
|
generate_reg_reg_modr(Test_Reg_Reg)
|
|
|
|
#### JUMP ####
|
|
|
|
class JZ(OneBindX86Instruction):
|
|
code = "0F 84 11 11 11 11"
|
|
|
|
def __init__(self, instr_block):
|
|
self.instr_block = instr_block
|
|
instr_block_size = len(instr_block.get_code())
|
|
super(JZ, self).__init__(instr_block_size)
|
|
|
|
def get_code(self):
|
|
return super(JZ, self).get_code() + self.instr_block.get_code()
|
|
|
|
class JNZ(OneBindX86Instruction):
|
|
code = "0F 85 11 11 11 11"
|
|
|
|
def __init__(self, instr_block):
|
|
self.instr_block = instr_block
|
|
instr_block_size = len(instr_block.get_code())
|
|
super(JNZ, self).__init__(instr_block_size)
|
|
|
|
def get_code(self):
|
|
return super(JNZ, self).get_code() + self.instr_block.get_code()
|
|
|
|
class MultipleInstr(object):
|
|
|
|
def __init__(self):
|
|
self.instrs = []
|
|
|
|
def __iadd__(self, value):
|
|
self.instrs.append(value)
|
|
return self
|
|
|
|
def get_code(self):
|
|
return "".join(i.get_code() for i in self.instrs)
|
|
|
|
def get_mnemo(self):
|
|
return "\n".join(i.get_mnemo() for i in self.instrs)
|
|
|