想写一个读写ntoskrnl.exe恢复ssdt的函数。然后我觉得总用RvaToRawPointer...太麻烦了。。就像用MapViewOfSection(....SEC_IMAGE...);然后写成了。也能用。但是蓝屏之旅就开始了。大多数情况是异常是系统的某个模块读取某些内存的时候就到Kitrap0e了。。然后就bugcheck了。。而且这个模块不是特定的完全是看心情。下面贴代码。
NTSTATUS GrabSSDT(PCHAR pNtosBase)
{
PIMAGE_DOS_HEADER pDosH = (PIMAGE_DOS_HEADER)pNtosBase;
PIMAGE_NT_HEADERS pNtH;
PIMAGE_EXPORT_DIRECTORY pExport;
size_t i;
PDWORD pNameAddressArray, pAddress, pKiServiceTable = NULL;
PWORD pAddressOdinary;
PCHAR pName, pEntry;
DWORD ImageBase, dwRelCount;
PKSYSTEM_SERVICE_TABLE pReloadSSDT = NULL;
PWORD pRelRecord;
PIMAGE_BASE_RELOCATION pRelBase;
BOOL isFind = FALSE;
if(pNtosBase == 0)
{
return STATUS_UNSUCCESSFUL;
}
if(pDosH->e_magic != IMAGE_DOS_SIGNATURE)
{
return STATUS_UNSUCCESSFUL;
}
pNtH = (PIMAGE_NT_HEADERS)(pNtosBase + pDosH->e_lfanew);
if(pNtH->Signature != IMAGE_NT_SIGNATURE)
{
return STATUS_UNSUCCESSFUL;
}
ImageBase = pNtH->OptionalHeader.ImageBase;
pExport = (PIMAGE_EXPORT_DIRECTORY)(pNtosBase + pNtH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
if((ULONG)pExport == (ULONG)pNtosBase)
{
return STATUS_UNSUCCESSFUL;
}
pNameAddressArray = (PDWORD)(pNtosBase + pExport->AddressOfNames);
pAddressOdinary = (PWORD)(pNtosBase + pExport->AddressOfNameOrdinals);
pAddress = (PDWORD)(pNtosBase + pExport->AddressOfFunctions);
for(i = 0; i < pExport->NumberOfNames; i++)
{
pName = pNtosBase + pNameAddressArray[i];
if(_stricmp(SSDTNAME, pName) == 0)
{
pReloadSSDT = (PKSYSTEM_SERVICE_TABLE)(ImageBase + pAddress[pAddressOdinary[i] + pExport->Base - 1]);
break;
}
}
if(pReloadSSDT == NULL)
{
return STATUS_UNSUCCESSFUL;
}
OrigSSDTAddress = ExAllocatePoolWithTag(NonPagedPool, pReloadSSDT->NumberOfService * sizeof(PVOID), 'Bu4n');
if(OrigSSDTAddress == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//现在问题在这
//下面在重定位表中寻找搜索对KeServiceDescriptor的引用KiServiceTable
//pEntry = pNtosBase + pNtH->OptionalHeader.AddressOfEntryPoint;
pRelBase = (PIMAGE_BASE_RELOCATION)(pNtosBase + pNtH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
if(pNtH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0 || (ULONG)pRelBase == (ULONG)pNtosBase)
{
return STATUS_UNSUCCESSFUL;
}
while((ULONG)pRelBase < (ULONG)pNtosBase + pNtH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + pNtH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size && !isFind)
{
dwRelCount = (pRelBase->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
pRelRecord = (PWORD)((ULONG)pRelBase + sizeof(IMAGE_BASE_RELOCATION));
for(i = 0; i < dwRelCount; i++)
{
if((pRelRecord[i] & 0xf000) == 0)
{
continue;
}
if(*(PULONG)((pRelRecord[i] & 0x0fff) + pRelBase->VirtualAddress + pNtosBase) == (ULONG)pReloadSSDT)
{
if(*(PWORD)((pRelRecord[i] & 0xfff) + pRelBase->VirtualAddress + pNtosBase - 2) == 0x05c7)
{
pKiServiceTable = (PDWORD)*(PULONG)((pRelRecord[i] & 0xfff) + pRelBase->VirtualAddress + pNtosBase + 4);
isFind = TRUE;
break;
}
}
}
(ULONG)pRelBase += pRelBase->SizeOfBlock;
}
if(pKiServiceTable == NULL)
{
return STATUS_UNSUCCESSFUL;
}
RtlCopyMemory(OrigSSDTAddress, pKiServiceTable, KeServiceDescriptorTable->NumberOfService * sizeof(PVOID));
for(i = 0; i < KeServiceDescriptorTable->NumberOfService; i++)
{
OrigSSDTAddress[i] = OrigSSDTAddress[i] - ImageBase + g_UlNtOsKernelBase;
#if DEBUG
dprintf("0x%08x\r\n", OrigSSDTAddress[i]);
#endif
}
return STATUS_SUCCESS;
}
NTSTATUS ReLoadKernel(PUNICODE_STRING pUsKeFileName)
{
HANDLE hFile, hSection;
NTSTATUS status;
SIZE_T size = 0;
PVOID section;
OBJECT_ATTRIBUTES objAttr;
IO_STATUS_BLOCK IoStatus;
PVOID BaseAddress;
LARGE_INTEGER length;
FILE_STANDARD_INFORMATION fileInfo;
PCHAR ReLoadBaseAddress;
__try
{
InitializeObjectAttributes(&objAttr, pUsKeFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
status = IoCreateFile(&hFile, GENERIC_READ | GENERIC_WRITE, &objAttr, &IoStatus, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0, CreateFileTypeNone, 0, 0);
if (!NT_SUCCESS(status))
{
dprintf("Open Os Kernel Error\r\n");
return status;
}
length.QuadPart = 0;
status = MmCreateSection(§ion, SECTION_ALL_ACCESS, NULL, &length, PAGE_READWRITE, SEC_IMAGE, hFile, NULL);
if (!NT_SUCCESS(status))
{
ZwClose(hFile);
dprintf("Create kernel File Sction Failed\r\n");
return status;
}
//status = ObReferenceObjectByHandle(hSection, SECTION_ALL_ACCESS, *MmSectionObjectType, KernelMode, §ion, NULL);
//ZwClose(hSection);
if(!NT_SUCCESS(status))
{
return status;
}
ReLoadBaseAddress = 0;
length.QuadPart = 0;
size = 0;
status = MmMapViewOfSection(section, PsGetCurrentProcess(), &ReLoadBaseAddress, 0, 1024, &length, &size, 2, MEM_TOP_DOWN, PAGE_READWRITE);
if (!NT_SUCCESS(status))
{
ObDereferenceObject(section);
ZwClose(hFile);
dprintf("MapView For ReKernel Failed0x%08x\r\n", status);
return status;
}
status = GrabSSDT(ReLoadBaseAddress);
if (!NT_SUCCESS(status))
{
dprintf("Grab SSDT Kernel File Failed\r\n");
return status;
}
status = MmUnmapViewOfSection(PsGetCurrentProcess(), ReLoadBaseAddress);
if(!NT_SUCCESS(status))
{
dprintf("UnMapViewFailed 0x%08x\r\n", status);
return STATUS_SUCCESS;
}
ObDereferenceObject(section);
ZwClose(hFile);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
dprintf("Exception occured in ReloadKernel Func\r\n");
}
return STATUS_SUCCESS;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)