吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 921|回复: 1
收起左侧

[C&C++ 原创] x64的内核重载

[复制链接]
luduxin 发表于 2023-5-23 15:59
ReX64.h
[C++] 纯文本查看 复制代码
#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
[mw_shl_code=cpp,true]#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%X  BaseDllName:%wZ FullDllName:%wZ ", szTemp->DllBase, szTemp->SizeOfImage, szTemp->BaseDllName, szTemp->FullDllName);
			return STATUS_SUCCESS;
		}
		pNextObject = pNextObject->Flink;
	}
	return STATUS_UNSUCCESSFUL;
}

// [1、获取新的内核模块虚拟缓存]
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[IMAGE_DIRECTORY_ENTRY_BASERELOC].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))[uCount] = (ULONG32)((((PULONG32)(UCHAR*)(m_pNewSSDT->serviceTableBase))[uCount] - m_uOffset) << 4) + (((CHAR)((UCHAR*)(m_pNewSSDT->paramTableBase))[uCount]) >> 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;
}

本人新手  参照x86写的   望大牛们指点

免费评分

参与人数 4威望 +1 吾爱币 +17 热心值 +4 收起 理由
cxw123 + 1 热心回复!
77341991 + 1 + 1 热心回复!
nico1004 + 1 + 1 热心回复!
苏紫方璇 + 1 + 15 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

PPYLL 发表于 2023-7-24 12:56
感谢分享,学习了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 18:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表