修复ctypes调用CreateProcessWithTokenW时参数1转换错误问题
调用CreateProcessWithTokenW报错的问题修复
问题代码
import ctypes import win32security h_token = win32security.OpenProcessToken(ctypes.windll.kernel32.GetCurrentProcess(), win32security.TOKEN_ALL_ACCESS) lpApplicationName = ctypes.c_wchar_p(rf"C:\Windows\System32\cmd.exe") lpCommandLine = ctypes.c_wchar_p("") dwCreationFlags = 0x00000010 lpEnvironment = None lpProcessAttributes = None lpThreadAttributes = None bInheritHandles = False ctypes.windll.advapi32.CreateProcessWithTokenW(h_token, 0, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, None, lpProcessAttributes, lpThreadAttributes, bInheritHandles)
报错信息
Traceback (most recent call last): File "testx.py", line 96, in <module> ctypes.windll.advapi32.CreateProcessWithTokenW(h_token, 0, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, None, lpProcessAttributes, lpThreadAttributes, bInheritHandles) ctypes.ArgumentError: argument 1: TypeError: Don't know how to convert parameter 1
错误原因与修复方案
1. 令牌句柄类型不匹配
win32security.OpenProcessToken返回的是PyHANDLE对象,而ctypes无法直接将该类型转换为Windows API所需的原生HANDLE(整数类型)。
修复方法:提取PyHANDLE的.handle属性,获取原生整数句柄:
native_token = h_token.handle
2. API参数顺序与结构体缺失
代码混淆了CreateProcessWithTokenW和CreateProcessW的参数列表,前者不需要lpProcessAttributes、lpThreadAttributes、bInheritHandles,而是要求最后两个参数为STARTUPINFO和PROCESS_INFORMATION结构体的指针。
修复后的完整代码:
import ctypes import win32security from ctypes import wintypes # 定义Windows API所需的结构体 class STARTUPINFO(ctypes.Structure): _fields_ = [ ("cb", wintypes.DWORD), ("lpReserved", wintypes.LPWSTR), ("lpDesktop", wintypes.LPWSTR), ("lpTitle", wintypes.LPWSTR), ("dwX", wintypes.DWORD), ("dwY", wintypes.DWORD), ("dwXSize", wintypes.DWORD), ("dwYSize", wintypes.DWORD), ("dwXCountChars", wintypes.DWORD), ("dwYCountChars", wintypes.DWORD), ("dwFillAttribute", wintypes.DWORD), ("dwFlags", wintypes.DWORD), ("wShowWindow", wintypes.WORD), ("cbReserved2", wintypes.WORD), ("lpReserved2", wintypes.LPBYTE), ("hStdInput", wintypes.HANDLE), ("hStdOutput", wintypes.HANDLE), ("hStdError", wintypes.HANDLE), ] class PROCESS_INFORMATION(ctypes.Structure): _fields_ = [ ("hProcess", wintypes.HANDLE), ("hThread", wintypes.HANDLE), ("dwProcessId", wintypes.DWORD), ("dwThreadId", wintypes.DWORD), ] # 获取当前进程令牌并转换为原生句柄 h_process = ctypes.windll.kernel32.GetCurrentProcess() h_token = win32security.OpenProcessToken(h_process, win32security.TOKEN_ALL_ACCESS) native_token = h_token.handle # 初始化结构体 si = STARTUPINFO() si.cb = ctypes.sizeof(STARTUPINFO) pi = PROCESS_INFORMATION() # 调用CreateProcessWithTokenW result = ctypes.windll.advapi32.CreateProcessWithTokenW( native_token, 0, # LOGON_WITH_PROFILE ctypes.c_wchar_p(r"C:\Windows\System32\cmd.exe"), ctypes.c_wchar_p(""), 0x00000010, # CREATE_NEW_CONSOLE None, None, ctypes.byref(si), ctypes.byref(pi) ) # 检查调用是否成功 if not result: raise ctypes.WinError(ctypes.get_last_error()) # 关闭句柄释放资源 ctypes.windll.kernel32.CloseHandle(pi.hProcess) ctypes.windll.kernel32.CloseHandle(pi.hThread)
额外注意事项
- 调用Windows API后要检查返回值,通过
ctypes.get_last_error()获取具体错误码,便于排查问题。 - 进程和线程句柄使用完毕后必须关闭,避免系统资源泄漏。
CreateProcessWithTokenW需要调用进程拥有SE_IMPERSONATE_NAME权限,否则会调用失败。
内容的提问来源于stack exchange,提问作者zzzzzzd
相关产品推荐
相关产品推荐

