681 lines
24 KiB
C++
681 lines
24 KiB
C++
#include "DDKCommon.h"
|
||
#include "HwidHook.h"
|
||
#include "ntddndis.h"
|
||
#include "kernelasm.h"
|
||
#include "ntifs.h"
|
||
#include "NtFunctionDefine.h"
|
||
#include "MyPEB.h"
|
||
|
||
#define printf
|
||
|
||
typedef struct _HOOK_DEVICE_IO_CONTEXT {
|
||
PVOID JmpPage;
|
||
PVOID Object;
|
||
ULONG64 iosb;
|
||
ULONG IoControlCode;
|
||
ULONG64 InputBuffer;
|
||
ULONG InputBufferLength;
|
||
ULONG64 OutputBuffer;
|
||
ULONG OutputBufferLength;
|
||
}HOOK_DEVICE_IO_CONTEXT;
|
||
typedef struct _HOOK_NTQUERY_CONTEXT {
|
||
PVOID JmpPage;
|
||
ULONG FsInformationClass;
|
||
ULONG64 FsInformation;
|
||
ULONG Length;
|
||
}HOOK_NTQUERY_CONTEXT;
|
||
|
||
typedef BOOL(*fnIoCtlPostCallback)(HOOK_DEVICE_IO_CONTEXT *);
|
||
fnIoCtlPostCallback g_IoCtlPostCallback = 0;
|
||
|
||
typedef void(*fndiccabk)(ULONG64, ULONG64, ULONG64, ULONG64, ULONG64);
|
||
typedef void(*fnntqcabk)(ULONG64, ULONG64, ULONG64);
|
||
typedef VOID(*fnExtraCallback)(VOID);
|
||
fndiccabk dicpostcabk = 0;
|
||
fndiccabk dicprecabk = 0;
|
||
fnntqcabk ntqcabk = 0;
|
||
fnExtraCallback pcabk = 0;
|
||
|
||
#include "vtstruct.h"
|
||
|
||
ULONG64 Search_FsInformation = 0;
|
||
ULONG Search_Length = 0;
|
||
ULONG64 Search_Object = 0;
|
||
|
||
ULONG64 pRetCodePage = 0;
|
||
ULONG64 pNtQueryRetCodePage = 0;
|
||
|
||
ULONG64 NtDeviceIoControlFileRet = 0;
|
||
ULONG64 NtFsControlFileRet = 0;
|
||
ULONG64 NtQueryVolumeInformationFileRet = 0;
|
||
|
||
ULONG RspOffset = 0;
|
||
ULONG RspOffset_NtQuery = 0;
|
||
|
||
ULONG NtDevice_Offset_Object = 0;
|
||
|
||
ULONG NtQuery_StackSize = 0;
|
||
LONG NtQuery_Offset_FsInformation = 0;
|
||
LONG NtQuery_Offset_Length = 0;
|
||
|
||
ULONG64 MyAllocEx() {
|
||
return 0;
|
||
}
|
||
VOID TestDeviceIoControl() {
|
||
HANDLE FileHandle = 0;
|
||
UNICODE_STRING name;
|
||
RtlInitUnicodeString(&name, L"\\??\\C:");
|
||
|
||
OBJECT_ATTRIBUTES oa;
|
||
InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, 0, 0);
|
||
IO_STATUS_BLOCK iosb;
|
||
RtlZeroMemory(&iosb, sizeof(IO_STATUS_BLOCK));
|
||
NTSTATUS stats = ZwCreateFile(&FileHandle, FILE_GENERIC_READ, &oa, &iosb, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, 0, 0);
|
||
RtlZeroMemory(&iosb, sizeof(IO_STATUS_BLOCK));
|
||
|
||
PFILE_OBJECT obj = 0;
|
||
OBJECT_HANDLE_INFORMATION objhandle = { 0 };
|
||
RtlZeroMemory(&objhandle, sizeof(objhandle));
|
||
stats = ObReferenceObjectByHandle(FileHandle, 0, *IoFileObjectType, KernelMode, (PVOID *)&obj, &objhandle);
|
||
if (!NT_SUCCESS(stats)) {
|
||
ZwClose(FileHandle);
|
||
KeBugCheck(0x56009);
|
||
}
|
||
ObDereferenceObject(obj);
|
||
Search_Object = (ULONG64)obj;
|
||
typedef NTSTATUS
|
||
(*NTAPI fnNtDeviceIoControlFile)(
|
||
_In_ HANDLE FileHandle,
|
||
_In_opt_ HANDLE Event,
|
||
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
|
||
_In_opt_ PVOID ApcContext,
|
||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
||
_In_ ULONG IoControlCode,
|
||
_In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer,
|
||
_In_ ULONG InputBufferLength,
|
||
_Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer,
|
||
_In_ ULONG OutputBufferLength
|
||
);
|
||
fnNtDeviceIoControlFile pNtDeviceIoControlFile = (fnNtDeviceIoControlFile)KGetProcAddress(KGetNtoskrnl(), "NtDeviceIoControlFile");
|
||
UCHAR Input[4] = { 0 };
|
||
UCHAR Output[4] = { 0 };
|
||
ULONG64 Magic[2];
|
||
Magic[0] = 0x1122334455667788;
|
||
Magic[1] = 0x8877665544772299;
|
||
pNtDeviceIoControlFile(FileHandle, 0, 0, 0, &iosb, IOCTL_NDIS_QUERY_GLOBAL_STATS, Input, 4, Output, 4);
|
||
|
||
ZwClose(FileHandle);
|
||
}
|
||
VOID TestNtQueryVolumeInformationFile() {
|
||
HANDLE FileHandle = 0;
|
||
UNICODE_STRING name;
|
||
RtlInitUnicodeString(&name, L"\\??\\C:");
|
||
|
||
OBJECT_ATTRIBUTES oa;
|
||
InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, 0, 0);
|
||
IO_STATUS_BLOCK iosb;
|
||
RtlZeroMemory(&iosb, sizeof(IO_STATUS_BLOCK));
|
||
|
||
NTSTATUS stats = ZwCreateFile(&FileHandle, FILE_GENERIC_READ, &oa, &iosb, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, 0, 0);
|
||
RtlZeroMemory(&iosb, sizeof(IO_STATUS_BLOCK));
|
||
FILE_FS_OBJECTID_INFORMATION *pinfo = (FILE_FS_OBJECTID_INFORMATION *)ExAllocatePoolWithTag(NonPagedPoolNx, 0x2000, POOL_TAG);
|
||
RtlZeroMemory(pinfo, sizeof(FILE_FS_OBJECTID_INFORMATION));
|
||
|
||
ULONG64 Mark[2];
|
||
Mark[0] = 0xCC22334455666688;
|
||
Mark[1] = 0xAA77665544333399;
|
||
|
||
Search_FsInformation = (ULONG64)pinfo;
|
||
Search_Length = 0x1238;
|
||
NtQueryVolumeInformationFile(FileHandle, &iosb, pinfo, 0x1238, FileFsObjectIdInformation);
|
||
ExFreePoolWithTag(pinfo, POOL_TAG);
|
||
ZwClose(FileHandle);
|
||
}
|
||
|
||
ULONG64 GetIopDispatchAllocateIrp() {
|
||
ULONG BuildNumber = KGetBuildNumber();
|
||
if (BuildNumber >= 15063) {
|
||
//8B 05 ?? ?? ?? ?? 44 8A C2
|
||
ULONG64 pos = ScanSection(".text", "8B05????????448AC2");
|
||
if (pos) {
|
||
return *(LONG *)(pos + 2) + pos + 6;
|
||
}
|
||
else {
|
||
pos = ScanSection(".text", "8B05????????440FB6C2");
|
||
if (pos) {
|
||
return *(LONG *)(pos + 2) + pos + 6;
|
||
}
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
BOOL InitStackSize() {
|
||
ULONG64 ntos = (ULONG64)KGetNtoskrnl();
|
||
|
||
ULONG64 pNtQueryVolumeInformationFile = (ULONG64)KGetProcAddress((PVOID)ntos, "NtQueryVolumeInformationFile");
|
||
|
||
//63 ?? 24 ?? ?? 00 00
|
||
ULONG64 pos = FindSignatureCode_nocheck((LPCVOID)pNtQueryVolumeInformationFile, 0x200, "63??24????0000", 0);
|
||
if (pos == -1)return FALSE;
|
||
NtQuery_StackSize = *(ULONG *)(pos + pNtQueryVolumeInformationFile + 3) - 0x28;
|
||
|
||
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
namespace DispatchControl {
|
||
BOOLEAN enable_ntq = TRUE;
|
||
BOOLEAN enable = FALSE;
|
||
BOOLEAN Inited = FALSE;
|
||
}
|
||
VOID DispatchCallback(ULONG64 pRsp) {
|
||
static const unsigned char shellcode[] = "\x48\xB9\x00\x00\x00\x00\x00\x10\x00\x00\x51\x48\xB9\x00\x00\x00\x00\x00\x10\x00\x00\x50\xC7\x04\x24\x00\x00\x00\x10\xC7\x44\x24\x04\x00\x00\x00\x10\xC3"
|
||
;
|
||
KIRQL irql = AsmReadCr8() & 0xFF;
|
||
if (irql >= DISPATCH_LEVEL)return;
|
||
ULONG64 RFlag = AsmGetRFlags();
|
||
if (RFlag & 0x10000) {
|
||
return;
|
||
}
|
||
int Pid = (int)PsGetProcessId(PsGetCurrentThreadProcess());
|
||
if ((int)Pid != 4) {
|
||
if (pcabk) {
|
||
pcabk();
|
||
|
||
}
|
||
}
|
||
ULONG64 Low = 0, High = 0;
|
||
IoGetStackLimits(&Low, &High);
|
||
if (DispatchControl::Inited == FALSE) {
|
||
if (RspOffset == 0 || DispatchControl::enable_ntq ? RspOffset_NtQuery == 0 : false) {
|
||
PULONG64 Rsp = (PULONG64)pRsp;
|
||
for (int i = 0; (ULONG64)Rsp < High - 8; Rsp++, i++) {
|
||
if (RspOffset == 0) {
|
||
if (Rsp[0] == 0x1122334455667788) {
|
||
if (Rsp[1] == 0x8877665544772299) {
|
||
//DbgBreakPoint();
|
||
ULONG64 OLRSP = (ULONG64)Rsp;
|
||
for (int j = 0; OLRSP > pRsp && j < 0x1000; OLRSP -= 8, j += 8) {
|
||
if (*(ULONG64*)OLRSP == NtDeviceIoControlFileRet) {
|
||
RspOffset = OLRSP - pRsp;
|
||
//printf("[112233] RspOffset %x\n", RspOffset);
|
||
ULONG64 OOLRSP = OLRSP;
|
||
for (int p = 0; OOLRSP > pRsp && p < 0x1000; OOLRSP -= 8, p += 8) {
|
||
//search arg offset
|
||
if (NtDevice_Offset_Object)
|
||
break;
|
||
if (NtDevice_Offset_Object == 0) {
|
||
if (*(ULONG64*)OOLRSP == Search_Object) {
|
||
NtDevice_Offset_Object = OOLRSP - pRsp;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (RspOffset)break;
|
||
}
|
||
if (RspOffset_NtQuery == 0 && DispatchControl::enable_ntq) {
|
||
if (Rsp[0] == 0xCC22334455666688) {
|
||
if (Rsp[1] == 0xAA77665544333399) {
|
||
ULONG64 OLRSP = (ULONG64)Rsp;
|
||
for (int j = 0; OLRSP > pRsp && j < 0x800; OLRSP -= 8, j += 8) {
|
||
if (*(ULONG64*)OLRSP == NtQueryVolumeInformationFileRet) {
|
||
RspOffset_NtQuery = OLRSP - pRsp;
|
||
ULONG64 OOLRSP = OLRSP;
|
||
for (int p = 0; OOLRSP > pRsp && p < 0x800; OOLRSP -= 8, p += 8) {
|
||
//search arg offset
|
||
if (NtQuery_Offset_FsInformation && NtQuery_Offset_Length)
|
||
break;
|
||
if (NtQuery_Offset_FsInformation == 0) {
|
||
if (*(ULONG64*)OOLRSP == Search_FsInformation) {
|
||
NtQuery_Offset_FsInformation = OOLRSP - pRsp;
|
||
continue;
|
||
}
|
||
}
|
||
if (NtQuery_Offset_Length == 0) {
|
||
if (*(ULONG*)OOLRSP == Search_Length) {
|
||
NtQuery_Offset_Length = OOLRSP - pRsp;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
}
|
||
if (NtQuery_Offset_Length == 0) {
|
||
KeBugCheck(0x33221);
|
||
}
|
||
if (NtQuery_Offset_FsInformation == 0) {
|
||
KeBugCheck(0x33222);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
printf("[112233] RspOffset_NtQuery:%x\n", RspOffset_NtQuery);
|
||
printf("[112233] FsInformation:%x Length:%x\n", NtQuery_Offset_FsInformation, NtQuery_Offset_Length);
|
||
}
|
||
}
|
||
if (RspOffset_NtQuery)break;
|
||
}
|
||
|
||
}
|
||
//printf("[112233] RspOffset:%x RspOffset_Ntquery:%x\n", RspOffset, RspOffset_NtQuery);
|
||
}
|
||
}
|
||
|
||
if (RspOffset) {
|
||
if (High - pRsp > RspOffset) {
|
||
if (*(ULONG64 *)(pRsp + RspOffset) == NtDeviceIoControlFileRet || *(ULONG64*)(pRsp + RspOffset) == NtFsControlFileRet) {
|
||
ULONG64 LRSP = (ULONG64)(pRsp + RspOffset);
|
||
|
||
ULONG64 Object = *(ULONG64 *)(pRsp + NtDevice_Offset_Object);
|
||
ULONG64 iosb = *(ULONG64*)(LRSP + 8 + 0x90);
|
||
ULONG ControlCode = *(ULONG *)(LRSP + 8 + 0x98);
|
||
ULONG64 InputBuffer = *(ULONG64 *)(LRSP + 8 + 0xA0);
|
||
ULONG InputBufferLength = *(ULONG *)(LRSP + 8 + 0xA8);
|
||
ULONG64 OutputBuffer = *(ULONG64 *)(LRSP + 8 + 0xB0);
|
||
ULONG OutputBufferLength = *(ULONG *)(LRSP + 8 + 0xB8);
|
||
|
||
HOOK_DEVICE_IO_CONTEXT lContext;
|
||
RtlZeroMemory(&lContext, sizeof(lContext));
|
||
lContext.iosb = iosb;
|
||
lContext.InputBuffer = InputBuffer;
|
||
lContext.InputBufferLength = InputBufferLength;
|
||
lContext.OutputBuffer = OutputBuffer;
|
||
lContext.OutputBufferLength = OutputBufferLength;
|
||
lContext.IoControlCode = ControlCode;
|
||
lContext.Object = (PVOID)Object;
|
||
|
||
if (g_IoCtlPostCallback(&lContext)) {
|
||
HOOK_DEVICE_IO_CONTEXT *Context = (HOOK_DEVICE_IO_CONTEXT *)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(lContext), POOL_TAG);
|
||
RtlZeroMemory(Context, sizeof(HOOK_DEVICE_IO_CONTEXT));
|
||
memcpy(Context, &lContext, sizeof(lContext));
|
||
PUCHAR JmpPage = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, sizeof(shellcode)+1, POOL_TAG);
|
||
memcpy(JmpPage, shellcode, sizeof(shellcode));
|
||
ULONG offset = 0;
|
||
*(ULONG64 *)(JmpPage + 0x2 + offset) = *(ULONG64 *)(LRSP + 0x70);
|
||
*(ULONG64 *)(JmpPage + 0xd + offset) = (ULONG64)Context;
|
||
LARGE_INTEGER Addr;
|
||
Addr.QuadPart = pRetCodePage;
|
||
*(ULONG *)(JmpPage + 0x19 + offset) = Addr.LowPart;
|
||
*(ULONG *)(JmpPage + 0x21 + offset) = Addr.HighPart;
|
||
|
||
Context->JmpPage = JmpPage;
|
||
*(ULONG64 *)(LRSP + 0x70) = (ULONG64)JmpPage;
|
||
}
|
||
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
if (RspOffset_NtQuery && DispatchControl::enable_ntq) {
|
||
if (High - pRsp > RspOffset_NtQuery) {
|
||
if (*(ULONG64 *)(pRsp + RspOffset_NtQuery) == NtQueryVolumeInformationFileRet) {
|
||
ULONG64 LRSP = (ULONG64)(pRsp + RspOffset_NtQuery);
|
||
ULONG FsInfomationClass = *(ULONG *)(LRSP + 8 + NtQuery_StackSize + 0x28);
|
||
ULONG64 FsInformation = *(ULONG64 *)(pRsp + NtQuery_Offset_FsInformation);
|
||
ULONG Length = *(ULONG *)(pRsp + NtQuery_Offset_Length);
|
||
|
||
printf("[112233] NtQ Class %d FsInfomation %p Length %x\n", FsInfomationClass, FsInformation, Length);
|
||
|
||
HOOK_NTQUERY_CONTEXT* Context = (HOOK_NTQUERY_CONTEXT*)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(HOOK_NTQUERY_CONTEXT), POOL_TAG);
|
||
RtlZeroMemory(Context, sizeof(HOOK_NTQUERY_CONTEXT));
|
||
|
||
Context->FsInformation = FsInformation;
|
||
Context->FsInformationClass = FsInfomationClass;
|
||
Context->Length = Length;
|
||
|
||
PUCHAR JmpPage = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, sizeof(shellcode)+1, POOL_TAG);
|
||
memcpy(JmpPage, shellcode, sizeof(shellcode));
|
||
ULONG offset = 0;
|
||
*(ULONG64 *)(JmpPage + 0x2 + offset) = *(ULONG64 *)(LRSP + 8 + NtQuery_StackSize);
|
||
*(ULONG64 *)(JmpPage + 0xd + offset) = (ULONG64)Context;
|
||
LARGE_INTEGER Addr;
|
||
Addr.QuadPart = pNtQueryRetCodePage;
|
||
*(ULONG *)(JmpPage + 0x19 + offset) = Addr.LowPart;
|
||
*(ULONG *)(JmpPage + 0x21 + offset) = Addr.HighPart;
|
||
|
||
Context->JmpPage = JmpPage;
|
||
|
||
*(ULONG64 *)(LRSP + 8 + NtQuery_StackSize) = (ULONG64)JmpPage;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
return;
|
||
}
|
||
|
||
BOOLEAN g_hooked = FALSE;
|
||
|
||
VOID InstallHook(fnIoCtlPostCallback PostCallback, PVOID PreCallback, PVOID NtQueryPre) {
|
||
if (g_hooked == TRUE) {
|
||
return;
|
||
}
|
||
|
||
static unsigned char shellcode[] = "\x50\x53\x51\x52\x56\x57\x55\x41\x50\x41\x51\x41\x52\x41\x53\x41\x54\x41\x55\x41\x56\x41\x57\x9C\x48\x8D\x8C\x24\x80\x00\x00\x00\x48\xB8\x00\x00\x00\x00\x00\x01\x00\x00\x48\x35\xFF\xFF\xFF\x7F\x48\x93\xE8\x30\x00\x00\x00\xFF\xD3\xE8\x3E\x00\x00\x00\x9D\x41\x5F\x41\x5E\x41\x5D\x41\x5C\x41\x5B\x41\x5A\x41\x59\x41\x58\x5D\x5F\x5E\x5A\x59\x5B\x58\x50\xC7\x04\x24\x00\x00\x00\x10\xC7\x44\x24\x04\x00\x00\x00\x10\xC3\x4C\x8D\x5C\x24\x08\x48\x83\xE4\xF0\x41\x53\x41\x53\x48\x83\xEC\x30\x41\xFF\x63\xF8\x41\x5B\x48\x83\xC4\x38\x5C\x41\xFF\xE3"
|
||
;
|
||
static unsigned char shellcode2[] = "\x50\x53\x51\x52\x56\x57\x55\x41\x50\x41\x51\x41\x52\x41\x53\x41\x54\x41\x55\x41\x56\x41\x57\x9C\x48\xB8\x00\x00\x00\x00\x00\x01\x00\x00\x48\x35\xFF\xFF\xFF\x7F\x48\x93\xE8\x20\x00\x00\x00\xFF\xD3\xE8\x2E\x00\x00\x00\x9D\x41\x5F\x41\x5E\x41\x5D\x41\x5C\x41\x5B\x41\x5A\x41\x59\x41\x58\x5D\x5F\x5E\x5A\x59\x5B\x58\xC3\x4C\x8D\x5C\x24\x08\x48\x83\xE4\xF0\x41\x53\x41\x53\x48\x83\xEC\x30\x41\xFF\x63\xF8\x41\x5B\x48\x83\xC4\x38\x5C\x41\xFF\xE3"
|
||
;
|
||
static unsigned char shellcode3[] = "\x50\x53\x51\x52\x56\x57\x55\x41\x50\x41\x51\x41\x52\x41\x53\x41\x54\x41\x55\x41\x56\x41\x57\x9C\x48\x89\xC2\x48\xB8\x00\x00\x00\x00\x01\x00\x00\x00\x48\x35\xFF\xFF\xFF\x7F\x48\x93\xE8\x20\x00\x00\x00\xFF\xD3\xE8\x2E\x00\x00\x00\x9D\x41\x5F\x41\x5E\x41\x5D\x41\x5C\x41\x5B\x41\x5A\x41\x59\x41\x58\x5D\x5F\x5E\x5A\x59\x5B\x58\xC3\x4C\x8D\x5C\x24\x08\x48\x83\xE4\xF0\x41\x53\x41\x53\x48\x83\xEC\x30\x41\xFF\x63\xF8\x41\x5B\x48\x83\xC4\x38\x5C\x41\xFF\xE3"
|
||
;
|
||
static unsigned char shellcode4[] = "\x53\x51\x52\x56\x57\x55\x41\x50\x41\x51\x41\x52\x41\x53\x41\x54\x41\x55\x41\x56\x41\x57\x9C\x48\x89\xC2\x48\xB8\x00\x00\x00\x00\x01\x00\x00\x00\x48\x35\xFF\xFF\xFF\x7F\x48\x93\xE8\x1F\x00\x00\x00\xFF\xD3\xE8\x2D\x00\x00\x00\x9D\x41\x5F\x41\x5E\x41\x5D\x41\x5C\x41\x5B\x41\x5A\x41\x59\x41\x58\x5D\x5F\x5E\x5A\x59\x5B\xC3\x4C\x8D\x5C\x24\x08\x48\x83\xE4\xF0\x41\x53\x41\x53\x48\x83\xEC\x30\x41\xFF\x63\xF8\x41\x5B\x48\x83\xC4\x38\x5C\x41\xFF\xE3"
|
||
;
|
||
|
||
if (!InitStackSize())KeBugCheck(0x897877);
|
||
ULONG BuildNumber = KGetBuildNumber();
|
||
ULONG64 ntos = (ULONG64)KGetNtoskrnl();
|
||
ULONG offset = 0;
|
||
|
||
ULONG64 ViPacketLookaside = 0;
|
||
//ViPacketLookaside
|
||
//48 8B F9 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 C9
|
||
//48 8D 0D ?? ?? ?? ?? 66 89 74 24 ?? 41 B9 00 02 00 00 C7 44 24 ?? 49 72 70 74
|
||
//48 8B D3 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? F0 FF 0D
|
||
ULONG64 pos = ScanSection("PAGEVRFY", "488BF9488D0D????????E8????????33C9");
|
||
if (pos) {
|
||
ViPacketLookaside = *(LONG*)(pos + 6) + pos + 10;
|
||
}
|
||
else {
|
||
pos = ScanSection("PAGEVRFY", "48 8D 0D ?? ?? ?? ?? 66 89 74 24 ?? 41 B9 00 02 00 00 C7 44 24 ?? 49 72 70 74");
|
||
if (pos) {
|
||
ViPacketLookaside = *(LONG*)(pos + 3) + pos + 7;
|
||
}
|
||
else {
|
||
pos = ScanSection("PAGEVRFY", "48 8B D3 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? F0 FF 0D");
|
||
if (pos) {
|
||
ViPacketLookaside = *(LONG*)(pos + 6) + pos + 10;
|
||
}
|
||
}
|
||
}
|
||
if (!ViPacketLookaside) {
|
||
KeBugCheck(0x957778);
|
||
}
|
||
//DbgPrint("[112233] ViPacketLookaside %p\n", ViPacketLookaside);
|
||
//48 8D 0D ?? ?? ?? ?? C7 05 ?? ?? ?? ?? 01 00 00 00 E8
|
||
|
||
if (*(ULONG64 *)(ViPacketLookaside + 0x30) == 0) {
|
||
pos = ScanSection("PAGEVRFY", "488D0D????????C705????????01000000E8");
|
||
if (!pos) {
|
||
pos = ScanSection("PAGE", "488D0D????????C705????????01000000E8");
|
||
if (!pos)KeBugCheck(0x957776);
|
||
}
|
||
ULONG64 VfInitVerifierComponents = *(LONG *)(pos + 3) + pos + 7;
|
||
typedef ULONG64(*fnVfInitVerifierComponents)(ULONG64, ULONG64, ULONG64);
|
||
fnVfInitVerifierComponents v = (fnVfInitVerifierComponents)VfInitVerifierComponents;
|
||
v(0, 0, 0);
|
||
}
|
||
ULONG64 VfIoDisabled = 0;
|
||
if (BuildNumber < 10240) {
|
||
//win7 8B 05 ?? ?? ?? ?? 33 FF 49 8B F1
|
||
pos = ScanSection("PAGEVRFY", "8B05????????33FF498BF1");
|
||
if (!pos) KeBugCheck(0x6765544);
|
||
VfIoDisabled = *(LONG *)(pos + 2) + pos + 6;
|
||
}
|
||
else {
|
||
//8B 05 ?? ?? ?? ?? 40 FE C5
|
||
pos = ScanSection("PAGEVRFY", "8B05????????40FEC5");
|
||
if (!pos) KeBugCheck(0x6765544);
|
||
VfIoDisabled = *(LONG *)(pos + 2) + pos + 6;
|
||
}
|
||
ULONG64 IovAllocateIrp = 0;
|
||
ULONG64 pIoAllocateIrp = 0;
|
||
ULONG64 IopDispatchAllocateIrp = 0;
|
||
if (BuildNumber < 10240) {
|
||
//48 8D 05 ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 89 05
|
||
pos = ScanSection("PAGEVRFY", "488D05????????488D15????????488905");
|
||
if (!pos) KeBugCheck(0x6725544);
|
||
IovAllocateIrp = *(LONG *)(pos + 3) + pos + 7;
|
||
pIoAllocateIrp = *(LONG *)(pos + 17) + pos + 21;
|
||
*(ULONG64 *)(pIoAllocateIrp) = IovAllocateIrp;
|
||
|
||
}
|
||
else if (BuildNumber >= 10240 && BuildNumber <= 14393) {
|
||
//48 8D 05 ?? ?? ?? ?? 48 87 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? 48 87 0D ?? ?? ?? ?? 48 8D 05
|
||
pos = ScanSection(".text", "488D05????????488705????????488D0D????????48870D????????488D05");
|
||
if (!pos) KeBugCheck(0x6725544);
|
||
IovAllocateIrp = *(LONG *)(pos + 3) + pos + 7;
|
||
pIoAllocateIrp = *(LONG *)(pos + 10) + pos + 14;
|
||
|
||
*(ULONG64 *)(pIoAllocateIrp) = IovAllocateIrp;
|
||
}
|
||
else if (BuildNumber >= 15063) {
|
||
//87 05 ?? ?? ?? ?? 87 0D
|
||
pos = ScanSection(".text", "8705????????870D");
|
||
if (!pos) KeBugCheck(0x6725544);
|
||
IopDispatchAllocateIrp = *(LONG *)(pos + 2) + pos + 6;
|
||
//if (!IopDispatchAllocateIrp)return;
|
||
*(int *)(IopDispatchAllocateIrp) = 1;
|
||
}
|
||
|
||
ULONG bn = KGetBuildNumber();
|
||
|
||
//E8 ?? ?? ?? ?? 48 8B D8 48 89 84 24 ?? ?? ?? ?? 48 85 C0
|
||
|
||
//E8 ?? ?? ?? ?? 48 83 C4
|
||
ULONG64 pNtDeviceIoControlFile = (ULONG64)KGetProcAddress((PVOID)ntos, "NtDeviceIoControlFile");
|
||
pos = FindSignatureCode_nocheck((LPCVOID)pNtDeviceIoControlFile, 0x200, "E8????????4883C4", 0);
|
||
if (pos == -1)KeBugCheck(0x89997);
|
||
NtDeviceIoControlFileRet = pos + pNtDeviceIoControlFile + 5;
|
||
|
||
ULONG64 pNtFsControlFile = (ULONG64)KGetProcAddress((PVOID)ntos, "NtFsControlFile");
|
||
pos = FindSignatureCode_nocheck((LPCVOID)pNtFsControlFile, 0x200, "E8????????4883C4", 0);
|
||
if (pos == -1)KeBugCheck(0x89998);
|
||
NtFsControlFileRet = pos + pNtFsControlFile + 5;
|
||
//printf("[112233] NtDeviceIoControlFileRet %p\n", NtDeviceIoControlFileRet);
|
||
//printf("[112233] NtFsControlFileRet %p\n", NtFsControlFileRet);
|
||
//DbgPrint("[112233] IoCreateFileRet:%p\n", IoCreateFileRet);
|
||
//45 33 C9 ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? ?? 8B ?? E8 ?? ?? ?? ??
|
||
//DbgPrint("[112233] IopCreateFileRet:%p\n", IopCreateFileRet);
|
||
//DbgBreakPoint();
|
||
ULONG64 pNtQueryVolumeInformationFile = (ULONG64)KGetProcAddress((PVOID)ntos, "NtQueryVolumeInformationFile");
|
||
if (BuildNumber < WIN10_1507) {
|
||
//4C E8 ?? ?? ?? ?? 48
|
||
pos = FindSignatureCode_nocheck((LPCVOID)pNtQueryVolumeInformationFile, 0x1000, "4CE8????????48", 0);
|
||
if (pos == -1)KeBugCheck(0x89967);
|
||
NtQueryVolumeInformationFileRet = pos + pNtQueryVolumeInformationFile + 6;
|
||
}
|
||
else if (BuildNumber >= WIN10_1507 && BuildNumber <= WIN10_1607) {
|
||
//4C ?? ?? ?? FF 15 ?? ?? ?? ?? ?? ?? ?? 48
|
||
pos = FindSignatureCode_nocheck((LPCVOID)pNtQueryVolumeInformationFile, 0x1000, "4C??????FF15??????????????48", 0);
|
||
if (pos == -1)KeBugCheck(0x89967);
|
||
NtQueryVolumeInformationFileRet = pos + pNtQueryVolumeInformationFile + 10;
|
||
}
|
||
else if (BuildNumber >= WIN10_1703) {
|
||
//4C ?? 8B ?? E8 ?? ?? ?? ?? ?? 89
|
||
//4C ?? 8B ?? E8 ?? ?? ?? ?? ?? 8B ?? 48 89 44 24
|
||
//4C E8 ?? ?? ?? ?? ?? 8B ?? 48 89 44 24
|
||
//4C ?? 8B ?? E8 ?? ?? ?? ?? 48 89 44 24
|
||
|
||
pos = FindSignatureCode_nocheck((LPCVOID)pNtQueryVolumeInformationFile, 0x1000, "4C ?? 8B ?? E8 ?? ?? ?? ?? ?? 89", 0);
|
||
if (pos != -1) {
|
||
NtQueryVolumeInformationFileRet = pos + pNtQueryVolumeInformationFile + 9;
|
||
}
|
||
else {
|
||
pos = FindSignatureCode_nocheck((LPCVOID)pNtQueryVolumeInformationFile, 0x600, "4C ?? 8B ?? E8 ?? ?? ?? ?? ?? 8B ?? 48 89 44 24", 0);
|
||
if (pos != -1) {
|
||
NtQueryVolumeInformationFileRet = pos + pNtQueryVolumeInformationFile + 9;
|
||
}
|
||
else {
|
||
pos = FindSignatureCode_nocheck((LPCVOID)pNtQueryVolumeInformationFile, 0x800, "4C E8 ?? ?? ?? ?? ?? 8B ?? 48 89 44 24", 0);
|
||
if (pos != -1) {
|
||
NtQueryVolumeInformationFileRet = pos + pNtQueryVolumeInformationFile + 6;
|
||
}
|
||
else {
|
||
KeBugCheck(0x89967);
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
//DbgPrint("[112233] NtQueryVolumeInformationFile %p\n", pNtQueryVolumeInformationFile);
|
||
//DbgPrint("[112233] NtQueryVolumeInformationFileRet %p\n", NtQueryVolumeInformationFileRet);
|
||
|
||
if (!NtQueryVolumeInformationFileRet)
|
||
KeBugCheck(0x89967);
|
||
if (BuildNumber < 10240) {
|
||
*(ULONG64*)(pIoAllocateIrp) = IovAllocateIrp;
|
||
}
|
||
else if (BuildNumber >= 10240 && BuildNumber <= 14393) {
|
||
*(ULONG64*)(pIoAllocateIrp) = IovAllocateIrp;
|
||
}
|
||
else if (BuildNumber >= 15063) {
|
||
*(int*)(IopDispatchAllocateIrp) = 1;
|
||
}
|
||
|
||
KIRQL irql = KeRaiseIrqlToDpcLevel();
|
||
|
||
pRetCodePage = (ULONG64)ExAllocatePool(NonPagedPool, 0x500);
|
||
memcpy((PVOID)pRetCodePage, shellcode2, sizeof(shellcode2));
|
||
*(ULONG64*)(pRetCodePage + 0x1A) = ((ULONG64)PreCallback) ^ 0x7fffffff;
|
||
|
||
pNtQueryRetCodePage = (ULONG64)ExAllocatePool(NonPagedPool, 0x500);
|
||
memcpy((PVOID)pNtQueryRetCodePage, shellcode3, sizeof(shellcode3));
|
||
*(ULONG64*)(pNtQueryRetCodePage + 0x1D) = ((ULONG64)NtQueryPre) ^ 0x7fffffff;
|
||
g_IoCtlPostCallback = PostCallback;
|
||
|
||
|
||
PUCHAR pcode = (PUCHAR)ExAllocatePool(NonPagedPool, 0x500);
|
||
memcpy(pcode, shellcode, sizeof(shellcode));
|
||
*(ULONG64 *)(pcode + 0x22 + offset) = ((ULONG64)DispatchCallback) ^ 0x7fffffff;
|
||
ULONG64 pfn = *(ULONG64*)(ViPacketLookaside + 0x30);
|
||
ULONG64 Origin = pfn;
|
||
if (MmiGetPhysicalAddress((PVOID)pfn)) {
|
||
if (*(ULONG64*)pfn == *(ULONG64*)shellcode) {
|
||
LARGE_INTEGER new_addr;
|
||
new_addr.LowPart = *(ULONG*)(pfn + 0x5A + offset);
|
||
new_addr.HighPart = *(ULONG*)(pfn + 0x62 + offset);
|
||
Origin = new_addr.QuadPart;
|
||
}
|
||
}
|
||
|
||
LARGE_INTEGER Addr;
|
||
Addr.QuadPart = (ULONG64)MyAllocEx;
|
||
*(ULONG *)(pcode + 0x5A + offset) = Addr.LowPart;
|
||
*(ULONG *)(pcode + 0x62 + offset) = Addr.HighPart;
|
||
InterlockedExchange64((volatile LONG64*)(ViPacketLookaside + 0x30), (LONG64)pcode);
|
||
|
||
*(DWORD*)(pcode + sizeof(shellcode)) = 0xDEADBEEF;
|
||
|
||
*(int*)(VfIoDisabled) = 0;
|
||
|
||
KeLowerIrql(irql);
|
||
//*(int *)(IopDispatchAllocateIrp) = 1;
|
||
TestDeviceIoControl();
|
||
TestNtQueryVolumeInformationFile();
|
||
|
||
|
||
DispatchControl::Inited = TRUE;
|
||
}
|
||
BOOL FnDICPostCallback(HOOK_DEVICE_IO_CONTEXT *Context) {
|
||
|
||
if (Context) {
|
||
PFILE_OBJECT FileObject = (PFILE_OBJECT)Context->Object;
|
||
if (dicpostcabk) {
|
||
dicpostcabk(Context->IoControlCode, Context->InputBuffer, Context->InputBufferLength, Context->OutputBuffer, Context->OutputBufferLength);
|
||
}
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
VOID FnDICPreCallback(HOOK_DEVICE_IO_CONTEXT *aContext){
|
||
if (aContext) {
|
||
HOOK_DEVICE_IO_CONTEXT Context = *aContext;
|
||
ExFreePoolWithTag(Context.JmpPage, POOL_TAG);
|
||
ExFreePoolWithTag(aContext, POOL_TAG);
|
||
if (dicprecabk) {
|
||
dicprecabk(Context.IoControlCode, Context.InputBuffer, Context.InputBufferLength, Context.OutputBuffer, Context.OutputBufferLength);
|
||
}
|
||
}
|
||
}
|
||
VOID FnNtQueryPreCallback(HOOK_NTQUERY_CONTEXT *aContext) {
|
||
if (aContext) {
|
||
HOOK_NTQUERY_CONTEXT Context = *aContext;
|
||
ExFreePoolWithTag(Context.JmpPage, POOL_TAG);
|
||
ExFreePoolWithTag(aContext, POOL_TAG);
|
||
|
||
if (ntqcabk) {
|
||
ntqcabk(Context.FsInformationClass, Context.FsInformation, Context.Length);
|
||
}
|
||
}
|
||
}
|
||
|
||
BOOL DICPostCallback(HOOK_DEVICE_IO_CONTEXT* Context) {
|
||
//<2F><><EFBFBD><EFBFBD>irql<71><6C>2,<2C>ر<EFBFBD>smap
|
||
IRQL_STATE state;
|
||
KRaiseIrqlToDpcOrHigh(&state);
|
||
Cr4 cr4;
|
||
cr4.all = __readcr4();
|
||
bool smap = cr4.fields.smap == 1;
|
||
if (smap) {
|
||
cr4.fields.smap = 0;
|
||
__writecr4(cr4.all);
|
||
}
|
||
BOOL ret = FnDICPostCallback(Context);
|
||
if (smap) {
|
||
cr4.fields.smap = 1;
|
||
__writecr4(cr4.all);
|
||
}
|
||
KLowerIrqlToState(&state);
|
||
return ret;
|
||
}
|
||
VOID DICPreCallback(HOOK_DEVICE_IO_CONTEXT* aContext) {
|
||
//<2F><><EFBFBD><EFBFBD>irql<71><6C>2,<2C>ر<EFBFBD>smap
|
||
IRQL_STATE state;
|
||
KRaiseIrqlToDpcOrHigh(&state);
|
||
Cr4 cr4;
|
||
cr4.all = __readcr4();
|
||
bool smap = cr4.fields.smap == 1;
|
||
if (smap) {
|
||
cr4.fields.smap = 0;
|
||
__writecr4(cr4.all);
|
||
}
|
||
FnDICPreCallback(aContext);
|
||
if (smap) {
|
||
cr4.fields.smap = 1;
|
||
__writecr4(cr4.all);
|
||
}
|
||
KLowerIrqlToState(&state);
|
||
}
|
||
VOID NtQueryPreCallback(HOOK_NTQUERY_CONTEXT* aContext) {
|
||
//<2F><><EFBFBD><EFBFBD>irql<71><6C>2,<2C>ر<EFBFBD>smap
|
||
IRQL_STATE state;
|
||
KRaiseIrqlToDpcOrHigh(&state);
|
||
Cr4 cr4;
|
||
cr4.all = __readcr4();
|
||
bool smap = cr4.fields.smap == 1;
|
||
if (smap) {
|
||
cr4.fields.smap = 0;
|
||
__writecr4(cr4.all);
|
||
}
|
||
FnNtQueryPreCallback(aContext);
|
||
if (smap) {
|
||
cr4.fields.smap = 1;
|
||
__writecr4(cr4.all);
|
||
}
|
||
KLowerIrqlToState(&state);
|
||
}
|
||
|
||
VOID setpcabk(PVOID fun) {
|
||
pcabk = (fnExtraCallback)fun;
|
||
InstallHook(DICPostCallback, DICPreCallback, NtQueryPreCallback);
|
||
}
|
||
VOID setdicpostcabk(PVOID func) {
|
||
dicpostcabk = (fndiccabk)func;
|
||
InstallHook(DICPostCallback, DICPreCallback, NtQueryPreCallback);
|
||
}
|
||
VOID setdicprecabk(PVOID func) {
|
||
dicprecabk = (fndiccabk)func;
|
||
InstallHook(DICPostCallback, DICPreCallback, NtQueryPreCallback);
|
||
}
|
||
VOID setntqcabk(PVOID func) {
|
||
ntqcabk = (fnntqcabk)func;
|
||
}
|
||
|
||
VOID setntqhookstats(BOOL stats) {
|
||
DispatchControl::enable_ntq = stats;
|
||
} |