python - 使用 python / ctypes 调用 GetThreadContext winapi
问题描述
我目前正在开发一个 Python/Winapi 项目。
我想用 Python 和 ctypes 调用 Get- 和 SetThreadContext。
我的设置是 Windows10 64 位和 Python 64 位。API 应该适用于 32 位和 64 位进程。
通过使用 WOW64Context 调用 Wow64GetThreadContext,它确实适用于 32 位进程。
但是,对于 64 位进程和 Get/SetThreadContex,它不起作用。
GetLastError 确实显示 87(参数不正确。)
可能我的 Context64 的实现是错误的,但我找不到错误。
我还使用https://github.com/MarioVilas/winappdbg
的实现进行了尝试,
这两个实现都使用 ctypes.sizeof(ctx) 显示了 1232 的大小。
我当前对 x64 的 CONTEXT 实现:
WORD = ctypes.c_ushort
BYTE = ctypes.c_ubyte
DWORD64 = ctypes.c_ulonglong
CONTEXT_AMD64 = 0x00100000
CONTEXT_CONTROL = (CONTEXT_AMD64 | 0x00000001)
CONTEXT_INTEGER = (CONTEXT_AMD64 | 0x00000002)
CONTEXT_SEGMENTS = (CONTEXT_AMD64 | 0x00000004)
CONTEXT_FLOATING_POINT = (CONTEXT_AMD64 | 0x00000008)
CONTEXT_DEBUG_REGISTERS = (CONTEXT_AMD64 | 0x00000010)
CONTEXT_MMX_REGISTERS = CONTEXT_FLOATING_POINT
CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS |
CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS)
CONTEXT_EXCEPTION_ACTIVE = 0x0000000008000000
CONTEXT_SERVICE_ACTIVE = 0x0000000010000000
CONTEXT_EXCEPTION_REQUEST = 0x0000000040000000
CONTEXT_EXCEPTION_REPORTING = 0x0000000080000000
class M128A(ctypes.Structure):
_fields_ = [
("Low", DWORD64),
("High", DWORD64)
]
class XMM_SAVE_AREA32(ctypes.Structure):
_fields_ = [
('ControlWord', WORD),
('StatusWord', WORD),
('TagWord', BYTE),
('Reserved1', BYTE),
('ErrorOpcode', WORD),
('ErrorOffset', DWORD),
('ErrorSelector', WORD),
('Reserved2', WORD),
('DataOffset', DWORD),
('DataSelector', WORD),
('Reserved3', WORD),
('MxCsr', DWORD),
('MxCsr_Mask', DWORD),
('FloatRegisters', M128A * 8),
('XmmRegisters', M128A * 16),
('Reserved4', BYTE * 96)
]
class DUMMYSTRUCTNAME(ctypes.Structure):
_fields_=[
("Header", M128A * 2),
("Legacy", M128A * 8),
("Xmm0", M128A),
("Xmm1", M128A),
("Xmm2", M128A),
("Xmm3", M128A),
("Xmm4", M128A),
("Xmm5", M128A),
("Xmm6", M128A),
("Xmm7", M128A),
("Xmm8", M128A),
("Xmm9", M128A),
("Xmm10", M128A),
("Xmm11", M128A),
("Xmm12", M128A),
("Xmm13", M128A),
("Xmm14", M128A),
("Xmm15", M128A)
]
class DUMMYUNIONNAME(ctypes.Union):
_fields_=[
("FltSave", XMM_SAVE_AREA32),
("DummyStruct", DUMMYSTRUCTNAME)
]
class CONTEXT64(ctypes.Structure):
_fields_ = [
("P1Home", DWORD64),
("P2Home", DWORD64),
("P3Home", DWORD64),
("P4Home", DWORD64),
("P5Home", DWORD64),
("P6Home", DWORD64),
("ContextFlags", DWORD),
("MxCsr", DWORD),
("SegCs", WORD),
("SegDs", WORD),
("SegEs", WORD),
("SegFs", WORD),
("SegGs", WORD),
("SegSs", WORD),
("EFlags", DWORD),
("Dr0", DWORD64),
("Dr1", DWORD64),
("Dr2", DWORD64),
("Dr3", DWORD64),
("Dr6", DWORD64),
("Dr7", DWORD64),
("Rax", DWORD64),
("Rcx", DWORD64),
("Rdx", DWORD64),
("Rbx", DWORD64),
("Rsp", DWORD64),
("Rbp", DWORD64),
("Rsi", DWORD64),
("Rdi", DWORD64),
("R8", DWORD64),
("R9", DWORD64),
("R10", DWORD64),
("R11", DWORD64),
("R12", DWORD64),
("R13", DWORD64),
("R14", DWORD64),
("R15", DWORD64),
("Rip", DWORD64),
("DebugControl", DWORD64),
("LastBranchToRip", DWORD64),
("LastBranchFromRip", DWORD64),
("LastExceptionToRip", DWORD64),
("LastExceptionFromRip", DWORD64),
("DUMMYUNIONNAME", DUMMYUNIONNAME),
("VectorRegister", M128A * 26),
("VectorControl", DWORD64)
]
我的代码实现:
KERNEL32 = ctypes.windll.kernel32
ctx = constants.CONTEXT64()
ctx.ContextFlags = constants.CONTEXT_FULL
_GetThreadContext = KERNEL32.GetThreadContext
_GetThreadContext.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_GetThreadContext.restype = ctypes.c_uint
_SetThreadContext = KERNEL32.SetThreadContext
_SetThreadContext.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_SetThreadContext.restype = ctypes.c_uint
if KERNEL32.SuspendThread(thandle) == -1:
print("[!] Failed to suspend thread, exit...")
print("[!] Last error code: " + str(KERNEL32.GetLastError()))
sys.exit(0)
if not _GetThreadContext(thandle, ctypes.byref(ctx)):
print("[!] Failed to get thread context, exit...")
print("[!] Last error code: " + str(KERNEL32.GetLastError()))
sys.exit(0)
注意:我使用记事本进行测试,因为目标进程(也尝试使用 puttyx64)
thdle 已经过测试,并且可以与其他调用和挂起一起使用。
thandle 确实具有以下权限 (0x0400 | 0x0010 | 0x0020 | 0x0008 | 0x0002 | 0x0040 | 0x0800)。
没有 Python 错误
我在这里做错了什么?
谢谢
编辑:最小(不)工作示例(notepad.exe 必须运行)
import ctypes
import time
import sys
WORD = ctypes.c_ushort
BYTE = ctypes.c_ubyte
DWORD64 = ctypes.c_ulonglong
DWORD = ctypes.c_uint
ULONG = ctypes.c_ulong
LONG = ctypes.c_long
CHAR = ctypes.c_char
CONTEXT_AMD64 = 0x00100000
CONTEXT_CONTROL = (CONTEXT_AMD64 | 0x00000001)
CONTEXT_INTEGER = (CONTEXT_AMD64 | 0x00000002)
CONTEXT_SEGMENTS = (CONTEXT_AMD64 | 0x00000004)
CONTEXT_FLOATING_POINT = (CONTEXT_AMD64 | 0x00000008)
CONTEXT_DEBUG_REGISTERS = (CONTEXT_AMD64 | 0x00000010)
CONTEXT_MMX_REGISTERS = CONTEXT_FLOATING_POINT
CONTEXT_FULL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
CONTEXT_ALL = (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS |
CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS)
CONTEXT_EXCEPTION_ACTIVE = 0x0000000008000000
CONTEXT_SERVICE_ACTIVE = 0x0000000010000000
CONTEXT_EXCEPTION_REQUEST = 0x0000000040000000
CONTEXT_EXCEPTION_REPORTING = 0x0000000080000000
class PROCESSENTRY32(ctypes.Structure):
_fields_ = [
('dwSize', DWORD),
('cntUsage', DWORD),
('th32ProcessID', DWORD),
('th32DefaultHeapID', ctypes.POINTER(ULONG)),
('th32ModuleID', DWORD),
('cntThreads', DWORD),
('th32ParentProcessID', DWORD),
('pcPriClassBase', LONG),
('dwFlags', DWORD),
('szExeFile', CHAR * 260)
]
class THREADENTRY32(ctypes.Structure):
_fields_ = [
('dwSize', DWORD),
('cntUsage', DWORD),
('th32ThreadID', DWORD),
('th32OwnerProcessID', DWORD),
('tpBasePri', DWORD),
('tpDeltaPri', DWORD),
('dwFlags', DWORD)
]
class M128A(ctypes.Structure):
_fields_ = [
("Low", DWORD64),
("High", DWORD64)
]
class XMM_SAVE_AREA32(ctypes.Structure):
_fields_ = [
('ControlWord', WORD),
('StatusWord', WORD),
('TagWord', BYTE),
('Reserved1', BYTE),
('ErrorOpcode', WORD),
('ErrorOffset', DWORD),
('ErrorSelector', WORD),
('Reserved2', WORD),
('DataOffset', DWORD),
('DataSelector', WORD),
('Reserved3', WORD),
('MxCsr', DWORD),
('MxCsr_Mask', DWORD),
('FloatRegisters', M128A * 8),
('XmmRegisters', M128A * 16),
('Reserved4', BYTE * 96)
]
class DUMMYSTRUCTNAME(ctypes.Structure):
_fields_=[
("Header", M128A * 2),
("Legacy", M128A * 8),
("Xmm0", M128A),
("Xmm1", M128A),
("Xmm2", M128A),
("Xmm3", M128A),
("Xmm4", M128A),
("Xmm5", M128A),
("Xmm6", M128A),
("Xmm7", M128A),
("Xmm8", M128A),
("Xmm9", M128A),
("Xmm10", M128A),
("Xmm11", M128A),
("Xmm12", M128A),
("Xmm13", M128A),
("Xmm14", M128A),
("Xmm15", M128A)
]
class DUMMYUNIONNAME(ctypes.Union):
_fields_=[
("FltSave", XMM_SAVE_AREA32),
("DummyStruct", DUMMYSTRUCTNAME)
]
class CONTEXT64(ctypes.Structure):
_fields_ = [
("P1Home", DWORD64),
("P2Home", DWORD64),
("P3Home", DWORD64),
("P4Home", DWORD64),
("P5Home", DWORD64),
("P6Home", DWORD64),
("ContextFlags", DWORD),
("MxCsr", DWORD),
("SegCs", WORD),
("SegDs", WORD),
("SegEs", WORD),
("SegFs", WORD),
("SegGs", WORD),
("SegSs", WORD),
("EFlags", DWORD),
("Dr0", DWORD64),
("Dr1", DWORD64),
("Dr2", DWORD64),
("Dr3", DWORD64),
("Dr6", DWORD64),
("Dr7", DWORD64),
("Rax", DWORD64),
("Rcx", DWORD64),
("Rdx", DWORD64),
("Rbx", DWORD64),
("Rsp", DWORD64),
("Rbp", DWORD64),
("Rsi", DWORD64),
("Rdi", DWORD64),
("R8", DWORD64),
("R9", DWORD64),
("R10", DWORD64),
("R11", DWORD64),
("R12", DWORD64),
("R13", DWORD64),
("R14", DWORD64),
("R15", DWORD64),
("Rip", DWORD64),
("DebugControl", DWORD64),
("LastBranchToRip", DWORD64),
("LastBranchFromRip", DWORD64),
("LastExceptionToRip", DWORD64),
("LastExceptionFromRip", DWORD64),
("DUMMYUNIONNAME", DUMMYUNIONNAME),
("VectorRegister", M128A * 26),
("VectorControl", DWORD64)
]
KERNEL32 = ctypes.WinDLL('kernel32', use_last_error=True)
PSAPI = ctypes.WinDLL('psapi', use_last_error=True)
name = "notepad.exe"
hSnapshot = KERNEL32.CreateToolhelp32Snapshot(0x00000002 | 0x00000004, 0)
pe32 = PROCESSENTRY32()
pe32.dwSize = ctypes.sizeof(PROCESSENTRY32)
processes = []
if KERNEL32.Process32First(hSnapshot, ctypes.byref(pe32)):
while True:
processes.append({'pid': pe32.th32ProcessID, 'name': pe32.szExeFile})
if not KERNEL32.Process32Next(hSnapshot, ctypes.byref(pe32)):
break
for n in processes:
if n['name'] == bytes(name, "utf-8"):
pid = n['pid']
if not pid:
sys.exit(0)
te32 = THREADENTRY32()
te32.dwSize = ctypes.sizeof(THREADENTRY32)
threads = []
if KERNEL32.Thread32First(hSnapshot, ctypes.byref(te32)):
while True:
if te32.th32OwnerProcessID == pid:
threads.append(te32.th32ThreadID)
if not KERNEL32.Thread32Next(hSnapshot, ctypes.byref(te32)):
break
access = (0x0400 | 0x0010 | 0x0020 | 0x0008 | 0x0002 | 0x0040 | 0x0800)
thandle = KERNEL32.OpenThread(access, 0, threads[0])
ctx = CONTEXT64()
ctx.ContextFlags = CONTEXT_FULL
_GetThreadContext = KERNEL32.GetThreadContext
_GetThreadContext.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_GetThreadContext.restype = ctypes.c_uint
_SetThreadContext = KERNEL32.SetThreadContext
_SetThreadContext.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
_SetThreadContext.restype = ctypes.c_uint
if KERNEL32.SuspendThread(thandle) == -1:
print("[!] Failed to suspend thread, exit...")
print("[!] Last error code: " + str(ctypes.get_last_error()))
sys.exit(0)
if not _GetThreadContext(thandle, ctypes.byref(ctx)):
print("[!] Failed to get thread context, exit...")
print("[!] Last error code: " + str(ctypes.get_last_error()))
sys.exit(0)
if not _SetThreadContext(thandle, ctypes.byref(ctx)):
print("[!] Failed to set thread context, exit...")
print("[!] Last error code: " + str(ctypes.get_last_error()))
sys.exit(0)
解决方案
推荐阅读
- android - 如何使用下面的数组显示我的 Firebase 数据库?
- php - 我需要这个选择有效
- c# - CS0023 C# 运算符不能应用于“字符串 []”类型的操作数
- ios - Square Point of Sales API 发送 reference_id 或 userInfoString
- javascript - Wikidata 查询城市使用的语言列表
- android - Kotlin 片段类型不匹配
- google-apps-script - Drive.Files.Copy 和“父母”不起作用
- php - 如何在非主键列上添加自动增量,但它们仍然是我想设置为主键的另一列
- mysql - 创建计数器时创建存储过程出错
- artifactory - Artifactory 启动脚本在 Ubuntu 18.04.1 上无法正常工作