在minifilter回调函数期间回溯线程的用户模式堆栈

时间:2014-03-31 23:44:06

标签: driver minifilter windows-kernel

我试图在minifilter回调函数中回溯一个线程的usermode堆栈。
假设我和调用线程处于相同的上下文中,从它的TEB / TIB获取线程堆栈地址并处理该堆栈上的地址应该允许我回溯它的堆栈。

由于我收到的地址不是调用系统调用的预期用户模式模块, 我一定有些不对劲。

如果你能指出我正确的方向,我会很高兴的。

提前致谢。


以下是读取堆栈内容的代码:

    pTEB = (PVOID *)((char *)pThread + 0x20);

    // Read TIB
    pTib = (NT_TIB*)pTEB;
    stackBottom = (PVOID*)pTib->StackLimit;
    stackTop = (PVOID*)pTib->StackBase;

    LogDbgView(("stackBottom=%p,  stackTop=%p",stackBottom, stackTop));

    if (!MyReadMemory(IoGetCurrentProcess(), stackBottom, buf, stackTop-stackBottom))
    {
        LogDbgView(("Read Memory = %x",buf));
        LogDbgView(("Read Memory = %x",buf+8));
        LogDbgView(("Read Memory = %x",buf+16));
        LogDbgView(("Read Memory = %x",buf+24));
    }

以下是获取模块名称和地址的函数:

    PVOID LoadModulesInformation()
    {
        PVOID pSystemInfoBuffer = NULL;

     __try
        {
            NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
            ULONG    SystemInfoBufferSize = 0;

            status = ZwQuerySystemInformation(SystemModuleInformation,
                &SystemInfoBufferSize,
                0,
                &SystemInfoBufferSize);

            if (!SystemInfoBufferSize)
                return NULL;

            pSystemInfoBuffer = (PVOID)ExAllocatePool(NonPagedPool, SystemInfoBufferSize*2);

            if (!pSystemInfoBuffer)
                return NULL;

            memset(pSystemInfoBuffer, 0, SystemInfoBufferSize*2);

            status = ZwQuerySystemInformation(SystemModuleInformation,
                pSystemInfoBuffer,
                SystemInfoBufferSize*2,
                &SystemInfoBufferSize);

            if (NT_SUCCESS(status))
            {
                return pSystemInfoBuffer;
            }

        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
        }

        return NULL;
    }


    PUNICODE_STRING findModuleName(PVOID addr, PVOID pSystemInfoBuffer, ULONG Tag FILE_AND_LINE_ARGS)
    {
        PVOID pModuleBase = NULL;
        PCHAR pCharRet=NULL;
        PUNICODE_STRING pus = NULL;

        __try
        {
            if (pSystemInfoBuffer != NULL && MmIsAddressValid(addr))
            {
                PSYSTEM_MODULE_ENTRY pSysModuleEntry = ((PSYSTEM_MODULE_INFORMATION)(pSystemInfoBuffer))->Module;
                ULONG i;

                for (i = 0; i <((PSYSTEM_MODULE_INFORMATION)(pSystemInfoBuffer))->Count; i++)
                {
                    if ((pSysModuleEntry[i].Base <= addr) && (pSysModuleEntry[i].Size < ((ULONG)addr - (ULONG)pSysModuleEntry[i].Base)))
                    {
                        pCharRet = pSysModuleEntry[i].ImageName+pSysModuleEntry[i].PathLength;
                        break;
                    }
                }
            }
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
            pCharRet = NULL;
        }

        if (pCharRet)
        {
            pus = UtlpCharToUnicode(pCharRet, TRUE, TRUE, Tag FILE_AND_LINE_PARAMS);
        }
        else
        {
            pus = UtlpCharToUnicode("UNKNOWN", TRUE, TRUE, Tag FILE_AND_LINE_PARAMS);
        }

        return pus;
    }

1 个答案:

答案 0 :(得分:0)

  

pTEB =(PVOID *)((char *)pThread + 0x20);

即使在PoC中,也不要这样做。结构布局不时变化。您可以使用PsGetProcessPeb(请参阅此处https://code.google.com/p/arkitlib/source/browse/trunk/ARKitDrv/Ps.c

  

LogDbgView((&#34;读取内存=%x&#34;,buf));

你不在buf地址读取内存,而是读取buf的值。在C中,您必须取消引用指针以从那里读取内存。喜欢这个

LogDbgView((&#34;读取内存=%x&#34;,(PVOID)* buf));

  

LogDbgView((&#34;读取内存=%x&#34;,buf + 8));

为了能够为x86和x64编译,你必须避免这样的事情。相反,使用sizeof(PVOID):

LogDbgView((&#34;读取内存=%x&#34;,(PVOID)*(buf + sizeof(PVOID))));