Source code of Windows XP (NT5)
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.

1260 lines
36 KiB

  1. #include <wmiexts.h>
  2. #include <malloc.h>
  3. void GetTeb(HANDLE hThread,TEB ** ppTeb)
  4. {
  5. NTSTATUS Status;
  6. ULONG Long;
  7. THREAD_BASIC_INFORMATION TBasicInfo;
  8. Status = NtQueryInformationThread(hThread,
  9. ThreadBasicInformation,
  10. &TBasicInfo,
  11. sizeof(TBasicInfo),
  12. &Long);
  13. if ( Status == 0 )
  14. {
  15. //dprintf(" %p %x.%x\n",TBasicInfo.TebBaseAddress,TBasicInfo.ClientId.UniqueProcess,TBasicInfo.ClientId.UniqueThread);
  16. if (ppTeb)
  17. {
  18. *ppTeb = TBasicInfo.TebBaseAddress;
  19. }
  20. }
  21. else
  22. {
  23. dprintf(" NtQueryInformationThread %08x\n",Status);
  24. }
  25. }
  26. void GetCid(HANDLE hThread,CLIENT_ID * pCid)
  27. {
  28. NTSTATUS Status;
  29. ULONG Long;
  30. THREAD_BASIC_INFORMATION TBasicInfo;
  31. Status = NtQueryInformationThread(hThread,
  32. ThreadBasicInformation,
  33. &TBasicInfo,
  34. sizeof(TBasicInfo),
  35. &Long);
  36. if ( Status == 0 )
  37. {
  38. //dprintf(" %p %x.%x\n",TBasicInfo.TebBaseAddress,TBasicInfo.ClientId.UniqueProcess,TBasicInfo.ClientId.UniqueThread);
  39. if (pCid)
  40. {
  41. memcpy(pCid,&TBasicInfo.ClientId, sizeof(CLIENT_ID));
  42. }
  43. }
  44. else
  45. {
  46. dprintf(" NtQueryInformationThread %08x\n",Status);
  47. }
  48. }
  49. void GetPeb(HANDLE hSourceProcess, PEB ** ppPeb, ULONG_PTR * pId)
  50. {
  51. NTSTATUS Status;
  52. ULONG Long;
  53. PROCESS_BASIC_INFORMATION PBasicInfo;
  54. Status = NtQueryInformationProcess(hSourceProcess,
  55. ProcessBasicInformation,
  56. &PBasicInfo,
  57. sizeof(PBasicInfo),
  58. &Long);
  59. if ( Status == 0 )
  60. {
  61. if (ppPeb)
  62. {
  63. *ppPeb = PBasicInfo.PebBaseAddress;
  64. }
  65. if (pId)
  66. {
  67. *pId = PBasicInfo.UniqueProcessId;
  68. }
  69. }
  70. else
  71. {
  72. dprintf(" NTSTATUS %08x\n",Status);
  73. }
  74. }
  75. //
  76. void PrintHandleBackTrace(HANDLE hHandle,WCHAR * pFileName)
  77. {
  78. WCHAR pPath[MAX_PATH+1];
  79. GetEnvironmentVariableW(L"windir",pPath,MAX_PATH);
  80. lstrcatW(pPath,L"\\system32\\");
  81. lstrcatW(pPath,pFileName);
  82. HANDLE hFile = NULL;
  83. hFile = CreateFileW(pPath,
  84. GENERIC_READ,
  85. FILE_SHARE_READ|FILE_SHARE_WRITE,
  86. NULL,
  87. OPEN_EXISTING,
  88. 0,NULL);
  89. if (INVALID_HANDLE_VALUE != hFile)
  90. {
  91. DWORD dwSize = GetFileSize(hFile,NULL);
  92. HANDLE hFileMap = CreateFileMapping(hFile,
  93. NULL,
  94. PAGE_READONLY,
  95. 0,
  96. dwSize,
  97. NULL);
  98. if (hFileMap)
  99. {
  100. HANDLE * pHandle = (HANDLE *)MapViewOfFile(hFileMap,
  101. FILE_MAP_READ,
  102. 0,0,0);
  103. if(pHandle)
  104. {
  105. //dprintf("hEvent %p dwSize %x\n",hEvent,dwSize);
  106. DWORD SizeRecord = 8*sizeof(HANDLE);
  107. DWORD nRecord = dwSize/SizeRecord;
  108. HANDLE * pThisHandle = NULL;
  109. DWORD i;
  110. if (hHandle)
  111. {
  112. for(i=0;i<nRecord;i++)
  113. {
  114. if (hHandle == pHandle[(SizeRecord/sizeof(HANDLE))*(nRecord-1-i)])
  115. {
  116. pThisHandle = &pHandle[(SizeRecord/sizeof(HANDLE))*(nRecord-1-i)];
  117. break;
  118. }
  119. else
  120. {
  121. //dprintf(" %d %p\n",nRecord-1-i,pHandle[(SizeRecord/sizeof(HANDLE))*(nRecord-1-i)]);
  122. }
  123. }
  124. if(pThisHandle)
  125. {
  126. dprintf(" found rec %x handle %p\n",nRecord-1-i,*pThisHandle);
  127. PrintStackTrace((ULONG_PTR)pThisHandle+sizeof(HANDLE),7,FALSE);
  128. }
  129. else
  130. {
  131. dprintf("handle %x not found\n",hHandle);
  132. }
  133. }
  134. else // print all of them
  135. {
  136. dprintf("all records\n");
  137. for(i=0;i<nRecord;i++)
  138. {
  139. pThisHandle = &pHandle[(SizeRecord/sizeof(HANDLE))*(nRecord-1-i)];
  140. dprintf(" ------ %p\n",*pThisHandle);
  141. PrintStackTrace((ULONG_PTR)pThisHandle+sizeof(HANDLE),7,FALSE);
  142. if (CheckControlC())
  143. break;
  144. }
  145. }
  146. UnmapViewOfFile(pHandle);
  147. }
  148. else
  149. {
  150. dprintf("MapViewOfFile %d\n",GetLastError());
  151. }
  152. CloseHandle(hFileMap);
  153. }
  154. else
  155. {
  156. dprintf("CreateFileMapping %d\n",GetLastError());
  157. };
  158. CloseHandle(hFile);
  159. }
  160. else
  161. {
  162. dprintf("CreateFile %S %d\n",pPath,GetLastError());
  163. }
  164. }
  165. //
  166. DECLARE_API( refcnt )
  167. {
  168. INIT_API();
  169. PrintHandleBackTrace(NULL,L"refcount.dat");
  170. }
  171. //
  172. DECLARE_API( evtst )
  173. {
  174. INIT_API();
  175. ULONG_PTR Addr = GetExpression(args);
  176. HANDLE hEvent = (HANDLE)Addr;
  177. if (hEvent)
  178. {
  179. PrintHandleBackTrace(hEvent,L"events.dat");
  180. }
  181. }
  182. #define INCREMENT_ALLOC (4*1024)
  183. char * g_HandleType[] =
  184. {
  185. "",
  186. "",
  187. "",
  188. "",
  189. "Event",
  190. "",
  191. "",
  192. "",
  193. "",
  194. "Token",
  195. "",
  196. "",
  197. "",
  198. "",
  199. "",
  200. "", // 15
  201. "",
  202. "",
  203. "",
  204. "",
  205. "Port",
  206. "",
  207. "",
  208. "",
  209. "",
  210. "",
  211. "",
  212. "",
  213. "",
  214. "",
  215. "",
  216. "",
  217. "",
  218. "",
  219. "",
  220. "",
  221. ""
  222. };
  223. DECLARE_API( handle )
  224. {
  225. INIT_API();
  226. NTSTATUS Status;
  227. SYSTEM_HANDLE_INFORMATION * pSysHandleInfo = NULL;
  228. DWORD dwSize = INCREMENT_ALLOC;
  229. DWORD nReturned;
  230. ULONG_PTR lProcId;
  231. GetPeb(hCurrentProcess,NULL,&lProcId);
  232. USHORT ProcId = (USHORT)lProcId;
  233. alloc_again:
  234. pSysHandleInfo = (SYSTEM_HANDLE_INFORMATION *)HeapAlloc(GetProcessHeap(),0,dwSize);
  235. if (pSysHandleInfo)
  236. {
  237. Status = NtQuerySystemInformation(SystemHandleInformation,
  238. pSysHandleInfo,
  239. dwSize,
  240. &nReturned);
  241. }
  242. else
  243. {
  244. goto leave;
  245. }
  246. if (STATUS_INFO_LENGTH_MISMATCH == Status)
  247. {
  248. HeapFree(GetProcessHeap(),0,pSysHandleInfo);
  249. dwSize += INCREMENT_ALLOC;
  250. goto alloc_again;
  251. }
  252. else if (0 == Status)
  253. {
  254. // we have all the handles
  255. // SYSTEM_HANDLE_TABLE_ENTRY_INFO
  256. for (DWORD i=0; i < pSysHandleInfo->NumberOfHandles; i++)
  257. {
  258. if (ProcId == pSysHandleInfo->Handles[i].UniqueProcessId)
  259. {
  260. //dprintf(" %s - %x\n",
  261. // g_HandleType[pSysHandleInfo->Handles[i].ObjectTypeIndex],
  262. // pSysHandleInfo->Handles[i].HandleValue);
  263. if (4 == pSysHandleInfo->Handles[i].ObjectTypeIndex)
  264. {
  265. PrintHandleBackTrace((HANDLE)(pSysHandleInfo->Handles[i].HandleValue),L"events.dat");
  266. }
  267. }
  268. if (CheckControlC())
  269. break;
  270. }
  271. }
  272. else
  273. {
  274. dprintf("");
  275. }
  276. leave:
  277. if (pSysHandleInfo)
  278. {
  279. HeapFree(GetProcessHeap(),0,pSysHandleInfo);
  280. }
  281. return;
  282. }
  283. //
  284. //
  285. // Invoke a function in the remote process
  286. //
  287. //////////////////////////////////////////
  288. DECLARE_API( inv )
  289. {
  290. INIT_API();
  291. int Len = strlen(args);
  292. CHAR * pArgs = (CHAR *)_alloca((Len+1));
  293. lstrcpy(pArgs,(CHAR *)args);
  294. ULONG_PTR pFunction = 0;
  295. ULONG_PTR pArgument = 0;
  296. while (isspace(*pArgs))
  297. {
  298. pArgs++;
  299. }
  300. CHAR * pSaved = pArgs;
  301. while(!isspace(*pArgs)) pArgs++;
  302. // terminate string, if possible
  303. if (isspace(*pArgs))
  304. {
  305. *pArgs = 0;
  306. pArgs++;
  307. }
  308. else
  309. {
  310. pArgs = NULL;
  311. }
  312. pFunction = GetExpression(pSaved);
  313. if (pArgs)
  314. {
  315. pArgument = GetExpression(pArgs);
  316. }
  317. dprintf("invoking %s(%p) @ %p\n",pSaved,pArgument,pFunction);
  318. DWORD dwID;
  319. HANDLE hThread = CreateRemoteThread(hCurrentProcess,
  320. NULL,
  321. 0,
  322. (LPTHREAD_START_ROUTINE )pFunction,
  323. (LPVOID)pArgument,
  324. 0,
  325. &dwID);
  326. if (hThread)
  327. {
  328. CLIENT_ID Cid;
  329. GetCid(hThread,&Cid);
  330. DEBUG_EVENT de;
  331. BOOL bRet = FALSE;
  332. BOOL StatusRemoteThreadCreated = FALSE;
  333. wait_again:
  334. bRet = WaitForDebugEvent(&de,INFINITE);
  335. if (bRet)
  336. {
  337. switch(de.dwDebugEventCode)
  338. {
  339. case OUTPUT_DEBUG_STRING_EVENT:
  340. {
  341. OUTPUT_DEBUG_STRING_INFO * pDbgStr = &de.u.DebugString;
  342. WCHAR * pData = new WCHAR[pDbgStr->nDebugStringLength+1];
  343. if(pDbgStr->fUnicode)
  344. {
  345. ReadMemory((ULONG_PTR)pDbgStr->lpDebugStringData,pData,pDbgStr->nDebugStringLength*sizeof(WCHAR),NULL);
  346. dprintf("%S",pData);
  347. }
  348. else
  349. {
  350. ReadMemory((ULONG_PTR)pDbgStr->lpDebugStringData,pData,pDbgStr->nDebugStringLength*sizeof(CHAR),NULL);
  351. dprintf("%s",pData);
  352. }
  353. delete [] pData;
  354. }
  355. bRet = ContinueDebugEvent((DWORD)((DWORD_PTR)Cid.UniqueProcess),(DWORD)((DWORD_PTR)Cid.UniqueThread),DBG_CONTINUE);
  356. if (bRet)
  357. {
  358. goto wait_again;
  359. }
  360. break;
  361. case CREATE_THREAD_DEBUG_EVENT:
  362. if ((DWORD)((DWORD_PTR)Cid.UniqueProcess) == de.dwProcessId &&
  363. (DWORD)((DWORD_PTR)Cid.UniqueThread) == de.dwThreadId)
  364. {
  365. if (!StatusRemoteThreadCreated)
  366. {
  367. StatusRemoteThreadCreated = TRUE;
  368. }
  369. }
  370. else
  371. {
  372. dprintf("%x.%x != %x.%x\n",
  373. de.dwProcessId,de.dwThreadId,
  374. (DWORD)((DWORD_PTR)Cid.UniqueProcess),(DWORD)((DWORD_PTR)Cid.UniqueThread));
  375. }
  376. bRet = ContinueDebugEvent((DWORD)((DWORD_PTR)Cid.UniqueProcess),(DWORD)((DWORD_PTR)Cid.UniqueThread),DBG_CONTINUE);
  377. if (bRet)
  378. {
  379. goto wait_again;
  380. };
  381. break;
  382. case CREATE_PROCESS_DEBUG_EVENT:
  383. case EXIT_PROCESS_DEBUG_EVENT:
  384. //dprintf("DebugEventCode %08x for %x.%x\n",de.dwDebugEventCode,de.dwProcessId,de.dwThreadId);
  385. bRet = ContinueDebugEvent((DWORD)((DWORD_PTR)Cid.UniqueProcess),(DWORD)((DWORD_PTR)Cid.UniqueThread),DBG_CONTINUE);
  386. if (bRet)
  387. {
  388. goto wait_again;
  389. };
  390. break;
  391. case EXCEPTION_DEBUG_EVENT:
  392. {
  393. EXCEPTION_DEBUG_INFO * pExcDebug = &de.u.Exception;
  394. dprintf("%08x %08x FIRST? %d\n",
  395. pExcDebug->ExceptionRecord.ExceptionCode,
  396. pExcDebug->ExceptionRecord.ExceptionAddress,
  397. pExcDebug->dwFirstChance);
  398. bRet = ContinueDebugEvent((DWORD)((DWORD_PTR)Cid.UniqueProcess),(DWORD)((DWORD_PTR)Cid.UniqueThread),DBG_TERMINATE_THREAD);
  399. if (bRet)
  400. {
  401. goto wait_again;
  402. }
  403. }
  404. break;
  405. case EXIT_THREAD_DEBUG_EVENT:
  406. if ((DWORD)((DWORD_PTR)Cid.UniqueProcess) == de.dwProcessId &&
  407. (DWORD)((DWORD_PTR)Cid.UniqueThread) == de.dwThreadId)
  408. {
  409. if (StatusRemoteThreadCreated)
  410. {
  411. // ok
  412. }
  413. else
  414. {
  415. dprintf("EXIT_THREAD_DEBUG_EVENT %x.%x =?= %x.%x\n",
  416. de.dwProcessId,de.dwThreadId,(DWORD)((DWORD_PTR)Cid.UniqueProcess),(DWORD)((DWORD_PTR)Cid.UniqueThread));
  417. }
  418. //
  419. // we are done
  420. //
  421. }
  422. else
  423. {
  424. bRet = ContinueDebugEvent((DWORD)((DWORD_PTR)Cid.UniqueProcess),(DWORD)((DWORD_PTR)Cid.UniqueThread),DBG_CONTINUE);
  425. if (bRet)
  426. {
  427. goto wait_again;
  428. }
  429. }
  430. break;
  431. case LOAD_DLL_DEBUG_EVENT:
  432. case UNLOAD_DLL_DEBUG_EVENT:
  433. //dprintf("DebugEventCode %08x for %x.%x CONTINUE\n",de.dwDebugEventCode,de.dwProcessId,de.dwThreadId);
  434. bRet = ContinueDebugEvent((DWORD)((DWORD_PTR)Cid.UniqueProcess),(DWORD)((DWORD_PTR)Cid.UniqueThread),DBG_CONTINUE);
  435. if (bRet)
  436. {
  437. goto wait_again;
  438. }
  439. break;
  440. default:
  441. dprintf("DebugEventCode %08x\n ?????",de.dwDebugEventCode);
  442. //ContinueDebugEvent((DWORD)Cid.UniqueProcess,(DWORD)Cid.UniqueThread,DBG_TERMINATE_THREAD);
  443. }
  444. }
  445. else
  446. {
  447. dprintf("WaitForDebugEvent err: %d\n",GetLastError());
  448. }
  449. CloseHandle(hThread);
  450. }
  451. else
  452. {
  453. dprintf("CreateRemoteThread %d\n",GetLastError());
  454. }
  455. }
  456. //
  457. //
  458. // Dumps the thread list with some info on OLE and RPC
  459. //
  460. //
  461. //
  462. //
  463. // rpcrt4!THREAD
  464. // ole32!SOleTlsData
  465. //
  466. void
  467. DumpRpcOle(ULONG_PTR pRpc,ULONG_PTR pOle)
  468. {
  469. if (pRpc)
  470. {
  471. ULONG OffsetContext;
  472. ULONG_PTR pRpcLRPC = 0;
  473. if (0 != GetFieldOffset("rpcrt4!THREAD","Context",&OffsetContext))
  474. {
  475. #ifdef _WIN64
  476. OffsetContext = 0x18;
  477. #else
  478. OffsetContext = 0x10;
  479. #endif
  480. }
  481. ReadMemory(pRpc+OffsetContext,&pRpcLRPC,sizeof(ULONG_PTR),0);
  482. ULONG_PTR pFirstVoid = 0;
  483. ReadMemory((ULONG_PTR)pRpcLRPC,&pFirstVoid,sizeof(ULONG_PTR),0);
  484. BYTE pString[256];
  485. pString[0]=0;
  486. #ifdef KDEXT_64BIT
  487. ULONG64 Displ;
  488. #else
  489. ULONG Displ;
  490. #endif
  491. if (pFirstVoid)
  492. GetSymbol(pFirstVoid,(PCHAR)pString,&Displ);
  493. if (lstrlenA((CHAR *)pString))
  494. {
  495. dprintf(" %s+%x %p\n",pString,Displ,pRpcLRPC);
  496. if (strstr((const char *)pString,"LRPC_SCALL"))
  497. {
  498. ULONG OffsetCID;
  499. if (0 != GetFieldOffset("rpcrt4!LRPC_SCALL","ClientId",&OffsetCID))
  500. {
  501. #ifdef _WIN64
  502. OffsetCID = 0x100;
  503. #else
  504. OffsetCID = 0xa0;
  505. #endif
  506. }
  507. CLIENT_ID CID;
  508. ReadMemory(pRpcLRPC+OffsetCID,&CID,sizeof(CLIENT_ID),NULL);
  509. dprintf(" - - - - called from: %x.%x\n",CID.UniqueProcess,CID.UniqueThread);
  510. }
  511. }
  512. else
  513. {
  514. dprintf(" rpcrt4!THREAD.Context %p\n",pRpcLRPC);
  515. }
  516. }
  517. if (pOle)
  518. {
  519. ULONG OffsetCallContext;
  520. ULONG_PTR pCallCtx = 0;
  521. if (0 != GetFieldOffset("ole32!SOleTlsData","pCallContext",&OffsetCallContext))
  522. {
  523. #ifdef _WIN64
  524. OffsetCallContext = 0x88;
  525. #else
  526. OffsetCallContext = 0x54;
  527. #endif
  528. }
  529. ReadMemory(pOle+OffsetCallContext,&pCallCtx,sizeof(ULONG_PTR),0);
  530. dprintf(" ole32!CServerSecurity %p\n",pCallCtx);
  531. }
  532. }
  533. //
  534. //
  535. // call HeapFree(GetProcessHeap) on the OUT pointers
  536. //
  537. //////////////////////////////////////////////////////
  538. DWORD
  539. GetThreadArrays(HANDLE hCurrentProcess,
  540. DWORD * pdwThreads,
  541. SYSTEM_EXTENDED_THREAD_INFORMATION ** ppExtThreadInfo,
  542. TEB *** pppTebs)
  543. {
  544. if (!pdwThreads || !ppExtThreadInfo || !pppTebs)
  545. {
  546. return ERROR_INVALID_PARAMETER;
  547. };
  548. NTSTATUS Status;
  549. DWORD dwInc = 8*1024;
  550. DWORD dwSize = dwInc;
  551. VOID * pData = NULL;
  552. DWORD dwReturned;
  553. loop_realloc:
  554. pData = HeapAlloc(GetProcessHeap(),0,dwSize);
  555. if (!pData)
  556. {
  557. return ERROR_OUTOFMEMORY;
  558. }
  559. Status = NtQuerySystemInformation(SystemExtendedProcessInformation,
  560. pData,
  561. dwSize,
  562. &dwReturned);
  563. if (STATUS_INFO_LENGTH_MISMATCH == Status)
  564. {
  565. HeapFree(GetProcessHeap(),0,pData);
  566. dwSize += dwInc;
  567. goto loop_realloc;
  568. }
  569. else if (STATUS_SUCCESS == Status)
  570. {
  571. // here we have the snapshot:parse it
  572. SYSTEM_PROCESS_INFORMATION * pProcInfo = (SYSTEM_PROCESS_INFORMATION *)pData;
  573. SYSTEM_EXTENDED_THREAD_INFORMATION * pThreadInfo;
  574. // get the process id;
  575. ULONG_PTR IdProc;
  576. GetPeb(hCurrentProcess,NULL,&IdProc);
  577. while (TRUE)
  578. {
  579. //dprintf(" process %p curr %p\n",pProcInfo->UniqueProcessId,IdProc);
  580. if (IdProc == (ULONG_PTR)pProcInfo->UniqueProcessId)
  581. {
  582. DWORD Threads = pProcInfo->NumberOfThreads;
  583. *pdwThreads = Threads;
  584. DWORD i;
  585. pThreadInfo = (SYSTEM_EXTENDED_THREAD_INFORMATION *)((ULONG_PTR)pProcInfo+sizeof(SYSTEM_PROCESS_INFORMATION));
  586. SYSTEM_EXTENDED_THREAD_INFORMATION * pOutThreadInfo = NULL;
  587. TEB ** ppOutTebs = NULL;
  588. pOutThreadInfo = (SYSTEM_EXTENDED_THREAD_INFORMATION *)HeapAlloc(GetProcessHeap(),0,Threads*sizeof(SYSTEM_EXTENDED_THREAD_INFORMATION));
  589. if (pOutThreadInfo)
  590. {
  591. ppOutTebs = (TEB **)HeapAlloc(GetProcessHeap(),0,Threads*sizeof(TEB *));
  592. if (!ppOutTebs)
  593. {
  594. HeapFree(GetProcessHeap(),0,pOutThreadInfo);
  595. Status = ERROR_OUTOFMEMORY;
  596. Threads = 0; // to stop loop
  597. }
  598. else
  599. {
  600. memcpy(pOutThreadInfo,pThreadInfo,Threads*sizeof(SYSTEM_EXTENDED_THREAD_INFORMATION));
  601. }
  602. }
  603. else
  604. {
  605. Status = ERROR_OUTOFMEMORY;
  606. Threads = 0; // to stop loop
  607. }
  608. for (i=0;i<Threads;i++)
  609. {
  610. //dprintf(" %x.%x\n",pThreadInfo->ThreadInfo.ClientId.UniqueProcess,pThreadInfo->ThreadInfo.ClientId.UniqueThread);
  611. NTSTATUS StatusThread;
  612. HANDLE hThread;
  613. OBJECT_ATTRIBUTES Obja = {sizeof( OBJECT_ATTRIBUTES ), 0, 0, 0 ,0 };
  614. StatusThread = NtOpenThread(&hThread,THREAD_QUERY_INFORMATION,&Obja,&(pThreadInfo->ThreadInfo.ClientId));
  615. if (((NTSTATUS)0L) == StatusThread)
  616. {
  617. TEB * pTeb = NULL;
  618. GetTeb(hThread,&pTeb);
  619. ppOutTebs[i] = pTeb;
  620. CloseHandle(hThread);
  621. }
  622. else
  623. {
  624. dprintf("NtOpenThread %d\n",StatusThread);
  625. }
  626. pThreadInfo++;
  627. }
  628. // once found our process,
  629. // don't bother with the others
  630. *pppTebs = ppOutTebs;
  631. *ppExtThreadInfo = pOutThreadInfo;
  632. Status = NO_ERROR;
  633. break;
  634. }
  635. if (0 == pProcInfo->NextEntryOffset)
  636. {
  637. break;
  638. }
  639. else
  640. {
  641. pProcInfo = (SYSTEM_PROCESS_INFORMATION *)((ULONG_PTR)pProcInfo+pProcInfo->NextEntryOffset);
  642. }
  643. }
  644. }
  645. else // other cases
  646. {
  647. dprintf("NtQuerySystemInformation %08x\n",Status);
  648. return Status;
  649. }
  650. return Status;
  651. }
  652. DECLARE_API(t)
  653. {
  654. INIT_API();
  655. DWORD dwThreads;
  656. TEB ** ppTebs;
  657. SYSTEM_EXTENDED_THREAD_INFORMATION * pSysThreadInfo;
  658. // get the offsets only once
  659. ULONG OffsetRPC;
  660. ULONG_PTR pRpcThread;
  661. if (0 != GetFieldOffset("ntdll!TEB","ReservedForNtRpc",&OffsetRPC))
  662. {
  663. #ifdef _WIN64
  664. OffsetRPC = 0x1698;
  665. #else
  666. OffsetRPC = 0xf1c;
  667. #endif
  668. }
  669. ULONG OffsetOLE;
  670. ULONG_PTR pOleThread;
  671. if (0 != GetFieldOffset("ntdll!TEB","ReservedForOle",&OffsetOLE))
  672. {
  673. #ifdef _WIN64
  674. OffsetOLE = 0x1758;
  675. #else
  676. OffsetOLE = 0xf80;
  677. #endif
  678. }
  679. if (NO_ERROR == GetThreadArrays(hCurrentProcess,&dwThreads,
  680. &pSysThreadInfo,&ppTebs))
  681. {
  682. for (DWORD i=0;i<dwThreads;i++)
  683. {
  684. TEB * pTeb = ppTebs[i];
  685. SYSTEM_EXTENDED_THREAD_INFORMATION * pThreadInfo = &pSysThreadInfo[i];
  686. if (ReadMemory((ULONG_PTR)pTeb+OffsetOLE,&pOleThread,sizeof(ULONG_PTR),0) &&
  687. ReadMemory((ULONG_PTR)pTeb+OffsetRPC,&pRpcThread,sizeof(ULONG_PTR),0))
  688. {
  689. NT_TIB NtTib;
  690. ReadMemory((ULONG_PTR)pTeb,&NtTib,sizeof(NT_TIB),NULL);
  691. dprintf(" %03d %x.%x Addr: %p TEB: %p FiberData %p\n"
  692. " limit %p base %p\n"
  693. " RPC %p OLE %p\n",
  694. i,
  695. pThreadInfo->ThreadInfo.ClientId.UniqueProcess,pThreadInfo->ThreadInfo.ClientId.UniqueThread,
  696. pThreadInfo->Win32StartAddress,
  697. pTeb,NtTib.FiberData,
  698. NtTib.StackLimit,NtTib.StackBase,
  699. pRpcThread,
  700. pOleThread);
  701. #ifdef _WIN64
  702. // +0x1788 DeallocationBStore : (null)
  703. // +0x1790 BStoreLimit : 0x000006fb`faba2000
  704. ULONG_PTR lDeAlloc;
  705. ULONG_PTR lBPLimit;
  706. ULONG Offset_DeallocationBStore = 0x1788;
  707. ReadMemory((ULONG_PTR)pTeb+Offset_DeallocationBStore,&lDeAlloc,sizeof(ULONG_PTR),0);
  708. ULONG Offset_BStoreLimit = 0x1790;
  709. ReadMemory((ULONG_PTR)pTeb+Offset_BStoreLimit,&lBPLimit,sizeof(ULONG_PTR),0);
  710. dprintf(" DAll %p BStL %p\n",lDeAlloc,lBPLimit);
  711. #endif
  712. DumpRpcOle(pRpcThread,pOleThread);
  713. }
  714. else
  715. {
  716. dprintf("RM %p %p\n",(ULONG_PTR)pTeb+OffsetOLE,(ULONG_PTR)pTeb+OffsetRPC);
  717. }
  718. }
  719. HeapFree(GetProcessHeap(),0,ppTebs);
  720. HeapFree(GetProcessHeap(),0,pSysThreadInfo);
  721. }
  722. }
  723. DECLARE_API(srt)
  724. {
  725. INIT_API();
  726. DWORD dwThreads;
  727. TEB ** ppTebs;
  728. SYSTEM_EXTENDED_THREAD_INFORMATION * pSysThreadInfo;
  729. ULONG_PTR Addr = GetExpression(args);
  730. ULONG_PTR * ThreadMem = NULL;
  731. ULONG_PTR Size = 0;
  732. if (NO_ERROR == GetThreadArrays(hCurrentProcess,&dwThreads,
  733. &pSysThreadInfo,&ppTebs))
  734. {
  735. for (DWORD i=0;i<dwThreads;i++)
  736. {
  737. TEB * pTeb = ppTebs[i];
  738. SYSTEM_EXTENDED_THREAD_INFORMATION * pThreadInfo = &pSysThreadInfo[i];
  739. NT_TIB NtTib;
  740. ReadMemory((ULONG_PTR)pTeb,&NtTib,sizeof(NT_TIB),NULL);
  741. ULONG_PTR Base = (ULONG_PTR)NtTib.StackBase;
  742. ULONG_PTR Limit = (ULONG_PTR)NtTib.StackLimit;
  743. ULONG_PTR CurrSize = Base-Limit;
  744. //dprintf("searching %p between %p and %p\n",Addr,Limit,Base);
  745. if (CurrSize > Size)
  746. {
  747. Size = CurrSize;
  748. if (ThreadMem)
  749. {
  750. HeapFree(GetProcessHeap(),0,ThreadMem);
  751. ThreadMem = NULL;
  752. }
  753. ThreadMem = (ULONG_PTR *)HeapAlloc(GetProcessHeap(),0,Size);
  754. }
  755. if (ThreadMem)
  756. {
  757. if (ReadMemory(Limit,ThreadMem,(ULONG)CurrSize,NULL))
  758. {
  759. for(DWORD j=0;j<CurrSize/sizeof(ULONG_PTR);j++)
  760. {
  761. if (Addr == ThreadMem[j])
  762. {
  763. dprintf(" %x.%x %p\n",
  764. pThreadInfo->ThreadInfo.ClientId.UniqueProcess,pThreadInfo->ThreadInfo.ClientId.UniqueThread,
  765. Limit+((ULONG_PTR)&ThreadMem[j]-(ULONG_PTR)ThreadMem));
  766. }
  767. }
  768. }
  769. };
  770. }
  771. HeapFree(GetProcessHeap(),0,ppTebs);
  772. HeapFree(GetProcessHeap(),0,pSysThreadInfo);
  773. }
  774. if (ThreadMem)
  775. HeapFree(GetProcessHeap(),0,ThreadMem);
  776. }
  777. #if defined(_X86_)
  778. #ifndef PAGE_SIZE
  779. #define PAGE_SIZE 0x1000
  780. #endif
  781. #define USER_ALIGNMENT 8
  782. #elif defined(_IA64_)
  783. #ifndef PAGE_SIZE
  784. #define PAGE_SIZE 0x2000
  785. #endif
  786. #define USER_ALIGNMENT 16
  787. #elif defined(_AMD64_)
  788. #ifndef PAGE_SIZE
  789. #define PAGE_SIZE 0x1000
  790. #endif
  791. #define USER_ALIGNMENT 16
  792. #else
  793. #error // platform not defined
  794. #endif
  795. DECLARE_API(ksrt)
  796. {
  797. INIT_API();
  798. char * pArgs = (char *)args;
  799. while(isspace(*pArgs)) pArgs++;
  800. ULONG_PTR EProcess = GetExpression(pArgs);
  801. while(!isspace(*pArgs)) pArgs++;
  802. ULONG_PTR SearchFor = GetExpression(pArgs);
  803. ULONG OffsetProcessThreadList;
  804. if (0 != GetFieldOffset("nt!_KPROCESS","ThreadListHead",&OffsetProcessThreadList))
  805. {
  806. #ifdef _WIN64
  807. OffsetProcessThreadList = 0x0; // BUGBUG
  808. #else
  809. OffsetProcessThreadList = 0x050;
  810. #endif
  811. }
  812. ULONG OffsetThreadThreadList;
  813. if (0 != GetFieldOffset("nt!_KTHREAD","ThreadListEntry",&OffsetThreadThreadList))
  814. {
  815. #ifdef _WIN64
  816. OffsetThreadThreadList = 0x0;
  817. #else
  818. OffsetThreadThreadList = 0x1b0; // BUGBUG
  819. #endif
  820. }
  821. ULONG OffsetThreadTEB;
  822. if (0 != GetFieldOffset("nt!_KTHREAD","Teb",&OffsetThreadTEB))
  823. {
  824. #ifdef _WIN64
  825. OffsetThreadTEB = 0x0;
  826. #else
  827. OffsetThreadTEB = 0x020; // BUGBUG
  828. #endif
  829. }
  830. if (EProcess)
  831. {
  832. LIST_ENTRY HeadList;
  833. LIST_ENTRY * pListEntry = &HeadList;
  834. EProcess += OffsetProcessThreadList;
  835. DWORD SizeToRead = max(OffsetThreadTEB,OffsetThreadThreadList)+sizeof(LIST_ENTRY);
  836. ULONG_PTR KThreadAddr;
  837. ULONG_PTR Teb;
  838. ULONG_PTR * pKTHREAD = (ULONG_PTR *)_alloca(SizeToRead);
  839. if (ReadMemory(EProcess,&HeadList,sizeof(LIST_ENTRY),NULL))
  840. {
  841. DWORD i = 0;
  842. while ((LIST_ENTRY *)EProcess != pListEntry->Flink)
  843. {
  844. //dprintf("pListEntry->Flink %p\n",pListEntry->Flink);
  845. KThreadAddr = (ULONG_PTR)pListEntry->Flink - (ULONG_PTR)OffsetThreadThreadList;
  846. if (ReadMemory((ULONG_PTR)KThreadAddr,pKTHREAD,SizeToRead,NULL))
  847. {
  848. // do useful work
  849. Teb = *((ULONG_PTR *)((BYTE *)pKTHREAD+OffsetThreadTEB));
  850. dprintf(" %d - _KTHREAD %p TEB %p\n",i++,KThreadAddr,Teb);
  851. NT_TIB ThreadTib;
  852. if (ReadMemory(Teb,&ThreadTib,sizeof(NT_TIB),NULL))
  853. {
  854. dprintf(" EL %p B %p L %p\n",ThreadTib.ExceptionList,ThreadTib.StackBase,ThreadTib.StackLimit);
  855. ULONG_PTR Current = (ULONG_PTR)ThreadTib.StackLimit;
  856. ULONG_PTR nPages = (ULONG_PTR)ThreadTib.StackBase-(ULONG_PTR)ThreadTib.StackLimit;
  857. nPages /= PAGE_SIZE;
  858. ULONG_PTR j;
  859. for (j=0;j<nPages;j++)
  860. {
  861. ULONG_PTR pPage[PAGE_SIZE/sizeof(ULONG_PTR)];
  862. if (ReadMemory(Current,pPage,sizeof(pPage),NULL))
  863. {
  864. for(DWORD k=0;k<(PAGE_SIZE/sizeof(ULONG_PTR));k++)
  865. {
  866. if(SearchFor == pPage[k])
  867. {
  868. dprintf(" %p\n",Current+k*sizeof(ULONG_PTR));
  869. }
  870. if (CheckControlC())
  871. break;
  872. }
  873. }
  874. else
  875. {
  876. dprintf(" page @ %p not paged-in\n",Current);
  877. }
  878. Current += PAGE_SIZE;
  879. if (CheckControlC())
  880. break;
  881. }
  882. }
  883. else
  884. {
  885. dprintf(" RM Teb %p\n",Teb);
  886. }
  887. // equivalent of i++
  888. pListEntry = (LIST_ENTRY *)((BYTE *)pKTHREAD+OffsetThreadThreadList);
  889. }
  890. else
  891. {
  892. dprintf("RM %p\n",KThreadAddr);
  893. break;
  894. }
  895. if (CheckControlC())
  896. break;
  897. }
  898. }
  899. else
  900. {
  901. dprintf("RM %p\n",EProcess);
  902. }
  903. }
  904. else
  905. {
  906. dprintf("unable to resolve %s\n",args);
  907. }
  908. }
  909. #ifdef i386
  910. #define MAGIC_START (16+2)
  911. #endif
  912. char *
  913. GetCall(ULONG_PTR Addr)
  914. {
  915. static char pBuff[1024];
  916. #ifdef KDEXT_64BIT
  917. ULONG64 ThisAddr = Addr-2;
  918. #else
  919. ULONG_PTR ThisAddr = Addr-2;
  920. #endif
  921. Disasm(&ThisAddr,pBuff,FALSE);
  922. if (strstr(pBuff,"call"))
  923. {
  924. dprintf(" %s\n",pBuff);
  925. return pBuff;
  926. }
  927. ThisAddr = Addr-3;
  928. Disasm(&ThisAddr,pBuff,FALSE);
  929. if (strstr(pBuff,"call"))
  930. {
  931. dprintf(" %s\n",pBuff);
  932. return pBuff;
  933. }
  934. ThisAddr = Addr-5;
  935. Disasm(&ThisAddr,pBuff,FALSE);
  936. if (strstr(pBuff,"call"))
  937. {
  938. dprintf(" %s\n",pBuff);
  939. return pBuff;
  940. }
  941. ThisAddr = Addr-6;
  942. Disasm(&ThisAddr,pBuff,FALSE);
  943. if (strstr(pBuff,"call"))
  944. {
  945. dprintf(" %s\n",pBuff);
  946. return pBuff;
  947. }
  948. return NULL;
  949. }
  950. DECLARE_API(bs)
  951. {
  952. #ifdef i386
  953. INIT_API();
  954. ULONG_PTR pTeb = GetExpression(args);
  955. if (pTeb)
  956. {
  957. NT_TIB Tib;
  958. ReadMemory(pTeb,&Tib,sizeof(Tib),NULL);
  959. dprintf(" exception %p base %p limit %p\n",
  960. Tib.ExceptionList,Tib.StackBase,Tib.StackLimit);
  961. ULONG_PTR dwSize = (ULONG_PTR)Tib.StackBase-(ULONG_PTR)Tib.StackLimit;
  962. BYTE * pStack = new BYTE[dwSize];
  963. ULONG_PTR OldEBP = 0;
  964. if (pStack)
  965. {
  966. ULONG_PTR * pBase = (ULONG_PTR *)(pStack+dwSize);
  967. ULONG_PTR * pLimit = (ULONG_PTR *)pStack;
  968. ReadMemory((ULONG_PTR)Tib.StackLimit,pStack,(ULONG_PTR)Tib.StackBase-(ULONG_PTR)Tib.StackLimit,NULL);
  969. ULONG_PTR EBP = (ULONG_PTR)(Tib.StackBase)-(MAGIC_START*sizeof(ULONG_PTR));
  970. ULONG_PTR * pEBP = (ULONG_PTR *)pBase-MAGIC_START;
  971. BOOL bGoOn = TRUE;
  972. BOOL bRpcRt4Fix = FALSE;
  973. while(bGoOn)
  974. {
  975. dprintf("%p %p\n",pEBP[0],pEBP[1]);
  976. char * pFunction = GetCall(pEBP[1]);
  977. BOOL bFound = FALSE;
  978. if (pFunction)
  979. {
  980. if (strstr(pFunction,"ComInvokeWithLockAndIPID"))
  981. {
  982. EBP -= 0x70;
  983. }
  984. }
  985. else // try to move back
  986. {
  987. pEBP--;
  988. EBP = OldEBP;
  989. }
  990. //dprintf("looking for %p = cmp %p \n",EBP,pEBP[0]);
  991. if (!bRpcRt4Fix)
  992. {
  993. if (pEBP[0] < (ULONG_PTR)Tib.StackLimit || pEBP[0] > (ULONG_PTR)Tib.StackBase)
  994. {
  995. bRpcRt4Fix = TRUE;
  996. // rpcrt4 call_stack fix
  997. EBP = (ULONG_PTR)(Tib.StackBase) - 0x6c;
  998. }
  999. }
  1000. //dprintf("looking for %p\n",EBP);
  1001. while ((ULONG_PTR)pEBP > (ULONG_PTR)pLimit){
  1002. if (*pEBP-- == EBP){
  1003. bFound = TRUE;
  1004. break;
  1005. }
  1006. }
  1007. if (bFound)
  1008. {
  1009. pEBP++;
  1010. OldEBP = EBP;
  1011. EBP = (ULONG_PTR)(Tib.StackBase)-((ULONG_PTR)pBase-(ULONG_PTR)pEBP);
  1012. }
  1013. else
  1014. {
  1015. bGoOn = FALSE;
  1016. }
  1017. }
  1018. delete [] pStack;
  1019. }
  1020. }
  1021. else
  1022. {
  1023. dprintf("%s cannot be interpreted\b",args);
  1024. }
  1025. #endif
  1026. }
  1027. //
  1028. // given the TEB, prints the ExceptionList
  1029. //
  1030. struct _C9_REGISTRATION_RECORD
  1031. {
  1032. _C9_REGISTRATION_RECORD * prev;
  1033. void * handler;
  1034. void * scopetable;
  1035. void * trylevel;
  1036. void * pSpare0;
  1037. void * pSpare1;
  1038. };
  1039. DECLARE_API(el)
  1040. {
  1041. INIT_API();
  1042. #ifndef _X86_
  1043. dprintf("unsupported on this platform\n");
  1044. return;
  1045. #endif
  1046. ULONG_PTR pTeb = GetExpression(args);
  1047. if (pTeb)
  1048. {
  1049. NT_TIB Tib;
  1050. if (ReadMemory(pTeb,&Tib,sizeof(Tib),NULL))
  1051. {
  1052. //Tib.ExceptionList,Tib.StackBase,Tib.StackLimit);
  1053. _C9_REGISTRATION_RECORD ExRegRec;
  1054. ExRegRec.prev = (_C9_REGISTRATION_RECORD *)Tib.ExceptionList;
  1055. do
  1056. {
  1057. _C9_REGISTRATION_RECORD * pThis = ExRegRec.prev;
  1058. if (ReadMemory((MEMORY_ADDRESS)pThis,&ExRegRec,sizeof(ExRegRec),NULL))
  1059. {
  1060. dprintf(" %p (%p %p %p %p)\n",pThis,ExRegRec.prev,ExRegRec.handler,ExRegRec.scopetable,ExRegRec.trylevel);
  1061. #ifdef KDEXT_64BIT
  1062. ULONG64 Displ;
  1063. #else
  1064. ULONG Displ;
  1065. #endif
  1066. char pString[256];
  1067. pString[0]=0;
  1068. GetSymbol((ULONG_PTR)ExRegRec.handler,(PCHAR)pString,&Displ);
  1069. if (lstrlenA((CHAR *)pString))
  1070. dprintf(" %s+%x\n",pString,Displ);
  1071. if (!GetCall((ULONG_PTR)ExRegRec.pSpare1))
  1072. {
  1073. GetCall((ULONG_PTR)ExRegRec.pSpare0);
  1074. }
  1075. }
  1076. else
  1077. {
  1078. dprintf("RM %p\n",Tib.ExceptionList);
  1079. break;
  1080. }
  1081. } while((ULONG_PTR)(-1) != (ULONG_PTR)ExRegRec.prev);
  1082. }
  1083. else
  1084. {
  1085. dprintf("RM %p\n",pTeb);
  1086. }
  1087. }
  1088. else
  1089. {
  1090. dprintf("invalid TEB %s\n",args);
  1091. }
  1092. }