Last active
August 23, 2018 10:01
-
-
Save NyaMisty/2a6b7d6a82c9724a92c29dddd41f15de to your computer and use it in GitHub Desktop.
Python APIHook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MAX_INSN_LEN = 15 # maximum length of x86 instruction | |
JMP_OPCODE = 0xE9 | |
PUSH_OPCODE = 0x68 | |
MOV_OPCODE = 0xC7 | |
RET_OPCODE = 0xC3 | |
MOV_MODRM_BYTE = 0x44 # write to address + 1 byte displacement | |
MOV_SIB_BYTE = 0x24 # write to [rsp] | |
MOV_OFFSET = 0x04 | |
# struct jmp64 { | |
# uint8_t push_opcode | |
# uint32_t push_addr /* lower 32-bits of the address to jump to */ | |
# uint8_t mov_opcode | |
# uint8_t mov_modrm | |
# uint8_t mov_sib | |
# uint8_t mov_offset | |
# uint32_t mov_addr /* upper 32-bits of the address to jump to */ | |
# uint8_t ret_opcode | |
# } | |
class Jmp64Struct(Structure): | |
_pack_ = 1 | |
_fields_ = [ | |
("push_opcode", c_byte), | |
("push_addr", c_int), | |
("mov_opcode", c_byte), | |
("mov_modrm", c_byte), | |
("mov_sib", c_byte), | |
("mov_offset", c_byte), | |
("mov_addr", c_int), | |
("ret_opcode", c_byte), | |
] | |
def make_jmp(src, dst): | |
jmp = cast(src, POINTER(Jmp64Struct)).contents | |
jmp.push_opcode = (PUSH_OPCODE) | |
jmp.push_addr = dst & 0xffffffff # truncate | |
jmp.mov_opcode = (MOV_OPCODE) | |
jmp.mov_modrm = (MOV_MODRM_BYTE) | |
jmp.mov_sib = (MOV_SIB_BYTE) | |
jmp.mov_offset = (MOV_OFFSET) | |
jmp.mov_addr = c_int((dst >> 32) & 0xffffffff) | |
jmp.ret_opcode = (RET_OPCODE) | |
return True | |
def get_jmp_size(): | |
return sizeof(Jmp64Struct) | |
def make_trampoline(trampoline, | |
src, | |
jmp_size, | |
trampoline_len_ret): | |
orig_size = 0 | |
trampoline_addr = trampoline | |
src_addr = src | |
assert (trampoline_len_ret is not None) | |
# Determine how many bytes of original code needs to be copied over | |
# to the trampoline. | |
while (orig_size < jmp_size): | |
reloc_op_offset = [0] | |
insn_len = disasm((src_addr + orig_size), reloc_op_offset) | |
if (insn_len == 0): | |
return False | |
# Copy this instruction to the trampoline. | |
memmove((trampoline_addr + orig_size), | |
(src_addr + orig_size), | |
insn_len) | |
# If the operand is a relative address, such as found in calls or | |
# jumps, it needs to be relocated because the original code and the | |
# trampoline reside at different locations in memory. | |
if (reloc_op_offset[0] > 0): | |
# Calculate how far our trampoline is from the source and change | |
# the address accordingly. | |
# print "Reloc: off:" + str(hex(trampoline_addr - src_addr)) | |
offset = c_int((trampoline_addr - src_addr) & 0xffffffff) | |
op_pointer = cast((trampoline_addr + orig_size + reloc_op_offset[0]), POINTER(c_int)) | |
op_pointer.contents.value -= offset.value | |
orig_size += insn_len | |
# print "orig_size: " + str(orig_size) | |
trampoline_len_ret[0] = orig_size + jmp_size | |
# Insert the final jump. It goes back to the original code at | |
# src + orig_size. | |
# print "make_jmp: %x %x" % ((trampoline_addr + orig_size), (src_addr + orig_size)) | |
return make_jmp((trampoline_addr + orig_size), | |
(src_addr + orig_size)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment