CreateProcessW Hook异常:管理员权限下无法拦截进程创建请求
我正在开发一款应用,使用EasyHook挂钩explorer.exe进程,监听kernel32.dll中的CreateProcessW方法调用。当用户双击文件以普通权限运行时,程序可正常拦截CreateProcessW;但以管理员权限运行文件时,进程成功创建,我的程序却无法拦截该方法。我尝试挂钩CreateProcessAsUser、CreateProcessWithLogonW以及ShellExecuteEx,但均无效果。
我的疑问:
- 为何程序无法捕获管理员权限运行文件时的进程创建调用?
- 以管理员权限运行文件是否调用了
CreateProcessW之外的其他方法?
注:我的程序通过app.manifest配置了highestAvailable权限。
我尝试过的内容:
// Install hooks // CreateProcess var createProcessHook = EasyHook.LocalHook.Create( EasyHook.LocalHook.GetProcAddress("kernel32.dll", "CreateProcessW"), new DCreateProcess(CreateProcess_HookedAsync), this); // CreateProcessAsUserA var createProcessAsUserHook = EasyHook.LocalHook.Create(EasyHook.LocalHook.GetProcAddress("advapi32.dll", "CreateProcessAsUserA"), new DCreateProcessAsUser(CreateProcessAsUser_Hooked), this); // CreateProcessWithLogonW var createProcessWithLogonW = EasyHook.LocalHook.Create(EasyHook.LocalHook.GetProcAddress("advapi32.dll", "CreateProcessWithLogonW"), new DCreateProcessWithLogonW(CreateProcessWithLogonW_Hooked), this); // ShellExecuteEx var createShellProcessHook = EasyHook.LocalHook.Create(EasyHook.LocalHook.GetProcAddress("shell32.dll", "ShellExecuteEx"), new DShellExecuteEx(ShellExecuteEx_Hooked), this); createProcessHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 }); createProcessAsUserHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 }); createProcessWithLogonW.ThreadACL.SetExclusiveACL(new Int32[] { 0 }); createShellProcessHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
核心原因
UAC权限边界隔离
普通权限运行的explorer.exe无法直接创建高权限进程,当用户选择“以管理员身份运行”时,系统会通过UAC弹窗验证权限,随后由系统级服务(如consent.exe、svchost.exe)协助创建高权限进程。这个流程绕开了当前被挂钩的explorer.exe的直接调用,因此你的钩子无法捕获到创建请求。API版本与遗漏
- 你挂钩了
CreateProcessAsUserA(ANSI编码版本),但Windows系统在现代环境下几乎统一使用Unicode编码的API(即CreateProcessAsUserW),因此实际调用的API未被拦截。 - 遗漏了高权限场景常用的
CreateProcessWithTokenWAPI,该API是UAC流程中创建高权限进程的关键调用之一。 ShellExecuteEx同样存在Unicode版本ShellExecuteExW,若系统调用的是该版本,你的钩子也无法生效。
- 权限配置局限性
highestAvailable权限仅会让程序在当前用户有管理员权限时以管理员身份运行,但无法突破UAC的权限边界——普通权限的explorer.exe仍然无法直接发起高权限进程创建,流程会被系统接管。
解决方案
- 补充挂钩关键Unicode版本API
修改钩子代码,替换为Unicode版本API,并添加CreateProcessWithTokenW的挂钩:
// 替换CreateProcessAsUserA为CreateProcessAsUserW var createProcessAsUserHook = EasyHook.LocalHook.Create( EasyHook.LocalHook.GetProcAddress("advapi32.dll", "CreateProcessAsUserW"), new DCreateProcessAsUser(CreateProcessAsUser_Hooked), this); // 添加CreateProcessWithTokenW挂钩 var createProcessWithTokenHook = EasyHook.LocalHook.Create( EasyHook.LocalHook.GetProcAddress("advapi32.dll", "CreateProcessWithTokenW"), new DCreateProcessWithTokenW(CreateProcessWithTokenW_Hooked), this); // 替换ShellExecuteEx为ShellExecuteExW var createShellProcessHook = EasyHook.LocalHook.Create( EasyHook.LocalHook.GetProcAddress("shell32.dll", "ShellExecuteExW"), new DShellExecuteEx(ShellExecuteEx_Hooked), this); // 同步更新ACL设置 createProcessWithTokenHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
底层API拦截(可选)
如果上述API仍无法覆盖所有场景,可以尝试挂钩ntdll.dll中的NtCreateUserProcess——这是所有用户态进程创建的底层入口,无论上层调用哪个API,最终都会走到这个函数,拦截范围更全面。权限适配
确保你的挂钩程序以管理员权限运行,同时确认explorer.exe被正确注入钩子。若explorer.exe是普通权限,管理员权限的程序可以正常注入,但需注意UAC流程的特殊性,部分场景下仍需依赖底层API拦截。
内容的提问来源于stack exchange,提问作者Nobody

