Возврат стека пользовательского режима потока во время функции обратного вызова минифильтра
Я пытаюсь отследить стек пользовательского режима потока во время функции обратного вызова минифильтра.
Предполагая, что я нахожусь в том же контексте, что и вызывающий поток, получение адреса стека потока из его 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 ответ
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)))));