通过API Hook获取R3下进程创建信息的一种较新的方案

一、挂钩普通进程(通过注入资源管理器)

使用 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服务)的效果:

be5fc76c7b1e476aba20b98ea8510487.png
测试截图 1
a03c7cdec1854d1eab695dc81757bf3e.png
测试截图 2

可能用到的库:

1.mhook库(相对老的项目了)

2.Detours库;

3.ExtremeInjector工具


三、更新内容

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涟幽516

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值