x64的内核重载源码
x64的内核重载源码,参照x86写的 望大牛们指点。
ReX64.h
#pragma once
#include <ntifs.h>
#include <ntimage.h>
#include <intrin.h>
PVOID pNewBuffer = nullptr;
typedef struct _SYSTEM_SERVICE_TABLE //SSDT结构
{
PVOID serviceTableBase;
PVOID serviceCounterTableBase;
ULONGLONG numberofServices;
PVOID paramTableBase;
}SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
typedef struct _BaseAddr_Size
{
DWORD_PTR mMoudleBaseAddress;
DWORD_PTR mMoudleSizeOf;
}BaseAddr_Size, *PBaseAddr_Size;
#pragma once
#include <ntifs.h>
#include <ntimage.h>
#include <intrin.h>
PVOID pNewBuffer = nullptr;
typedef struct _SYSTEM_SERVICE_TABLE //SSDT结构
{
PVOID serviceTableBase;
PVOID serviceCounterTableBase;
ULONGLONG numberofServices;
PVOID paramTableBase;
}SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
typedef struct _BaseAddr_Size
{
DWORD_PTR mMoudleBaseAddress;
DWORD_PTR mMoudleSizeOf;
}BaseAddr_Size, *PBaseAddr_Size;
typedef struct _PE
{
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS32 NtHeaders;
IMAGE_SECTION_HEADER SectionHeader;
}PE, *pPE;
typedef struct _LDR_DATA_TABLE_ENTRY
{
struct _LIST_ENTRY InLoadOrderLinks; //0x0
struct _LIST_ENTRY InMemoryOrderLinks; //0x8
struct _LIST_ENTRY InInitializationOrderLinks; //0x10
VOID* DllBase; //0x18
VOID* EntryPoint; //0x1c
ULONG SizeOfImage; //0x20
struct _UNICODE_STRING FullDllName; //0x24
struct _UNICODE_STRING BaseDllName; //0x2c
ULONG Flags; //0x34
USHORT LoadCount; //0x38
USHORT TlsIndex; //0x3a
union
{
struct _LIST_ENTRY HashLinks; //0x3c
struct
{
VOID* SectionPointer; //0x3c
ULONG CheckSum; //0x40
}u;
};
union
{
ULONG TimeDateStamp; //0x44
VOID* LoadedImports; //0x44
};
VOID* EntryPointActivationContext; //0x48
VOID* PatchInformation; //0x4c
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;//0x50 bytes (sizeof)
EXTERN_C{
VOID UnLoad(PDRIVER_OBJECT pDriver);
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg);
}
NTSTATUS GetKernelImageBase_1(IN PDRIVER_OBJECT pDriver, IN PUNICODE_STRING szMoudeName, OUT PBaseAddr_Size mBeseAddrOfSize);
PVOID GetNewKernelBuffer_1(IN PUNICODE_STRING pStrKernelPathName);
VOID RepirRelocTable(IN DWORD_PTR uNewModule, IN DWORD_PTR uOldModule);
NTSTATUS RepirSSDT(IN PDRIVER_OBJECT pDriver, IN ULONG64 pNewKernelBuffer, IN ULONG64 uOldModule);
NTSTATUS GetSSDT(IN PDRIVER_OBJECT pdriver, OUT PVOID* addr); //通过链表找到ssdt
ReX64.cpp
#pragma once
#include "ReX64Knrl.h"
#pragma warning (disable:4310)
VOID UnLoad(PDRIVER_OBJECT pDriver)
{
UNREFERENCED_PARAMETER(pDriver);
if (pNewBuffer) ExFreePool(pNewBuffer);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
UNREFERENCED_PARAMETER(pReg);
pDriver->DriverUnload = UnLoad;
DbgBreakPoint();
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING szMoudleName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
BaseAddr_Size sz = { 0 };
status= GetKernelImageBase_1(pDriver, &szMoudleName, &sz);
if (NT_SUCCESS(status))
{
DbgPrintEx(77, 0, "GetKernelImageBase_1 sucess!\n");
}
else
{
DbgPrintEx(77, 0, "GetKernelImageBase_1 Faild!\n");
return STATUS_UNSUCCESSFUL;
}
UNICODE_STRING szFileName = RTL_CONSTANT_STRING(L"\\??\\C:\\Windows\\system32\\ntoskrnl.exe");//ntdll.dll //\\??\\C:\\WINDOWS\\system32\\ntkrnlpa.exe
PVOID pNewKernelBuffer = GetNewKernelBuffer_1(&szFileName);
if (!MmIsAddressValid(pNewKernelBuffer))
{
DbgPrintEx(77, 0, "pNewKernelBuffer is faild");
return STATUS_UNSUCCESSFUL;
}
DbgPrintEx(77, 0, "pNewKernelBuffer is: %llx", pNewKernelBuffer);
//基址重定位
RepirRelocTable((DWORD_PTR)pNewKernelBuffer, sz.mMoudleBaseAddress);
//系统服务表重定位
status = RepirSSDT(pDriver, (ULONG64)pNewKernelBuffer, sz.mMoudleBaseAddress);
if (NT_SUCCESS(status))
{
DbgPrintEx(77, 0, "RepirSSDT sucess!\n");
}
else
{
DbgPrintEx(77, 0, "RepirSSDT Faild!\n");
return STATUS_UNSUCCESSFUL;
}
//>>>>>>>>插入HOOK代码
return STATUS_SUCCESS;
}
//[获取当前内核模块基址_1]
NTSTATUS GetKernelImageBase_1(IN PDRIVER_OBJECT pDriver, IN PUNICODE_STRING szMoudeName, OUT PBaseAddr_Size mBeseAddrOfSize)
{
PLIST_ENTRY pCurrObject = (PLIST_ENTRY)pDriver->DriverSection;
PLIST_ENTRY pNextObject = pCurrObject->Flink;
PLDR_DATA_TABLE_ENTRY szTemp = nullptr;
while (pCurrObject != pNextObject)
{
szTemp = (PLDR_DATA_TABLE_ENTRY)pNextObject;
if (RtlCompareUnicodeString(&szTemp->BaseDllName, szMoudeName, TRUE) == NULL)
{
mBeseAddrOfSize->mMoudleBaseAddress = (DWORD_PTR)(szTemp->DllBase);
mBeseAddrOfSize->mMoudleSizeOf = szTemp->SizeOfImage;
DbgPrintEx(77, 0, "DllBase:0x%llX SizeOfImage:0x%XBaseDllName:%wZ FullDllName:%wZ ", szTemp->DllBase, szTemp->SizeOfImage, szTemp->BaseDllName, szTemp->FullDllName);
return STATUS_SUCCESS;
}
pNextObject = pNextObject->Flink;
}
return STATUS_UNSUCCESSFUL;
}
//
PVOID GetNewKernelBuffer_1(IN PUNICODE_STRING pStrKernelPathName)
{
PE pe = { 0 };
HANDLE hFile = NULL;
OBJECT_ATTRIBUTES objectAttributes = { 0 };
IO_STATUS_BLOCK ioStatusBlock = { 0 };
InitializeObjectAttributes(&objectAttributes, pStrKernelPathName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS ntStatus = ZwCreateFile(&hFile, GENERIC_READ, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, NULL, 0);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("ZwCreateFile错误:%x\n", ntStatus));
return NULL;
}
LARGE_INTEGER fileOffset = { 0 };
fileOffset.QuadPart = 0;
//读取DOS头
ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, &pe.DosHeader, sizeof(IMAGE_DOS_HEADER), &fileOffset, NULL);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("ZwReadFile错误:%x\n", ntStatus));
goto exit;
}
fileOffset.QuadPart += pe.DosHeader.e_lfanew;
//读取NT头
ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, &pe.NtHeaders, sizeof(IMAGE_NT_HEADERS), &fileOffset, NULL);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("ZwReadFile错误:%x\n", ntStatus));
goto exit;
}
pNewBuffer = ExAllocatePool(NonPagedPool, pe.NtHeaders.OptionalHeader.SizeOfImage);
if (pNewBuffer == NULL)
{
KdPrint(("pNewBuffer错误\n"));
goto exit;
}
PVOID pTempBuffer = pNewBuffer;
RtlCopyMemory(pTempBuffer, &pe.DosHeader, sizeof(IMAGE_DOS_HEADER));
pTempBuffer = (PVOID)((DWORD_PTR)pTempBuffer + pe.DosHeader.e_lfanew);
RtlCopyMemory(pTempBuffer, &pe.NtHeaders, sizeof(IMAGE_NT_HEADERS));
fileOffset.QuadPart += sizeof(IMAGE_NT_HEADERS);
pTempBuffer = (PVOID)((DWORD_PTR)pTempBuffer + sizeof(IMAGE_NT_HEADERS));
//读取节表
ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, pTempBuffer, (sizeof(IMAGE_SECTION_HEADER) * pe.NtHeaders.FileHeader.NumberOfSections), &fileOffset, NULL);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("ZwReadFile错误:%x\n", ntStatus));
pNewBuffer = nullptr;
goto exit;
}
PIMAGE_SECTION_HEADER pTempSectionHeader = (PIMAGE_SECTION_HEADER)pTempBuffer;
//读取节内容
for (ULONG32 uCount = 0; uCount < pe.NtHeaders.FileHeader.NumberOfSections; uCount++)
{
pTempBuffer = (PVOID)((DWORD_PTR)pNewBuffer + pTempSectionHeader->VirtualAddress);
fileOffset.QuadPart = pTempSectionHeader->PointerToRawData;
ntStatus = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, pTempBuffer, pTempSectionHeader->SizeOfRawData, &fileOffset, NULL);
if (!NT_SUCCESS(ntStatus))
{
KdPrint(("ZwReadFile错误:%x\n", ntStatus));
pNewBuffer = nullptr;
goto exit;
}
pTempSectionHeader++;
}
exit:
if (hFile) ZwClose(hFile);
//if (pNewBuffer) ExFreePool(pNewBuffer);
return pNewBuffer;
}
//修复重定位表
VOID RepirRelocTable(IN DWORD_PTR uNewModule,IN DWORD_PTR uOldModule)
{
UNREFERENCED_PARAMETER(uOldModule);
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNtHeaders = NULL;
PIMAGE_BASE_RELOCATION pRelocation = NULL;
PIMAGE_DATA_DIRECTORY pData = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)uNewModule;
pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)pDosHeader + pDosHeader->e_lfanew);
pData = pNtHeaders->OptionalHeader.DataDirectory;
//定位重定位表
pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)uNewModule + pData.VirtualAddress);
//由于新的内核里面的全局变量地址都是用的老的 所以要加上它们之间的偏移量 就等于我们新的内核全局变量地址
DWORD_PTR uOffset = uNewModule - pNtHeaders->OptionalHeader.ImageBase; //需要改正的偏移
while (pRelocation->VirtualAddress != 0 && pRelocation->SizeOfBlock != 0 && pRelocation->VirtualAddress != 01)
{
LONG32 uNumOfRelocs = (pRelocation->SizeOfBlock - 8) / 2;//取得重定位数量
PUSHORT pUShort = (PUSHORT)((DWORD_PTR)pRelocation + 8);
for (DWORD_PTR uCount = 0; uCount < uNumOfRelocs; uCount++, pUShort++)
{
if (((*pUShort) >> 12) == IMAGE_REL_BASED_DIR64)
{
PULONG64 pUlong32 = (PULONG64)(((*pUShort) & 0x0FFF) + pRelocation->VirtualAddress + uNewModule);
*pUlong32 += uOffset; //改好数据写入目的地址
}
}
pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)pRelocation + pRelocation->SizeOfBlock);
}
}
//修复新的系统服务表
NTSTATUS RepirSSDT(IN PDRIVER_OBJECT pDriver, IN ULONG64 pNewKernelBuffer, IN ULONG64 uOldModule)
{
ULONG64 g_uOffset = pNewKernelBuffer - uOldModule;
PVOID szAddr = nullptr;
NTSTATUS status = GetSSDT(pDriver, &szAddr);
if (!NT_SUCCESS(status))
{
DbgPrintEx(77, 0, "GetSSDT Faile!\n");
return STATUS_UNSUCCESSFUL;
}
PSYSTEM_SERVICE_TABLE m_pOldSSDT = { 0 };
m_pOldSSDT = (PSYSTEM_SERVICE_TABLE)szAddr;
PSYSTEM_SERVICE_TABLE m_pNewSSDT = (PSYSTEM_SERVICE_TABLE)((ULONGLONG)m_pOldSSDT + g_uOffset);
m_pNewSSDT->numberofServices = m_pOldSSDT->numberofServices;
ULONG64 m_uOffset = (ULONG64)m_pOldSSDT->serviceTableBase - uOldModule;
m_pNewSSDT->serviceTableBase = (PULONG32)(pNewKernelBuffer + m_uOffset);
m_uOffset = ((ULONGLONG)m_pOldSSDT->serviceCounterTableBase - uOldModule);
m_pNewSSDT->serviceCounterTableBase = (PULONG32)(pNewKernelBuffer + m_uOffset);
m_uOffset = ((ULONGLONG)m_pOldSSDT->paramTableBase - uOldModule);
m_pNewSSDT->paramTableBase = (PCHAR)(pNewKernelBuffer + m_uOffset);
RtlCopyMemory((PULONGLONG)m_pNewSSDT->paramTableBase, (PULONGLONG)m_pOldSSDT->paramTableBase, (ULONG64)m_pNewSSDT->numberofServices);//复制参数
m_uOffset = (ULONG64)m_pNewSSDT->serviceTableBase - pNewKernelBuffer;
//计算ssdt表中函数地址注:win10 ssdt表中函数地址为:高28位为偏移 低4位为参数个数-4 不足4个参数时为零
for (ULONG32 uCount = 0; uCount < m_pNewSSDT->numberofServices; uCount++)
{
((PULONG32)(UCHAR*)(m_pNewSSDT->serviceTableBase)) = (ULONG32)((((PULONG32)(UCHAR*)(m_pNewSSDT->serviceTableBase)) - m_uOffset) << 4) + (((CHAR)((UCHAR*)(m_pNewSSDT->paramTableBase))) >> 2);
}
return STATUS_SUCCESS;
}
NTSTATUS GetSSDT(IN PDRIVER_OBJECT pdriver, OUT PVOID* addr)//通过链表找到ssdt
{
PLDR_DATA_TABLE_ENTRY entry = (PLDR_DATA_TABLE_ENTRY)pdriver->DriverSection;
PLDR_DATA_TABLE_ENTRY head = entry;
UNICODE_STRING temp = { 0 };
RtlInitUnicodeString(&temp, L"ntoskrnl.exe");
PCHAR start = NULL;
ULONG size = 0;
do
{//通过链表找到ntoskrnl.exe 内核文件。
if (RtlCompareUnicodeString(&temp, &entry->BaseDllName, TRUE) == NULL)
{
//DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "%wZ\n", &entry->BaseDllName);
start = (PCHAR)entry->DllBase;
size = entry->SizeOfImage;
break;
}
entry = (PLDR_DATA_TABLE_ENTRY)entry->InLoadOrderLinks.Flink;
} while (entry != head);
for (ULONG i = 0; i < size; i++)
{
if (MmIsAddressValid(start))
{
if (*start == (CHAR)0x4c && *(CHAR*)(start + 1) == (CHAR)0x8d && *(CHAR*)(start + 2) == (CHAR)0x15)//注:必需强制转换字符串类型
{
start += 7;
if (MmIsAddressValid(start))
{
if (*start == (CHAR)0x4c && *(CHAR*)(start + 1) == (CHAR)0x8d && *(CHAR*)(start + 2) == (CHAR)0x1d)
{
*(PULONGLONG)addr = *(PULONG)(start - 4) + (ULONGLONG)start;
return STATUS_SUCCESS;
}
}
}
}
if (MmIsAddressValid(start))
{
start++;
}
}
return STATUS_UNSUCCESSFUL;
}
页:
[1]