mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
73 lines
3.0 KiB
Python
73 lines
3.0 KiB
Python
import struct
|
|
import ctypes
|
|
import windows
|
|
import windows.native_exec.simple_x64 as x64
|
|
from generated_def.winstructs import *
|
|
|
|
# Special code for syswow64 process
|
|
CS_32bits = 0x23
|
|
CS_64bits = 0x33
|
|
|
|
# See assembly into doc/NtCreateThreadStub_64b.asm
|
|
Pretty_NtCreateThreadStub = """
|
|
50 50 53 51 52 56 57 41 50 41 51 41 52 41 53 41
|
|
54 41 55 48 C7 C0 00 00 00 00 50 48 B8 54 68 72
|
|
65 61 64 45 78 50 48 B8 4E 74 43 72 65 61 74 65
|
|
50 4C 8B DC 48 C7 C3 61 72 79 41 53 48 BB 4C 6F
|
|
61 64 4C 69 62 72 53 4C 8B E4 65 48 8B 04 25 60
|
|
00 00 00 48 8B 40 18 48 8B 40 20 48 8B D0 48 8B
|
|
C2 48 8B 58 20 48 23 DB 74 14 48 8B 48 50 48 8B
|
|
09 81 F9 6E 00 74 00 74 0B 48 8B 10 EB E0 68 42
|
|
42 42 42 C3 8B 43 3C 48 03 C3 48 83 C0 18 8B 48
|
|
70 48 03 CB 48 8B C1 50 8B 48 18 4C 8B E9 8B 50
|
|
20 48 03 D3 48 33 C9 8B 34 8A 48 03 F3 51 49 8B
|
|
FB 48 C7 C1 11 00 00 00 F3 A6 8B C1 59 48 FF C1
|
|
85 C0 75 E3 48 FF C9 58 8B 50 24 48 03 D3 66 8B
|
|
0C 4A 48 81 E1 FF FF 00 00 8B 50 1C 48 03 D3 8B
|
|
14 8A 48 03 D3 4C 8B EA 6A 00 48 8B CC 48 C7 C2
|
|
FF FF 1F 00 49 C7 C0 00 00 00 00 49 B9 40 40 40
|
|
40 40 40 40 40 48 C7 C0 00 00 00 00 50 50 50 50
|
|
50 48 B8 42 42 42 42 42 42 42 42 50 48 B8 41 41
|
|
41 41 41 41 41 41 50 41 51 41 50 52 51 41 FF D5
|
|
48 89 84 24 E8 00 00 00 48 83 C4 40 48 83 C4 28
|
|
48 83 C4 20 41 5D 41 5C 41 5B 41 5A 41 59 41 58
|
|
5F 5E 5A 59 5B 58 58
|
|
"""
|
|
NtCreateThreadStub = Pretty_NtCreateThreadStub.replace(" ", "").replace("\n", "").decode('hex')
|
|
|
|
def genere_return_32bits_stub(ret_addr):
|
|
ret_32b = x64.MultipleInstr()
|
|
ret_32b += x64.Mov('RCX', (CS_32bits << 32) + ret_addr)
|
|
ret_32b += x64.Push('RCX')
|
|
ret_32b += x64.Retf32() #32 bits return addr
|
|
return ret_32b.get_code()
|
|
|
|
# The format of a jump to 64bits mode
|
|
dummy_jump = "\xea" + struct.pack("<I", 0) + chr(CS_64bits) + "\x00\x00"
|
|
|
|
def execute_64bits_code_from_syswow(shellcode):
|
|
if not windows.current_process.is_wow_64:
|
|
raise ValueError("Calling execute_64bits_code_from_syswow from non-syswow process")
|
|
addr = windows.k32testing.VirtualAlloc(dwSize=0x1000)
|
|
# post-exec 32bits stub (xor eax, eax; ret)
|
|
ret = "\xC3"
|
|
ret_addr = addr
|
|
shell_code_addr = ret_addr + len(ret) + len(dummy_jump)
|
|
# ljmp
|
|
jump = "\xea" + struct.pack("<I", shell_code_addr) + chr(CS_64bits) + "\x00\x00"
|
|
jump_addr = ret_addr + len(ret)
|
|
# Return to 32bits stub
|
|
shellcode += genere_return_32bits_stub(ret_addr)
|
|
# WRITE ALL THE STUBS
|
|
windows.current_process.write_memory(ret_addr, ret)
|
|
windows.current_process.write_memory(jump_addr, jump)
|
|
windows.current_process.write_memory(shell_code_addr, shellcode)
|
|
# Execute
|
|
exec_stub = ctypes.CFUNCTYPE(HRESULT)(jump_addr)
|
|
return exec_stub()
|
|
|
|
def NtCreateThreadEx_32_to_64(process, addr, param):
|
|
shellcode = NtCreateThreadStub.replace("\x40" * 8, struct.pack("<Q", process.handle))
|
|
shellcode = shellcode.replace("\x41" * 8, struct.pack("<Q", addr))
|
|
shellcode = shellcode.replace("\x42" * 8, struct.pack("<Q", param))
|
|
return execute_64bits_code_from_syswow(shellcode) |