首页 > 代码库 > Win7 内核重载 1 ——内核版PELoader

Win7 内核重载 1 ——内核版PELoader

重载重点,其实就是自己实现一个山寨版的Windows PELoader  ,重载其实就是将一个模块自己重新加载一份到别的内存,运行它。

所谓内核重载,则是将内核文件即:ntkrnlpa.exe 自己加载一份到内存,并运行它,这样的好处可以避免一切HOOK,如SSDT ,InLineHook 等等,原理就是HOOK继续

HOOK主原来内核,但是实际上Windows走的是我们自己的内核。

废话不多说,开始干起来,首先查找内核模块,遍历内核模块的方式很多种,这里我使用的是通过LDR链表:

// 查找内核模块
PLDR_DATA_TABLE_ENTRY SearchDriver(PDRIVER_OBJECT pDriverObject, wchar_t *strDriverName)
{
	LDR_DATA_TABLE_ENTRY	*pDataTableEntry, *pTempDataTableEntry;
	PLIST_ENTRY				pList;
	UNICODE_STRING			usModuleName;

	RtlInitUnicodeString(&usModuleName, strDriverName);

	pDataTableEntry = (LDR_DATA_TABLE_ENTRY*)pDriverObject->DriverSection;
	if (!pDataTableEntry)
	{
		return 0;
	}

	pList = pDataTableEntry->InLoadOrderLinks.Flink;

	while (pList != &pDataTableEntry->InLoadOrderLinks)
	{
		pTempDataTableEntry = (LDR_DATA_TABLE_ENTRY *)pList;

		if (0 == RtlCompareUnicodeString(&pTempDataTableEntry->BaseDllName, &usModuleName, FALSE))
		{
			return pTempDataTableEntry;
		}

		pList = pList->Flink;
	}

	return 0;
}
找到内核模块,就开始读文件到内存~

NTSTATUS ReadFileToMemory(LPWSTR lpFileName, PVOID* lpVirtualPoint, PVOID pOriImage)
{
	NTSTATUS				Status;
	HANDLE					hFile;
	OBJECT_ATTRIBUTES		ObjAttr;
	UNICODE_STRING			usFileName;
	IO_STATUS_BLOCK			IoStatusBlock;
	LARGE_INTEGER			FileOffset;
	PVOID					pVirtualAddress;
	ULONG					uIndex;
	ULONG					uSizeOfSection;
	ULONG					uSectionAddress;

	IMAGE_DOS_HEADER		ImageDosHeader;
	IMAGE_NT_HEADERS		ImageNtHeader;
	PIMAGE_SECTION_HEADER	pImageSectionHeader;


	RtlInitUnicodeString(&usFileName, lpFileName);

	InitializeObjectAttributes(
		&ObjAttr,
		&usFileName,
		OBJ_CASE_INSENSITIVE,
		NULL,
		NULL);


	Status = ZwCreateFile(
		&hFile,
		FILE_ALL_ACCESS,
		&ObjAttr,
		&IoStatusBlock,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN,
		FILE_NON_DIRECTORY_FILE,
		NULL,
		0);

	if (!NT_SUCCESS(Status))
	{
		DbgPrint("ZwCreateFile faild\n");
		return Status;
	}


	FileOffset.QuadPart = 0;
	Status = ZwReadFile(
		hFile,
		NULL,
		NULL,
		NULL,
		&IoStatusBlock,
		&ImageDosHeader,
		sizeof(IMAGE_DOS_HEADER),
		&FileOffset,
		NULL);

	if (!NT_SUCCESS(Status))
	{
		DbgPrint("ZwReadFile ImageDosHeader faild\n");
		ZwClose(hFile);
		return Status;
	}

	FileOffset.QuadPart = ImageDosHeader.e_lfanew;

	Status = ZwReadFile(
		hFile,
		NULL,
		NULL,
		NULL,
		&IoStatusBlock,
		&ImageNtHeader,
		sizeof(IMAGE_NT_HEADERS),
		&FileOffset,
		NULL);

	if (!NT_SUCCESS(Status))
	{
		DbgPrint("ZwReadFile ImageNtHeader faild\n");
		ZwClose(hFile);
		return Status;
	}

	// 读节段
	pImageSectionHeader = (PIMAGE_SECTION_HEADER)ExAllocatePool(NonPagedPool,
		sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader.FileHeader.NumberOfSections);

	if (NULL == pImageSectionHeader)
	{
		DbgPrint("ExAllocatePool pImageSectionHeader faild\n");
		ZwClose(hFile);
		return STATUS_UNSUCCESSFUL;
	}

	FileOffset.QuadPart += sizeof(IMAGE_NT_HEADERS);
	Status = ZwReadFile(
		hFile,
		NULL,
		NULL,
		NULL,
		&IoStatusBlock,
		pImageSectionHeader,
		sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader.FileHeader.NumberOfSections,
		&FileOffset,
		NULL);

	if (!NT_SUCCESS(Status))
	{
		DbgPrint("ZwReadFile pImageSectionHeader faild\n");
		ExFreePool(pImageSectionHeader);
		ZwClose(hFile);
		return Status;
	}


	// 复制内存
	pVirtualAddress = ExAllocatePool(NonPagedPool, ImageNtHeader.OptionalHeader.SizeOfImage);

	if (NULL == pVirtualAddress)
	{
		DbgPrint("ExAllocatePool pVirtualAddress faild\n");
		ExFreePool(pImageSectionHeader);
		ZwClose(hFile);
		return STATUS_UNSUCCESSFUL;
	}

	RtlZeroMemory(pVirtualAddress, ImageNtHeader.OptionalHeader.SizeOfImage);

	RtlCopyMemory(pVirtualAddress, &ImageDosHeader, sizeof(IMAGE_DOS_HEADER));
	RtlCopyMemory(
		(PVOID)((ULONG)pVirtualAddress + ImageDosHeader.e_lfanew), 
		&ImageNtHeader, 
		sizeof(IMAGE_NT_HEADERS));
	RtlCopyMemory(
		(PVOID)((ULONG)pVirtualAddress + ImageDosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)),
		pImageSectionHeader,
		sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader.FileHeader.NumberOfSections);

	for (uIndex = 0; uIndex < ImageNtHeader.FileHeader.NumberOfSections; uIndex++)
	{
		uSectionAddress = pImageSectionHeader[uIndex].VirtualAddress;
		if (pImageSectionHeader[uIndex].Misc.VirtualSize > pImageSectionHeader[uIndex].SizeOfRawData)
			uSizeOfSection = pImageSectionHeader[uIndex].Misc.VirtualSize;
		else
			uSizeOfSection = pImageSectionHeader[uIndex].SizeOfRawData;

		FileOffset.QuadPart = pImageSectionHeader[uIndex].PointerToRawData;

		Status = ZwReadFile(
			hFile,
			NULL,
			NULL,
			NULL,
			&IoStatusBlock,
			(PVOID)((ULONG)pVirtualAddress + uSectionAddress),
			uSizeOfSection,
			&FileOffset,
			NULL);

		if (!NT_SUCCESS(Status))
		{
			DbgPrint("ZwReadFile ImageSectionHeader faild\n");
			ExFreePool(pImageSectionHeader);
			ExFreePool(pVirtualAddress);
			ZwClose(hFile);
			return Status;
		}
	}

	FixRelocTable(pVirtualAddress, pOriImage);

	DbgPrint("OK\n");
	ExFreePool(pImageSectionHeader);
	*lpVirtualPoint = pVirtualAddress;
	ZwClose(hFile);
	return Status;
}

