x86重载内核[源码在最后]

X86重载内核

测试系统:WinXp, 环境:vs2017

一、内核重载简述

涉及PE文件,驱动程序编写, 对X86内核的了解
内核重载其实就是让所有的SSDT函数全部走自己写入的一块新内核

内核重载不是什么高端技术,但对于学习驱动编程的新手而言,还是有学习参考价值的

二、实现步骤(部分代码)

1.打开内核文件存为buffer,拉伸PE,修重定向表,IAT表

​
NTSTATUS LoadNtkrnlpa() 
{
    
    
	NTSTATUS						status = STATUS_SUCCESS;
	HANDLE							hFile = NULL;
	OBJECT_ATTRIBUTES				objAttr;
	IO_STATUS_BLOCK					ioBlock;
	UNICODE_STRING					FileName;
	FILE_STANDARD_INFORMATION		FileInfo;
	LARGE_INTEGER					Lageint; // 读取位置offset

	RtlInitUnicodeString(&FileName, FILEPATH);
	InitializeObjectAttributes(&objAttr, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL);

	status = ZwOpenFile(&hFile, FILE_ALL_ACCESS, &objAttr, &ioBlock, 0, FILE_NON_DIRECTORY_FILE);
	if (!NT_SUCCESS(status))
	{
    
    
		DbgPrint("ZwOpenFile Failed!, status:%d\n", status);
		return STATUS_UNSUCCESSFUL;
	}

	status = ZwQueryInformationFile(hFile, &ioBlock, &FileInfo, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
	if (!NT_SUCCESS(status))
	{
    
    
		ZwClose(hFile);
		DbgPrint("ZwQueryInformationFile Failed!\n");
		return STATUS_UNSUCCESSFUL;
	}
	FileSize = FileInfo.EndOfFile.LowPart;
	pFileBuffer = ExAllocatePool(NonPagedPool, FileSize);

	Lageint.QuadPart = 0;
	status = ZwReadFile(hFile, NULL, NULL, NULL, &ioBlock, pFileBuffer, FileSize, &Lageint, NULL);
	if (!NT_SUCCESS(status))
	{
    
    
		ZwClose(hFile);
		DbgPrint("ZwReadFile Failed!\n");
		return STATUS_UNSUCCESSFUL;
	}

	ZwClose(hFile);
	// 读取PE信息
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
	{
    
    
		ExFreePool(pFileBuffer);
		pFileBuffer = NULL;
		DbgPrint("Read PE File Failed\n");
		return STATUS_UNSUCCESSFUL;
	}

	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
	{
    
    
		ExFreePool(pFileBuffer);
		pFileBuffer = NULL;
		DbgPrint("Read PE File Failed\n");
		return STATUS_UNSUCCESSFUL;
	}

	pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
	pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);
	pReloactionDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)pDosHeader + RVA_TO_FOA(pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress));
	pIATDirectory = (PIMAGE_THUNK_DATA)((DWORD)pDosHeader + RVA_TO_FOA(pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress));
	
	return status;
}

(1)修重定向表

​
NTSTATUS FixRelocTable(DWORD OrignalImageBase)
{
    
    
	if (pReloactionDirectory == NULL) return STATUS_UNSUCCESSFUL;

	// 修复重定位表
	DWORD AddItem = OrignalImageBase - pOptionalHeader->ImageBase;
	// pOptionalHeader->ImageBase = NewImageBase;

	PIMAGE_BASE_RELOCATION pTempRelocationDir = pReloactionDirectory;
	UINT Count = 0;

	do
	{
    
    
		DWORD ChunkNum = (pTempRelocationDir->SizeOfBlock - 0x8) / 0x2;

		for (UINT i = 0; i < ChunkNum; i++)
		{
    
    
			PWORD pItem = (PWORD)(((DWORD)pTempRelocationDir + 0x8) + 0x2 * i);
			DWORD Type = (*pItem) >> 12;
			if (Type == 3)
			{
    
    
				PDWORD pFixAddress = (PDWORD)((DWORD)pDosHeader + RVA_TO_FOA(pTempRelocationDir->VirtualAddress + (*pItem & 0x0FFF)));
				*pFixAddress += AddItem;
			}
		}

		pTempRelocationDir = (PIMAGE_BASE_RELOCATION)((DWORD)pTempRelocationDir + pTempRelocationDir->SizeOfBlock);
		Count++;
	} while (pTempRelocationDir->VirtualAddress != 0 && pTempRelocationDir->SizeOfBlock != 0);

	// DbgPrint("FixBlockCount:%d\n", Count);
	return STATUS_SUCCESS;
}

(2)修IAT表

​
NTSTATUS FixIATTable()
{
    
    
	PIMAGE_THUNK_DATA pTemIATDir = pIATDirectory;
	ULONG CopySize = 0;

	while (pTemIATDir->u1.Function != 0)
	{
    
    
		CopySize += 4;
		pTemIATDir++;
	}

	PULONG pCurrentIATDir = OrignImage + pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
	RtlCopyMemory(pIATDirectory, pCurrentIATDir, CopySize);
	
	return STATUS_SUCCESS;
}

2.内核层申请一块内存贴入buffer

