mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Add support for 64bits injection + hooks
This commit is contained in:
+135
-12
@@ -2,6 +2,9 @@ import ctypes
|
||||
import mmap
|
||||
import platform
|
||||
|
||||
import windows
|
||||
import windows.k32testing as k32api
|
||||
|
||||
class PyObj(ctypes.Structure):
|
||||
_fields_ = [("ob_refcnt", ctypes.c_size_t),
|
||||
("ob_type", ctypes.c_void_p)] #must be cast
|
||||
@@ -36,7 +39,7 @@ class Win32MyMap(MyMap):
|
||||
#access = mmap.ACCESS_READ | mmap.ACCESS_WRITE
|
||||
#return cls(-1, size, access=access)
|
||||
access = mmap.ACCESS_READ | mmap.ACCESS_WRITE
|
||||
addr = ctypes.windll.kernel32.VirtualAlloc(0, size, 0x1000, 0x40)
|
||||
addr = k32api.VirtualAlloc(0, size, 0x1000, 0x40)
|
||||
|
||||
new_map = (ctypes.c_char * size).from_address(addr)
|
||||
new_map.addr = addr
|
||||
@@ -95,15 +98,13 @@ allocator = CustomAllocator()
|
||||
|
||||
|
||||
def get_functions():
|
||||
# Windows only with python27.dll | improve this
|
||||
# Windows only with python27.dll | improve this ?
|
||||
import sys
|
||||
|
||||
sys.path.append(r"C:\Users\hakril\Documents\Work\Python_Injection")
|
||||
|
||||
import windows
|
||||
PyGILState_Ensure = windows.get_func_addr('python27', 'PyGILState_Ensure')
|
||||
PyObject_CallObject = windows.get_func_addr('python27', 'PyObject_CallObject')
|
||||
PyGILState_Release = windows.get_func_addr('python27', 'PyGILState_Release')
|
||||
|
||||
PyGILState_Ensure = windows.utils.get_func_addr('python27', 'PyGILState_Ensure')
|
||||
PyObject_CallObject = windows.utils.get_func_addr('python27', 'PyObject_CallObject')
|
||||
PyGILState_Release = windows.utils.get_func_addr('python27', 'PyGILState_Release')
|
||||
return [PyGILState_Ensure, PyObject_CallObject, PyGILState_Release]
|
||||
|
||||
def analyse_callback(callback):
|
||||
@@ -114,16 +115,17 @@ def analyse_callback(callback):
|
||||
raise ValueError("Need a ctypes PyCFuncPtr")
|
||||
return obj_id
|
||||
|
||||
from simple_x86 import *
|
||||
|
||||
|
||||
# For windows 32 bits with stdcall
|
||||
def generate_stub(callback):
|
||||
from simple_x86 import *
|
||||
obj_id = analyse_callback(callback)
|
||||
|
||||
c_callback = ctypes.c_ulong.from_address(id(callback._objects['0']) + 0xc).value
|
||||
c_callback = ctypes.c_ulong.from_address(id(callback._objects['0']) + 3 * ctypes.sizeof(ctypes.c_void_p)).value
|
||||
gstate_save_addr = allocator.reserve_int()
|
||||
return_addr_save_addr = allocator.reserve_int()
|
||||
|
||||
|
||||
save_ebx = allocator.reserve_int()
|
||||
save_ecx = allocator.reserve_int()
|
||||
save_edx = allocator.reserve_int()
|
||||
@@ -155,6 +157,7 @@ def generate_stub(callback):
|
||||
code += Mov_EAX_X(c_callback)
|
||||
code += Call_EAX()
|
||||
|
||||
# TODO : Remove this and setup callback as WinFuncType
|
||||
for i in range(len(callback.argtypes)):
|
||||
code += Pop_EBX()
|
||||
|
||||
@@ -181,12 +184,132 @@ def generate_stub(callback):
|
||||
code += Mov_EDI_DX(save_edi)
|
||||
code += Ret()
|
||||
return code
|
||||
|
||||
# For windows 32 bits with stdcall
|
||||
def generate_stub_64(callback):
|
||||
from simple_x64 import *
|
||||
obj_id = analyse_callback(callback)
|
||||
|
||||
c_callback = ctypes.c_ulong.from_address(id(callback._objects['0']) + 3 * ctypes.sizeof(ctypes.c_void_p)).value
|
||||
gstate_save_addr = allocator.reserve_int()
|
||||
return_addr_save_addr = allocator.reserve_int()
|
||||
|
||||
Reserve_space_for_call = MultipleInstr([Push_RDI()] * 4)
|
||||
Clean_space_for_call = MultipleInstr([Pop_RDI()] * 4)
|
||||
|
||||
save_rbx = allocator.reserve_int()
|
||||
save_rcx = allocator.reserve_int()
|
||||
save_rdx = allocator.reserve_int()
|
||||
save_rsi = allocator.reserve_int()
|
||||
save_rdi = allocator.reserve_int()
|
||||
|
||||
ensure, objcall, release = get_functions()
|
||||
print("save_rbx = {0}".format(hex(save_rbx)))
|
||||
|
||||
### Shellcode ###
|
||||
code = MultipleInstr()
|
||||
|
||||
code += Mov_RAX_X(save_rbx)
|
||||
code += Mov_DRAX_RBX()
|
||||
|
||||
code += Mov_RAX_X(save_rcx)
|
||||
code += Mov_DRAX_RCX()
|
||||
|
||||
code += Mov_RAX_X(save_rdx)
|
||||
code += Mov_DRAX_RDX()
|
||||
|
||||
code += Mov_RAX_X(save_rsi)
|
||||
code += Mov_DRAX_RSI()
|
||||
|
||||
code += Mov_RAX_X(save_rdi)
|
||||
code += Mov_DRAX_RDI()
|
||||
|
||||
# need to save other registers ?
|
||||
|
||||
code += Mov_RAX_X(ensure)
|
||||
code += Reserve_space_for_call
|
||||
code += Call_RAX()
|
||||
code += Clean_space_for_call
|
||||
code += Mov_DX_RAX(gstate_save_addr)
|
||||
#Save real return addr (for good argument parsing by the callback)
|
||||
code += Pop_RAX()
|
||||
code += Mov_DX_RAX(return_addr_save_addr)
|
||||
# Restore parameters for real function call
|
||||
code += Mov_RAX_X(save_rbx)
|
||||
code += Mov_RBX_DRAX()
|
||||
code += Mov_RAX_X(save_rcx)
|
||||
code += Mov_RCX_DRAX()
|
||||
code += Mov_RAX_X(save_rdx)
|
||||
code += Mov_RDX_DRAX()
|
||||
code += Mov_RAX_X(save_rsi)
|
||||
code += Mov_RSI_DRAX()
|
||||
code += Mov_RAX_X(save_rdi)
|
||||
code += Mov_DRAX_RDI()
|
||||
code += Reserve_space_for_call
|
||||
# Call python code
|
||||
code += Mov_RAX_X(c_callback)
|
||||
code += Clean_space_for_call
|
||||
code += Call_RAX()
|
||||
code += Mov_RAX_DX(return_addr_save_addr)
|
||||
code += Push_RAX()
|
||||
code += Mov_RAX_X(release)
|
||||
code += Reserve_space_for_call
|
||||
code += Call_RAX()
|
||||
code += Clean_space_for_call
|
||||
# Restore registers
|
||||
code += Mov_RAX_X(save_rbx)
|
||||
code += Mov_RBX_DRAX()
|
||||
code += Mov_RAX_X(save_rcx)
|
||||
code += Mov_RCX_DRAX()
|
||||
code += Mov_RAX_X(save_rdx)
|
||||
code += Mov_RDX_DRAX()
|
||||
code += Mov_RAX_X(save_rsi)
|
||||
code += Mov_RSI_DRAX()
|
||||
code += Mov_RAX_X(save_rdi)
|
||||
code += Mov_DRAX_RDI()
|
||||
code += Ret()
|
||||
|
||||
|
||||
###### CODE 32 %%%%%%%%
|
||||
#
|
||||
##Save real return addr (for good argument parsing by the callback)
|
||||
#
|
||||
## TODO : Remove this and setup callback as WinFuncType
|
||||
#for i in range(len(callback.argtypes)):
|
||||
# code += Pop_EBX()
|
||||
#
|
||||
## Restore real return value
|
||||
#code += Mov_EBX_DX(return_addr_save_addr)
|
||||
#code += Push_EBX()
|
||||
#
|
||||
## Save return value
|
||||
#code += Push_EAX()
|
||||
#code += Mov_EBX_DX(gstate_save_addr)
|
||||
#code += Push_EBX()
|
||||
#
|
||||
#code += Mov_EAX_X(release)
|
||||
#code += Call_EAX()
|
||||
#
|
||||
## Discard `release` argument
|
||||
#code += Pop_EAX()
|
||||
## Restore return value
|
||||
#code += Pop_EAX()
|
||||
#code += Mov_EBX_DX(save_ebx)
|
||||
#code += Mov_ECX_DX(save_ecx)
|
||||
#code += Mov_EDX_DX(save_edx)
|
||||
#code += Mov_ESI_DX(save_esi)
|
||||
#code += Mov_EDI_DX(save_edi)
|
||||
#code += Ret()
|
||||
return code
|
||||
|
||||
|
||||
def generate_callback_stub(callback, types):
|
||||
func_type = ctypes.CFUNCTYPE(*types)
|
||||
c_callable = func_type(callback)
|
||||
stub = generate_stub(c_callable)
|
||||
if windows.current_process.bitness == 32:
|
||||
stub = generate_stub(c_callable)
|
||||
else:
|
||||
stub = generate_stub_64(c_callable)
|
||||
stub_addr = allocator.write_code(stub.get_code())
|
||||
generate_callback_stub.l.append((stub, c_callable))
|
||||
return stub_addr
|
||||
|
||||
Reference in New Issue
Block a user