|
|
1.1 ! root 1: #include "pwalk.h" ! 2: #include <memory.h> ! 3: ! 4: ! 5: /* module globals */ ! 6: LPVOID PMAAddress; ! 7: LPVOID PMABuffer; ! 8: DWORD PMASize; ! 9: extern char szCurPath[MAX_PATH]; ! 10: ! 11: ! 12: /* local debug functions */ ! 13: BOOL WINAPI DebugEventThread (DBGPROCESS *); ! 14: BOOL WINAPI CreateDebugEvents (LPHANDLE); ! 15: void WINAPI AddThreadNode (DBGPROCESS *, DWORD, HANDLE, int, LPTHREAD_START_ROUTINE, HANDLE); ! 16: int WINAPI HandleMipsBreakPoint(DBGPROCESS *, DWORD); ! 17: void WINAPI RemoveThreadNode (DBGPROCESS *, DWORD); ! 18: void WINAPI AddDllNode (DBGPROCESS *, LOAD_DLL_DEBUG_INFO *); ! 19: void WINAPI RemoveDllNode (DBGPROCESS *, LOAD_DLL_DEBUG_INFO *); ! 20: void WINAPI SuspendDebuggeeProcess (DBGPROCESS *); ! 21: void WINAPI ResumeDebuggeeProcess (DBGPROCESS *); ! 22: void WINAPI NameObjects (HANDLE, LPVOID, LPVMOBJECT, int, char *, char *); ! 23: BOOL WINAPI VMCompare (LPVMOBJECT, LPVMOBJECT); ! 24: BOOL WINAPI InterruptThread_HookProcess (DBGPROCESS *, LPPROCESS_STATE); ! 25: void WINAPI ResetInterruptedThread (DBGPROCESS *, LPPROCESS_STATE); ! 26: void WINAPI RecordException (DBGPROCESS *, DEBUG_EVENT *); ! 27: HANDLE WINAPI FindThreadHandle (DBGPROCESS *, DWORD); ! 28: ! 29: ! 30: ! 31: /* start debug thread, and return event active handle */ ! 32: DBGPROCESS* WINAPI StartChildProcess ( ! 33: HWND hWnd, ! 34: char *lpszModule, ! 35: LPHANDLE lpDbgEvents) ! 36: { ! 37: DWORD TID; ! 38: HANDLE hDebugHeap; ! 39: DBGPROCESS *lpDbgProcess; ! 40: int i; ! 41: ! 42: /* create unique debug events using debuggee process ID */ ! 43: if (!CreateDebugEvents (lpDbgEvents)) ! 44: return NULL; ! 45: ! 46: /* create serialized heap of dynamic size */ ! 47: if (!(hDebugHeap = HeapCreate (0, sizeof (DBGPROCESS) + sizeof (DBGTHREAD), 0))) ! 48: { ! 49: /* close all event handles */ ! 50: for (i=0; i<nDEBUGEVENTS; i++) ! 51: CloseHandle (lpDbgEvents[i]); ! 52: ! 53: return NULL; ! 54: } ! 55: ! 56: /* allocate and initialize debug heap structure */ ! 57: lpDbgProcess = (DBGPROCESS *)HeapAlloc (hDebugHeap, 0, sizeof (DBGPROCESS)); ! 58: lpDbgProcess->hDbgHeap = hDebugHeap; ! 59: strcpy (lpDbgProcess->szModule, lpszModule); ! 60: lpDbgProcess->hWnd = hWnd; ! 61: lpDbgProcess->lpThreads = NULL; ! 62: lpDbgProcess->lpSection = NULL; ! 63: lpDbgProcess->lpERs = NULL; ! 64: ! 65: /* create debug thread */ ! 66: if (!(CreateThread ((LPSECURITY_ATTRIBUTES)NULL, ! 67: 4096, ! 68: (LPTHREAD_START_ROUTINE)DebugEventThread, ! 69: (LPVOID)lpDbgProcess, ! 70: 0, ! 71: &TID))) ! 72: return NULL; ! 73: ! 74: /* wait 15 seconds for debugger to complete initialization, else error */ ! 75: if (WAIT_TIMEOUT == WaitForSingleObject (lpDbgEvents[ACKNOWLEDGE], 15000)) ! 76: { ! 77: HeapDestroy (lpDbgProcess->hDbgHeap); ! 78: ! 79: /* close all event handles */ ! 80: for (i=0; i<nDEBUGEVENTS; i++) ! 81: CloseHandle (lpDbgEvents[i]); ! 82: ! 83: return NULL; ! 84: } ! 85: ! 86: /* reset acknowledge event */ ! 87: ResetEvent (lpDbgEvents[ACKNOWLEDGE]); ! 88: ! 89: /* successfull thread and event start */ ! 90: return lpDbgProcess; ! 91: } ! 92: ! 93: ! 94: ! 95: ! 96: /* function notifies debug thread to terminate, frees handles, and destroys heap */ ! 97: void WINAPI CloseChildProcess ( ! 98: DBGPROCESS *lpDbgProcess, ! 99: LPHANDLE lpDbgEvents) ! 100: { ! 101: int i; ! 102: DBGTHREAD *pNode = lpDbgProcess->lpThreads; ! 103: ! 104: /* set close event for debug thread and wait for acknowledge */ ! 105: SetEvent (lpDbgEvents[CLOSEDEBUGGER]); ! 106: WaitForSingleObject (lpDbgEvents[ACKNOWLEDGE], INFINITE); ! 107: ! 108: /* close all event handles */ ! 109: for (i=0; i<nDEBUGEVENTS; i++) ! 110: CloseHandle (lpDbgEvents[i]); ! 111: ! 112: /* close all thread handles in the list */ ! 113: while (pNode != NULL) ! 114: { ! 115: RemoveThreadNode (lpDbgProcess, pNode->dwThreadID); ! 116: pNode = lpDbgProcess->lpThreads; ! 117: } ! 118: ! 119: /* destroy the debug heap */ ! 120: HeapDestroy (lpDbgProcess->hDbgHeap); ! 121: } ! 122: ! 123: ! 124: ! 125: ! 126: /* local function creates debug event objects for thread synchronization */ ! 127: BOOL WINAPI CreateDebugEvents ( ! 128: LPHANDLE lpDbgEvents) ! 129: { ! 130: char szEvent[MAX_PATH]; ! 131: ! 132: ! 133: LoadString (GetModuleHandle (NULL), IDS_DBGEVNTACTIVE, szEvent, sizeof (szEvent)); ! 134: if (!(lpDbgEvents[DEBUGACTIVE] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL, ! 135: TRUE, ! 136: TRUE, ! 137: szEvent))) ! 138: return FALSE; ! 139: ! 140: LoadString (GetModuleHandle (NULL), IDS_DBGEVNTCLOSE, szEvent, sizeof (szEvent)); ! 141: if (!(lpDbgEvents[CLOSEDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL, ! 142: TRUE, ! 143: FALSE, ! 144: szEvent))) ! 145: { ! 146: CloseHandle (lpDbgEvents[DEBUGACTIVE]); ! 147: return FALSE; ! 148: } ! 149: ! 150: LoadString (GetModuleHandle (NULL), IDS_DBGEVNTSTOP, szEvent, sizeof (szEvent)); ! 151: if (!(lpDbgEvents[SUSPENDDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL, ! 152: TRUE, ! 153: FALSE, ! 154: szEvent))) ! 155: { ! 156: CloseHandle (lpDbgEvents[DEBUGACTIVE]); ! 157: CloseHandle (lpDbgEvents[CLOSEDEBUGGER]); ! 158: return FALSE; ! 159: } ! 160: ! 161: LoadString (GetModuleHandle (NULL), IDS_DBGEVNTSTART, szEvent, sizeof (szEvent)); ! 162: if (!(lpDbgEvents[RESUMEDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL, ! 163: TRUE, ! 164: FALSE, ! 165: szEvent))) ! 166: { ! 167: CloseHandle (lpDbgEvents[DEBUGACTIVE]); ! 168: CloseHandle (lpDbgEvents[CLOSEDEBUGGER]); ! 169: CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]); ! 170: return FALSE; ! 171: } ! 172: ! 173: LoadString (GetModuleHandle (NULL), IDS_DBGEVNTREAD, szEvent, sizeof (szEvent)); ! 174: if (!(lpDbgEvents[READMEMORY] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL, ! 175: TRUE, ! 176: FALSE, ! 177: szEvent))) ! 178: { ! 179: CloseHandle (lpDbgEvents[DEBUGACTIVE]); ! 180: CloseHandle (lpDbgEvents[CLOSEDEBUGGER]); ! 181: CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]); ! 182: CloseHandle (lpDbgEvents[RESUMEDEBUGGER]); ! 183: return FALSE; ! 184: } ! 185: ! 186: LoadString (GetModuleHandle (NULL), IDS_DBGEVNTWRITE, szEvent, sizeof (szEvent)); ! 187: if (!(lpDbgEvents[WRITEMEMORY] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL, ! 188: TRUE, ! 189: FALSE, ! 190: szEvent))) ! 191: { ! 192: CloseHandle (lpDbgEvents[DEBUGACTIVE]); ! 193: CloseHandle (lpDbgEvents[CLOSEDEBUGGER]); ! 194: CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]); ! 195: CloseHandle (lpDbgEvents[RESUMEDEBUGGER]); ! 196: CloseHandle (lpDbgEvents[READMEMORY]); ! 197: return FALSE; ! 198: } ! 199: ! 200: LoadString (GetModuleHandle (NULL), IDS_DBGEVNTACK, szEvent, sizeof (szEvent)); ! 201: if (!(lpDbgEvents[ACKNOWLEDGE] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL, ! 202: TRUE, ! 203: FALSE, ! 204: szEvent))) ! 205: { ! 206: CloseHandle (lpDbgEvents[DEBUGACTIVE]); ! 207: CloseHandle (lpDbgEvents[CLOSEDEBUGGER]); ! 208: CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]); ! 209: CloseHandle (lpDbgEvents[RESUMEDEBUGGER]); ! 210: CloseHandle (lpDbgEvents[READMEMORY]); ! 211: CloseHandle (lpDbgEvents[WRITEMEMORY]); ! 212: return FALSE; ! 213: } ! 214: ! 215: /* success */ ! 216: return TRUE; ! 217: } ! 218: ! 219: ! 220: ! 221: ! 222: ! 223: /* main daddyo thread that is the debugger residing over a debuggee */ ! 224: BOOL WINAPI DebugEventThread ( ! 225: DBGPROCESS *lpDbgProcess) ! 226: { ! 227: DEBUG_EVENT de; ! 228: HANDLE hDbgEvent[nDEBUGEVENTS]; ! 229: STARTUPINFO si; ! 230: PROCESS_INFORMATION pi; ! 231: HANDLE hChildProcess; ! 232: BOOL bHooked, bUnHooked; ! 233: PROCESS_STATE ProcessState; ! 234: ! 235: ! 236: bHooked = FALSE; ! 237: bUnHooked = FALSE; ! 238: ! 239: /* initialize process startup information */ ! 240: si.cb = sizeof (si); ! 241: si.lpReserved = NULL; ! 242: si.lpDesktop = NULL; ! 243: si.lpTitle = NULL; ! 244: si.dwX = 0; ! 245: si.dwY = 0; ! 246: si.dwXSize = 0; ! 247: si.dwYSize = 0; ! 248: si.dwXCountChars = 0; ! 249: si.dwYCountChars = 0; ! 250: si.dwFillAttribute = 0; ! 251: si.dwFlags = STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW; ! 252: si.wShowWindow = SW_SHOWNORMAL; ! 253: si.cbReserved2 = 0; ! 254: si.lpReserved2 = NULL; ! 255: ! 256: /* create debug process on module name */ ! 257: if (!CreateProcess (lpDbgProcess->szModule, ! 258: NULL, ! 259: (LPSECURITY_ATTRIBUTES)NULL, ! 260: (LPSECURITY_ATTRIBUTES)NULL, ! 261: FALSE, ! 262: DEBUG_PROCESS, ! 263: NULL, ! 264: NULL, ! 265: (LPSTARTUPINFO)&si, ! 266: (LPPROCESS_INFORMATION)&pi)) ! 267: { ! 268: ReportError (IDS_ERRCREATEPROCESS); ! 269: return FALSE; ! 270: } ! 271: /* open process for all access */ ! 272: if ((hChildProcess = OpenProcess (PROCESS_ALL_ACCESS, ! 273: FALSE, ! 274: pi.dwProcessId)) == NULL) ! 275: { ! 276: ReportError (IDS_ERROPENPROCESS); ! 277: TerminateProcess (pi.hProcess, 0); ! 278: return FALSE; ! 279: } ! 280: ! 281: /* store process info */ ! 282: lpDbgProcess->hProcess = hChildProcess; ! 283: lpDbgProcess->dwPriority = GetPriorityClass (pi.hProcess); ! 284: lpDbgProcess->dwProcessID = pi.dwProcessId; ! 285: lpDbgProcess->bActive = TRUE; ! 286: ! 287: /* close process and thread handles in pi structure */ ! 288: CloseHandle (pi.hThread); ! 289: CloseHandle (pi.hProcess); ! 290: ! 291: /* open debug events */ ! 292: CreateDebugEvents (hDbgEvent); ! 293: ! 294: /* signale completion of task */ ! 295: SetEvent (hDbgEvent[ACKNOWLEDGE]); ! 296: ! 297: /* start debug event loop */ ! 298: while (TRUE) ! 299: { ! 300: int nIndex; ! 301: ! 302: /* wait for debugger active */ ! 303: switch (nIndex = WaitForMultipleObjects (nDEBUGEVENTS, hDbgEvent, FALSE, INFINITE)) ! 304: { ! 305: case CLOSEDEBUGGER: ! 306: { ! 307: int i; ! 308: ! 309: /* terminate debuggee process */ ! 310: TerminateProcess (lpDbgProcess->hProcess, 0); ! 311: CloseHandle (lpDbgProcess->hProcess); ! 312: ! 313: /* signal completion of task */ ! 314: SetEvent (hDbgEvent[ACKNOWLEDGE]); ! 315: ! 316: /* close all debug events */ ! 317: for (i=0; i<nDEBUGEVENTS; i++) ! 318: CloseHandle (hDbgEvent[i]); ! 319: ! 320: /* exit debugger now */ ! 321: return TRUE; ! 322: } ! 323: break; ! 324: ! 325: case SUSPENDDEBUGGER: ! 326: SuspendDebuggeeProcess (lpDbgProcess); ! 327: ResetEvent (hDbgEvent[DEBUGACTIVE]); ! 328: ResetEvent (hDbgEvent[SUSPENDDEBUGGER]); ! 329: break; ! 330: ! 331: case RESUMEDEBUGGER: ! 332: ResumeDebuggeeProcess (lpDbgProcess); ! 333: SetEvent (hDbgEvent[DEBUGACTIVE]); ! 334: ResetEvent (hDbgEvent[RESUMEDEBUGGER]); ! 335: break; ! 336: ! 337: case READMEMORY: ! 338: { ! 339: MEMORY_BASIC_INFORMATION mbi; ! 340: DWORD Protect = 0; ! 341: ! 342: /* reset event so we don't do repeat */ ! 343: ResetEvent (hDbgEvent [READMEMORY]); ! 344: ! 345: /* if not committed memory abort */ ! 346: if (!VirtualQueryEx (lpDbgProcess->hProcess, ! 347: PMAAddress, ! 348: &mbi, ! 349: sizeof (MEMORY_BASIC_INFORMATION)) || ! 350: mbi.State != MEM_COMMIT) ! 351: { ! 352: PMASize = 0; ! 353: SetEvent (hDbgEvent [ACKNOWLEDGE]); ! 354: break; ! 355: } ! 356: ! 357: /* if guarded memory, change protection temporarily */ ! 358: if (!(mbi.Protect & PAGE_READONLY) && ! 359: !(mbi.Protect & PAGE_READWRITE)) ! 360: VirtualProtectEx (lpDbgProcess->hProcess, ! 361: PMAAddress, ! 362: PMASize, ! 363: PAGE_READONLY, ! 364: &Protect); ! 365: ! 366: if (!ReadProcessMemory (lpDbgProcess->hProcess, ! 367: PMAAddress, ! 368: PMABuffer, ! 369: PMASize, ! 370: NULL)) ! 371: { ! 372: if (mbi.AllocationProtect != PAGE_READONLY && ! 373: mbi.AllocationProtect != PAGE_READWRITE) ! 374: NotifyUser (NULL, IDS_ERROR, 0, "BaseProtect NOACCESS", 0); ! 375: else ! 376: { ! 377: ReportError (IDS_ERRREADPROCESSMEMORY); ! 378: PMASize = 0; ! 379: } ! 380: } ! 381: ! 382: /* reset protection if changed */ ! 383: if (Protect) ! 384: VirtualProtectEx (lpDbgProcess->hProcess, ! 385: PMAAddress, ! 386: PMASize, ! 387: Protect, ! 388: &Protect); ! 389: ! 390: /* acknowledge success */ ! 391: SetEvent (hDbgEvent [ACKNOWLEDGE]); ! 392: } ! 393: break; ! 394: ! 395: case WRITEMEMORY: ! 396: if (!WriteProcessMemory (lpDbgProcess->hProcess, ! 397: PMAAddress, ! 398: PMABuffer, ! 399: PMASize, ! 400: NULL)) ! 401: { ! 402: ReportError (IDS_ERRWRITEPROCESSMEMORY); ! 403: PMASize = 0; ! 404: } ! 405: ! 406: ResetEvent (hDbgEvent [WRITEMEMORY]); ! 407: SetEvent (hDbgEvent [ACKNOWLEDGE]); ! 408: break; ! 409: ! 410: case DEBUGACTIVE: ! 411: /* if debug active */ ! 412: if ((WaitForDebugEvent (&de, (DWORD)100))) ! 413: { ! 414: if (de.dwProcessId == lpDbgProcess->dwProcessID) ! 415: { ! 416: switch (de.dwDebugEventCode) ! 417: { ! 418: case EXIT_PROCESS_DEBUG_EVENT: ! 419: SetStatusText (lpDbgProcess->hWnd, IDS_EXITPROCESS, 0); ! 420: ! 421: /* uninitialize probe dll */ ! 422: ResetProbe (); ! 423: ! 424: /* process is going away so notify main window */ ! 425: SendNotifyMessage (lpDbgProcess->hWnd, ! 426: WM_COMMAND, ! 427: IDM_PROCESSUNLOAD, ! 428: 0); ! 429: break; ! 430: ! 431: case LOAD_DLL_DEBUG_EVENT: ! 432: SetStatusText (lpDbgProcess->hWnd, IDS_LOADDLL, 0); ! 433: AddDllNode (lpDbgProcess, ! 434: (LOAD_DLL_DEBUG_INFO *)&(de.u.LoadDll)); ! 435: break; ! 436: ! 437: case UNLOAD_DLL_DEBUG_EVENT: ! 438: SetStatusText (lpDbgProcess->hWnd, IDS_UNLOADDLL, 0); ! 439: RemoveDllNode (lpDbgProcess, ! 440: (LOAD_DLL_DEBUG_INFO *)&(de.u.LoadDll)); ! 441: break; ! 442: ! 443: case CREATE_PROCESS_DEBUG_EVENT: ! 444: SetStatusText (lpDbgProcess->hWnd, IDS_CREATEPROCESS, 0); ! 445: /* add first thread to linked list of dbg structures */ ! 446: AddThreadNode (lpDbgProcess, ! 447: de.dwThreadId, ! 448: de.u.CreateProcessInfo.hThread, ! 449: GetThreadPriority (de.u.CreateProcessInfo.hThread), ! 450: de.u.CreateProcessInfo.lpStartAddress, ! 451: de.u.CreateProcessInfo.hFile); ! 452: lpDbgProcess->hFile = de.u.CreateProcessInfo.hFile; ! 453: lpDbgProcess->lpImage = de.u.CreateProcessInfo.lpBaseOfImage; ! 454: lpDbgProcess->dwDbgInfoOffset = de.u.CreateProcessInfo.dwDebugInfoFileOffset; ! 455: lpDbgProcess->nDbgInfoSize = de.u.CreateProcessInfo.nDebugInfoSize; ! 456: break; ! 457: ! 458: case CREATE_THREAD_DEBUG_EVENT: ! 459: SetStatusText (lpDbgProcess->hWnd, IDS_CREATETHREAD, 0); ! 460: /* add thread to linked list of dbg structures */ ! 461: AddThreadNode (lpDbgProcess, ! 462: de.dwThreadId, ! 463: de.u.CreateThread.hThread, ! 464: GetThreadPriority (de.u.CreateThread.hThread), ! 465: de.u.CreateThread.lpStartAddress, ! 466: NULL); ! 467: break; ! 468: ! 469: case EXIT_THREAD_DEBUG_EVENT: ! 470: SetStatusText (lpDbgProcess->hWnd, IDS_EXITTHREAD, 0); ! 471: /* remove thread record */ ! 472: RemoveThreadNode (lpDbgProcess, ! 473: de.dwThreadId); ! 474: break; ! 475: ! 476: case EXCEPTION_DEBUG_EVENT: ! 477: switch (de.u.Exception.ExceptionRecord.ExceptionCode) ! 478: { ! 479: case EXCEPTION_BREAKPOINT: ! 480: #ifdef _MIPS_ /* mips needs special handling here to reset breakpoint */ ! 481: HandleMipsBreakPoint(lpDbgProcess, de.dwThreadId); ! 482: SetStatusText (lpDbgProcess->hWnd, ! 483: IDS_BREAKPOINTEXCEPTION, ! 484: RGB (0, 0xff, 0)); ! 485: break; ! 486: #endif ! 487: ! 488: /* set up process hook */ ! 489: if (!bHooked) ! 490: { ! 491: if (InterruptThread_HookProcess (lpDbgProcess, &ProcessState)) ! 492: SetStatusText (lpDbgProcess->hWnd, ! 493: IDS_PROCESSINIT, ! 494: RGB (0, 0xff, 0)); ! 495: else ! 496: ReportError (IDS_HOOKPROCESS); ! 497: ! 498: bHooked = TRUE; ! 499: } ! 500: ! 501: else if (bHooked && ! 502: !bUnHooked) ! 503: { ! 504: ResetInterruptedThread (lpDbgProcess, &ProcessState); ! 505: SetStatusText (lpDbgProcess->hWnd, ! 506: IDS_STATUSREADY, ! 507: 0); ! 508: ! 509: /* post message to get ball rolling in main thread */ ! 510: PostMessage (lpDbgProcess->hWnd, ! 511: WM_COMMAND, ! 512: IDM_PROCESSREWALK, ! 513: 0); ! 514: bUnHooked = TRUE; ! 515: } ! 516: ! 517: else ! 518: SetStatusText (lpDbgProcess->hWnd, ! 519: IDS_BREAKPOINTEXCEPTION, ! 520: RGB (0, 0xff, 0)); ! 521: break; ! 522: ! 523: case EXCEPTION_ACCESS_VIOLATION: ! 524: /* record exception information */ ! 525: SetStatusText (lpDbgProcess->hWnd, ! 526: IDS_ACCESSVIOLATIONEXCEPTION, ! 527: RGB (0xff, 0, 0)); ! 528: RecordException (lpDbgProcess, &de); ! 529: break; ! 530: ! 531: default: ! 532: SetStatusText (lpDbgProcess->hWnd, ! 533: IDS_UNHANDLEDEXCEPTION, ! 534: RGB (0xff, 0, 0)); ! 535: RecordException (lpDbgProcess, &de); ! 536: break; ! 537: } ! 538: break; ! 539: ! 540: case RIP_EVENT: ! 541: SetStatusText (lpDbgProcess->hWnd, ! 542: IDS_RIPEVENT, ! 543: RGB (0, 0xff, 0)); ! 544: break; ! 545: ! 546: case OUTPUT_DEBUG_STRING_EVENT: ! 547: SetStatusText (lpDbgProcess->hWnd, ! 548: IDS_OUTPUTDEBUGSTRING, ! 549: RGB (0, 0xff, 0)); ! 550: break; ! 551: ! 552: default: ! 553: break; ! 554: } ! 555: } ! 556: ! 557: ContinueDebugEvent (de.dwProcessId, de.dwThreadId, DBG_CONTINUE); ! 558: } ! 559: break; ! 560: } ! 561: ! 562: } ! 563: ! 564: return TRUE; ! 565: } ! 566: ! 567: ! 568: ! 569: ! 570: void WINAPI SuspendDebuggeeProcess ( ! 571: DBGPROCESS *lppr) ! 572: { ! 573: DBGTHREAD *lpth = (DBGTHREAD *)lppr->lpThreads; ! 574: ! 575: while (lpth) ! 576: { ! 577: SuspendThread (lpth->hThread); ! 578: lpth = (DBGTHREAD *)lpth->Next; ! 579: } ! 580: ! 581: /* inform user via status bar */ ! 582: SetStatusText (lppr->hWnd, IDS_PROCESSSUSPENDED, RGB (0xff, 0, 0)); ! 583: lppr->bActive = FALSE; ! 584: } ! 585: ! 586: ! 587: ! 588: ! 589: void WINAPI ResumeDebuggeeProcess ( ! 590: DBGPROCESS *lppr) ! 591: { ! 592: DBGTHREAD *lpth = (DBGTHREAD *)lppr->lpThreads; ! 593: ! 594: while (lpth) ! 595: { ! 596: ResumeThread (lpth->hThread); ! 597: lpth = (DBGTHREAD *)lpth->Next; ! 598: } ! 599: ! 600: /* inform user via status bar */ ! 601: SetStatusText (lppr->hWnd, IDS_PROCESSRESUMED, RGB (0, 0xff, 0)); ! 602: lppr->bActive = TRUE; ! 603: } ! 604: ! 605: ! 606: ! 607: ! 608: void WINAPI AddThreadNode ( ! 609: DBGPROCESS *lppr, ! 610: DWORD dwThreadID, ! 611: HANDLE hThread, ! 612: int nPriority, ! 613: LPTHREAD_START_ROUTINE lpStart, ! 614: HANDLE hFile) ! 615: { ! 616: DBGTHREAD *lpth; ! 617: DBGTHREAD *pNode = lppr->lpThreads; ! 618: ! 619: /* allocate thread node off heap */ ! 620: lpth = (DBGTHREAD *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGTHREAD)); ! 621: ! 622: /* initialize thread data */ ! 623: lpth->lpStartAddress = lpStart; ! 624: lpth->nPriority = nPriority; ! 625: lpth->dwThreadID = dwThreadID; ! 626: lpth->hThread = hThread; ! 627: lpth->Next = NULL; ! 628: ! 629: /* retieve section names for executable module if file handle passed */ ! 630: if (hFile) ! 631: { ! 632: RetrieveModuleName (lppr->szModule, hFile); ! 633: lppr->lpSection = NULL; ! 634: RetrieveSectionNames (lppr->hDbgHeap, hFile, &(lppr->lpSection)); ! 635: } ! 636: ! 637: /* set linked list pointers */ ! 638: while (pNode && pNode->Next) ! 639: pNode = (DBGTHREAD *)pNode->Next; ! 640: ! 641: if (!pNode) ! 642: lppr->lpThreads = lpth; ! 643: else ! 644: (DBGTHREAD *)pNode->Next = lpth; ! 645: } ! 646: ! 647: ! 648: ! 649: ! 650: void WINAPI RemoveThreadNode ( ! 651: DBGPROCESS *lppr, ! 652: DWORD dwThreadID) ! 653: { ! 654: DBGTHREAD *pNode = lppr->lpThreads; ! 655: DBGTHREAD *lpth; ! 656: ! 657: while (pNode->Next && ! 658: ((DBGTHREAD *)(pNode->Next))->dwThreadID != dwThreadID) ! 659: pNode = (DBGTHREAD *)pNode->Next; ! 660: ! 661: if (pNode->Next) ! 662: { ! 663: lpth = (DBGTHREAD *)pNode->Next; ! 664: pNode->Next = ((DBGTHREAD *)(pNode->Next))->Next; ! 665: CloseHandle (lpth->hThread); ! 666: HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpth); ! 667: } ! 668: ! 669: else if (pNode->dwThreadID == dwThreadID) ! 670: { ! 671: lpth = pNode; ! 672: lppr->lpThreads = NULL; ! 673: CloseHandle (lpth->hThread); ! 674: HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpth); ! 675: } ! 676: } ! 677: ! 678: ! 679: ! 680: /* find a thread's handle based on thread ID */ ! 681: HANDLE WINAPI FindThreadHandle ( ! 682: DBGPROCESS *lppr, ! 683: DWORD dwThreadId) ! 684: { ! 685: DBGTHREAD *pNode = lppr->lpThreads; ! 686: ! 687: while (pNode != NULL) ! 688: if (pNode->dwThreadID == dwThreadId) ! 689: return (pNode->hThread); ! 690: return NULL; ! 691: } ! 692: ! 693: ! 694: ! 695: ! 696: void WINAPI AddDllNode ( ! 697: DBGPROCESS *lppr, ! 698: LOAD_DLL_DEBUG_INFO *lpdbgDll) ! 699: { ! 700: DBGDLL *lpdll; ! 701: DBGDLL *pNode = lppr->lpDlls; ! 702: char szImageName[MAX_PATH*2]; ! 703: BOOL bDummy; ! 704: ! 705: /* allocate Dll node off heap */ ! 706: if ((lpdll = (DBGDLL *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGDLL))) == NULL) ! 707: ReportError (IDS_ERRHEAPALLOC); ! 708: ! 709: /* initialize Dll structure */ ! 710: lpdll->hFile = lpdbgDll->hFile; ! 711: lpdll->lpBaseOfDll = lpdbgDll->lpBaseOfDll; ! 712: lpdll->dwDebugInfoFileOffset = lpdbgDll->dwDebugInfoFileOffset; ! 713: lpdll->nDebugInfoSize = lpdbgDll->nDebugInfoSize; ! 714: lpdll->fUnicode = lpdbgDll->fUnicode; ! 715: lpdll->Next = NULL; ! 716: lpdll->lpSection = NULL; ! 717: ! 718: /* if imagename is valid, copy locally */ ! 719: if ((lpdbgDll->lpImageName != NULL) && ! 720: (*(char **)(lpdbgDll->lpImageName)) != NULL) ! 721: { ! 722: /* if unicode, convert to ascii */ ! 723: if (lpdbgDll->fUnicode) ! 724: { ! 725: if (!ReadProcessMemory (lppr->hProcess, ! 726: *(char **)(lpdbgDll->lpImageName), ! 727: szImageName, ! 728: MAX_PATH*2, ! 729: NULL)) ! 730: ReportError (IDS_ERRREADPROCESSMEMORY); ! 731: else ! 732: WideCharToMultiByte (CP_ACP, ! 733: 0, ! 734: (LPWSTR)szImageName, ! 735: -1, ! 736: lpdll->szImageName, ! 737: MAX_PATH, ! 738: NULL, ! 739: &bDummy); ! 740: } ! 741: else ! 742: { ! 743: if (!ReadProcessMemory (lppr->hProcess, ! 744: *(char **)(lpdbgDll->lpImageName), ! 745: lpdll->szImageName, ! 746: MAX_PATH, ! 747: NULL)) ! 748: ReportError (IDS_ERRREADPROCESSMEMORY); ! 749: } ! 750: } ! 751: else ! 752: RetrieveModuleName (lpdll->szImageName, lpdbgDll->hFile); ! 753: ! 754: /* get section names for DLL */ ! 755: RetrieveSectionNames (lppr->hDbgHeap, lpdbgDll->hFile, &(lpdll->lpSection)); ! 756: ! 757: /* set linked list pointers */ ! 758: while (pNode && pNode->Next) ! 759: pNode = (DBGDLL *)pNode->Next; ! 760: ! 761: if (!pNode) ! 762: lppr->lpDlls = lpdll; ! 763: else ! 764: (DBGDLL *)pNode->Next = lpdll; ! 765: } ! 766: ! 767: ! 768: ! 769: void WINAPI RemoveDllNode ( ! 770: DBGPROCESS *lppr, ! 771: LOAD_DLL_DEBUG_INFO *lpdbgDll) ! 772: { ! 773: DBGDLL *pNode = lppr->lpDlls; ! 774: DBGDLL *lpdll; ! 775: SECTIONINFO *pSection, *pNext; ! 776: ! 777: while (pNode->Next && ! 778: ((DBGDLL *)(pNode->Next))->lpBaseOfDll != lpdbgDll->lpBaseOfDll) ! 779: pNode = (DBGDLL *)pNode->Next; ! 780: ! 781: if (pNode->Next) ! 782: { ! 783: lpdll = (DBGDLL *)pNode->Next; ! 784: pNode->Next = ((DBGDLL *)(pNode->Next))->Next; ! 785: ! 786: pSection = pNext = lpdll->lpSection; ! 787: while (pNext) ! 788: { ! 789: pNext = (SECTIONINFO *)pSection->Next; ! 790: HeapFree (lppr->hDbgHeap, 0, (LPSTR)pSection); ! 791: pSection = pNext; ! 792: } ! 793: ! 794: HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpdll); ! 795: } ! 796: ! 797: else if (pNode->lpBaseOfDll == lpdbgDll->lpBaseOfDll) ! 798: { ! 799: lpdll = pNode; ! 800: lppr->lpDlls = NULL; ! 801: ! 802: pSection = pNext = lpdll->lpSection; ! 803: while (pNext) ! 804: { ! 805: pNext = (SECTIONINFO *)pSection->Next; ! 806: HeapFree (lppr->hDbgHeap, 0, (LPSTR)pSection); ! 807: pSection = pNext; ! 808: } ! 809: ! 810: HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpdll); ! 811: } ! 812: } ! 813: ! 814: ! 815: ! 816: void WINAPI RecordException ( ! 817: DBGPROCESS *lppr, ! 818: DEBUG_EVENT *de) ! 819: { ! 820: DBGEXCEPTREC *lper; ! 821: DBGEXCEPTREC *per = lppr->lpERs; ! 822: HANDLE hThread; ! 823: int i; ! 824: ! 825: /* allocate Dll node off heap */ ! 826: if ((lper = (DBGEXCEPTREC *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGEXCEPTREC))) == NULL) ! 827: ReportError (IDS_ERRHEAPALLOC); ! 828: ! 829: /* initialize exception record structure */ ! 830: lper->dwThreadId = de->dwThreadId; ! 831: lper->dwFirstChance = de->u.Exception.dwFirstChance; ! 832: lper->ExceptRecord.ExceptionCode = de->u.Exception.ExceptionRecord.ExceptionCode; ! 833: lper->ExceptRecord.ExceptionFlags = de->u.Exception.ExceptionRecord.ExceptionFlags; ! 834: lper->ExceptRecord.ExceptionRecord = NULL; ! 835: lper->ExceptRecord.ExceptionAddress = de->u.Exception.ExceptionRecord.ExceptionAddress; ! 836: lper->ExceptRecord.NumberParameters = de->u.Exception.ExceptionRecord.NumberParameters; ! 837: for (i=0; i<EXCEPTION_MAXIMUM_PARAMETERS; i++) ! 838: lper->ExceptRecord.ExceptionInformation[i] = ! 839: de->u.Exception.ExceptionRecord.ExceptionInformation[i]; ! 840: ! 841: /* get exception thread handle */ ! 842: hThread = FindThreadHandle (lppr, de->dwThreadId); ! 843: lper->Context.ContextFlags = CONTEXT_CONTROL; ! 844: GetThreadContext (hThread, &(lper->Context)); ! 845: ! 846: /* set linked list pointers */ ! 847: while (per && per->Next) ! 848: per = (DBGEXCEPTREC *)per->Next; ! 849: if (!per) ! 850: lppr->lpERs = lper; ! 851: else ! 852: (DBGEXCEPTREC *)per->Next = lper; ! 853: } ! 854: ! 855: ! 856: ! 857: #ifdef _MIPS_ ! 858: /* ! 859: * MIPS must increment the FIR on a breakpoint ! 860: * in order to fetch the next instruction ! 861: */ ! 862: ! 863: int WINAPI HandleMipsBreakPoint( ! 864: DBGPROCESS *lppr, ! 865: DWORD dwThreadID ! 866: ) ! 867: { ! 868: CONTEXT ThreadContext; ! 869: DBGTHREAD *pNode = lppr->lpThreads; ! 870: HANDLE hThread; ! 871: ! 872: while (pNode && pNode->dwThreadID != dwThreadID) ! 873: pNode = (DBGTHREAD *)pNode->Next; ! 874: ! 875: if(!pNode) ! 876: return(0); ! 877: else ! 878: { ! 879: hThread = (HANDLE) pNode->hThread; ! 880: ! 881: ThreadContext.ContextFlags = CONTEXT_CONTROL; ! 882: if (!GetThreadContext (hThread, &ThreadContext)) ! 883: { ! 884: ReportError (IDS_ERRGETTHREADCONTEXT); ! 885: return(0); ! 886: } ! 887: ! 888: ThreadContext.Fir += 4; ! 889: ! 890: if (!SetThreadContext (hThread, &ThreadContext)) ! 891: { ! 892: ReportError (IDS_ERRSETTHREADCONTEXT); ! 893: return (0); ! 894: } ! 895: ! 896: return (1); ! 897: } ! 898: } ! 899: #endif /* _MIPS_ */ ! 900: ! 901: ! 902: ! 903: int WINAPI WhereIsStack ( ! 904: HANDLE hThreadContext) ! 905: { ! 906: CONTEXT ThreadContext; ! 907: ! 908: ThreadContext.ContextFlags = CONTEXT_CONTROL; ! 909: if (!GetThreadContext (hThreadContext, &ThreadContext)) ! 910: ReportError (IDS_ERRGETTHREADCONTEXT); ! 911: ! 912: #ifdef _X86_ ! 913: return ThreadContext.Esp; ! 914: #else /* _MIPS_ */ ! 915: return ThreadContext.IntSp; ! 916: #endif ! 917: ! 918: } ! 919: ! 920: ! 921: ! 922: /* function walks memory regions of process */ ! 923: int WINAPI WalkProcess ( ! 924: HANDLE hChildProcess, ! 925: LPVOID *lpWalk, ! 926: LPINT *lpObjects) ! 927: { ! 928: LPVMOBJECT lpList; ! 929: LPVOID lpMem = 0; ! 930: LPVOID lpStack = 0; ! 931: int nCnt, i; ! 932: ! 933: /* if pointer exists, reset to no commit */ ! 934: if (*lpWalk) ! 935: { ! 936: if (!VirtualFree (*lpWalk, 0, MEM_DECOMMIT)) ! 937: ReportError (IDS_ERRVIRTUALFREE); ! 938: } ! 939: ! 940: /* else perform initial reserve */ ! 941: else ! 942: if ((*lpWalk = VirtualAlloc (NULL, ! 943: TOTALVMRESERVE, ! 944: MEM_RESERVE, ! 945: PAGE_NOACCESS)) == NULL) ! 946: ReportError (IDS_ERRVIRTUALALLOC); ! 947: ! 948: /* initialize list pointer to beginning of walker list */ ! 949: lpList = (LPVMOBJECT)*lpWalk; ! 950: ! 951: /* walk process addresses */ ! 952: while ((DWORD)lpMem < 0x7fff0000) ! 953: { ! 954: try /* virtual memory exception handler automatically commits mem */ ! 955: { ! 956: /* touch memory in VMOBJECT structure that exists after mbi field to trigger ! 957: access violation for a new page of memory. Do this here since VirtualQueryEx ! 958: does not seem to generate exceptions, rather it just fails calls */ ! 959: *lpList->szObjType = 0; ! 960: *lpList->szModule = 0; ! 961: *lpList->szSection = 0; ! 962: lpList->bNew = 0; ! 963: ! 964: VirtualQueryEx (hChildProcess, ! 965: lpMem, ! 966: &(lpList->mbi), ! 967: sizeof (MEMORY_BASIC_INFORMATION)); ! 968: ! 969: /* increment lpMem to next region of memory */ ! 970: lpMem = (LPVOID)((DWORD)lpList->mbi.BaseAddress + ! 971: (DWORD)lpList->mbi.RegionSize); ! 972: ! 973: lpList++; ! 974: } ! 975: ! 976: except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ! 977: { ! 978: /* commit next page of walker list memory */ ! 979: if (((int)lpList + 4096) < (int)*lpWalk + TOTALVMRESERVE) ! 980: VirtualAlloc ((LPVOID)((int)lpList + sizeof (VMOBJECT)), ! 981: 4096, ! 982: MEM_COMMIT, ! 983: PAGE_READWRITE); ! 984: else ! 985: { ! 986: NotifyUser (NULL, ! 987: IDS_ERROR, ! 988: IDS_NOTENOUGHMEM, ! 989: " reserved for Objects", ! 990: MB_OK); ! 991: return 0; ! 992: } ! 993: } ! 994: } ! 995: ! 996: /* allocate objects index array */ ! 997: if (*lpObjects) ! 998: LocalFree (*lpObjects); ! 999: nCnt = (((int)(LPVOID)lpList)-(int)*lpWalk)/sizeof (VMOBJECT); ! 1000: *lpObjects = LocalAlloc (LPTR, nCnt * sizeof (int)); ! 1001: for (i=0; i<nCnt; i++) ! 1002: (*lpObjects)[i] = i; ! 1003: ! 1004: /* return number of item in list */ ! 1005: return (nCnt); ! 1006: } ! 1007: ! 1008: ! 1009: ! 1010: ! 1011: void WINAPI AnalyzeProcess ( ! 1012: DBGPROCESS *lpDbgProcess, ! 1013: LPVMOBJECT lpVMObject, ! 1014: int nObjects) ! 1015: { ! 1016: DBGTHREAD *pTh = lpDbgProcess->lpThreads; ! 1017: DBGDLL *pDll = lpDbgProcess->lpDlls; ! 1018: int nStack; ! 1019: int nThreadCnt = 0; ! 1020: char szNum[10]; ! 1021: char szObjDesc[MAX_PATH]; ! 1022: SECTIONINFO *pSection; ! 1023: int i; ! 1024: MEMORY_BASIC_INFORMATION mbi; ! 1025: LPPROBE lpProbe; ! 1026: ! 1027: ! 1028: /* name default heap in process if available */ ! 1029: if (lpProbe = RetrieveProbeData ()) ! 1030: { ! 1031: VirtualQueryEx (lpDbgProcess->hProcess, (PVOID)lpProbe->hDefHeap, &mbi, sizeof (mbi)); ! 1032: ! 1033: /* ignore invalid regions with a base region of 0 */ ! 1034: if (mbi.AllocationBase) ! 1035: { ! 1036: /* find all objects with same base region */ ! 1037: for (i=0; i<nObjects; i++) ! 1038: { ! 1039: if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase) ! 1040: { ! 1041: strcpy (lpVMObject[i].szObjType, "heap"); ! 1042: strcpy (lpVMObject[i].szModule, "process default"); ! 1043: } ! 1044: } ! 1045: } ! 1046: } ! 1047: ! 1048: /* name stack object for each thread in process */ ! 1049: while (pTh != NULL) ! 1050: { ! 1051: /* get stack location for thread */ ! 1052: nStack = WhereIsStack (pTh->hThread); ! 1053: ! 1054: strcpy (szObjDesc, "Thread "); ! 1055: strcat (szObjDesc, itoa (nThreadCnt, szNum, 10)); ! 1056: ! 1057: /* locate base region */ ! 1058: VirtualQueryEx (lpDbgProcess->hProcess, (PVOID)nStack, &mbi, sizeof (mbi)); ! 1059: ! 1060: /* ignore invalid regions with a base region of 0 */ ! 1061: if (mbi.AllocationBase) ! 1062: { ! 1063: /* find all objects with same base region */ ! 1064: for (i=0; i<nObjects; i++) ! 1065: { ! 1066: if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase) ! 1067: { ! 1068: strcpy (lpVMObject[i].szObjType, "stack"); ! 1069: strcpy (lpVMObject[i].szModule, szObjDesc); ! 1070: } ! 1071: } ! 1072: } ! 1073: ! 1074: /* locate and identify the guard page in each stack. ! 1075: The guard page is a single page of committed memory at the lower end of ! 1076: committed memory and immediately adjacent to the stack's reserved memory. ! 1077: If there is no more reserved stack space left, the guard page will be the ! 1078: last page of committed memory. A stack cannot exist without a guard page. ! 1079: There will be at most three regions of memory in the stack: the actual stack ! 1080: space is committed, the guard page is committed and the remaining address ! 1081: space is marked reserved. */ ! 1082: /* locate lowest region of stack, since objects array is not sorted until after ! 1083: this function, it is always in ascending address order :) */ ! 1084: i=0; ! 1085: while (i<nObjects && ! 1086: (int)lpVMObject[i].mbi.BaseAddress < nStack && ! 1087: lpVMObject[i].mbi.AllocationBase != mbi.AllocationBase) ! 1088: i++; ! 1089: ! 1090: if (i<nObjects && ! 1091: lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase) ! 1092: { ! 1093: if (lpVMObject[i].mbi.State == MEM_RESERVE) ! 1094: i++; ! 1095: ! 1096: /* identify guard page in section field */ ! 1097: strcpy (lpVMObject[i].szSection, "guard"); ! 1098: } ! 1099: ! 1100: /* increment thread count */ ! 1101: nThreadCnt++; ! 1102: ! 1103: /* increment list pointer */ ! 1104: pTh = (DBGTHREAD *)pTh->Next; ! 1105: } ! 1106: ! 1107: /* name DLL objects in process */ ! 1108: while (pDll != NULL) ! 1109: { ! 1110: /* locate dll base region */ ! 1111: VirtualQueryEx (lpDbgProcess->hProcess, pDll->lpBaseOfDll, &mbi, sizeof (mbi)); ! 1112: ! 1113: /* ignore invalid regions with a base region of 0 */ ! 1114: if (mbi.AllocationBase) ! 1115: { ! 1116: /* find all objects with same base region */ ! 1117: for (i=0; i<nObjects; i++) ! 1118: { ! 1119: if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase) ! 1120: { ! 1121: strcpy (lpVMObject[i].szObjType, "dll"); ! 1122: strcpy (lpVMObject[i].szModule, pDll->szImageName); ! 1123: } ! 1124: } ! 1125: } ! 1126: ! 1127: /* name dll sections */ ! 1128: pSection = (SECTIONINFO *)pDll->lpSection; ! 1129: while (pSection != NULL) ! 1130: { ! 1131: i = 0; ! 1132: while (i++<nObjects) ! 1133: { ! 1134: if (lpVMObject[i].mbi.BaseAddress == ! 1135: ((char *)pDll->lpBaseOfDll + pSection->uVirtualAddress)) ! 1136: { ! 1137: strcpy (lpVMObject[i].szSection, pSection->szSection); ! 1138: break; ! 1139: } ! 1140: } ! 1141: pSection = (SECTIONINFO *)pSection->Next; ! 1142: } ! 1143: ! 1144: /* increment list pointer */ ! 1145: pDll = (DBGDLL *)pDll->Next; ! 1146: } ! 1147: ! 1148: /* locate exe base region */ ! 1149: VirtualQueryEx (lpDbgProcess->hProcess, lpDbgProcess->lpImage, &mbi, sizeof (mbi)); ! 1150: ! 1151: /* ignore invalid regions with a base region of 0 */ ! 1152: if (mbi.AllocationBase) ! 1153: { ! 1154: /* find all objects with same base region */ ! 1155: for (i=0; i<nObjects; i++) ! 1156: { ! 1157: if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase) ! 1158: { ! 1159: strcpy (lpVMObject[i].szObjType, "exe"); ! 1160: strcpy (lpVMObject[i].szModule, lpDbgProcess->szModule); ! 1161: } ! 1162: } ! 1163: } ! 1164: ! 1165: /* name exe sections */ ! 1166: pSection = lpDbgProcess->lpSection; ! 1167: while (pSection != NULL) ! 1168: { ! 1169: i = 0; ! 1170: while (i++<nObjects) ! 1171: { ! 1172: if (lpVMObject[i].mbi.BaseAddress == ! 1173: ((char *)lpDbgProcess->lpImage + pSection->uVirtualAddress)) ! 1174: { ! 1175: strcpy (lpVMObject[i].szSection, pSection->szSection); ! 1176: break; ! 1177: } ! 1178: } ! 1179: pSection = (SECTIONINFO *)pSection->Next; ! 1180: } ! 1181: } ! 1182: ! 1183: ! 1184: ! 1185: ! 1186: /* find all occurrances of objects having same base region */ ! 1187: void WINAPI NameObjects ( ! 1188: HANDLE hProcess, ! 1189: LPVOID lpAddress, ! 1190: LPVMOBJECT lpVMObj, ! 1191: int nObjects, ! 1192: char *lpszObjType, ! 1193: char *lpszModule) ! 1194: { ! 1195: int i; ! 1196: MEMORY_BASIC_INFORMATION mbi; ! 1197: ! 1198: /* locate base region */ ! 1199: VirtualQueryEx (hProcess, lpAddress, &mbi, sizeof (mbi)); ! 1200: ! 1201: /* ignore invalid regions with a base region of 0 */ ! 1202: if (!mbi.AllocationBase) ! 1203: return; ! 1204: ! 1205: /* find all objects with same base region */ ! 1206: for (i=0; i<nObjects; i++) ! 1207: { ! 1208: if (lpVMObj[i].mbi.AllocationBase == mbi.AllocationBase) ! 1209: { ! 1210: strcpy (lpVMObj[i].szObjType, lpszObjType); ! 1211: strcpy (lpVMObj[i].szModule, lpszModule); ! 1212: } ! 1213: } ! 1214: } ! 1215: ! 1216: ! 1217: ! 1218: ! 1219: void WINAPI IdentifyNewObjects ( ! 1220: LPVMOBJECT lpVMObjectOld, ! 1221: int nObjectsOld, ! 1222: LPVMOBJECT lpVMObject, ! 1223: int nObjects) ! 1224: { ! 1225: int i, j; ! 1226: ! 1227: for (i=0; i<nObjects; i++) ! 1228: { ! 1229: for (j=0; j<nObjectsOld; j++) ! 1230: { ! 1231: if (VMCompare (lpVMObject+i, lpVMObjectOld+j)) ! 1232: goto NEXT; ! 1233: } ! 1234: ! 1235: /* if not found must be a new item */ ! 1236: lpVMObject[i].bNew = TRUE; ! 1237: NEXT:; ! 1238: } ! 1239: } ! 1240: ! 1241: ! 1242: BOOL WINAPI VMCompare ( ! 1243: LPVMOBJECT lpVM1, ! 1244: LPVMOBJECT lpVM2) ! 1245: { ! 1246: ! 1247: /* compare memory info */ ! 1248: if (lpVM1->mbi.AllocationBase != lpVM2->mbi.AllocationBase || ! 1249: lpVM1->mbi.BaseAddress != lpVM2->mbi.BaseAddress || ! 1250: lpVM1->mbi.RegionSize != lpVM2->mbi.RegionSize || ! 1251: lpVM1->mbi.Protect != lpVM2->mbi.Protect || ! 1252: lpVM1->mbi.AllocationProtect != lpVM2->mbi.AllocationProtect || ! 1253: lpVM1->mbi.State != lpVM2->mbi.State || ! 1254: lpVM1->mbi.Type != lpVM2->mbi.Type ) ! 1255: return FALSE; ! 1256: ! 1257: /* compare character information */ ! 1258: if (memcmp ((LPVOID)lpVM1->szObjType, (LPVOID)lpVM2->szObjType, 12) || ! 1259: memcmp ((LPVOID)lpVM1->szSection, ! 1260: (LPVOID)lpVM2->szSection, ! 1261: IMAGE_SIZEOF_SHORT_NAME) || ! 1262: memcmp ((LPVOID)lpVM1->szModule, (LPVOID)lpVM2->szModule, MAX_PATH)) ! 1263: return FALSE; ! 1264: ! 1265: /* if still here, must be a match */ ! 1266: return TRUE; ! 1267: } ! 1268: ! 1269: ! 1270: ! 1271: ! 1272: /* test to see if all memory objects in range are committed */ ! 1273: BOOL WINAPI CommittedMemoryRange ( ! 1274: int i, ! 1275: int j, ! 1276: LPVMOBJECT lpvm, ! 1277: int *Objects) ! 1278: { ! 1279: int k; ! 1280: ! 1281: /* test each memory object in range */ ! 1282: for (k = min(i, j); k <= max (i, j); k++) ! 1283: /* report any non committed memory regions */ ! 1284: if (lpvm[Objects[k]].mbi.State != MEM_COMMIT) ! 1285: return FALSE; ! 1286: ! 1287: /* report all committed range */ ! 1288: return TRUE; ! 1289: } ! 1290: ! 1291: ! 1292: ! 1293: ! 1294: /* signal debugger thread to access process memory */ ! 1295: BOOL WINAPI AccessProcessMemory ( ! 1296: HANDLE hMemoryEvent, ! 1297: HANDLE hAckEvent, ! 1298: LPVOID lpAddress, ! 1299: LPVOID lpBuffer, ! 1300: DWORD *dwSize) ! 1301: { ! 1302: DWORD dwResult; ! 1303: ! 1304: /* copy data to module globals */ ! 1305: PMAAddress = lpAddress; ! 1306: PMABuffer = lpBuffer; ! 1307: PMASize = *dwSize; ! 1308: ! 1309: /* signal debugger thread to read memory from process */ ! 1310: SetEvent (hMemoryEvent); ! 1311: ! 1312: /* wait on debugger thread to signal completion of memory task */ ! 1313: dwResult = WaitForSingleObject (hAckEvent, 100000); ! 1314: ResetEvent (hAckEvent); ! 1315: ! 1316: /* reset size accessed to verify operation */ ! 1317: *dwSize = PMASize; ! 1318: ! 1319: return (dwResult == WAIT_OBJECT_0 && ! 1320: PMASize != 0); ! 1321: } ! 1322: ! 1323: ! 1324: ! 1325: ! 1326: BOOL WINAPI InterruptThread_HookProcess ( ! 1327: DBGPROCESS *lpDbgProcess, ! 1328: LPPROCESS_STATE lpState) ! 1329: { ! 1330: DBGDLL *pDlls = lpDbgProcess->lpDlls; ! 1331: int nBytes, nLen, i; ! 1332: MEMORY_BASIC_INFORMATION mbi; ! 1333: LPVOID lpLoadLibrary = NULL; ! 1334: char szKernel[] = "KERNEL32.DLL"; ! 1335: char szFunction[] = "LoadLibraryA"; ! 1336: BYTE pCode[PAGESIZE]; ! 1337: BYTE pStack[PAGESIZE]; ! 1338: HANDLE hDll; ! 1339: ! 1340: ! 1341: /* initialize stack and code pages */ ! 1342: for (i=0; i<PAGESIZE; i++) ! 1343: { ! 1344: pStack[i] = 0; ! 1345: pCode[i] = 0; ! 1346: } ! 1347: ! 1348: /* find kernel32 Dll */ ! 1349: while (pDlls != NULL) ! 1350: { ! 1351: if (!stricmp (pDlls->szImageName, szKernel)) ! 1352: break; ! 1353: pDlls = (DBGDLL *)pDlls->Next; ! 1354: } ! 1355: ! 1356: /* if DLL not loaded abort */ ! 1357: if (pDlls == NULL) ! 1358: return FALSE; ! 1359: ! 1360: /* load the dll in this process, find the function offset in this ! 1361: process and normalize to the offset in the child process */ ! 1362: hDll = LoadLibrary (szKernel); ! 1363: lpLoadLibrary = GetProcAddress (hDll, szFunction); ! 1364: VirtualQuery (lpLoadLibrary, &mbi, sizeof (mbi)); ! 1365: (int)lpLoadLibrary += ((int)pDlls->lpBaseOfDll - (int)mbi.AllocationBase); ! 1366: FreeLibrary (hDll); ! 1367: ! 1368: /* get thread context information and save for replacement */ ! 1369: lpState->Context.ContextFlags = CONTEXT_FULL; ! 1370: if (!GetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context))) ! 1371: return FALSE; ! 1372: ! 1373: #ifdef _X86_ ! 1374: lpState->Eip = (LPVOID)lpState->Context.Eip; ! 1375: lpState->Esp = (LPVOID)lpState->Context.Esp; ! 1376: #else /* MIPS */ ! 1377: lpState->Eip = (LPVOID)lpState->Context.Fir; ! 1378: lpState->Esp = (LPVOID)lpState->Context.IntSp; ! 1379: #endif ! 1380: ! 1381: /* locate first writeable code page in exe module */ ! 1382: lpState->pCodePage = lpDbgProcess->lpImage; ! 1383: VirtualQueryEx (lpDbgProcess->hProcess, lpState->pCodePage, &mbi, sizeof (mbi)); ! 1384: while (!(mbi.Protect & PAGE_READWRITE) && ! 1385: mbi.AllocationBase == lpDbgProcess->lpImage) ! 1386: { ! 1387: (int)lpState->pCodePage = (int)mbi.BaseAddress + mbi.RegionSize; ! 1388: VirtualQueryEx (lpDbgProcess->hProcess, lpState->pCodePage, &mbi, sizeof (mbi)); ! 1389: } ! 1390: ! 1391: if (mbi.AllocationBase != lpDbgProcess->lpImage) ! 1392: return FALSE; ! 1393: ! 1394: /* save code page for reset process */ ! 1395: ReadProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes); ! 1396: ! 1397: /* write DLL path to code page */ ! 1398: strcpy ((char *)pCode, szCurPath); ! 1399: strcat ((char *)pCode, "\\probe.dll"); ! 1400: nLen = strlen ((char *)pCode) + 1; ! 1401: ! 1402: /* find current stack page and save */ ! 1403: ! 1404: #ifdef _X86_ ! 1405: lpState->pStackPage = (LPVOID)((((int)lpState->Context.Esp)/PAGESIZE) * PAGESIZE); ! 1406: #else /* MIPS */ ! 1407: lpState->pStackPage = (LPVOID)((((int)lpState->Context.IntSp)/PAGESIZE) * PAGESIZE); ! 1408: #endif ! 1409: ! 1410: ReadProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes); ! 1411: ! 1412: /* push address of DLL string on stack */ ! 1413: *((int *)(pStack+4092)) = (int)lpState->pCodePage; ! 1414: ! 1415: /* push return address on stack */ ! 1416: *((int *)(pStack+4088)) = (int)lpState->pCodePage+nLen; ! 1417: ! 1418: /* return to Int 3 breakpoint instruction */ ! 1419: pCode[nLen] = 0xCC; ! 1420: ! 1421: /* write new code and stack pages */ ! 1422: WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, pCode, PAGESIZE, &nBytes); ! 1423: WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, pStack, PAGESIZE, &nBytes); ! 1424: ! 1425: /* update Eip to execute at actual LoadLibrary function */ ! 1426: /* adjust stack pointer to point to return address */ ! 1427: ! 1428: #ifdef _X86_ ! 1429: lpState->Context.Eip = (UINT)lpLoadLibrary; ! 1430: lpState->Context.Esp = (UINT)lpState->pStackPage+4088; ! 1431: #else /* _MIPS_ */ ! 1432: lpState->Context.Fir = (UINT)lpLoadLibrary; ! 1433: lpState->Context.IntSp = (UINT)lpState->pStackPage+4088; ! 1434: #endif ! 1435: ! 1436: if (!SetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context))) ! 1437: { ! 1438: ReportError (IDS_ERRSETTHREADCONTEXT); ! 1439: /* replace code and stack pages */ ! 1440: WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes); ! 1441: WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes); ! 1442: return FALSE; ! 1443: } ! 1444: ! 1445: return TRUE; ! 1446: } ! 1447: ! 1448: ! 1449: ! 1450: ! 1451: void WINAPI ResetInterruptedThread ( ! 1452: DBGPROCESS *lpDbgProcess, ! 1453: LPPROCESS_STATE lpState) ! 1454: { ! 1455: int nBytes; ! 1456: ! 1457: /* return thread context information */ ! 1458: ! 1459: #ifdef _X86_ ! 1460: lpState->Context.Eip = (UINT)lpState->Eip; ! 1461: lpState->Context.Esp = (UINT)lpState->Esp; ! 1462: #else /* MIPS */ ! 1463: lpState->Context.Fir = (UINT)lpState->Eip; ! 1464: lpState->Context.IntSp = (UINT)lpState->Esp; ! 1465: #endif ! 1466: ! 1467: SetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context)); ! 1468: ! 1469: /* return code and stack information */ ! 1470: WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes); ! 1471: WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes); ! 1472: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.