三木目 发表于 2023-7-12 12:02:56

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]
查看完整版本: x64的内核重载源码