I'm trying to backtrace the usermode stack of a thread during a minifilter callback function.
Assuming that I'm in the same context as the calling thread, getting the thread stack address from it's TEB/TIB and processing the addresses on that stack should allow me to backtrace it's stack.
Since the addresses I'm getting are not the expected usermode modules that are calling the system-call, there must be something wrong I'm doing.
I will be glad if you would point me to the correct direction.
Thanks in advance.
Following is the code that is reading the stack content:
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));
}
Below are the functions that gets the module names and addresses:
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;
}
pTEB = (PVOID *)((char *)pThread + 0x20);
Don't do this at all, even in PoC. Structure layout changes time to time. You can use PsGetProcessPeb instead (see here how https://code.google.com/p/arkitlib/source/browse/trunk/ARKitDrv/Ps.c)
LogDbgView(("Read Memory = %x",buf));
You don`t read memory at buf address, you read value of buf instead. In C you must dereference pointer to read memory from there. Like this
LogDbgView(("Read Memory = %x",(PVOID)*buf));
LogDbgView(("Read Memory = %x",buf+8));
To be able to compile for x86 as well as for x64 you must avoid such things. Instead, use sizeof(PVOID):
LogDbgView(("Read Memory = %x",(PVOID)*(buf+sizeof(PVOID))));
I'm trying to backtrace the usermode stack of a thread during a minifilter callback function.
Assuming that I'm in the same context as the calling thread, getting the thread stack address from it's TEB/TIB and processing the addresses on that stack should allow me to backtrace it's stack.
Since the addresses I'm getting are not the expected usermode modules that are calling the system-call, there must be something wrong I'm doing.
I will be glad if you would point me to the correct direction.
Thanks in advance.
Following is the code that is reading the stack content:
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));
}
Below are the functions that gets the module names and addresses:
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;
}
pTEB = (PVOID *)((char *)pThread + 0x20);
Don't do this at all, even in PoC. Structure layout changes time to time. You can use PsGetProcessPeb instead (see here how https://code.google.com/p/arkitlib/source/browse/trunk/ARKitDrv/Ps.c)
LogDbgView(("Read Memory = %x",buf));
You don`t read memory at buf address, you read value of buf instead. In C you must dereference pointer to read memory from there. Like this
LogDbgView(("Read Memory = %x",(PVOID)*buf));
LogDbgView(("Read Memory = %x",buf+8));
To be able to compile for x86 as well as for x64 you must avoid such things. Instead, use sizeof(PVOID):
LogDbgView(("Read Memory = %x",(PVOID)*(buf+sizeof(PVOID))));
0 commentaires:
Enregistrer un commentaire