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

来源:互联网 发布:沃尔玛的库存优化 编辑:程序博客网 时间:2024/06/15 14:12

重载重点,其实就是自己实现一个山寨版的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_ENTRYpList;UNICODE_STRINGusModuleName;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){NTSTATUSStatus;HANDLEhFile;OBJECT_ATTRIBUTESObjAttr;UNICODE_STRINGusFileName;IO_STATUS_BLOCKIoStatusBlock;LARGE_INTEGERFileOffset;PVOIDpVirtualAddress;ULONGuIndex;ULONGuSizeOfSection;ULONGuSectionAddress;IMAGE_DOS_HEADERImageDosHeader;IMAGE_NT_HEADERSImageNtHeader;PIMAGE_SECTION_HEADERpImageSectionHeader;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;elseuSizeOfSection = 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_HEADERpImageDosHeader;PIMAGE_NT_HEADERSpImageNtHeadaers;IMAGE_DATA_DIRECTORYImageDataDirectory;PIMAGE_BASE_RELOCATIONpImageBaseRelocation;ULONGuRelocTableSize;ULONGuCount;ULONGuIndex;USHORT*pwOffsetAddress;USHORTuTypeValue;ULONGuRelocOffset;ULONGuRelocAddress;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 = pwOffsetAddress[uIndex];if ((uTypeValue >> 12) == IMAGE_REL_BASED_HIGHLOW){uRelocAddress = (uTypeValue & 0xfff) + pImageBaseRelocation->VirtualAddress + (ULONG)pNewImage;if (!MmIsAddressValid((PVOID)uRelocAddress)){continue;}*(PULONG)uRelocAddress += uRelocOffset;}}uRelocTableSize -= pImageBaseRelocation->SizeOfBlock;pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)((ULONG)pImageBaseRelocation + pImageBaseRelocation->SizeOfBlock);}}

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


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

0 0