接下来这步也是最关键一步,就是修复重定位表:

void FixRelocTable(PVOID pNewImage, PVOID pOriImage)
{
	PIMAGE_DOS_HEADER			pImageDosHeader;
	PIMAGE_NT_HEADERS			pImageNtHeadaers;
	IMAGE_DATA_DIRECTORY		ImageDataDirectory;
	PIMAGE_BASE_RELOCATION		pImageBaseRelocation;

	ULONG						uRelocTableSize;
	ULONG						uCount;
	ULONG						uIndex;
	USHORT						*pwOffsetAddress;
	USHORT						uTypeValue;
	ULONG						uRelocOffset;
	ULONG						uRelocAddress;


	pImageDosHeader = (PIMAGE_DOS_HEADER)pNewImage;
	pImageNtHeadaers = (PIMAGE_NT_HEADERS)(pImageDosHeader->e_lfanew + (ULONG)pNewImage);
	uRelocOffset = (ULONG)pOriImage - pImageNtHeadaers->OptionalHeader.ImageBase;
	ImageDataDirectory = pImageNtHeadaers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
	pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)(ImageDataDirectory.VirtualAddress + (ULONG)pNewImage);
	uRelocTableSize = ImageDataDirectory.Size;

	while (uRelocTableSize)
	{
		uCount = (pImageBaseRelocation->SizeOfBlock - sizeof(ULONG)* 2) / sizeof(USHORT);
		pwOffsetAddress = pImageBaseRelocation->TypeOffset;

		for (uIndex = 0; uIndex < uCount; uIndex++)
		{
			uTypeValue = http://www.mamicode.com/pwOffsetAddress[uIndex];>

通过上面步骤,我们成功的将内核文件完全复制了一遍。


之后就是如何让相关黑科技走我们的内核了,明天再继续!

Win7 内核重载 1 ——内核版PELoader