0

我试图在微过滤器回调函数期间回溯线程的用户模式堆栈。
假设我与调用线程处于相同的上下文中,从它的 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;
    }
4

1 回答 1

0

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

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

LogDbgView(("读取内存 = %x",buf));

您不会在 buf 地址读取内存,而是读取 buf 的值。在 C 中,您必须取消引用指针才能从那里读取内存。像这样

LogDbgView(("读取内存 = %x",(PVOID)*buf));

LogDbgView(("读取内存 = %x",buf+8));

为了能够为 x86 和 x64 编译,您必须避免此类事情。相反,使用 sizeof(PVOID):

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

于 2014-04-01T09:07:34.783 回答