You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2144 lines
64 KiB
2144 lines
64 KiB
#include <wmiexts.h>
|
|
#include <malloc.h>
|
|
#include <objbase.h>
|
|
#include <obase.h>
|
|
|
|
//IID_IStdIdentity {0000001B-0000-0000-C000-000000000046}
|
|
const GUID IID_IStdIdentity = {0x0000001B,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
|
|
|
#include <data.h>
|
|
|
|
#include <utilfun.h>
|
|
|
|
DECLARE_API(iid) {
|
|
|
|
INIT_API();
|
|
|
|
GUID CurrUUID;
|
|
|
|
MEMORY_ADDRESS pUUID = 0;
|
|
pUUID = GetExpression(args);
|
|
if (pUUID){
|
|
ReadMemory(pUUID,&CurrUUID,sizeof(GUID),0);
|
|
|
|
WCHAR pszClsID[40];
|
|
StringFromGUID2(CurrUUID,pszClsID,40);
|
|
WCHAR pszFullPath[MAX_PATH];
|
|
lstrcpyW(pszFullPath,L"Interface\\");
|
|
lstrcatW(pszFullPath,pszClsID);
|
|
|
|
char pDataA[MAX_PATH];
|
|
HKEY hKey;
|
|
LONG lRes;
|
|
|
|
lRes = RegOpenKeyExW(HKEY_CLASSES_ROOT,
|
|
pszFullPath,
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
|
|
if (lRes == ERROR_SUCCESS){
|
|
DWORD dwType;
|
|
WCHAR pData[MAX_PATH];
|
|
DWORD dwSize=sizeof(pData);
|
|
|
|
lRes = RegQueryValueExW(hKey,
|
|
NULL, // default
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)pData,
|
|
&dwSize);
|
|
if (lRes == ERROR_SUCCESS) {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pData,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf(" IID_%s\n",pDataA);
|
|
}
|
|
RegCloseKey(hKey);
|
|
|
|
} else {
|
|
|
|
if (IsEqualGUID(CurrUUID,IID_IMarshal)){
|
|
|
|
dprintf(" IID_IMarshal\n");
|
|
|
|
} else if (IsEqualGUID(CurrUUID,IID_IStdIdentity)) {
|
|
|
|
dprintf(" IID_IStdIdentity\n");
|
|
|
|
} else if (IsEqualGUID(CurrUUID,IID_ICallFactory)) {
|
|
|
|
dprintf(" IID_ICallFactory\n");
|
|
|
|
} else {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pszClsID,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf("unable to open key %s\n",pDataA);
|
|
|
|
}
|
|
}
|
|
|
|
} else {
|
|
dprintf("unable to resolve %s\n",args);
|
|
}
|
|
|
|
}
|
|
|
|
extern ArrayCLSID g_ArrayCLSID[];
|
|
|
|
DECLARE_API(clsid) {
|
|
|
|
INIT_API();
|
|
|
|
GUID CurrUUID;
|
|
|
|
MEMORY_ADDRESS pUUID = 0;
|
|
pUUID = GetExpression(args);
|
|
if (pUUID){
|
|
ReadMemory(pUUID,&CurrUUID,sizeof(GUID),0);
|
|
|
|
WCHAR pszClsID[40];
|
|
StringFromGUID2(CurrUUID,pszClsID,40);
|
|
|
|
// look-up known
|
|
DWORD i;
|
|
for (i=0;i<g_nClsids;i++){
|
|
if(IsEqualGUID(CurrUUID,*g_ArrayCLSID[i].pClsid)){
|
|
dprintf(" CLSID : %s\n",g_ArrayCLSID[i].pStrClsid);
|
|
break;
|
|
}
|
|
}
|
|
|
|
WCHAR pszFullPath[MAX_PATH];
|
|
lstrcpyW(pszFullPath,L"CLSID\\");
|
|
lstrcatW(pszFullPath,pszClsID);
|
|
|
|
char pDataA[MAX_PATH];
|
|
HKEY hKey;
|
|
LONG lRes;
|
|
|
|
lRes = RegOpenKeyExW(HKEY_CLASSES_ROOT,
|
|
pszFullPath,
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
|
|
if (lRes == ERROR_SUCCESS){
|
|
DWORD dwType;
|
|
WCHAR pData[MAX_PATH];
|
|
DWORD dwSize=sizeof(pData);
|
|
|
|
lRes = RegQueryValueExW(hKey,
|
|
NULL, // default
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)pData,
|
|
&dwSize);
|
|
if (lRes == ERROR_SUCCESS) {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pData,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf(" ProgID %s\n",pDataA);
|
|
|
|
};
|
|
RegCloseKey(hKey);
|
|
|
|
// no open InProcServer32
|
|
WCHAR pszFullPathDll[MAX_PATH];
|
|
lstrcpyW(pszFullPathDll,pszFullPath);
|
|
lstrcatW(pszFullPathDll,L"\\InprocServer32");
|
|
|
|
lRes = RegOpenKeyExW(HKEY_CLASSES_ROOT,
|
|
pszFullPathDll,
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
if (lRes == ERROR_SUCCESS){
|
|
|
|
dwSize = sizeof(pData);
|
|
lRes = RegQueryValueExW(hKey,
|
|
NULL, // default
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)pData,
|
|
&dwSize);
|
|
|
|
if (lRes == ERROR_SUCCESS) {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pData,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf(" Path: %s\n",pDataA);
|
|
|
|
};
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
} else {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pszClsID,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf("unable to open key %s\n",pDataA);
|
|
|
|
}
|
|
|
|
} else {
|
|
dprintf("unable to resolve %s\n",args);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
//
|
|
// Dumps a SAFE_ARRAY
|
|
//
|
|
//
|
|
|
|
DECLARE_API(sa) {
|
|
|
|
INIT_API();
|
|
|
|
SAFEARRAY SA;
|
|
|
|
MEMORY_ADDRESS pSA = 0;
|
|
pSA = GetExpression(args);
|
|
|
|
if (pSA){
|
|
ReadMemory(pSA,&SA,sizeof(SA),0);
|
|
|
|
dprintf(" cDims %d cbElements %d pvData %08x\n",SA.cDims,SA.cbElements,SA.pvData);
|
|
dprintf("rgsabound.cElements %d lLbound %d\n",SA.rgsabound[0].cElements,SA.rgsabound[0].lLbound);
|
|
|
|
} else {
|
|
dprintf("invalid address %s\n",args);
|
|
}
|
|
}
|
|
|
|
//
|
|
// help for the extension
|
|
// may commands are not listed here
|
|
//
|
|
//
|
|
|
|
DECLARE_API(help) {
|
|
|
|
INIT_API();
|
|
|
|
dprintf(" WMI debugger extension\n");
|
|
dprintf(" iid : print the human readable IID_xxx\n");
|
|
dprintf(" clsid : print the human readable CLSID_xxx\n");
|
|
dprintf(" rot : print the human readable rpcss!gpClassTable\n");
|
|
dprintf(" gpl : print the human readable rpcss!gpProcessList\n");
|
|
dprintf(" gipid : print the global list of IPIDEntry\n");
|
|
dprintf(" goxid : print the global list of OXIDEntry\n");
|
|
dprintf(" ipidl : print the list of IPIDEntry for CStdIdentiry\n");
|
|
dprintf(" srtbl : print the list of secure reference IPID in ole32!gSRFTbl\n");
|
|
dprintf(" llc : print linked list count\n");
|
|
dprintf(" cs : print the list of CRITICAL_SECTION\n");
|
|
dprintf(" std_map : print the first 3 DWORD of a std::map<K,V>\n");
|
|
dprintf(" std_queue: print the first ULONG_PTR of a std::queue<V>\n");
|
|
dprintf(" std_deque: print the first ULONG_PTR of a std::deque<V>\n");
|
|
//dprintf(" mapobj : print a std::map<IUnk,bool>\n");
|
|
dprintf(" -------- HEAP family\n");
|
|
dprintf(" he : print the HEAP_ENTRY\n");
|
|
dprintf(" hef : walks the HEAP_ENTRY list forward\n");
|
|
dprintf(" hef : walks the HEAP_ENTRY list backward\n");
|
|
dprintf(" hs : print the HEAP_SEGMENT\n");
|
|
dprintf(" hp : print the HEAP\n");
|
|
dprintf(" lhp : <HEAP> prints the LookAside list for the HEAP\n");
|
|
dprintf(" hps : print a summary for all the HEAP in the process\n");
|
|
dprintf(" shp : <HEAP> <ADDR> search heap HEAP for address ADDR\n");
|
|
dprintf(" rllc : <ADDR> prints the free list in reverse order\n");
|
|
dprintf(" hpf : <HEAP> prints the free list of the heap at HEAP\n");
|
|
dprintf(" php : <HEAP> [s ADDR] prints the pageheap and searches\n");
|
|
dprintf(" -------- FASTPROX family\n");
|
|
dprintf(" wc : print the human readable WbemClass\n");
|
|
dprintf(" wi : print the human readable WbemClass\n");
|
|
dprintf(" blob : ADDR [size] print (part of) the ClassObject BLOB\n");
|
|
dprintf(" datap : ADDR print the WBEMDATA marshaling BLOB\n");
|
|
dprintf(" cp : print the human readable CClassPart\n");
|
|
dprintf(" cvar : print the CVar\n");
|
|
dprintf(" -------- WBEMCORE\n");
|
|
dprintf(" q : print wbemcore!g_pAsyncSvcQueue\n");
|
|
dprintf(" arb : print wbemcore!CWmiArbitrator__m_pArb\n");
|
|
dprintf(" -------- REPDRVFS\n");
|
|
dprintf(" tmpall : print the Allocators in repdrvfs\n");
|
|
dprintf(" forestc : [Addr] print the repdrvfs!CForestCache at Addr\n");
|
|
dprintf(" filec : [Addr] print repdrvfs!CFileCache at Addr\n");
|
|
dprintf(" fmap : \\fs\\[objects|index].map dumps the .MAP file from disk \n");
|
|
dprintf(" btr : dumps the index.btr/index.map file from disk \n");
|
|
dprintf(" varobj : dumps part of objects.data file from disk \n");
|
|
dprintf(" -------- THREAD family\n");
|
|
dprintf(" t : print RPC and OLE data for each thread\n");
|
|
dprintf(" inv : <addr> [param] invokes a function in the remote thread\n");
|
|
dprintf(" bs : <teb> rebuilds the stack from the info in the TEB\n");
|
|
dprintf(" st : <addr> <num> prints the num DWORD saved by RtlCaptureStackBackTrace\n");
|
|
dprintf(" lpp : print linked list and unassemble backtrace\n");
|
|
dprintf(" vq : -a <addr> | -f Flag : calls VirtualQuery on the addr\n");
|
|
dprintf(" srt : <addr> searches the stacks of all threads for addr\n");
|
|
dprintf(" ksrt : <addr> searches the stacks of all threads for addr - KD only\n");
|
|
dprintf(" el : <TEB> prints the exception list of the current thread x86 only\n");
|
|
dprintf(" -------- ESS\n");
|
|
dprintf(" ess : print wbemcore!g_pNewESS\n");
|
|
dprintf(" -------- PROVSS\n");
|
|
dprintf(" pc : print wbemcore!CCoreServices__m_pProvSS\n");
|
|
dprintf(" pf : print CServerObject_BindingFactory\n");
|
|
dprintf(" -------- 32-K-64\n");
|
|
dprintf(" hef64 : <addr> HEAP_ENTRY list forward\n");
|
|
dprintf(" heb64 : <addr> HEAP_ENTRY list backward\n");
|
|
dprintf(" hps64 : print heap summary\n");
|
|
dprintf(" cs64 : print CritSec list\n");
|
|
}
|
|
|
|
void
|
|
EnumLinkedListCB(IN LIST_ENTRY * pListHead,
|
|
IN DWORD cbSizeOfStructure,
|
|
IN DWORD cbListEntryOffset,
|
|
IN pfnCallBack2 CallBack,
|
|
IN VOID * Context)
|
|
{
|
|
LIST_ENTRY ListHead;
|
|
LIST_ENTRY * pListEntry;
|
|
DWORD cItems = 0;
|
|
|
|
void * pStorage = (void *)_alloca(cbSizeOfStructure);
|
|
LIST_ENTRY * pListEntryLocal = (LIST_ENTRY *)((BYTE *)pStorage + cbListEntryOffset);
|
|
|
|
if (ReadMemory((ULONG_PTR)pListHead,&ListHead,sizeof(LIST_ENTRY),NULL))
|
|
{
|
|
|
|
if (CallBack)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
dprintf(" H %p -> %p <-\n",ListHead.Flink,ListHead.Blink);
|
|
}
|
|
|
|
for ( pListEntry = ListHead.Flink;
|
|
pListEntry != pListHead;)
|
|
{
|
|
if (CheckControlC())
|
|
break;
|
|
|
|
ULONG_PTR pStructure_OOP = (ULONG_PTR)((BYTE *) pListEntry - cbListEntryOffset);
|
|
|
|
// make a local copy of the debuggee structure
|
|
if (ReadMemory(pStructure_OOP,pStorage,cbSizeOfStructure,NULL))
|
|
{
|
|
if (CallBack)
|
|
{
|
|
//dprintf(" CallBack %p\n",CallBack);
|
|
if (NULL == Context)
|
|
{
|
|
CallBack((VOID *)pStructure_OOP,pStorage);
|
|
}
|
|
else
|
|
{
|
|
//dprintf(" CallBackEx %p %p\n",CallBack,Context);
|
|
pfnCallBack3 CallBackEx = (pfnCallBack3)CallBack;
|
|
CallBackEx((VOID *)pStructure_OOP,pStorage,Context);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf(" %p -> %p <- - %p\n",pListEntryLocal->Flink,pListEntryLocal->Blink,pStructure_OOP);
|
|
}
|
|
|
|
pListEntry = pListEntryLocal->Flink;
|
|
cItems++;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pStructure_OOP);
|
|
break;
|
|
}
|
|
}
|
|
|
|
dprintf( "%d entries traversed\n", cItems );
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pListHead);
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
EnumReverseLinkedListCB(IN LIST_ENTRY * pListHead,
|
|
IN DWORD cbSizeOfStructure,
|
|
IN DWORD cbListEntryOffset,
|
|
IN pfnCallBack2 CallBack)
|
|
{
|
|
LIST_ENTRY ListHead;
|
|
LIST_ENTRY * pListEntry;
|
|
DWORD cItems = 0;
|
|
|
|
void * pStorage = (void *)_alloca(cbSizeOfStructure);
|
|
LIST_ENTRY * pListEntryLocal = (LIST_ENTRY *)((BYTE *)pStorage + cbListEntryOffset);
|
|
|
|
if (ReadMemory((ULONG_PTR)pListHead,&ListHead,sizeof(LIST_ENTRY),NULL))
|
|
{
|
|
|
|
if (CallBack)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
dprintf(" H %p -> %p <-\n",ListHead.Flink,ListHead.Blink);
|
|
}
|
|
|
|
for ( pListEntry = ListHead.Blink;
|
|
pListEntry != pListHead;)
|
|
{
|
|
if (CheckControlC())
|
|
break;
|
|
|
|
ULONG_PTR pStructure_OOP = (ULONG_PTR)((BYTE *) pListEntry - cbListEntryOffset);
|
|
|
|
// make a local copy of the debuggee structure
|
|
if (ReadMemory(pStructure_OOP,pStorage,cbSizeOfStructure,NULL))
|
|
{
|
|
if (CallBack)
|
|
{
|
|
CallBack((VOID *)pStructure_OOP,pStorage);
|
|
}
|
|
else
|
|
{
|
|
dprintf(" %p -> %p <- - %p\n",pListEntryLocal->Flink,pListEntryLocal->Blink,pStructure_OOP);
|
|
}
|
|
|
|
pListEntry = pListEntryLocal->Blink;
|
|
cItems++;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pStructure_OOP);
|
|
break;
|
|
}
|
|
}
|
|
|
|
dprintf( "%d entries traversed\n", cItems );
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pListHead);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
// NO-OP callback just for getting the number of items
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
CallBackListCount(VOID * pStructure_OOP,
|
|
VOID * pLocalCopy)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
DECLARE_API( llc )
|
|
{
|
|
INIT_API();
|
|
|
|
MEMORY_ADDRESS Addr = GetExpression(args);
|
|
|
|
if (Addr)
|
|
{
|
|
EnumLinkedListCB((LIST_ENTRY *)Addr,sizeof(LIST_ENTRY),0,CallBackListCount);
|
|
}
|
|
else
|
|
{
|
|
dprintf("cannot resolve %s\n",args);
|
|
}
|
|
}
|
|
|
|
void
|
|
PrintStackTrace(MEMORY_ADDRESS ArrayAddr_OOP,DWORD dwNum,BOOL bOOP)
|
|
{
|
|
MEMORY_ADDRESS * pArray;
|
|
BOOL bRet = FALSE;
|
|
if (bOOP)
|
|
{
|
|
pArray = ( MEMORY_ADDRESS *)_alloca(dwNum*sizeof(MEMORY_ADDRESS));
|
|
bRet = ReadMemory(ArrayAddr_OOP,pArray,dwNum*sizeof(MEMORY_ADDRESS),NULL);
|
|
}
|
|
else
|
|
{
|
|
pArray = (MEMORY_ADDRESS *)ArrayAddr_OOP;
|
|
bRet = TRUE;
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
DWORD i;
|
|
for (i=0;i<dwNum;i++)
|
|
{
|
|
BYTE pString[256];
|
|
pString[0] = 0;
|
|
|
|
#ifdef KDEXT_64BIT
|
|
ULONG64 Displ = 0;
|
|
#else
|
|
ULONG Displ = 0;
|
|
#endif
|
|
if (pArray[i])
|
|
{
|
|
GetSymbol(pArray[i],(PCHAR)pString,&Displ);
|
|
pString[255] = 0;
|
|
dprintf(" %s+%x\n",pString,Displ);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// printf stack trace
|
|
//
|
|
DECLARE_API( st )
|
|
{
|
|
INIT_API();
|
|
|
|
int Len = strlen(args);
|
|
CHAR * pArgs = (CHAR *)_alloca((Len+1));
|
|
lstrcpy(pArgs,(CHAR *)args);
|
|
|
|
MEMORY_ADDRESS NumInst = 6;
|
|
MEMORY_ADDRESS pAddr = 0;
|
|
|
|
while (isspace(*pArgs))
|
|
{
|
|
pArgs++;
|
|
}
|
|
|
|
CHAR * pFirst = pArgs;
|
|
|
|
while(!isspace(*pArgs)) pArgs++;
|
|
// terminate string, if possible
|
|
if (isspace(*pArgs))
|
|
{
|
|
*pArgs = 0;
|
|
pArgs++;
|
|
}
|
|
else
|
|
{
|
|
pArgs = NULL;
|
|
}
|
|
|
|
pAddr = GetExpression(pFirst);
|
|
|
|
if (pArgs)
|
|
{
|
|
NumInst = GetExpression(pArgs);
|
|
}
|
|
|
|
if (pAddr)
|
|
{
|
|
dprintf("StackTrace @ %p num %d\n",pAddr,NumInst);
|
|
PrintStackTrace(pAddr,(DWORD)NumInst,TRUE);
|
|
}
|
|
else
|
|
{
|
|
dprintf("usage: address num\n");
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
// this is the CallBack called by the enumerator
|
|
// of a Double-Liked list of objects with
|
|
// struct _Instrument
|
|
// {
|
|
// LIST_ENTRY ListEntry;
|
|
// ULONG_PTR ArrayFuncts[32];
|
|
// }
|
|
//
|
|
//////////////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
CallBackCreateStacks(VOID * pStructure_OOP,
|
|
VOID * pLocalStructure)
|
|
{
|
|
dprintf(" ----- %p \n",pStructure_OOP);
|
|
PrintStackTrace((ULONG_PTR)((BYTE *)pLocalStructure+sizeof(LIST_ENTRY)),6,FALSE);
|
|
return 0;
|
|
}
|
|
|
|
DECLARE_API( lpp )
|
|
{
|
|
INIT_API();
|
|
|
|
MEMORY_ADDRESS Addr = GetExpression(args);
|
|
|
|
if (Addr)
|
|
{
|
|
EnumLinkedListCB((LIST_ENTRY *)Addr,
|
|
sizeof(LIST_ENTRY)+32*sizeof(ULONG_PTR),
|
|
0,
|
|
CallBackCreateStacks);
|
|
}
|
|
else
|
|
{
|
|
dprintf("cannot resolve %s\n",args);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
/////////////
|
|
|
|
void PrintDequeCB(MEMORY_ADDRESS pDeque_OOP,pfnCallBack2 pCallBack)
|
|
{
|
|
_Deque Deque;
|
|
if (ReadMemory(pDeque_OOP,&Deque,sizeof(Deque),NULL))
|
|
{
|
|
dprintf(" std::deque @ %p _Allocator %p head %p tail %p _Size %p\n",pDeque_OOP,Deque._Allocator,Deque._First._Next,Deque._Last._Next,Deque._Size);
|
|
ULONG_PTR Size = Deque._Size;
|
|
ULONG_PTR ByteSize = (ULONG_PTR)Deque._Last._Next-(ULONG_PTR)Deque._First._Next;
|
|
ULONG_PTR pArray_OOP = (ULONG_PTR)Deque._First._Next;
|
|
BYTE * pArray = NULL;
|
|
if (Size)
|
|
pArray = (BYTE *)HeapAlloc(GetProcessHeap(),0,ByteSize);
|
|
if (pArray)
|
|
{
|
|
ULONG_PTR SizeElem = ByteSize/Size;
|
|
if (ReadMemory(pArray_OOP,pArray,(ULONG)ByteSize,0))
|
|
{
|
|
for (ULONG_PTR i=0;i<Size;i++)
|
|
{
|
|
dprintf(" %p -[%p] %p\n",i,pArray_OOP+i*SizeElem,*((void **)(&pArray[i*SizeElem])));
|
|
if (pCallBack)
|
|
{
|
|
// address OOP and address of the In-Proc opy of the memory are passed down
|
|
pCallBack((void *)(pArray_OOP+i*SizeElem),(void *)(&pArray[i*SizeElem]));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pArray_OOP);
|
|
}
|
|
HeapFree(GetProcessHeap(),0,pArray);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pDeque_OOP);
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
// prints a generic std::deque
|
|
//
|
|
////////////////////////////////////
|
|
|
|
|
|
DECLARE_API( std_deque )
|
|
{
|
|
|
|
INIT_API();
|
|
|
|
_Deque * pDeque = (_Deque *)GetExpression( args );
|
|
|
|
if (pDeque)
|
|
{
|
|
PrintDequeCB((MEMORY_ADDRESS)pDeque,NULL);
|
|
}
|
|
else
|
|
{
|
|
dprintf("invalid address %s\n",args);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// left parent right
|
|
|
|
BOOL
|
|
IsNil(_BRN * pNode){
|
|
|
|
_BRN_HEAD BRN;
|
|
ReadMemory((ULONG_PTR)pNode,&BRN,sizeof(_BRN_HEAD),NULL);
|
|
|
|
return ((BRN._Left == NULL) &&
|
|
(BRN._Right == NULL));
|
|
}
|
|
|
|
void
|
|
PrintTree(_BRN * pNode,
|
|
DWORD * pNum,
|
|
BOOL Verbose,
|
|
ULONG_PTR Size,
|
|
pfnCallBack2 CallBack){
|
|
|
|
//dprintf(" Node %p\n",pNode);
|
|
_BRN BRN;
|
|
if (ReadMemory((ULONG_PTR)pNode,&BRN,sizeof(_BRN),NULL))
|
|
{
|
|
if (!IsNil(BRN._Left)){
|
|
PrintTree(BRN._Left,pNum,Verbose,Size,CallBack);
|
|
};
|
|
|
|
if (CheckControlC())
|
|
return;
|
|
|
|
if (pNum){
|
|
(*pNum)++;
|
|
}
|
|
|
|
if (*pNum > Size)
|
|
{
|
|
dprintf("invalid tree\n");
|
|
return;
|
|
}
|
|
|
|
if (Verbose) {
|
|
dprintf(" %p %p (%p,%p,%p) - %p %p %p\n",
|
|
(*pNum)-1,
|
|
pNode,
|
|
BRN._Left,BRN._Parent,BRN._Right,
|
|
BRN.Values[0],
|
|
BRN.Values[1],
|
|
BRN.Values[2]);
|
|
if (CallBack)
|
|
{
|
|
//dprintf("CAllBack\n");
|
|
CallBack((VOID *)BRN.Values[0],(VOID *)BRN.Values[1]);
|
|
}
|
|
}
|
|
|
|
if (!IsNil(BRN._Right)){
|
|
PrintTree(BRN._Right,pNum,Verbose,Size,CallBack);
|
|
};
|
|
}
|
|
else
|
|
{
|
|
dprintf(" RM %p err %d\n",pNode,GetLastError());
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
PrintMapCB(_Map * pMap,BOOL Verbose, pfnCallBack2 CallBack)
|
|
{
|
|
|
|
_Map MAP;
|
|
|
|
if (ReadMemory((ULONG_PTR)pMap,&MAP,sizeof(_Map),NULL))
|
|
{
|
|
if (MAP.pQm)
|
|
{
|
|
dprintf(" std::map at %p : size %p\n",pMap,MAP.Size);
|
|
|
|
_QM QM;
|
|
|
|
if (ReadMemory((ULONG_PTR)MAP.pQm,&QM,sizeof(QM),NULL))
|
|
{
|
|
if (QM._Parent && !IsNil(QM._Parent))
|
|
{
|
|
DWORD Num = 0;
|
|
PrintTree(QM._Parent,&Num,Verbose,MAP.Size,CallBack);
|
|
dprintf(" traversed %d nodes\n",Num);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p err %d\n",MAP.pQm,GetLastError());
|
|
}
|
|
} else {
|
|
dprintf("empty tree\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pMap);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
// prints a generic std::map
|
|
//
|
|
////////////////////////////////////
|
|
|
|
|
|
DECLARE_API( std_map )
|
|
{
|
|
|
|
INIT_API();
|
|
|
|
_Map * pMap = (_Map *)GetExpression( args );
|
|
|
|
if (pMap){
|
|
|
|
PrintMapCB(pMap,TRUE,NULL);
|
|
|
|
} else {
|
|
dprintf("invalid address %s\n",args);
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
PrintListCB(_List * pList_OOP, pfnCallBack1 CallBack)
|
|
{
|
|
_List List;
|
|
if (ReadMemory((ULONG_PTR)pList_OOP,&List,sizeof(_List),NULL))
|
|
{
|
|
dprintf(" std::queue @ %p _Allocator %p _Head %p _Size %p\n",pList_OOP,List._Allocator,List._Head,List._Size);
|
|
_Node_List NodeList;
|
|
|
|
if (ReadMemory((ULONG_PTR)List._Head,&NodeList,sizeof(_Node_List),NULL))
|
|
{
|
|
_Node_List * pNodeList = NodeList._Next;
|
|
|
|
DWORD i = 0;
|
|
|
|
while (pNodeList != List._Head)
|
|
{
|
|
if (CheckControlC())
|
|
break;
|
|
|
|
if (ReadMemory((ULONG_PTR)pNodeList,&NodeList,sizeof(_Node_List),NULL))
|
|
{
|
|
dprintf(" %x %p (%p, %p) - %p\n",i++,pNodeList,NodeList._Next,NodeList._Prev,NodeList._Value);
|
|
if (CallBack)
|
|
{
|
|
CallBack(NodeList._Value);
|
|
}
|
|
|
|
pNodeList = NodeList._Next;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pNodeList);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",List._Head);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pList_OOP);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
// prints a generic std::list
|
|
//
|
|
//////////////////////////////////////
|
|
|
|
DECLARE_API( std_queue)
|
|
{
|
|
INIT_API();
|
|
|
|
_List * pList = (_List *)GetExpression( args );
|
|
|
|
if (pList){
|
|
|
|
PrintListCB(pList,NULL);
|
|
|
|
} else {
|
|
dprintf("invalid address %s\n",args);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
//
|
|
// this is for Pat
|
|
// he has a std::map<pObject,BOOL>
|
|
//
|
|
//////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
CallBackObj(void * pKey, void * pValue)
|
|
{
|
|
GetVTable((MEMORY_ADDRESS)pKey);
|
|
return 0;
|
|
}
|
|
|
|
DECLARE_API( mapobj )
|
|
{
|
|
|
|
INIT_API();
|
|
|
|
|
|
_Map * pMap = (_Map *)GetExpression( args );
|
|
|
|
if (pMap){
|
|
|
|
PrintMapCB(pMap,TRUE,CallBackObj);
|
|
|
|
} else {
|
|
dprintf("invalid address %s\n",args);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void PrintIID(GUID & CurrUUID){
|
|
|
|
WCHAR pszClsID[40];
|
|
StringFromGUID2(CurrUUID,pszClsID,40);
|
|
WCHAR pszFullPath[MAX_PATH];
|
|
lstrcpyW(pszFullPath,L"Interface\\");
|
|
lstrcatW(pszFullPath,pszClsID);
|
|
|
|
char pDataA[MAX_PATH];
|
|
HKEY hKey;
|
|
LONG lRes;
|
|
|
|
lRes = RegOpenKeyExW(HKEY_CLASSES_ROOT,
|
|
pszFullPath,
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
|
|
if (lRes == ERROR_SUCCESS){
|
|
DWORD dwType;
|
|
WCHAR pData[MAX_PATH];
|
|
DWORD dwSize=sizeof(pData);
|
|
|
|
lRes = RegQueryValueExW(hKey,
|
|
NULL, // default
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)pData,
|
|
&dwSize);
|
|
if (lRes == ERROR_SUCCESS) {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pData,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf(" IID_%s\n",pDataA);
|
|
}
|
|
RegCloseKey(hKey);
|
|
|
|
} else {
|
|
|
|
if (IsEqualGUID(CurrUUID,IID_IMarshal)){
|
|
|
|
dprintf(" IID_IMarshal\n");
|
|
|
|
} else if (IsEqualGUID(CurrUUID,IID_IStdIdentity)) {
|
|
|
|
dprintf(" IID_IStdIdentity\n");
|
|
|
|
} else if (IsEqualGUID(CurrUUID,IID_ICallFactory)) {
|
|
|
|
dprintf(" IID_ICallFactory\n");
|
|
|
|
} else {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pszClsID,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf(" %s\n",pDataA);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
class OXIDEntry;
|
|
class CCtxComChnl;
|
|
class IRCEntry;
|
|
|
|
typedef GUID IPID;
|
|
|
|
typedef enum tagIPIDFLAGS
|
|
{
|
|
IPIDF_CONNECTING = 0x1, // ipid is being connected
|
|
IPIDF_DISCONNECTED = 0x2, // ipid is disconnected
|
|
IPIDF_SERVERENTRY = 0x4, // SERVER IPID vs CLIENT IPID
|
|
IPIDF_NOPING = 0x8, // dont need to ping the server or release
|
|
IPIDF_COPY = 0x10, // copy for security only
|
|
IPIDF_VACANT = 0x80, // entry is vacant (ie available to reuse)
|
|
IPIDF_NONNDRSTUB = 0x100, // stub does not use NDR marshaling
|
|
IPIDF_NONNDRPROXY = 0x200, // proxy does not use NDR marshaling
|
|
IPIDF_NOTIFYACT = 0x400, // notify activation on marshal/release
|
|
IPIDF_TRIED_ASYNC = 0x800, // tried to call this server interface async
|
|
IPIDF_ASYNC_SERVER = 0x1000, // server implements an async interface
|
|
IPIDF_DEACTIVATED = 0x2000, // IPID has been deactivated
|
|
IPIDF_WEAKREFCACHE = 0x4000, // IPID holds weak references in refcache
|
|
IPIDF_STRONGREFCACHE = 0x8000 // IPID holds strong references in refcache
|
|
} IPIDFLAGS;
|
|
|
|
typedef struct tagIPIDEntry
|
|
{
|
|
struct tagIPIDEntry *pNextIPID; // next IPIDEntry for same object
|
|
|
|
// WARNING: next 6 fields must remain in their respective locations
|
|
// and in the same format as the IPIDTmp structure above.
|
|
DWORD dwFlags; // flags (see IPIDFLAGS)
|
|
ULONG cStrongRefs; // strong reference count
|
|
ULONG cWeakRefs; // weak reference count
|
|
ULONG cPrivateRefs; // private reference count
|
|
void *pv; // real interface pointer
|
|
IUnknown *pStub; // proxy or stub pointer
|
|
OXIDEntry *pOXIDEntry; // ptr to OXIDEntry in OXID Table
|
|
// WARNING: previous 7 fields must remain in their respective locations
|
|
// and in the same format as the IPIDTmp structure above.
|
|
|
|
IPID ipid; // interface pointer identifier
|
|
IID iid; // interface iid
|
|
CCtxComChnl *pChnl; // channel pointer
|
|
IRCEntry *pIRCEntry; // reference cache line
|
|
struct tagIPIDEntry *pOIDFLink; // In use OID list
|
|
struct tagIPIDEntry *pOIDBLink;
|
|
} IPIDEntry;
|
|
|
|
void PrintIPIDFlags(DWORD Flags)
|
|
{
|
|
if (Flags & IPIDF_CONNECTING) dprintf("IPIDF_CONNECTING ");
|
|
if (Flags & IPIDF_DISCONNECTED) dprintf("IPIDF_DISCONNECTED ");
|
|
if (Flags & IPIDF_SERVERENTRY) dprintf("IPIDF_SERVERENTRY ");
|
|
if (Flags & IPIDF_NOPING) dprintf("IPIDF_NOPING ");
|
|
if (Flags & IPIDF_COPY) dprintf("IPIDF_COPY ");
|
|
if (Flags & IPIDF_VACANT) dprintf("IPIDF_VACANT ");
|
|
if (Flags & IPIDF_NONNDRSTUB) dprintf("IPIDF_NONNDRSTUB ");
|
|
if (Flags & IPIDF_NONNDRPROXY) dprintf("IPIDF_NONNDRPROXY ");
|
|
if (Flags & IPIDF_NOTIFYACT) dprintf("IPIDF_NOTIFYACT ");
|
|
if (Flags & IPIDF_TRIED_ASYNC) dprintf("IPIDF_TRIED_ASYNC ");
|
|
if (Flags & IPIDF_ASYNC_SERVER) dprintf("IPIDF_ASYNC_SERVER ");
|
|
if (Flags & IPIDF_DEACTIVATED) dprintf("IPIDF_DEACTIVATED ");
|
|
if (Flags & IPIDF_WEAKREFCACHE) dprintf("IPIDF_WEAKREFCACHE ");
|
|
if (Flags & IPIDF_WEAKREFCACHE) dprintf("IPIDF_WEAKREFCACHE ");
|
|
};
|
|
|
|
void DumpIPID(IPIDEntry & IpId)
|
|
{
|
|
dprintf(" pNextIPID %p\n",IpId.pNextIPID);
|
|
dprintf(" dwFlags "); PrintIPIDFlags(IpId.dwFlags); dprintf("\n");
|
|
dprintf(" cStrongRefs %08x\n",IpId.cStrongRefs);
|
|
dprintf(" cWeakRefs %08x\n",IpId.cWeakRefs);
|
|
dprintf(" cPrivateRefs %08x\n",IpId.cPrivateRefs);
|
|
dprintf(" pv %p\n",IpId.pv);
|
|
GetVTable((ULONG_PTR)IpId.pv);
|
|
dprintf(" pStub %p\n",IpId.pStub);
|
|
dprintf(" pOXIDEntry %p\n",IpId.pOXIDEntry);
|
|
PrintIID(IpId.ipid);
|
|
PrintIID(IpId.iid);
|
|
dprintf(" pChnl %p\n",IpId.pChnl);
|
|
dprintf(" pIRCEntry %p\n",IpId.pIRCEntry);
|
|
//dprintf(" pOIDFLink %p\n",IpId.pOIDFLink);
|
|
//dprintf(" pOIDBLink %p\n",IpId.pOIDBLink);
|
|
}
|
|
|
|
DECLARE_API( gipid )
|
|
{
|
|
INIT_API();
|
|
|
|
char * pString = (CHAR *)args;
|
|
CLSID ClsidToSearch;
|
|
BOOL bClsIdFound = FALSE;
|
|
if (pString)
|
|
{
|
|
while (isspace((char)pString)) pString++;
|
|
WCHAR pClsid[64];
|
|
DWORD nChar = 0;
|
|
for (;*pString && nChar < 64;nChar++,pString++)
|
|
{
|
|
pClsid[nChar] = (WCHAR)(*pString);
|
|
}
|
|
pClsid[nChar] = 0;
|
|
|
|
if (SUCCEEDED(CLSIDFromString(pClsid,&ClsidToSearch)))
|
|
bClsIdFound = TRUE;
|
|
}
|
|
|
|
IPIDEntry gIpId;
|
|
MEMORY_ADDRESS Addr = GetExpression("ole32!CIPIDTable___oidListHead");
|
|
if (Addr)
|
|
{
|
|
dprintf("ole32!CIPIDTable___oidListHead @ %p\n",Addr);
|
|
|
|
DWORD nItems = 0;
|
|
gIpId.pOIDFLink = (IPIDEntry *)Addr;
|
|
do
|
|
{
|
|
MEMORY_ADDRESS pCurrentIPID = (MEMORY_ADDRESS)gIpId.pOIDFLink;
|
|
if (ReadMemory(pCurrentIPID,&gIpId,sizeof(gIpId),NULL))
|
|
{
|
|
if (bClsIdFound)
|
|
{
|
|
if (0 == memcmp(&gIpId.ipid,&ClsidToSearch,sizeof(CLSID)))
|
|
{
|
|
DumpIPID(gIpId);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (nItems > 0)
|
|
{
|
|
dprintf(" -------- tagIPIDEntry %p - %x\n",pCurrentIPID,nItems-1);
|
|
DumpIPID(gIpId);
|
|
}
|
|
nItems++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",Addr);
|
|
break;
|
|
}
|
|
if (CheckControlC())
|
|
break;
|
|
} while (Addr != (MEMORY_ADDRESS)gIpId.pOIDFLink);
|
|
}
|
|
else
|
|
{
|
|
dprintf("uanble to resolve ole32!CIPIDTable___oidListHead\n");
|
|
}
|
|
}
|
|
|
|
typedef GUID MOXID;
|
|
typedef ULONG64 MID;
|
|
typedef void CComApartment;
|
|
typedef void CChannelHandle;
|
|
typedef void MIDEntry;
|
|
typedef void IRemUnknown;
|
|
|
|
class OXIDEntry
|
|
{
|
|
private:
|
|
OXIDEntry *_pNext; // next entry on free/inuse list
|
|
OXIDEntry *_pPrev; // previous entry on inuse list
|
|
DWORD _dwPid; // process id of server
|
|
DWORD _dwTid; // thread id of server
|
|
MOXID _moxid; // object exporter identifier + machine id
|
|
MID _mid; // copy of our _pMIDEntry's mid value
|
|
IPID _ipidRundown; // IPID of IRundown and Remote Unknown
|
|
DWORD _dwFlags; // state flags
|
|
HWND _hServerSTA; // HWND of server
|
|
CComApartment *_pParentApt; // Parent apartment, not ref counted
|
|
public:
|
|
// CODEWORK: channel accessing this member variable directly
|
|
CChannelHandle *_pRpc; // Binding handle info for server
|
|
private:
|
|
void *_pAuthId; // must be held till rpc handle is freed
|
|
DUALSTRINGARRAY *_pBinding; // protseq and security strings.
|
|
DWORD _dwAuthnHint; // authentication level hint.
|
|
DWORD _dwAuthnSvc; // index of default authentication service.
|
|
MIDEntry *_pMIDEntry; // MIDEntry for machine where server lives
|
|
IRemUnknown *_pRUSTA; // proxy for Remote Unknown
|
|
LONG _cRefs; // count of IPIDs using this OXIDEntry
|
|
HANDLE _hComplete; // set when last outstanding call completes
|
|
LONG _cCalls; // number of calls dispatched
|
|
LONG _cResolverRef; //References to resolver
|
|
DWORD _dwExpiredTime; // rundown timer ID for STA servers
|
|
COMVERSION _version; // COM version of the machine
|
|
unsigned long _ulMarshaledTargetInfoLength; // credman credentials length
|
|
unsigned char *_pMarshaledTargetInfo; // credman credentials
|
|
|
|
|
|
};
|
|
|
|
void PrintDSA(DUALSTRINGARRAY * pDSA_OOP)
|
|
{
|
|
if (pDSA_OOP)
|
|
{
|
|
DUALSTRINGARRAY DSA;
|
|
if (ReadMemory((ULONG_PTR)pDSA_OOP,&DSA,sizeof(DSA),NULL))
|
|
{
|
|
DWORD Size = sizeof(DUALSTRINGARRAY)+(1+DSA.wNumEntries)*sizeof(WCHAR);
|
|
DUALSTRINGARRAY * pDSA = (DUALSTRINGARRAY *)_alloca(Size);
|
|
if (ReadMemory((ULONG_PTR)pDSA_OOP,pDSA,Size,0))
|
|
{
|
|
dprintf(" %S\n",pDSA->aStringArray);
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pDSA_OOP);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pDSA_OOP);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintOxid(OXIDEntry * pEntry)
|
|
{
|
|
// _pNext
|
|
// _pPrev
|
|
dprintf(" _dwPid %x\n",pEntry->_dwPid);
|
|
dprintf(" _dwTid %x\n",pEntry->_dwTid);
|
|
dprintf(" _moxid\n");
|
|
PrintIID(pEntry->_moxid);
|
|
dprintf(" _mid %016x\n",pEntry->_mid);
|
|
dprintf(" _ipidRundown\n");
|
|
PrintIID(pEntry->_ipidRundown);
|
|
dprintf(" _dwFlags %08x\n",pEntry->_dwFlags);
|
|
dprintf(" _hServerSTA %p\n",pEntry->_hServerSTA);
|
|
dprintf(" _pParentApt %p\n",pEntry->_pParentApt);
|
|
dprintf(" _pRpc %p\n",pEntry->_pRpc);
|
|
dprintf(" _pAuthId %p\n",pEntry->_pAuthId);
|
|
dprintf(" _pBinding %p\n",pEntry->_pBinding);
|
|
PrintDSA(pEntry->_pBinding);
|
|
dprintf(" _dwAuthnHint %x\n",pEntry->_dwAuthnHint);
|
|
dprintf(" _dwAuthnSvc %x\n",pEntry->_dwAuthnSvc);
|
|
dprintf(" _pMIDEntry %p\n",pEntry->_pMIDEntry);
|
|
dprintf(" _pRUSTA %p\n",pEntry->_pRUSTA);
|
|
dprintf(" _cRefs %x\n",pEntry->_cRefs);
|
|
dprintf(" _hComplete %x\n",pEntry->_hComplete);
|
|
dprintf(" _cCalls %x\n",pEntry->_cCalls);
|
|
dprintf(" _cResolverRef %x\n",pEntry->_cResolverRef);
|
|
// _dwExpiredTime
|
|
// _version
|
|
// _ulMarshaledTargetInfoLength
|
|
// _pMarshaledTargetInfo
|
|
}
|
|
|
|
DECLARE_API( goxid )
|
|
{
|
|
INIT_API();
|
|
ULONG_PTR Addr = GetExpression("ole32!gOXIDTbl");
|
|
if (NULL == Addr)
|
|
{
|
|
dprintf("unable to resolve ole32!gOXIDTbl\n");
|
|
return;
|
|
}
|
|
struct OxidTable
|
|
{
|
|
DWORD _cExpired;
|
|
OXIDEntry _InUseHead;
|
|
OXIDEntry _ExpireHead;
|
|
OXIDEntry _CleanupHead;
|
|
} _OxidTable;
|
|
if (ReadMemory(Addr,&_OxidTable,sizeof(_OxidTable),NULL))
|
|
{
|
|
OXIDEntry * pHead_OOP;
|
|
DWORD nEntry;
|
|
|
|
|
|
pHead_OOP = (OXIDEntry *)GetExpression("ole32!COXIDTable::_InUseHead");
|
|
nEntry = 0;
|
|
|
|
dprintf("ole32!gOXIDTbl:_InUseHead %p\n",pHead_OOP);
|
|
|
|
ULONG_PTR AddrToRead = (ULONG_PTR)pHead_OOP;
|
|
do
|
|
{
|
|
if (ReadMemory(AddrToRead,&_OxidTable._InUseHead,sizeof(OXIDEntry),NULL))
|
|
{
|
|
if (nEntry)
|
|
{
|
|
dprintf(" OXIDEntry %p - %d\n",AddrToRead,nEntry-1);
|
|
PrintOxid(&_OxidTable._InUseHead);
|
|
}
|
|
AddrToRead = (ULONG_PTR)_OxidTable._InUseHead._pNext;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",AddrToRead);
|
|
}
|
|
nEntry++;
|
|
if (CheckControlC())
|
|
break;
|
|
}
|
|
while (pHead_OOP != _OxidTable._InUseHead._pNext);
|
|
|
|
pHead_OOP = (OXIDEntry *)GetExpression("ole32!COXIDTable::_ExpireHead");
|
|
nEntry = 0;
|
|
dprintf("ole32!gOXIDTbl:_ExpireHead %p\n",pHead_OOP);
|
|
|
|
AddrToRead = (ULONG_PTR)pHead_OOP;
|
|
do
|
|
{
|
|
if (ReadMemory(AddrToRead,&_OxidTable._InUseHead,sizeof(OXIDEntry),NULL))
|
|
{
|
|
if (nEntry)
|
|
{
|
|
dprintf(" OXIDEntry %p - %d\n",AddrToRead,nEntry-1);
|
|
PrintOxid(&_OxidTable._InUseHead);
|
|
}
|
|
AddrToRead = (ULONG_PTR)_OxidTable._InUseHead._pNext;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",AddrToRead);
|
|
}
|
|
nEntry++;
|
|
if (CheckControlC())
|
|
break;
|
|
}
|
|
while (pHead_OOP != _OxidTable._InUseHead._pNext);
|
|
|
|
|
|
pHead_OOP = (OXIDEntry *)GetExpression("ole32!COXIDTable::_CleanupHead");
|
|
nEntry = 0;
|
|
dprintf("ole32!gOXIDTbl:_InUseHead %p\n",pHead_OOP);
|
|
|
|
AddrToRead = (ULONG_PTR)pHead_OOP;
|
|
do
|
|
{
|
|
if (ReadMemory(AddrToRead,&_OxidTable._InUseHead,sizeof(OXIDEntry),NULL))
|
|
{
|
|
if (nEntry)
|
|
{
|
|
dprintf(" OXIDEntry %p - %d\n",AddrToRead,nEntry-1);
|
|
PrintOxid(&_OxidTable._InUseHead);
|
|
}
|
|
AddrToRead = (ULONG_PTR)_OxidTable._InUseHead._pNext;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",AddrToRead);
|
|
}
|
|
nEntry++;
|
|
if (CheckControlC())
|
|
break;
|
|
}
|
|
while (pHead_OOP != _OxidTable._InUseHead._pNext);
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",Addr);
|
|
}
|
|
}
|
|
|
|
DECLARE_API( ipidl )
|
|
{
|
|
INIT_API();
|
|
|
|
IPIDEntry IpId;
|
|
MEMORY_ADDRESS Addr = GetExpression(args);
|
|
|
|
if (Addr)
|
|
{
|
|
|
|
DWORD nCount=0;
|
|
|
|
while (Addr &&
|
|
ReadMemory(Addr,&IpId,sizeof(IpId),NULL))
|
|
{
|
|
dprintf(" -- %x\n",nCount);
|
|
DumpIPID(IpId);
|
|
|
|
Addr = (MEMORY_ADDRESS)IpId.pNextIPID;
|
|
nCount++;
|
|
|
|
if (CheckControlC())
|
|
break;
|
|
|
|
};
|
|
}
|
|
else
|
|
{
|
|
dprintf(" unable to resolve %s\n",args);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void PrintCLSID(GUID & CurrUUID){
|
|
|
|
WCHAR pszClsID[40];
|
|
StringFromGUID2(CurrUUID,pszClsID,40);
|
|
|
|
// look-up known
|
|
DWORD i;
|
|
for (i=0;i<g_nClsids;i++){
|
|
if(IsEqualGUID(CurrUUID,*g_ArrayCLSID[i].pClsid)){
|
|
dprintf(" CLSID %s\n",g_ArrayCLSID[i].pStrClsid);
|
|
break;
|
|
}
|
|
}
|
|
|
|
WCHAR pszFullPath[MAX_PATH];
|
|
lstrcpyW(pszFullPath,L"CLSID\\");
|
|
lstrcatW(pszFullPath,pszClsID);
|
|
|
|
char pDataA[MAX_PATH];
|
|
HKEY hKey;
|
|
LONG lRes;
|
|
|
|
lRes = RegOpenKeyExW(HKEY_CLASSES_ROOT,
|
|
pszFullPath,
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
|
|
if (lRes == ERROR_SUCCESS){
|
|
DWORD dwType;
|
|
WCHAR pData[MAX_PATH];
|
|
DWORD dwSize=sizeof(pData);
|
|
|
|
lRes = RegQueryValueExW(hKey,
|
|
NULL, // default
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)pData,
|
|
&dwSize);
|
|
if (lRes == ERROR_SUCCESS) {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pData,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf(" ProgID %s\n",pDataA);
|
|
|
|
};
|
|
RegCloseKey(hKey);
|
|
|
|
// no open InProcServer32
|
|
WCHAR pszFullPathDll[MAX_PATH];
|
|
lstrcpyW(pszFullPathDll,pszFullPath);
|
|
lstrcatW(pszFullPathDll,L"\\InprocServer32");
|
|
|
|
lRes = RegOpenKeyExW(HKEY_CLASSES_ROOT,
|
|
pszFullPathDll,
|
|
0,
|
|
KEY_READ,
|
|
&hKey);
|
|
if (lRes == ERROR_SUCCESS){
|
|
|
|
dwSize = sizeof(pData);
|
|
lRes = RegQueryValueExW(hKey,
|
|
NULL, // default
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)pData,
|
|
&dwSize);
|
|
|
|
if (lRes == ERROR_SUCCESS) {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pData,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf(" Path: %s\n",pDataA);
|
|
|
|
};
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
} else {
|
|
|
|
WideCharToMultiByte(CP_ACP,0,pszClsID,-1,pDataA,sizeof(pDataA),NULL,NULL);
|
|
dprintf(" CLSID %s\n",pDataA);
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
class CTableElement;
|
|
|
|
class CHashTable
|
|
{
|
|
private:
|
|
DWORD _cBuckets;
|
|
DWORD _cElements;
|
|
CTableElement **_buckets;
|
|
CTableElement *_last;
|
|
};
|
|
|
|
typedef int EnumEntryType;
|
|
typedef void CSharedLock;
|
|
typedef void CServerTable;
|
|
class CProcess;
|
|
|
|
class CServerList
|
|
{
|
|
public:
|
|
void * _first;
|
|
void * _last;
|
|
};
|
|
|
|
class CServerTableEntry{
|
|
private:
|
|
void * pvtable;
|
|
DWORD _references;
|
|
CServerTableEntry * _pnext;
|
|
|
|
//CLSID _GUID;
|
|
unsigned __int64 _id1;
|
|
unsigned __int64 _id2;
|
|
|
|
EnumEntryType _EntryType;
|
|
|
|
CSharedLock * _pParentTableLock;
|
|
CServerTable * _pParentTable;
|
|
LONG _lThreadToken;
|
|
DWORD _dwProcessId;
|
|
HANDLE _hProcess;
|
|
CProcess* _pProcess;
|
|
void * _pvRunAsHandle;
|
|
BOOL _bSuspendedClsid;
|
|
BOOL _bSuspendedApplication;
|
|
|
|
// the _bRetired flag exists per-running process/application
|
|
|
|
CServerList _ServerList;
|
|
//CSharedLock _ServerLock;
|
|
|
|
|
|
};
|
|
|
|
/*
|
|
0:008> dt rpcss!CServerListEntry 000a2608
|
|
+0x008 _flink : (null)
|
|
+0x00c _blink : (null)
|
|
+0x000 __VFN_table : 0x757f3a58
|
|
+0x004 _references :
|
|
+0x010 _pServerTableEntry : 0x000a3e38
|
|
+0x014 _pServerProcess : 0x00092568
|
|
+0x018 _hRpc : (null)
|
|
+0x01c _ipid : _GUID {0000dc01-0304-0000-905a-1b00ffec5639}
|
|
+0x02c _Context : 0x2 ''
|
|
+0x02d _State : 0 ''
|
|
+0x02e _NumCalls : 0
|
|
+0x030 _RegistrationKey : 0x10
|
|
+0x034 _lThreadToken : 0
|
|
+0x038 _SubContext : 0 ''
|
|
+0x03c _lSingleUseStatus : 0
|
|
+0x040 _dwServerFaults : 0
|
|
*/
|
|
|
|
struct CServerListEntry
|
|
{
|
|
void * pvtable;
|
|
DWORD _references;
|
|
void * _flink;
|
|
void * _blink;
|
|
void * _pServerTableEntry;
|
|
void * _pServerProcess;
|
|
void * _hRpc;
|
|
GUID _ipid;
|
|
};
|
|
|
|
/*
|
|
0:002> dt rpcss!CServerTableEntry 6fb`ffcdb170
|
|
+0x000 __VFN_table : 0x00000000`702a2b60
|
|
+0x008 _references :
|
|
+0x010 _pnext : (null)
|
|
+0x018 _id : 0x11d0f196`61738644
|
|
+0x020 _id2 : 0xc119d94f`c0005399
|
|
+0x028 _EntryType : 0 ( ENTRY_TYPE_CLASS )
|
|
+0x030 _pParentTableLock : 0x000006fb`ffc9d590
|
|
+0x038 _pParentTable : 0x000006fb`ffc9d700
|
|
+0x040 _bComPlusProcess : 0
|
|
+0x044 _lThreadToken : 0
|
|
+0x048 _dwProcessId : 0
|
|
+0x050 _hProcess : (null)
|
|
+0x058 _pProcess : (null)
|
|
+0x060 _pvRunAsHandle : (null)
|
|
+0x068 _bSuspendedClsid : 0
|
|
+0x06c _bSuspendedApplication : 0
|
|
+0x070 _ServerList : CServerList
|
|
+0x080 _ServerLock : CSharedLock
|
|
*/
|
|
|
|
DECLARE_API( rot )
|
|
{
|
|
|
|
INIT_API();
|
|
|
|
CHashTable * pChashTable;
|
|
MEMORY_ADDRESS Addr = GetExpression("rpcss!gpClassTable");
|
|
if (Addr)
|
|
{
|
|
CHashTable * pChashTable;
|
|
CHashTable MyHashTable;
|
|
|
|
if (ReadMemory(Addr,&pChashTable,sizeof(CHashTable *),0))
|
|
{
|
|
dprintf("CServerTable %p\n",pChashTable);
|
|
|
|
if (ReadMemory((ULONG_PTR)pChashTable,&MyHashTable,sizeof(CHashTable),NULL))
|
|
{
|
|
CTableElement ** StackArray = (CTableElement **)_alloca(MyHashTable._cBuckets * sizeof(CTableElement *));
|
|
|
|
ReadMemory((ULONG_PTR)MyHashTable._buckets,StackArray,MyHashTable._cBuckets * sizeof(CTableElement *),NULL);
|
|
|
|
DWORD i;
|
|
for (i=0;i<MyHashTable._cBuckets;i++)
|
|
{
|
|
CServerTableEntry * pEntry = (CServerTableEntry *)StackArray[i];
|
|
|
|
while (pEntry)
|
|
{
|
|
CheckControlC();
|
|
CServerTableEntry ClassEntry;
|
|
if (ReadMemory((ULONG_PTR)pEntry,&ClassEntry,sizeof(ClassEntry),NULL))
|
|
{
|
|
dprintf("CServerTableEntry %p\n",pEntry);
|
|
PrintCLSID(*(GUID *)(&(ClassEntry._id1)));
|
|
//dprintf(" _hProcess %x\n",ClassEntry._hProcess);
|
|
//dprintf(" _dwProcessId %d\n",ClassEntry._dwProcessId);
|
|
dprintf(" _ServerList %p %p\n",ClassEntry._ServerList._first,ClassEntry._ServerList._last);
|
|
|
|
CServerListEntry * pSrvListEntry = CONTAINING_RECORD(ClassEntry._ServerList._first,CServerListEntry,_flink);
|
|
while(pSrvListEntry)
|
|
{
|
|
CServerListEntry SrvListEntry;
|
|
if (ReadMemory((ULONG_PTR)pSrvListEntry,&SrvListEntry,sizeof(SrvListEntry),NULL))
|
|
{
|
|
dprintf(" CServerListEntry %p\n",pSrvListEntry);
|
|
dprintf(" _pServerTableEntry %p\n",SrvListEntry._pServerTableEntry);
|
|
dprintf(" _pServerProcess %p\n",SrvListEntry._pServerProcess);
|
|
dprintf(" _hRpc %p\n",SrvListEntry._hRpc);
|
|
WCHAR TmpGuid[64];
|
|
StringFromGUID2(SrvListEntry._ipid,TmpGuid,64);
|
|
dprintf(" _ipid %S\n",TmpGuid);
|
|
pSrvListEntry = (CServerListEntry *)SrvListEntry._flink;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pSrvListEntry);
|
|
pSrvListEntry = NULL;
|
|
}
|
|
}
|
|
|
|
pEntry = ClassEntry._pnext;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pEntry);
|
|
pEntry = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pChashTable);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",Addr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("unable to resolve rpcss!gpClassTable");
|
|
}
|
|
|
|
}
|
|
|
|
class CBList
|
|
{
|
|
public:
|
|
ULONG _ulmaxData;
|
|
ULONG _ulcElements;
|
|
PVOID *_data;
|
|
};
|
|
|
|
class CReferencedObject
|
|
{
|
|
public:
|
|
ULONG _references;
|
|
virtual ~CReferencedObject(){};
|
|
};
|
|
|
|
class CToken;
|
|
class ScmProcessReg;
|
|
class CList;
|
|
|
|
class CListElement
|
|
{
|
|
public:
|
|
CListElement *_flink;
|
|
CListElement *_blink;
|
|
};
|
|
|
|
class CClassReg : public CListElement
|
|
{
|
|
public :
|
|
GUID _Guid;
|
|
DWORD _Reg;
|
|
};
|
|
|
|
class CList
|
|
{
|
|
private:
|
|
CListElement *_first;
|
|
CListElement *_last;
|
|
};
|
|
|
|
class CProcess : public CReferencedObject
|
|
{
|
|
private:
|
|
|
|
DWORD _cClientReferences;
|
|
CToken *_pToken;
|
|
WCHAR *_pwszWinstaDesktop;
|
|
RPC_BINDING_HANDLE _hProcess;
|
|
BOOL _fCacheFree;
|
|
DUALSTRINGARRAY *_pdsaLocalBindings;
|
|
DUALSTRINGARRAY *_pdsaRemoteBindings;
|
|
ULONG _ulClasses;
|
|
ScmProcessReg *_pScmProcessReg;
|
|
DUALSTRINGARRAY *_pdsaCustomProtseqs;
|
|
void *_pvRunAsHandle;
|
|
DWORD _procID;
|
|
volatile DWORD _dwFlags;
|
|
void* _pSCMProcessInfo;
|
|
GUID _guidProcessIdentifier;
|
|
HANDLE _hProcHandle;
|
|
FILETIME _ftCreated;
|
|
DWORD64 _dwCurrentBindingsID;
|
|
DWORD _dwAsyncUpdatesOutstanding; // for debug purposes?
|
|
|
|
void *_pvFirstROTEntry;
|
|
|
|
BOOL _fReadCustomProtseqs;
|
|
CBList _blistOxids;
|
|
CBList _blistOids;
|
|
CList _listClasses;
|
|
|
|
DWORD _cDropTargets;
|
|
};
|
|
|
|
|
|
DECLARE_API(gpl)
|
|
{
|
|
INIT_API();
|
|
//dt rpcss!gpProcessList
|
|
ULONG_PTR Addr = GetExpression("rpcss!gpProcessList");
|
|
if (Addr)
|
|
{
|
|
CBList * pList_OOP;
|
|
if (ReadMemory(Addr,&pList_OOP,sizeof(ULONG_PTR),NULL))
|
|
{
|
|
CBList List;
|
|
if (ReadMemory((ULONG_PTR)pList_OOP,&List,sizeof(List),0))
|
|
{
|
|
PVOID * ppData = new PVOID[List._ulmaxData];
|
|
if (ppData)
|
|
{
|
|
if (ReadMemory((ULONG_PTR)List._data,ppData,sizeof(PVOID)*List._ulmaxData,NULL))
|
|
{
|
|
for (ULONG_PTR i=0;i<List._ulmaxData;i++)
|
|
{
|
|
CProcess * pProc = (CProcess *)ppData[i];
|
|
if (pProc)
|
|
{
|
|
CProcess Proc;
|
|
if (ReadMemory((ULONG_PTR)pProc,&Proc,sizeof(Proc),0))
|
|
{
|
|
dprintf(" CProcess %p\n",pProc);
|
|
dprintf(" _procID %08x BINDING_HANDLE %p\n",Proc._procID,Proc._hProcess);
|
|
|
|
CClassReg ClassRegInst;
|
|
CClassReg * pFirst = (CClassReg *)Proc._listClasses._first;
|
|
while(pFirst)
|
|
{
|
|
if (ReadMemory((ULONG_PTR)pFirst,&ClassRegInst,sizeof(ClassRegInst),0))
|
|
{
|
|
PrintCLSID(ClassRegInst._Guid);
|
|
pFirst = (CClassReg *)ClassRegInst._flink;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pFirst);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pProc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",List._data);
|
|
}
|
|
delete [] ppData;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pList_OOP);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",Addr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("unable to resolve rpcss!gpProcessList");
|
|
}
|
|
}
|
|
|
|
|
|
typedef struct SHashChain
|
|
{
|
|
struct SHashChain *pNext; // ptr to next node in chain
|
|
struct SHashChain *pPrev; // ptr to prev node in chain
|
|
} SHashChain;
|
|
|
|
|
|
typedef struct SNameHashNode
|
|
{
|
|
SHashChain chain; // double linked list ptrs
|
|
DWORD dwHash; // hash value of the key
|
|
ULONG cRef; // count of references
|
|
IPID ipid; // ipid holding the reference
|
|
SECURITYBINDING sName; // user name
|
|
} SNameHashNode;
|
|
|
|
|
|
class COleStaticMutexSem;
|
|
class CStaticRWLock;
|
|
|
|
class CHashTable2
|
|
{
|
|
public:
|
|
virtual ~CHashTable2(){};
|
|
|
|
COleStaticMutexSem *_pExLock; // exclusive lock
|
|
CStaticRWLock *_pRWLock; // read-write lock
|
|
SHashChain *_buckets; // ptr to array of double linked lists
|
|
ULONG _cCurEntries; // current num entries in the table
|
|
ULONG _cMaxEntries; // max num entries in the table at 1 time
|
|
};
|
|
|
|
void PrintNameNode(SNameHashNode * pNode)
|
|
{
|
|
dprintf(" dwHash %08x\n",pNode->dwHash); // hash value of the key
|
|
dprintf(" cRef %08x\n",pNode->cRef); // count of references
|
|
dprintf(" ipid\n");
|
|
PrintIID(pNode->ipid); // ipid holding the reference
|
|
dprintf(" sName %S\n",&pNode->sName.aPrincName);
|
|
}
|
|
|
|
|
|
#define NUM_HASH_BUCKETS 23
|
|
|
|
DECLARE_API( srtbl )
|
|
{
|
|
|
|
INIT_API();
|
|
|
|
CHashTable2 * pChashTable;
|
|
MEMORY_ADDRESS Addr = GetExpression("ole32!gSRFTbl");
|
|
if (Addr)
|
|
{
|
|
dprintf("CNameHashTable %p\n",Addr);
|
|
CHashTable2 MyHashTable;
|
|
if (ReadMemory((ULONG_PTR)Addr,&MyHashTable,sizeof(CHashTable2),NULL))
|
|
{
|
|
SHashChain * StackArray = (SHashChain *)_alloca(NUM_HASH_BUCKETS * sizeof(SHashChain));
|
|
|
|
ReadMemory((ULONG_PTR)MyHashTable._buckets,StackArray,NUM_HASH_BUCKETS * sizeof(SHashChain),NULL);
|
|
|
|
DWORD i;
|
|
SHashChain * pEntry_OOP = (SHashChain *)MyHashTable._buckets;
|
|
for (i=0;i < NUM_HASH_BUCKETS;pEntry_OOP++,i++)
|
|
{
|
|
SHashChain * pEntry = StackArray[i].pNext;
|
|
//dprintf("%p %p\n",pEntry_OOP,pEntry);
|
|
while (pEntry != pEntry_OOP)
|
|
{
|
|
if (CheckControlC()) break;
|
|
|
|
struct _NameNode : SNameHashNode
|
|
{
|
|
WCHAR UserName[256];
|
|
} Node;
|
|
Node.UserName[0] = 0;
|
|
if (ReadMemory((ULONG_PTR)pEntry,&Node,sizeof(Node),NULL))
|
|
{
|
|
dprintf("SNameHashNode %p\n",pEntry);
|
|
PrintNameNode(&Node);
|
|
pEntry = Node.chain.pNext;
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",Addr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("unable to resolve ole32!gSRFTbl");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
struct RTL_CRITICAL_SECTION_DEBUG {
|
|
USHORT Type; //: 0x0
|
|
USHORT CreatorBackTraceIndex; //: 0x0
|
|
CRITICAL_SECTION * CriticalSection; //: 0x77fcae40
|
|
LIST_ENTRY ProcessLocksList; //:
|
|
DWORD EntryCount; //: 0x0
|
|
DWORD ContentionCount; //: 0x0
|
|
DWORD Spare[2]; //:0x0
|
|
};
|
|
*/
|
|
|
|
//
|
|
//
|
|
// CallBack for enumeration of critical section
|
|
//
|
|
//
|
|
/////////////////////////////////////////////////////////////
|
|
|
|
DWORD
|
|
EnumListCritSec(VOID * pStructure_OOP,
|
|
VOID * pLocalStructure)
|
|
{
|
|
|
|
RTL_CRITICAL_SECTION_DEBUG * pDebugInfo = (RTL_CRITICAL_SECTION_DEBUG *)pLocalStructure;
|
|
dprintf(" CS %p DI %p \n",pDebugInfo->CriticalSection,pStructure_OOP);
|
|
|
|
RTL_CRITICAL_SECTION CritSec;
|
|
|
|
if (ReadMemory((ULONG_PTR)pDebugInfo->CriticalSection,&CritSec,sizeof(RTL_CRITICAL_SECTION),NULL))
|
|
{
|
|
dprintf(" - %p %x %x %x\n",
|
|
CritSec.DebugInfo,
|
|
CritSec.LockCount,
|
|
CritSec.RecursionCount,
|
|
CritSec.OwningThread);
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",pDebugInfo->CriticalSection);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define ARRAY_TO_GO_BACK 16
|
|
|
|
DWORD
|
|
EnumListCritSec2(VOID * pStructure_OOP,
|
|
VOID * pLocalStructure)
|
|
{
|
|
|
|
RTL_CRITICAL_SECTION_DEBUG * pDebugInfo = (RTL_CRITICAL_SECTION_DEBUG *)pLocalStructure;
|
|
dprintf(" CS %p DI %p \n",pDebugInfo->CriticalSection,pStructure_OOP);
|
|
|
|
struct _TmpStr {
|
|
ULONG_PTR Array[ARRAY_TO_GO_BACK];
|
|
RTL_CRITICAL_SECTION CritSec;
|
|
} TmpStr;
|
|
|
|
if (ReadMemory(((ULONG_PTR)pDebugInfo->CriticalSection) - FIELD_OFFSET(_TmpStr,CritSec),&TmpStr,sizeof(_TmpStr),NULL))
|
|
{
|
|
dprintf(" - %p %x %x %x\n",
|
|
TmpStr.CritSec.DebugInfo,
|
|
TmpStr.CritSec.LockCount,
|
|
TmpStr.CritSec.RecursionCount,
|
|
TmpStr.CritSec.OwningThread);
|
|
|
|
for (int i=(ARRAY_TO_GO_BACK-1);i>=0;i--)
|
|
{
|
|
if (GetVTable((MEMORY_ADDRESS)TmpStr.Array[i]))
|
|
{
|
|
break; // don't be too verbose
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM around %p\n",pDebugInfo->CriticalSection);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
DECLARE_API( cs )
|
|
{
|
|
INIT_API();
|
|
|
|
MEMORY_ADDRESS Addr = GetExpression("ntdll!RtlCriticalSectionList");
|
|
|
|
MEMORY_ADDRESS bGoAndFindVTable = TRUE;
|
|
|
|
if (!Addr)
|
|
{
|
|
Addr = GetExpression(args);
|
|
}
|
|
else
|
|
{
|
|
bGoAndFindVTable = GetExpression(args);
|
|
}
|
|
|
|
if (Addr)
|
|
{
|
|
if (bGoAndFindVTable)
|
|
{
|
|
EnumLinkedListCB((LIST_ENTRY *)Addr,
|
|
sizeof(RTL_CRITICAL_SECTION_DEBUG),
|
|
FIELD_OFFSET(RTL_CRITICAL_SECTION_DEBUG,ProcessLocksList),
|
|
EnumListCritSec2);
|
|
}
|
|
else
|
|
{
|
|
EnumLinkedListCB((LIST_ENTRY *)Addr,
|
|
sizeof(RTL_CRITICAL_SECTION_DEBUG),
|
|
FIELD_OFFSET(RTL_CRITICAL_SECTION_DEBUG,ProcessLocksList),
|
|
EnumListCritSec);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("unable to resolve ntdll!RtlCriticalSectionList\n");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
GetVTable(MEMORY_ADDRESS pThis_OOP){
|
|
|
|
MEMORY_ADDRESS pVTable;
|
|
ReadMemory(pThis_OOP,&pVTable,sizeof(pVTable),0);
|
|
|
|
BYTE pString[256];
|
|
pString[0]=0;
|
|
|
|
#ifdef KDEXT_64BIT
|
|
ULONG64 Displ;
|
|
#else
|
|
ULONG Displ;
|
|
#endif
|
|
|
|
GetSymbol(pVTable,(PCHAR)pString,&Displ);
|
|
if (lstrlenA((CHAR *)pString))
|
|
{
|
|
dprintf(" %s+%x\n",pString,Displ);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
kd> dt ntdll!RTL_CRITICAL_SECTION
|
|
+0x000 DebugInfo : Ptr64 _RTL_CRITICAL_SECTION_DEBUG
|
|
+0x008 LockCount : Int4B
|
|
+0x00c RecursionCount : Int4B
|
|
+0x010 OwningThread : Ptr64 Void
|
|
+0x018 LockSemaphore : Ptr64 Void
|
|
+0x020 SpinCount : Uint8B
|
|
kd> dt ntdll!_RTL_CRITICAL_SECTION_DEBUG
|
|
+0x000 Type : Uint2B
|
|
+0x002 CreatorBackTraceIndex : Uint2B
|
|
+0x008 CriticalSection : Ptr64 _RTL_CRITICAL_SECTION
|
|
+0x010 ProcessLocksList : _LIST_ENTRY
|
|
+0x020 EntryCount : Uint4B
|
|
+0x024 ContentionCount : Uint4B
|
|
+0x028 Spare : [2] Uint4B
|
|
kd>
|
|
*/
|
|
|
|
#ifdef KDEXT_64BIT
|
|
|
|
struct _LIST_ENTRY_64
|
|
{
|
|
ULONG64 Flink;
|
|
ULONG64 Blink;
|
|
};
|
|
|
|
struct _RTL_CRITICAL_SECTION_64
|
|
{
|
|
ULONG64 DebugInfo;
|
|
DWORD LockCount;
|
|
DWORD RecursionCount;
|
|
ULONG64 OwningThread;
|
|
ULONG64 LockSemaphore;
|
|
ULONG64 SpinCount;
|
|
};
|
|
|
|
struct _RTL_CRITICAL_SECTION_DEBUG_64
|
|
{
|
|
WORD Type;
|
|
WORD CreatorBackTraceIndex;
|
|
ULONG64 CriticalSection;
|
|
_LIST_ENTRY_64 ProcessLocksList;
|
|
DWORD EntryCount;
|
|
DWORD ContentionCount;
|
|
DWORD Spare;
|
|
};
|
|
|
|
#endif /*KDEXT_64BIT*/
|
|
|
|
DECLARE_API(cs64)
|
|
{
|
|
INIT_API();
|
|
#ifdef KDEXT_64BIT
|
|
|
|
_RTL_CRITICAL_SECTION_DEBUG_64 DebugInfo;
|
|
_RTL_CRITICAL_SECTION_64 CritSec;
|
|
_LIST_ENTRY_64 ListEntry;
|
|
ULONG64 MemAddr = GetExpression(args);
|
|
|
|
if (MemAddr)
|
|
{
|
|
ULONG64 AddrHead = MemAddr;
|
|
if (ReadMemory(MemAddr,&ListEntry,sizeof(ListEntry),NULL))
|
|
{
|
|
DebugInfo.ProcessLocksList.Flink = ListEntry.Flink;
|
|
while (DebugInfo.ProcessLocksList.Flink != AddrHead)
|
|
{
|
|
if (CheckControlC())
|
|
break;
|
|
|
|
MemAddr = DebugInfo.ProcessLocksList.Flink - FIELD_OFFSET(_RTL_CRITICAL_SECTION_DEBUG_64,ProcessLocksList);
|
|
|
|
if (ReadMemory((MEMORY_ADDRESS)MemAddr,&DebugInfo,sizeof(DebugInfo),NULL))
|
|
{
|
|
dprintf(" C %p D %p\n",DebugInfo.CriticalSection,MemAddr);
|
|
|
|
if (ReadMemory((MEMORY_ADDRESS)DebugInfo.CriticalSection,&CritSec,sizeof(CritSec),NULL))
|
|
{
|
|
dprintf(" - CS %p %x %x %p\n",
|
|
CritSec.DebugInfo,
|
|
CritSec.LockCount,
|
|
CritSec.RecursionCount,
|
|
CritSec.OwningThread);
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",DebugInfo.CriticalSection);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("RM %p\n",MemAddr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf("unable to resolve %s\n",args);
|
|
}
|
|
|
|
#endif /*KDEXT_64BIT*/
|
|
}
|
|
|
|
|