首页
社区
课程
招聘
[原创]Windows内存篇Ⅱ x64内核内存布局的迁移演变
发表于: 2020-10-25 05:52 17477

[原创]Windows内存篇Ⅱ x64内核内存布局的迁移演变

2020-10-25 05:52
17477

内存扫描一直都是比较根本的威胁检测手法,对于顽固型木马外挂而言,依赖于操作系统API相关的传统检测方式,模块扫描,窗口扫描,进程扫描以及文件扫描等都显得较为吃力,应用层而言如此,到内核层亦是如此。对于x86内核而言,0x80000000~0xFFFFFFFF 2GB内存扫描检测不是什么难事,因为整个区域就这么大。但是对于x64内核空间而言,就没有这么简单,尽管64位地址高16位一直都是保留字节0xffff,48位地址虚拟内存总量也大的有些离谱。或许有人会说物理内存就这么大,现在见的比较大的是16GB、32GB内存条,直接扫描物理内存不就好了。起初我也这么想,但是最主要的是要访问物理内存本质上需要通过虚拟内存经过页表转换到MMU单元才能完成对物理页的访问,而且抛开这个层面,尽管可以直接访问物理内存最终我们也是需要转为虚拟内存地址。那么本篇就来探索下从Win7开始到Win10 x64内核的虚拟地址空间布局以及经历了哪些更新变化。

黑暗之门

WIN7相关资料也比较多,WIN8总体上与WIN7很像,就放在一起介绍了。推荐下面两篇文章

原文版本Kernel Virtual Address Layout
翻译版本内核虚拟地址空间布局

引用下这张图

那我们看看怎么获取MmNonPagedPoolStart与MmNonpagedPoolEnd吧:
固定思路先从MiInitializeNonPagedPool函数找到未导出变量MmNonPagedPoolStart,发现他在MiCreatePfnDatabase里初始化
图片描述

自己算不太现实,有几个因子也不好确定。查看MmNonpagedPool的引用发现数据段上有个引用:
图片描述

最上面有个KdDebuggerDataBlock好像跟调试有关,发现导出函数KeCapturePersistentThreadState有用到这个,记得Blackbone有用到这个函数,可以获取一堆未导出变量地址

dumpHeader->KdDebuggerDataBlock就是KdDebuggerDataBlock地址,另外在0x2080偏移处还有另外一份Copy

那么拿到内存区域,就可以扫描一些自己想要的东西了,我最想扫的就是PG代码了...... 也可以扫隐藏驱动,隐藏进程
这里实际的应用我就不再做阐述了,简单的做个验证吧,找了几种可以在内核申请内存的方式:

图片描述

可以得出
MmMapViewInSystemSpace是直接映射到System Ptes区域,与驱动映像属于同一块区域;
MDL申请出来的虚拟内存也是在System Ptes区域;
MmAllocateContiguousMemory申请的连续非分页物理内存 对应的虚拟内存空间 也是在SystemPtes区域。

说起这个阶段,印象最为深刻的就是这两个函数了
MiInitializeDynamicRegion 与 MiInitializeDynamicBitmap

MiInitializeDynamicRegion看着就以为好多区域都动态了,不再静态了,实际上呢?
图片描述
图片描述
图片描述

就拿这三个区域说事,唬人还是巨硬强。
不过 引入的这两个结构管理内存区域,算是很值得称赞的,内存块全部用Bitmap管理,优化了性能(_MI_DYNAMIC_BITMAP Win8.1没有符号)

其实比较难找的还是NonPagePool区域,因为从Win8.1开始,KdDebuggerDataBlock就不再导出MmNonPagedPoolStart内核变量了,再来Win8.1开始就直接去掉了MmNonPagedPoolStart变量...真令人发指!

跟进去MiInitializeNonpagedPool函数看看,由于Win8.1结构体没符号,拿10240作为样例分析
图片描述

