|
|
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);
1.1.1.2 ! root 16: int WINAPI HandleRiscBreakPoint(DBGPROCESS *, DWORD);
1.1 root 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:
1.1.1.2 ! root 480: #ifndef _X86_ /* Risc needs special handling here to reset breakpoint */
! 481: HandleRiscBreakPoint(lpDbgProcess, de.dwThreadId);
1.1 root 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:
1.1.1.2 ! root 857: #ifndef _X86_
1.1 root 858: /*
1.1.1.2 ! root 859: * MIPS/ALPHA must increment the FIR on a breakpoint
1.1 root 860: * in order to fetch the next instruction
861: */
862:
1.1.1.2 ! root 863: int WINAPI HandleRiscBreakPoint(
1.1 root 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: }
1.1.1.2 ! root 899: #endif /* !_X86_ */
1.1 root 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_ */
1.1.1.2 ! root 915: return (int) ThreadContext.IntSp;
1.1 root 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.