​
NTSTATUS CopyFileBufferToImageBuffer(_In_ LPVOID pFilebuffer_, _Out_ LPVOID* pImageBuffer_)
{
    
    
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFilebuffer_;
	PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFilebuffer_ + pDosHeader->e_lfanew);

	PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 0x4);
	PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);

	DWORD AlignImageSize = Align(pOptionalHeader->SizeOfImage, pOptionalHeader->SectionAlignment);
	*pImageBuffer_ = ExAllocatePool(NonPagedPool, AlignImageSize);
	memset(*pImageBuffer_, 0, AlignImageSize);
	memcpy(*pImageBuffer_, pFilebuffer_, pOptionalHeader->SizeOfHeaders);

	PIMAGE_SECTION_HEADER TempSectionHeader = pSectionHeader;

	for (int i = 0; i < pFileHeader->NumberOfSections; i++)
	{
    
    
		memcpy((LPVOID)((DWORD)*pImageBuffer_ + TempSectionHeader->VirtualAddress), (LPVOID)((DWORD)pDosHeader + TempSectionHeader->PointerToRawData), TempSectionHeader->SizeOfRawData);
		TempSectionHeader++;
	}

	return STATUS_SUCCESS;
}

3.修复ssdt中函数地址为新内核函数地址

4.创建山寨系统服务表

​
NTSTATUS SetNewSSDT(DWORD NewImageBase)
{
    
    

	pNewKeServiceDescriptorTable = (PKSERVICE_TABLE_DESCRIPTOR)((DWORD)KeServiceDescriptorTable - OrignImage + NewImageBase);

	// 函数表
	pNewKeServiceDescriptorTable->ntoskrnl.ServiceTableBase = (PULONG)((DWORD)KeServiceDescriptorTable->ntoskrnl.ServiceTableBase - OrignImage + NewImageBase);
	
	// 函数个数
	pNewKeServiceDescriptorTable->ntoskrnl.NumberOfService = KeServiceDescriptorTable->ntoskrnl.NumberOfService;

	// 调用次数
	// pNewKeServiceDescriptorTable->ntoskrnl.ServiceCounterTableBase = (PULONG)((DWORD)KeServiceDescriptorTable->ntoskrnl.ServiceCounterTableBase - OrignImage + NewImageBase);

	// 参数表
	pNewKeServiceDescriptorTable->ntoskrnl.ParamTableBase = (PULONG)((DWORD)KeServiceDescriptorTable->ntoskrnl.ParamTableBase - OrignImage + NewImageBase);

	 PageProtectOff();

	// 修复函数地址表 ,其实重定位表修复那里就修好了
	for (ULONG i = 0; i < pNewKeServiceDescriptorTable->ntoskrnl.NumberOfService; i++)
	{
    
    
		pNewKeServiceDescriptorTable->ntoskrnl.ServiceTableBase[i] += (-OrignImage + NewImageBase);

	}
	 PageProtectOn();

	return STATUS_SUCCESS;
}

5.hook KiFastCallEntry

​
NTSTATUS HookKiFastCallEntry()
{
    
    
	ULONG	HookAddr = 0;
	ULONG	uKiFastCallEntry = 0;
	// 找到KiFastCallEntry函数首地址, 在特殊模组寄存器的0x176号寄存器中
	__asm
	{
    
    
		push ecx;
		push eax;
		push edx;
		mov ecx, 0x176; // 设置编号
		rdmsr; ;// 读取到edx:eax
		mov uKiFastCallEntry, eax;// 保存到变量
		pop edx;
		pop eax;
		pop ecx;
	}

	for (ULONG i = 0; i < 0x1FF; ++i)
	{
    
    
		if (RtlCompareMemory((UCHAR*)uKiFastCallEntry + i, OriginalCode, 5) == 5)
		{
    
    
			HookAddr = uKiFastCallEntry + i;
			break;
		}
	}
	if (HookAddr == 0)
	{
    
    
		DbgPrint("Not Find 2be1c1e902 bytes");
		return STATUS_UNSUCCESSFUL;
	}

	PDWORD JmpAddr = (PDWORD)HookProc;

	PageProtectOff();
	DWORD32 X = (HookAddr + 5) - ((DWORD32)&OriginalCode[5] + 5);
	OriginalCode[5] = '\xE9';
	*(DWORD32*)(OriginalCode + 5 + 1) = X;
	pOrigianlCmd = (PORIGINALCOMD)(CHAR*)OriginalCode;
	BackAddr = HookAddr + 5;

	memset(NewCode, 0, 64);
	NewCode[0] = '\xE9';
	X = (DWORD32)JmpAddr - (HookAddr + 5);
	*(DWORD32*)(NewCode + 1) = (DWORD32)X;
	int Numnop = 5 - 5;
	for (int i = 0; i < Numnop; i++)
	{
    
    
		NewCode[5 + i] = '\x90';
	}

	RtlMoveMemory(HookAddr, NewCode, 5);

	PageProtectOn();

	return STATUS_SUCCESS;
}

三、代码测试截图

在这里插入图片描述

四、总结(源码地址)

​​

github地址
https://github.com/DeadpoolWilson12/kernelReload_

猜你喜欢

转载自blog.csdn.net/deadpoolwilson12/article/details/130168309