首页
社区
课程
招聘
[求助]弄读取ntoskrnl.exe恢复ssdt时本来想偷个懒。。结果蓝屏无数次。。发帖求助一下。。
发表于: 2013-5-5 15:33 8762

[求助]弄读取ntoskrnl.exe恢复ssdt时本来想偷个懒。。结果蓝屏无数次。。发帖求助一下。。

2013-5-5 15:33
8762
想写一个读写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期)

收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 84
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
发出来看着有点长。。我还是稍微加两句注释。。
其实就是
IoCreateFile
MmCreateSection
MmMapViewOfSection
解析Ntoskrnrl.exe的导出表获取KeServiceDescriptor的地址
然后从ntoskrnl.exe的重定位表中搜索用到这个地址的代码,从而获得_KiSystemTable
然后就RtlCopyMemory()把KiSystemTable的内容保存在我申请的NonPagedPool中。。。
然后还有人可能会说。。让我用ZwXxx函数。。我用了差不多的参数改成了ZwXxx还是蓝屏。。。情况没有改变。。我觉得。。应该是我的参数传递的有问题。。但是。。改来改去。。还是蓝。。
2013-5-5 15:38
0
雪    币: 45
活跃值: (55)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
问下楼主 SSDT HOOK 注入这类的东西在哪些书学的?
2013-5-5 15:46
0
雪    币: 84
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
各种书。。。太多了每本讲内核安全的书都提到了。。还有看雪有个Rootkit专题。。。介绍了各种Hook。。
2013-5-5 15:50
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
申请空间。。把map的内存复制到申请的空间里面。。。然后再搜索。。。。。。
2013-5-5 16:28
0
雪    币: 84
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
用了。。你说的办法。。立刻好了。。不知道有没有时间。。跟我稍微说一下这是为什么。。我想搞明白。。以后不再这么蛋疼。。。看来这个内核的section跟用户的map。。差别还是很大的啊
2013-5-5 17:58
0
雪    币: 84
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
测试了一下午。。灰常的稳定啊。。看来就是这个原因。。。谢谢。。
2013-5-5 19:37
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
2013-5-5 21:12
0
雪    币: 15
活跃值: (40)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
这两天我也在弄这个。看到别人说了,顺便给你回一句。

蓝屏的原因是,你搜索的时候内核中的一些INIT的内存在用完之后,已经交换出去了??(好像是这样吧,我刚学,小白一个)然后,在你读取的时候,就会发生缺页异常。

所以你读取的时候就bsod了。
2013-7-14 23:11
0
雪    币: 220
活跃值: (117)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
二楼已经说了


NonPagedPool
2013-7-15 13:49
0
雪    币: 84
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
听着很有道理。谢了。
2013-7-16 19:52
0
雪    币: 84
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
12
你楼上的意思是。。Map的ntoskrnl..因为ntoskrnl里有INIT节的内存。。也许会在Map以后换出。。唉。。这个问题。很头疼。。也不好调试。。只能差不都懂个大概。现在也说不好是不是这个原因。好在这个Map以后拷贝出来的解决方案可以完美解决这个问题。。
2013-7-16 19:54
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
13
9楼正解,内存被交换出去了,你读到的内存就会触发缺页异常,
就算你使用 try 来捕获异常也没用,照样蓝屏.
2013-7-16 20:29
0
游客
登录 | 注册 方可回帖
返回
//