1. 基本原理
以前的操作系统上,挂钩 CreateProcessInternel 即可监视进程创建,在 以管理员身份启动的时候,情况发生了变化,我们的 explorer 不再调用原来的路径,而是使用一个未被导出的函数 AicFindLaunchAdminProcess。
AicFindLaunchAdminProcess 函数定义为:
ULONG_PTR WINAPI AicFindLaunchAdminProcess(
LPWSTR lpApplicationName,
LPWSTR lpParameters,
DWORD UacRequestFlag,
DWORD dwCreationFlags,
LPWSTR lpCurrentDirectory,
HWND hWnd,
PVOID StartupInfo,
PVOID ProcessInfo,
ELEVATION_REASON* ElevationReason
);
我们只需要根据特征码定位该函数的入口点,并挂钩该函数,即可监视资源管理器中,那些以管理员身份启动的程序。
2.定位函数的代码
这里给出截止 Win 10,该函数的入口点定位代码:
//#include "FindLaunchAdminFunc.h"
#include <cassert>
#include <iomanip>
#include <iostream>
#include <vector>
//#pragma once
//disable nonmeaningful warnings.
#pragma warning(push)
//#pragma warning(disable: 4005) // macro redefinition
//#pragma warning(disable: 4055) // %s : from data pointer %s to function pointer %s
//#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union
//#pragma comment(lib, "ntdll.lib")
#pragma warning(disable: 4005) // macro redefinition
#pragma warning(disable: 4055) // %s : from data pointer %s to function pointer %s
#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union
#include <windows.h>
#include <ntstatus.h>
#include <bcrypt.h>
//typedef PIMAGE_NT_HEADERS(NTAPI* RTLIMAGENTHEADER)(PVOID);
//HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll");
//RTLIMAGENTHEADER RtlImageNtHeader = (RTLIMAGENTHEADER)GetProcAddress(hNtdll, "RtlImageNtHeader");
//
//typedef NTSTATUS(NTAPI* RTLGETVERSION)(PRTL_OSVERSIONINFOW);
//RTLGETVERSION RtlGetVersion = (RTLGETVERSION)GetProcAddress(hNtdll, "RtlGetVersion");
#define _NTDEF_
//#include <ntsecapi.h>
#undef _NTDEF_
#ifndef PAGE_SIZE
#define PAGE_SIZE 0x1000ull
#endif
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
typedef ULONG ELEVATION_REASON;
#define ALIGN_UP_BY(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1))
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
ULONG_PTR AicFindLaunchAdminProcess(
_Out_ PNTSTATUS StatusCode);
#define SUCCESS 0L
#define FAILURE_NULL_ARGUMENT 1L
#define FAILURE_API_CALL 2L
#define FAILURE_INSUFFICIENT_BUFFER 3L
#define MAX_PATH_LEN 260
#define MAX_ARGS_LEN 32768
#define UNICODE
// 下面是 FindLaunchAdminFunc.cpp
#define SHELL32_DLL L"shell32.dll"
#define WINDOWS_STORAGE_DLL L"windows.storage.dll"
HINSTANCE hNtdll = GetModuleHandleA("ntdll.dll");
typedef PIMAGE_NT_HEADERS(NTAPI* RTLIMAGENTHEADER)(PVOID);
RTLIMAGENTHEADER RtlImageNtHeader = (RTLIMAGENTHEADER)GetProcAddress(hNtdll, "RtlImageNtHeader");
typedef NTSTATUS(NTAPI* RTLGETVERSION)(PRTL_OSVERSIONINFOW);
RTLGETVERSION RtlGetVersion = (RTLGETVERSION)GetProcAddress(hNtdll, "RtlGetVersion");
//RTLIMAGENTHEADER RtlImageNtHeader = (RTLIMAGENTHEADER)GetProcAddress(hNtdll, "RtlImageNtHeader");
//
// AicLaunchAdminProcess prologue signature.
//
unsigned char LaunchAdminProcessSignature760x[] = {
0xFF, 0xF3, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81,
0xEC, 0x30, 0x04, 0x00, 0x00
};
unsigned char LaunchAdminProcessSignature9200[] = {
0x44, 0x89, 0x44, 0x24, 0x18, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56,
0x41, 0x57, 0x48, 0x81, 0xEC, 0xF0, 0x03, 0x00, 0x00
};
unsigned char LaunchAdminProcessSignature9600[] = {
0x44, 0x89, 0x4C, 0x24, 0x20, 0x44, 0x89, 0x44, 0x24, 0x18, 0x53, 0x56, 0x57, 0x41,
0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81, 0xEC, 0x00, 0x04, 0x00, 0x00
};
unsigned char LaunchAdminProcessSignature10240_10586[] = {
0x40, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81,
0xEC, 0x30, 0x04, 0x00, 0x00
};
unsigned char LaunchAdminProcessSignature14393[] = {
0x40, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81,
0xEC, 0x20, 0x04, 0x00, 0x00
};
unsigned char LaunchAdminProcessSignature_15063_18362[] = {
0x40, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81,
0xEC, 0x20, 0x04, 0x00, 0x00
};
//40 53 56 57 41 54 41 55 41 56 41 57 48 81 EC 30 04 00 00
unsigned char LaunchAdminProcessSignature_18363_xxxxx[] = {
0x40, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x81,
0xEC, 0x30, 0x04, 0x00, 0x00
};
/*
* supFindPattern
*
* Purpose:
*
* Lookup pattern in buffer.
*
*/
PVOID supFindPattern(
CONST PBYTE Buffer,
SIZE_T BufferSize,
CONST PBYTE Pattern,
SIZE_T PatternSize
)
{
PBYTE p = Buffer;
if (PatternSize == 0)
return NULL;
if (BufferSize < PatternSize)
return NULL;
BufferSize -= PatternSize;
do {
p = (PBYTE)memchr(p, Pattern[0], BufferSize - (p - Buffer));
if (p == NULL)
break;
if (memcmp(p, Pattern, PatternSize) == 0)
return p;
p++;
} while (BufferSize - (p - Buffer) > 0); //-V555
return NULL;
}
/*
* AicFindLaunchAdminProcess
*
* Purpose:
*
* Locate unexported AppInfo routine in memory by signature.
*
*/
ULONG_PTR AicFindLaunchAdminProcess(
_Out_ PNTSTATUS StatusCode)
{
ULONG_PTR Address = 0;
PBYTE Pattern = NULL, ScanBase = NULL;
DWORD PatternSize = 0, ScanSize = 0;
IMAGE_NT_HEADERS* NtHeaders;
LPCWSTR ScanModule = NULL;// LPWSTR
RTL_OSVERSIONINFOW g_ctx{};
RtlSecureZeroMemory(&g_ctx, sizeof(g_ctx));
g_ctx.dwOSVersionInfoSize = sizeof(g_ctx);
RtlGetVersion((PRTL_OSVERSIONINFOW)&g_ctx);
DWORD dwBuildNumber = g_ctx.dwBuildNumber;
if (g_ctx.dwBuildNumber < 10240)
ScanModule = SHELL32_DLL;
else
ScanModule = WINDOWS_STORAGE_DLL;
switch (g_ctx.dwBuildNumber) {
case 7600:
case 7601:
Pattern = LaunchAdminProcessSignature760x;
PatternSize = sizeof(LaunchAdminProcessSignature760x);
break;
case 9200:
Pattern = LaunchAdminProcessSignature9200;
PatternSize = sizeof(LaunchAdminProcessSignature9200);
break;
case 9600:
Pattern = LaunchAdminProcessSignature9600;
PatternSize = sizeof(LaunchAdminProcessSignature9600);
break;
case 10240:
case 10586:
Pattern = LaunchAdminProcessSignature10240_10586;
PatternSize = sizeof(LaunchAdminProcessSignature10240_10586);
break;
case 14393:
Pattern = LaunchAdminProcessSignature14393;
PatternSize = sizeof(LaunchAdminProcessSignature14393);
break;
case 15063:
case 16299:
case 17134:
case 17763:
case 18362:
Pattern = LaunchAdminProcessSignature_15063_18362;
PatternSize = sizeof(LaunchAdminProcessSignature_15063_18362);
break;
case 18363:
default:
Pattern = LaunchAdminProcessSignature_18363_xxxxx;
PatternSize = sizeof(LaunchAdminProcessSignature_18363_xxxxx);
break;
}
ScanBase = (PBYTE)GetModuleHandleW(ScanModule);
if (ScanBase == NULL) {
ScanBase = (PBYTE)LoadLibraryExW(ScanModule, NULL, 0); //is in \KnownDlls
}
if (ScanBase == NULL) {
*StatusCode = STATUS_INTERNAL_ERROR;
return 0;
}
NtHeaders = RtlImageNtHeader(ScanBase);
if (NtHeaders->OptionalHeader.SizeOfImage <= PatternSize) {
*StatusCode = STATUS_INTERNAL_ERROR;
return 0;
}
ScanSize = NtHeaders->OptionalHeader.SizeOfImage - PatternSize;
Address = (ULONG_PTR)supFindPattern(ScanBase, (SIZE_T)ScanSize, Pattern, (SIZE_T)PatternSize);
if (Address == 0) {
*StatusCode = STATUS_PROCEDURE_NOT_FOUND;
return 0;
}
*StatusCode = STATUS_SUCCESS;
return Address;
}
3. 挂钩和注入的例程
找到该函数的地址后,我们就可以使用 Detours 挂钩该函数了,我们的钩子函数如下:
ULONG_PTR WINAPI AicLaunchAdminProcessHook(
LPWSTR lpApplicationName,
LPWSTR lpParameters,
DWORD UacRequestFlag,
DWORD dwCreationFlags,
LPWSTR lpCurrentDirectory,
HWND hWnd,
PVOID StartupInfo,
PVOID ProcessInfo,
ELEVATION_REASON* ElevationReason) {
ULONG Str = { '\0' };
//ULONG new_ElevationReason = 10;
//DWORD NewUacRequestFlag = 17; //admin
if (_wcsicmp(lpApplicationName, L"C:\\Windows\\System32\\cmd.exe") == 0) {
WCHAR text[128] = { 0 };
wsprintf(text, L"进程已终止。位于: %s ", lpApplicationName);
int RetSD = MessageBoxW(NULL, text, L"Hooking!CallMessage", MB_OK | MB_ICONERROR);
return Str;
}
else {
ULONG_PTR ret = TrueAicLaunchAdminProcess(lpApplicationName, lpParameters, UacRequestFlag, dwCreationFlags, lpCurrentDirectory, hWnd, StartupInfo, ProcessInfo, ElevationReason);
return ret;
}
}
完整注入代码如下:
#include <stdlib.h>
#include <iostream>
#include <detours.h>
#include <Windows.h>
#include <TlHelp32.h>
#include <Shellapi.h>
#include <fstream>
#include <algorithm>
#include <Shlwapi.h>
#include "FindLaunchAdminFunc.h"
#pragma comment(lib,"Shlwapi.lib")
#include <cassert>
#pragma warning(disable:4996)
HMODULE s_hDll;
//共享代码段
#pragma data_seg("SHARED")
HHOOK g_hCreateProcessHook = NULL;
BOOL g_bStopHook = FALSE;
BOOL g_bHookInstalled = FALSE;
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,RWS")
//#define WM_SHOWTASK (WM_USER + 1309)// 专用消息
using namespace std;
#define MAKEINTRESOURCE MAKEINTRESOURCEW
extern HINSTANCE hAppInstance;
ULONG_PTR(WINAPI* TrueAicLaunchAdminProcess)(
LPWSTR lpApplicationName,
LPWSTR lpParameters,
DWORD UacRequestFlag,
DWORD dwCreationFlags,
LPWSTR lpCurrentDirectory,
HWND hWnd,
PVOID StartupInfo,
PVOID ProcessInfo,
ELEVATION_REASON* ElevationReason
) = NULL;
typedef ULONG_PTR(WINAPI* pfnAipFindLaunchAdminProcess)(
LPWSTR lpApplicationName,
LPWSTR lpParameters,
DWORD UacRequestFlag,
DWORD dwCreationFlags,
LPWSTR lpCurrentDirectory,
HWND hWnd,
PVOID StartupInfo,
PVOID ProcessInfo,
ELEVATION_REASON* ElevationReason);
/**
* If lpApplicationName is powershell or cmd, append to lpParameters to run payload.
* Otherwise, copies payload to same name as app name from lpApplicationName and keeps
* original lpParameters to spoof path.
*/
ULONG_PTR WINAPI AicLaunchAdminProcessHook(
LPWSTR lpApplicationName,
LPWSTR lpParameters,
DWORD UacRequestFlag,
DWORD dwCreationFlags,
LPWSTR lpCurrentDirectory,
HWND hWnd,
PVOID StartupInfo,
PVOID ProcessInfo,
ELEVATION_REASON* ElevationReason) {
//ULONG new_ElevationReason = 10;
ULONG Str = { '\0' };
//DWORD NewUacRequestFlag = 17; //admin
//
if (_wcsicmp(lpApplicationName, L"C:\\Users\\Lenovo\\Desktop\\FindEXPpath.exe") == 0) {
//wcscat_s(lpParameters, MAX_PATH_LEN, L"-c \"& C:\\Users\\Lenovo\\Desktop\\FindEXPpath.exe\"");
WCHAR text[128] = { 0 };
wsprintf(text, L"进程已终止。位于: %s ", lpApplicationName);
int RetSD = MessageBoxW(NULL, text, L"Hooking!CallMessage", MB_OK | MB_ICONERROR);
return Str;
}
else {
ULONG_PTR ret = TrueAicLaunchAdminProcess(lpApplicationName, lpParameters, UacRequestFlag, dwCreationFlags, lpCurrentDirectory, hWnd, StartupInfo, ProcessInfo, ElevationReason);
return ret;
}
//return new_ElevationReason;
}
//查找函数地址
HMODULE WINAPI ModuleFromAddress(PVOID pv) {
MEMORY_BASIC_INFORMATION mbi;
if (::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
return (HMODULE)mbi.AllocationBase;
else
return NULL;
}
BOOL APIENTRY SetHook() {
// 如果已经安装就return
if (g_bHookInstalled)
return TRUE;
NTSTATUS ErrorCode;
LONG error;
PVOID LaunchAdminProcessPtr = NULL;
if (DetourIsHelperProcess()) {
return TRUE;
}
DetourRestoreAfterWith();
LaunchAdminProcessPtr = (PVOID)AicFindLaunchAdminProcess(&ErrorCode);
TrueAicLaunchAdminProcess = (pfnAipFindLaunchAdminProcess)LaunchAdminProcessPtr;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueAicLaunchAdminProcess, AicLaunchAdminProcessHook);
error = DetourTransactionCommit();
g_bHookInstalled = TRUE;
return TRUE;
}
BOOL APIENTRY DropHook() {
//如果已经卸载就return
if (!g_bHookInstalled)return TRUE;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
// Detach functions found from the export table.
if (TrueAicLaunchAdminProcess != NULL) {
DetourDetach(&(PVOID&)TrueAicLaunchAdminProcess, AicLaunchAdminProcessHook);
}
LONG ret = DetourTransactionCommit();
fflush(stdout);
g_bHookInstalled = FALSE;
return ret == NO_ERROR;
}
static LRESULT CALLBACK CreateProcessHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
//wchar_t Dir[_MAX_DIR];
wchar_t FullPath[MAX_PATH]; // [sp+200h] [bp-614h]@1
//wchar_t Ext[_MAX_EXT];
//wchar_t Filename[_MAX_FNAME];
//wchar_t Drive[_MAX_DRIVE];
GetModuleFileNameW(0, FullPath, MAX_PATH);
//_wsplitpath_s(FullPath, Drive, _MAX_DRIVE, Dir, _MAX_DIR, Filename, _MAX_FNAME, Ext, _MAX_EXT);
//wstring tar = Filename;
//transform(tar.begin(), tar.end(), tar.begin(), towlower);
//C:\Windows\explorer.exe
//C:\Windows\System32\Taskmgr.exe
//if ((_wcsicmp(Filename, L"explorer") == 0)) {
// 忽略字符串大小写查找
if (StrStrIW(FullPath, L"explorer.exe")) {
if (!g_bStopHook)
{
SetHook();
}
else
DropHook();
}
return CallNextHookEx(g_hCreateProcessHook, nCode, wParam, lParam);
}
// 导出函数 加载全局钩子
extern "C" __declspec(dllexport) BOOL SetGlobalHook() {
g_bStopHook = FALSE;
g_hCreateProcessHook = SetWindowsHookExW(WH_GETMESSAGE,
CreateProcessHookProc,
ModuleFromAddress(CreateProcessHookProc), 0);
if (g_hCreateProcessHook == NULL) {
wchar_t text[30];
wsprintf(text, L"HOOK失败!error : %d.\n", GetLastError());
MessageBox(0, text, TEXT("错误"), MB_OK);
return false;
}
return TRUE;
}
// 导出函数 卸载全局钩子
extern "C" __declspec(dllexport) BOOL DropGlobalHook() {
//DropHook();
g_bStopHook = TRUE;
Sleep(3000);
UnhookWindowsHookEx(g_hCreateProcessHook);
return TRUE;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
s_hDll = hModule;
DisableThreadLibraryCalls(hModule);
//DropGlobalHook();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
//DropGlobalHook();
break;
}
return TRUE;
}
4. 运行效果截图
更新于:2023.10.24