mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
128 lines
3.9 KiB
Python
128 lines
3.9 KiB
Python
import sys
|
|
import os
|
|
import utils
|
|
import windows
|
|
|
|
|
|
# 32 to 32 injection
|
|
def generate_python_exec_shellcode_32(PYDLL_addr, PyInit, PyRun, PYCODE_ADDR):
|
|
from native_exec.simple_x86 import *
|
|
LoadLibraryA = utils.get_func_addr('kernel32', 'LoadLibraryA')
|
|
GetProcAddress = utils.get_func_addr('kernel32', 'GetProcAddress')
|
|
code = MultipleInstr()
|
|
# Load python27.dll
|
|
code += Push_X(PYDLL_addr)
|
|
code += Mov_EAX_X(LoadLibraryA)
|
|
code += Call_EAX()
|
|
# Get PyInit function into pythondll
|
|
code += Push_EAX()
|
|
code += Pop_EDI()
|
|
code += Push_X(PyInit)
|
|
code += Push_EDI()
|
|
code += Mov_EBX_X(GetProcAddress)
|
|
code += Call_EBX()
|
|
# Call PyInit
|
|
code += Call_EAX()
|
|
# Get PyRun function into pythondll
|
|
code += Push_X(PyRun)
|
|
code += Push_EDI()
|
|
code += Call_EBX()
|
|
# Call PyRun with python code to exec
|
|
code += Push_X(PYCODE_ADDR)
|
|
code += Call_EAX()
|
|
code += Pop_EDI()
|
|
code += Ret()
|
|
return code.get_code()
|
|
|
|
# 64 to 64 injection
|
|
def generate_python_exec_shellcode_64(PYDLL_addr, PyInit, PyRun, PYCODE_ADDR):
|
|
from native_exec.simple_x64 import *
|
|
LoadLibraryA = utils.get_func_addr('kernel32', 'LoadLibraryA')
|
|
GetProcAddress = utils.get_func_addr('kernel32', 'GetProcAddress')
|
|
|
|
Reserve_space_for_call = MultipleInstr([Push_RDI()] * 4)
|
|
Clean_space_for_call = MultipleInstr([Pop_RDI()] * 4)
|
|
|
|
code = MultipleInstr()
|
|
# Do stack alignement
|
|
code += Push_RAX()
|
|
# Load python27.dll
|
|
code += Mov_RCX_X(PYDLL_addr)
|
|
code += Mov_RAX_X(LoadLibraryA)
|
|
code += Reserve_space_for_call
|
|
code += Call_RAX()
|
|
code += Clean_space_for_call
|
|
code += Push_RAX()
|
|
code += Pop_RCX()
|
|
# Save RCX
|
|
code += Push_RCX()
|
|
# Align stack
|
|
code += Push_RDI()
|
|
# Get PyInit function into pythondll
|
|
code += Reserve_space_for_call
|
|
code += Mov_RDX_X(PyInit)
|
|
code += Mov_RBX_X(GetProcAddress)
|
|
code += Call_RBX()
|
|
# Call PyInit
|
|
code += Call_RAX()
|
|
code += Clean_space_for_call
|
|
# Remove Stack align
|
|
code += Pop_RDI()
|
|
# Restore pythondll base into rcx
|
|
code += Pop_RCX()
|
|
# Get PyRun function into pythondll
|
|
code += Mov_RDX_X(PyRun)
|
|
code += Reserve_space_for_call
|
|
code += Call_RBX()
|
|
# Call PyInit with python code to exec
|
|
code += Mov_RCX_X(PYCODE_ADDR)
|
|
code += Call_RAX()
|
|
code += Clean_space_for_call
|
|
# Remove stack alignement
|
|
code += Pop_RAX()
|
|
code += Ret()
|
|
return code.get_code()
|
|
|
|
|
|
def inject_python_command(process, code_injected, PYDLL="python27.dll\x00"):
|
|
PyInitT = "Py_Initialize\x00"
|
|
Pyrun = "PyRun_SimpleString\x00"
|
|
PYCODE = code_injected + "\x00"
|
|
remote_addr_base = process.virtual_alloc(len(code_injected) + 0x100)
|
|
remote_addr = remote_addr_base
|
|
|
|
PYDLL_addr = remote_addr
|
|
process.write_memory(remote_addr, PYDLL)
|
|
remote_addr += len(PYDLL)
|
|
|
|
|
|
PyInitT_ADDR = remote_addr
|
|
process.write_memory(remote_addr, PyInitT)
|
|
remote_addr += len(PyInitT)
|
|
|
|
Pyrun_ADDR = remote_addr
|
|
process.write_memory(remote_addr, Pyrun)
|
|
remote_addr += len(Pyrun)
|
|
|
|
PYCODE_ADDR = remote_addr
|
|
process.write_memory(remote_addr, PYCODE)
|
|
remote_addr += len(PYCODE)
|
|
|
|
SHELLCODE_ADDR = remote_addr
|
|
if process.bitness == 32:
|
|
shellcode = generate_python_exec_shellcode_32(PYDLL_addr, PyInitT_ADDR, Pyrun_ADDR, PYCODE_ADDR)
|
|
else:
|
|
shellcode = generate_python_exec_shellcode_64(PYDLL_addr, PyInitT_ADDR, Pyrun_ADDR, PYCODE_ADDR)
|
|
process.write_memory(SHELLCODE_ADDR, shellcode)
|
|
return SHELLCODE_ADDR
|
|
|
|
|
|
|
|
def execute_python_code(process, code):
|
|
print("me = {0}".format(windows.current_process.bitness))
|
|
print("him = {0}".format(process.bitness))
|
|
if windows.current_process.bitness != process.bitness:
|
|
raise NotImplementedError("Cannot perform 32 <-> 64 injection")
|
|
shellcode_remote_addr = inject_python_command(process, code)
|
|
return process.create_thread(shellcode_remote_addr, 0)
|