这个qword_140340930原名叫做MiNodeInformation,Win10把这个变量符号拿掉了。
这个函数其实是对 0x100000000000 大小的NonpagedPool内存进行等分(份数就是KeNumberNodes的值,这个值是干什么的呢?目前我还没搞懂)
那么NonpagedPool基地址是多少呢? 是 ((0x8000000 / KeNumberNodes) << 9 * Index - 0x2000000000) << 12 (Release版本优化才会这么难看)
其实地址就是 Index 为0的时候,正好是 0xFFFFE000`00000000

整理之后,得到

看看Win8.1 测试结果
图片描述

结果有些不一样,MmMapViewInSystemSpace映射的地址空间在DriverImage,而MDL与连续的物理页面映射的虚拟地址都在SystemPtes
其实从Win8.1开始,DriverImage不再纳入System Ptes空间,而是归入Initial Loader Mapping区域,统一改名为DriverImage,MapViewOfSection这种方式就会在DriverImage中申请虚拟内存空间

要是说Win8.1与早期的Win10版本没有真正意义上的内存布局动态化的话,那么Win10RS1以后的就是真正的动态化了,这个动态化从调试来看不是nt内部做的初始化,是更上一层,推测应该是Hal或者是Hyper-V进行的初始化布局。

之前研究过这篇文章 Win10 1909 反向计算windows内核内存布局及代码实现 知道了内核有个0x100大小的Mark标记数组,可以通过数组计算每个区域的具体位置,可惜的是到Win10 2004就已经找不到Mark的踪迹了。

观前顾后,我找到了MiQuerySystembase函数用到的一个未导出变量
图片描述

我是怎么找到他的呢?很简单,还是看的MiInitializeNonpagedPool,发现用了这个数组的0号成员,很明显这个数组就是存放各种区域的地址范围的,并且Nt初始化时这个数组也早已被初始化了
图片描述

通过一些猜测与符号的查找,发现这个数组结构体以及宏定义如下

在NT内核初始化时,会将Assignment数组里的地址范围全部应用到系统中。
那么找这个数组就用MiQuerySytemBase的特征码就行了。

不过...
最让人头疼的事情 是...

尽管8号之前没什么变化,但是后面序号一直在变,也不知道微软程序员抽了什么风...
最后看下Win10的测试结果吧,由于序号变得快,调试信息有不准的地方我也没做修改了...

图片描述
结论还是与Win8.1一致,MmMapViewInSystemSpace映射在DriverImage区域,MDL与连续物理页的虚拟页映射在SystemPtes区域。

五点了,睡觉睡觉!

 
 
 
 
 
 
#ifndef _WIN64
#define DUMP_BLOCK_SIZE        0x20000
#else
#define DUMP_BLOCK_SIZE        0x40000
#endif
 
#ifndef _WIN64
#define KDDEBUGGER_DATA_OFFSET 0x1068
#else
#define KDDEBUGGER_DATA_OFFSET 0x2080
#endif
 
 
VOID InitializeDebuggerBlock()
{
    CONTEXT context = { 0 };
    context.ContextFlags = CONTEXT_FULL;
    RtlCaptureContext(&context);
 
    PDUMP_HEADER dumpHeader = (PDUMP_HEADER)ExAllocatePoolWithTag(NonPagedPool, DUMP_BLOCK_SIZE, MMS_POOL_TAG);
    if (dumpHeader)
    {
        KeCapturePersistentThreadState(&context, NULL, 0, 0, 0, 0, 0, dumpHeader);
 
        g_KdDebuggerDataBlock = dumpHeader->KdDebuggerDataBlock;
        RtlCopyMemory(&g_KdBlock, (PUCHAR)dumpHeader + KDDEBUGGER_DATA_OFFSET, sizeof(g_KdBlock));
 
        ExFreePool(dumpHeader);
    }
}
#ifndef _WIN64
#define DUMP_BLOCK_SIZE        0x20000
#else
#define DUMP_BLOCK_SIZE        0x40000
#endif
 
#ifndef _WIN64
#define KDDEBUGGER_DATA_OFFSET 0x1068
#else
#define KDDEBUGGER_DATA_OFFSET 0x2080
#endif
 
 
VOID InitializeDebuggerBlock()
{
    CONTEXT context = { 0 };
    context.ContextFlags = CONTEXT_FULL;
    RtlCaptureContext(&context);
 
    PDUMP_HEADER dumpHeader = (PDUMP_HEADER)ExAllocatePoolWithTag(NonPagedPool, DUMP_BLOCK_SIZE, MMS_POOL_TAG);
    if (dumpHeader)
    {
        KeCapturePersistentThreadState(&context, NULL, 0, 0, 0, 0, 0, dumpHeader);
 
        g_KdDebuggerDataBlock = dumpHeader->KdDebuggerDataBlock;
        RtlCopyMemory(&g_KdBlock, (PUCHAR)dumpHeader + KDDEBUGGER_DATA_OFFSET, sizeof(g_KdBlock));
 
        ExFreePool(dumpHeader);
    }
}
 
VOID MmsTestAllocateMemory()
{
    MmsTestAllocatePagedPoolMemory();
    MmsTestAllocateNonPagedPoolMemory();
    MmsTestMapViewInSystemSpace();
    MmsTestAllocateMDLMemory();
    MmsTestAllocateContiguousMemory();
}
VOID MmsTestAllocateMemory()
{
    MmsTestAllocatePagedPoolMemory();
    MmsTestAllocateNonPagedPoolMemory();
    MmsTestMapViewInSystemSpace();
    MmsTestAllocateMDLMemory();
    MmsTestAllocateContiguousMemory();
}
 
 
 
 
//0x68 bytes (sizeof)
struct _MI_SYSTEM_PTE_TYPE
{
    struct _RTL_BITMAP_EX Bitmap;                                           //0x0
    struct _MMPTE* BasePte;                                                 //0x10
    ULONG Flags;                                                            //0x18
    enum _MI_SYSTEM_VA_TYPE VaType;                                         //0x1c
    ULONG* FailureCount;                                                    //0x20
    ULONG PteFailures;                                                      //0x28
    union
    {
        ULONGLONG SpinLock;                                                 //0x30
        struct _FAST_MUTEX* GlobalMutex;                                    //0x30
    };
    struct _MMSUPPORT* Vm;                                                  //0x38
    volatile ULONGLONG TotalSystemPtes;                                     //0x40
    ULONGLONG Hint;                                                         //0x48
    struct _MI_CACHED_PTE* CachedPtes;                                      //0x50
    volatile ULONGLONG TotalFreeSystemPtes;                                 //0x58
    volatile LONG CachedPteCount;                                           //0x60
};
 
//0x50 bytes (sizeof)
struct _MI_DYNAMIC_BITMAP
{
    struct _RTL_BITMAP_EX Bitmap;                                           //0x0
    ULONGLONG MaximumSize;                                                  //0x10
    ULONGLONG Hint;                                                         //0x18
    VOID* BaseVa;                                                           //0x20
    ULONGLONG SizeTopDown;                                                  //0x28
    ULONGLONG HintTopDown;                                                  //0x30
    VOID* BaseVaTopDown;                                                    //0x38
    ULONGLONG SpinLock;                                                     //0x40
    struct _MMSUPPORT* Vm;                                                  //0x48
};
//0x68 bytes (sizeof)
struct _MI_SYSTEM_PTE_TYPE
{
    struct _RTL_BITMAP_EX Bitmap;                                           //0x0
    struct _MMPTE* BasePte;                                                 //0x10
    ULONG Flags;                                                            //0x18
    enum _MI_SYSTEM_VA_TYPE VaType;                                         //0x1c
    ULONG* FailureCount;                                                    //0x20
    ULONG PteFailures;                                                      //0x28
    union
    {
        ULONGLONG SpinLock;                                                 //0x30
        struct _FAST_MUTEX* GlobalMutex;                                    //0x30
    };
    struct _MMSUPPORT* Vm;                                                  //0x38
    volatile ULONGLONG TotalSystemPtes;                                     //0x40
    ULONGLONG Hint;                                                         //0x48
    struct _MI_CACHED_PTE* CachedPtes;                                      //0x50
    volatile ULONGLONG TotalFreeSystemPtes;                                 //0x58
    volatile LONG CachedPteCount;                                           //0x60
};
 
//0x50 bytes (sizeof)
struct _MI_DYNAMIC_BITMAP
{
    struct _RTL_BITMAP_EX Bitmap;                                           //0x0
    ULONGLONG MaximumSize;                                                  //0x10
    ULONGLONG Hint;                                                         //0x18
    VOID* BaseVa;                                                           //0x20
    ULONGLONG SizeTopDown;                                                  //0x28
    ULONGLONG HintTopDown;                                                  //0x30
    VOID* BaseVaTopDown;                                                    //0x38
    ULONGLONG SpinLock;                                                     //0x40
    struct _MMSUPPORT* Vm;                                                  //0x48
};
 
 
 
NTSTATUS MmsInitMemoryLayoutForWin8_1ToWin10TH2(IN OUT PDYNAMIC_DATA pData)
{
    if (!pData)
    {
        return STATUS_INVALID_ADDRESS;
    }
 
    pData->MmPteSpaceStart = (PVOID)0xFFFFF68000000000;
    pData->MmPteSpacecEnd  = (PVOID)0xFFFFF6FFFFFFFFFF;
 
    pData->MmHyperSpaceStart = (PVOID)0xFFFFF70000000000;
    pData->MmHyperSpaceEnd   = (PVOID)0xFFFFF77FFFFFFFFF;
 
    pData->MmSharedSystemPageStart = (PVOID)0xFFFFF78000000000;
    pData->MmSharedSystemPageEnd   = (PVOID)0xFFFFF78000000FFF;
 
    pData->MmSystemCacheStart = (PVOID)0xFFFFB00000000000;
    pData->MmSystemCacheEnd   = (PVOID)0xFFFFBFFFFFFFFFFF;
 
    pData->MmPagedPoolStart = (PVOID)0xFFFFC00000000000;
    pData->MmPagedPoolEnd   = (PVOID)0xFFFFCF7FFFFFFFFF;
 
    pData->MmSpecialPoolStart = (PVOID)0xFFFFCF8000000000;
    pData->MmSpecialPoolEnd   = (PVOID)0xFFFFCFFFFFFFFFFF;
 
    pData->MmSystemPtesStart = (PVOID)0xFFFFD00000000000;
    pData->MmSystemPtesEnd   = (PVOID)0xFFFFDFFFFFFFFFFF;
 
    pData->MmNonpagedPoolStart = (PVOID)0xFFFFE00000000000;
    pData->MmNonpagedPoolEnd   = (PVOID)0xFFFFF00000000000;//等分成KeNumberNodes块
 
    pData->MmDriverImageStart = (PVOID)0xFFFFF80000000000;
    pData->MmDriverImageEnd   = (PVOID)0xFFFFF87FFFFFFFFF;
 
    pData->MmSessionSpaceStart = (PVOID)0xFFFFF90000000000;
    pData->MmSessionSpaceEnd   = (PVOID)0xFFFFF97FFFFFFFFF;
 
    pData->MmDynamicVASpaceStart = (PVOID)0xFFFFF98000000000;
    pData->MmDynamicVASpaceEnd   = (PVOID)0xFFFFFA70FFFFFFFF;
 
    pData->MmPfnDatabaseStart = (PVOID)0xFFFFFA8000000000;
    pData->MmPfnDatabaseEnd   = (PVOID)((ULONG_PTR)pData->MmNonpagedPoolStart - 1);
 
    return STATUS_SUCCESS;
}
NTSTATUS MmsInitMemoryLayoutForWin8_1ToWin10TH2(IN OUT PDYNAMIC_DATA pData)
{
    if (!pData)
    {
        return STATUS_INVALID_ADDRESS;
    }
 
    pData->MmPteSpaceStart = (PVOID)0xFFFFF68000000000;
    pData->MmPteSpacecEnd  = (PVOID)0xFFFFF6FFFFFFFFFF;
 
    pData->MmHyperSpaceStart = (PVOID)0xFFFFF70000000000;
    pData->MmHyperSpaceEnd   = (PVOID)0xFFFFF77FFFFFFFFF;
 
    pData->MmSharedSystemPageStart = (PVOID)0xFFFFF78000000000;
    pData->MmSharedSystemPageEnd   = (PVOID)0xFFFFF78000000FFF;
 
    pData->MmSystemCacheStart = (PVOID)0xFFFFB00000000000;
    pData->MmSystemCacheEnd   = (PVOID)0xFFFFBFFFFFFFFFFF;
 
    pData->MmPagedPoolStart = (PVOID)0xFFFFC00000000000;
    pData->MmPagedPoolEnd   = (PVOID)0xFFFFCF7FFFFFFFFF;
 
    pData->MmSpecialPoolStart = (PVOID)0xFFFFCF8000000000;
    pData->MmSpecialPoolEnd   = (PVOID)0xFFFFCFFFFFFFFFFF;
 
    pData->MmSystemPtesStart = (PVOID)0xFFFFD00000000000;
    pData->MmSystemPtesEnd   = (PVOID)0xFFFFDFFFFFFFFFFF;
 
    pData->MmNonpagedPoolStart = (PVOID)0xFFFFE00000000000;
    pData->MmNonpagedPoolEnd   = (PVOID)0xFFFFF00000000000;//等分成KeNumberNodes块
 
    pData->MmDriverImageStart = (PVOID)0xFFFFF80000000000;
    pData->MmDriverImageEnd   = (PVOID)0xFFFFF87FFFFFFFFF;
 
    pData->MmSessionSpaceStart = (PVOID)0xFFFFF90000000000;
    pData->MmSessionSpaceEnd   = (PVOID)0xFFFFF97FFFFFFFFF;
 
    pData->MmDynamicVASpaceStart = (PVOID)0xFFFFF98000000000;
    pData->MmDynamicVASpaceEnd   = (PVOID)0xFFFFFA70FFFFFFFF;
 
    pData->MmPfnDatabaseStart = (PVOID)0xFFFFFA8000000000;
    pData->MmPfnDatabaseEnd   = (PVOID)((ULONG_PTR)pData->MmNonpagedPoolStart - 1);
 
    return STATUS_SUCCESS;
}
 
 
 
 
 
 
enum _MI_ASSIGNED_REGION_TYPES
{
    AssignedRegionNonPagedPool = 0,
    AssignedRegionPagedPool = 1,
    AssignedRegionSystemCache = 2,
    AssignedRegionSystemPtes = 3,
    AssignedRegionUltraZero = 4,
    AssignedRegionPfnDatabase = 5,
    AssignedRegionCfg = 6,
    AssignedRegionHyperSpace = 7,
    AssignedRegionKernelStacks = 8,
    AssignedRegionPageTables = 9,
    AssignedRegionSession = 10,
    AssignedRegionSecureNonPagedPool = 11,
    AssignedRegionSystemImages = 12,
    AssignedRegionMaximum = 13
};
 
typedef struct _MI_SYSTEM_VA_ASSIGNMENT
{
    VOID* BaseAddress;                                                      //0x0
    ULONGLONG NumberOfBytes;                                                //0x8
} MI_SYSTEM_VA_ASSIGNMENT, * PMI_SYSTEM_VA_ASSIGNMENT;
enum _MI_ASSIGNED_REGION_TYPES
{
    AssignedRegionNonPagedPool = 0,
    AssignedRegionPagedPool = 1,
    AssignedRegionSystemCache = 2,
    AssignedRegionSystemPtes = 3,
    AssignedRegionUltraZero = 4,
    AssignedRegionPfnDatabase = 5,
    AssignedRegionCfg = 6,
    AssignedRegionHyperSpace = 7,
    AssignedRegionKernelStacks = 8,
    AssignedRegionPageTables = 9,
    AssignedRegionSession = 10,
    AssignedRegionSecureNonPagedPool = 11,
    AssignedRegionSystemImages = 12,
    AssignedRegionMaximum = 13
};
 
typedef struct _MI_SYSTEM_VA_ASSIGNMENT
{
    VOID* BaseAddress;                                                      //0x0
    ULONGLONG NumberOfBytes;                                                //0x8
} MI_SYSTEM_VA_ASSIGNMENT, * PMI_SYSTEM_VA_ASSIGNMENT;

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-10-25 10:54 被FaEry编辑 ,原因:
收藏
免费 16
支持
分享
最新回复 (18)
雪    币: 2278
活跃值: (12799)
能力值: ( LV12,RANK:312 )
在线值:
发帖
回帖
粉丝
2
2020-10-25 07:59
0
雪    币: 12512
活跃值: (6019)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3

win10的nonpagedpool大小应该不是巨硬pdb所说的0x100000000000,实测在这个区域搜DriverObject只能搜出零星的几个,巨硬大概率在内存管理函数里面多做了一些手脚。
另外对于其他内存区域,想暴力搜必须考虑Transition Prototype PageFile这三种情况,Win8.1+有MmCopyMemory,但是实现复杂,很难移植到Win8及以下

最后于 2020-10-25 10:53 被hhkqqs编辑 ,原因:
2020-10-25 10:51
0
雪    币: 5039
活跃值: (2646)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
4
hhkqqs win10的nonpagedpool大小应该不是巨硬pdb所说的0x100000000000,实测在这个区域搜DriverObject只能搜出零星的几个,巨硬大概率在内存管理函数里面多做了一些手脚。另 ...
为啥我搜出来好多DriverObject
2020-10-25 10:53
0
雪    币: 12512
活跃值: (6019)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
FaEry 为啥我搜出来好多DriverObject
我在windbg用!poolfind Driv 只搜到零星的几个,非常奇怪,我看了眼IoDriverObjectType上面登记的个数可是一百多个
2020-10-25 10:57
0
雪    币: 3785
活跃值: (3947)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
666,感谢分享!
2020-10-25 11:03
0
雪    币: 5039
活跃值: (2646)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
7
hhkqqs 我在windbg用!poolfind Driv 只搜到零星的几个,非常奇怪,我看了眼IoDriverObjectType上面登记的个数可是一百多个

Show you my code,I don't believe windbg in some situation..


VOID EnumDriverByDriverObjectMemory()
{
    PVOID                    lpStartAddr = NULL;
    SIZE_T                   ulSize = 0;
    UNICODE_STRING           uniFuncName = { 0 };
    ULONG_PTR                lpSearchAddr = 0;
    ULONG_PTR                lpEndAddr = 0;
    ULONG                    ulEntrySize = 0;
    ULONG                    ulRemainSize = 0;
    ULONG_PTR                pDriverObject = 0;
    NTSTATUS                 status = STATUS_SUCCESS;
    PLDR_DATA_TABLE_ENTRY    pLdr = NULL;

    if (!g_ObGetObjectType)
    {
        RtlInitUnicodeString(&uniFuncName, L"ObGetObjectType");
        g_ObGetObjectType = (pfnObGetObjectType)MmGetSystemRoutineAddress(&uniFuncName);
    }

    if (g_BuildNumber >= 7600)
    {
        lpStartAddr = g_DriverObject; // 用自己的DriverObject就好,没必要全盘搜NonpagedPool
        lpStartAddr = (PVOID)((ULONG_PTR)lpStartAddr & 0xFFFFFFFF00000000);
        ulSize = 0x300000000;
    }
    else
    {
        return;
    }

    lpSearchAddr = (ULONG_PTR)lpStartAddr;
    lpEndAddr = lpSearchAddr + ulSize - sizeof(DRIVER_OBJECT);

    KdPrint(("[%s] lpSearchAddr:%p lpEndAddr:%p\n", __FUNCTION__, lpSearchAddr, lpEndAddr));

    while (TRUE)
    {
        if (lpSearchAddr + PAGE_SIZE > lpEndAddr)
        {
            ulEntrySize = (ULONG)(lpEndAddr - lpSearchAddr);
        }
        else
        {
            ulEntrySize = PAGE_SIZE;
        }

        if (!IsAddressValidLength((PVOID)lpSearchAddr, ulEntrySize))
        {
            goto NextLoop;
        }

        pDriverObject = lpSearchAddr + 0x30;
        ulRemainSize = 0x30;

        while (ulRemainSize < ulEntrySize)
        {
            POBJECT_TYPE ObjectType = KeGetObjectType((PVOID)pDriverObject);
            if (ObjectType == *IoDriverObjectType)
            {
                if (IsRealDriverObject((PDRIVER_OBJECT)pDriverObject)) // 一堆校验
                {
                    pLdr = (PLDR_DATA_TABLE_ENTRY)(((PDRIVER_OBJECT)pDriverObject)->DriverSection);
                    KdPrint(("[%s] pDriverObject:%p FullName:%wZ, DllBase:%I64x, Size:%x\n", __FUNCTION__, pDriverObject, &pLdr->FullDllName, pLdr->DllBase, pLdr->SizeOfImage));
                }

                ulRemainSize += sizeof(DRIVER_OBJECT);
                pDriverObject += sizeof(DRIVER_OBJECT);
            }
            else
            {
                ulRemainSize += 8;
                pDriverObject += 8;
            }
        }

    NextLoop:
        lpSearchAddr += PAGE_SIZE;
        if (lpSearchAddr >= lpEndAddr)
        {
            break;
        }
    }
}

最后于 2020-10-25 11:17 被FaEry编辑 ,原因:
2020-10-25 11:04
0
雪    币: 12512
活跃值: (6019)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
FaEry hhkqqs 我在windbg用!poolfind Driv 只搜到零星的几个,非常奇怪,我看了眼IoDriverObjectType上面登记的个数可是一百多个 ...
windbg这个poolfind的指令在6.x版本下能正常用,到了10.0版本不知道为啥少了好多信息。我用特征码的方法找了一遍,基本能全找出来,首先找ULONG_PTR PoolHeader,使得*(PULONGLONG)PoolHeader & 0x7FFFFFFFFF000000 == 0x7669724402000000。进一步判断(*(PULONGLONG)(PoolHeader + 0x10) == DriverObjectDirectory || *(PULONGLONG)(PoolHeader + 0x10) == FileSystemDirectory) && *(PULONGLONG)(PoolHeader + 0x60) == 0x1500004,基本能确定是一个驱动,然后PoolHeader += (((PPOOL_HEADER)PoolHeader)->BlockSize << 4)继续扫下去,兼容Vista SP0。你代码用到的ObGetObjectType不兼容Vista。
2020-10-25 17:40
0
雪    币: 5039
活跃值: (2646)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
9
hhkqqs windbg这个poolfind的指令在6.x版本下能正常用,到了10.0版本不知道为啥少了好多信息。我用特征码的方法找了一遍,基本能全找出来,首先找ULONG_PTR PoolHeader,使得*( ...
对,win10windbg有点问题所以不太信他的处理结果,用poolheader比较舒服,小内存都能按tag找,头+0xC就是DriverObject了,没做vista xp的兼容了
2020-10-25 18:07
0
雪    币: 12512
活跃值: (6019)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
FaEry 对,win10windbg有点问题所以不太信他的处理结果,用poolheader比较舒服,小内存都能按tag找,头+0xC就是DriverObject了,没做vista xp的兼容了
搜poolheader虽然流程简单点,直接暴力搜效率还是比较慢的,我看了篇论文,说定位PhysicalMemoryBackupPool的Bitmap可以筛掉很多无效页面,但也要符号或特征码定位
2020-10-25 18:49
0
雪    币: 5039
活跃值: (2646)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
11
hhkqqs 搜poolheader虽然流程简单点,直接暴力搜效率还是比较慢的,我看了篇论文,说定位PhysicalMemoryBackupPool的Bitmap可以筛掉很多无效页面,但也要符号或特征码定位[em_ ...
找到进bitmap的锁就可以了,目前这种方式最大的问题是访问内存时如果在MmIsAddressValid调用完内存被释放了就有蓝屏风险,lock内存也没用,lock了别人调用ExFreePool发现内存引用不为零也会KeBugCheck蓝屏。蓝瘦
2020-10-25 19:23
0
雪    币: 12512
活跃值: (6019)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
12
FaEry 找到进bitmap的锁就可以了,目前这种方式最大的问题是访问内存时如果在MmIsAddressValid调用完内存被释放了就有蓝屏风险,lock内存也没用,lock了别人调用ExFreePool发现内 ...
毕竟是非分页内存,我一般拉高IRQL防止被切换,当然如果对方的代码也在DPC_LEVEL,照样防不住
2020-10-25 22:00
0
雪    币: 5039
活跃值: (2646)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
13
hhkqqs 毕竟是非分页内存,我一般拉高IRQL防止被切换,当然如果对方的代码也在DPC_LEVEL,照样防不住[em_10]
哈哈,锁死其他核心,当前核心不允许线程切换就可以了
2020-10-26 00:05
0
雪    币: 1129
活跃值: (2901)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
感谢分享,牛逼
2020-10-26 21:14
0
雪    币: 919
活跃值: (1340)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
15
请问一下,MmNonPagedPoolStart不应该是在MiInitMachineDependent函数中动态计算出来的吗?
2020-11-25 16:50
0
雪    币: 5039
活跃值: (2646)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
16
丿一叶知秋 请问一下,MmNonPagedPoolStart不应该是在MiInitMachineDependent函数中动态计算出来的吗?
MmNonPagedPoolStart应该是在MmPfnDataBase后面,计算出来的
2021-1-4 21:01
0
雪    币: 919
活跃值: (1340)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
17
FaEry MmNonPagedPoolStart应该是在MmPfnDataBase后面,计算出来的
可能小弟看记错了吧,我大概记得我在看MiInitMachineDependent的时候,MmNonPagedPoolStart是固定的点(xp),然后后面根据注册表,物理内存的大小都划分虚拟空间,最后才建立的MmPfnDataBase的虚拟空间,从而挂上物理页。 
2021-1-6 16:17
0
雪    币: 20
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
贴主   请看下私信
2021-7-15 23:10
0
雪    币: 519
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
请问有关于32位的内核布局吗?
2022-8-23 16:30
0
游客
登录 | 注册 方可回帖
返回
//