一、挂钩普通进程(通过注入资源管理器)
使用 Detours 挂钩 CreateProcessA 、CreateProcessW 等函数(网上各种模板很多,不建议使用全局消息钩子,容易造成系统卡死)
二、挂钩提升进程(通过注入服务)
服务:Application Information(Appinfo)、Background Tasks Infrastructure Service(BrokerInfrastructure)、DCOM Server Process Launcher(DcomLaunch)
第一个在使用管理员权限(提升)启动的时候首先在该进程中响应请求,然后转移至consent.exe(子进程)
后两个属于参数相同的服务项,是同一个进程,管理DCOM的请求。
这需要涉及到位于Kernel32.dll中的关键函数CreateProcessAsUserW()[通常调用Unicode版本]、CreateProcessAsUserA()
函数原型是这样子的:
BOOL CreateProcessAsUserW(
[in, optional] HANDLE hToken,
[in, optional] LPCWSTR lpApplicationName,
[in, out, optional] LPWSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCWSTR lpCurrentDirectory,
[in] LPSTARTUPINFOW lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
这个函数使用 Detours 挂钩 Kernel32 下的 CreateProcessAsUserW 会失败,使用其他 inline hook 即可完成任务(原因见 9.16 更新)。我推荐采用的是 mhook 或者 minhook 库。
这里给出一个简单的mhook例子,用于在从普通用户上下文中创建提升的进程时抛出相关参数的提示,由于使用了WTSSendMessageW作为服务注册系统消息对话框的方法,这不会阻滞相关例程的调用。你可以修改我们挂钩的函数,实现相关的过滤工作。
#include "stdafx.h"
#include "mhook-lib/mhook.h"
#include <Shlwapi.h>
#include <WtsApi32.h>
#pragma comment(lib,"Shlwapi.lib")
#pragma comment(lib, "WtsApi32.lib")
// CreateProcessAsUserW定义
typedef BOOL(WINAPI* pfnCreateProcessAsUserW)(
HANDLE hToken,
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
pfnCreateProcessAsUserW _CreateProcessAsUserW = (pfnCreateProcessAsUserW)GetProcAddress(GetModuleHandleW(L"Kernel32.dll"), "CreateProcessAsUserW");
BOOL SvcMessageBox(LPWSTR lpCap, LPWSTR lpMsg, DWORD style, DWORD& result)
{
if (NULL == lpMsg || NULL == lpCap)
return FALSE;
result = 0;
DWORD sessionXId = WTSGetActiveConsoleSessionId();
return WTSSendMessageW(WTS_CURRENT_SERVER_HANDLE, sessionXId,
lpCap, (DWORD)wcslen(lpCap) * sizeof(DWORD),
lpMsg, (DWORD)wcslen(lpMsg) * sizeof(DWORD),
style, 0, &result, FALSE);
}
//===========================================================
//定制我们自己的CreateProcessAsUserW
BOOL WINAPI Hook_pfnCreateProcessAsUserW(
HANDLE hToken,
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation)
{
//if (wcsstr(lpApplicationName, L"consent.exe") || wcsstr(lpCommandLine, L"consent.exe")) {
//return FALSE;
//}
//BOOL result =
WCHAR wstrTile[] = L"来自 Application Information 服务的通知";
WCHAR wstrContent[1024];
DWORD WTSresult = 0;
wsprintf(wstrContent, L"%s - %s\n", lpApplicationName, lpCommandLine);
SvcMessageBox(wstrTile, wstrContent, MB_OK | MB_ICONINFORMATION, WTSresult);
return _CreateProcessAsUserW(
hToken, lpApplicationName,
lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles,
dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);;
}
//==============================================================
// 变量
HHOOK glhHook = NULL;
HINSTANCE glhInstance = NULL;
DWORD gProtectProcessID = 0;
BOOL WINAPI DllMain(
__in HINSTANCE hInstance,
__in DWORD Reason,
__in LPVOID Reserved
)
{
DisableThreadLibraryCalls(hInstance);
glhInstance = hInstance;
switch (Reason)
{
case DLL_PROCESS_ATTACH:
Mhook_SetHook((PVOID*)&_CreateProcessAsUserW, Hook_pfnCreateProcessAsUserW);
break;
case DLL_PROCESS_DETACH:
Mhook_Unhook((PVOID*)&_CreateProcessAsUserW);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
链接库可以遍历成Dll,然后使用ExtremeInjector等工具测试注入效果。
这里给出注入测试(DcomLaunch服务)的效果:
可能用到的库:
三、更新内容
1. 2023.09.16 更新内容
在此处补充说明一下,后面可能会单独开一篇博客讲一下。Windows Vista 以上系统有一个叫做API伞集的位于内核的加载器。至于说 detours 挂钩的 CreateProcessAsUserW 并不应该在在 kernel32.dll 和 kernelbase.dll 中,原因其实是这个函数正真的定义位于伞集中规范的虚拟链接文件:api-ms-win-core-processthreads-l1-1-0.dll 中,真正运行时通过 API 伞集转发位于 Kernel32 中的这个函数。这和通过 IDA 反汇编的结果相同,经测试使用 API 伞集作为DetourFindFunction 函数的参数能够实现 Detours 挂钩 CreateProcessAsUserW 函数,说明在Detours 上使用 API 伞集名称是比较妥当的。
2. 2024.01.28 更新内容
CreateProcessAsUserW 就是调用的 CreateProcessInternal 函数(参数和CreateProcessAsUserW 完全一样), CreateProcess 也是,对于一般进程,只需要挂钩 CreateProcessInternal 函数即可拦截一切 CreateProcess 等启动。对于需要提权启动的,挂钩 AppInfo 服务对应的 svchost.exe 进程的 CreateProcessInternal 函数。至于 ShellExecuteEx 则需要注入 DcomLunch 服务进程对应的 svchost.exe,依然是挂钩 CreateProcessInternal 函数。总结:只要CreateProcessInternal 函数被挂钩即可。
新人初学,如有错误,望指正!海涵。
发布于 2023.05.29,修改于 2024.01.28