PDEBUG.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:39k
源码类别:
Windows编程
开发平台:
Visual C++
- /******************************************************************************
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1993-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- ******************************************************************************/
- #include "pwalk.h"
- #include <memory.h>
- /* module globals */
- LPVOID PMAAddress;
- LPVOID PMABuffer;
- DWORD PMASize;
- extern char szCurPath[MAX_PATH];
- /* local debug functions */
- BOOL WINAPI DebugEventThread (DBGPROCESS *);
- BOOL WINAPI CreateDebugEvents (LPHANDLE);
- void WINAPI AddThreadNode (DBGPROCESS *, DWORD, HANDLE, int, LPTHREAD_START_ROUTINE, HANDLE);
- int WINAPI HandleBreakPoint(DBGPROCESS *, DWORD);
- void WINAPI RemoveThreadNode (DBGPROCESS *, DWORD);
- void WINAPI AddDllNode (DBGPROCESS *, LOAD_DLL_DEBUG_INFO *);
- void WINAPI RemoveDllNode (DBGPROCESS *, LOAD_DLL_DEBUG_INFO *);
- void WINAPI SuspendDebuggeeProcess (DBGPROCESS *);
- void WINAPI ResumeDebuggeeProcess (DBGPROCESS *);
- void WINAPI NameObjects (HANDLE, LPVOID, LPVMOBJECT, int, char *, char *);
- BOOL WINAPI VMCompare (LPVMOBJECT, LPVMOBJECT);
- BOOL WINAPI InterruptThread_HookProcess (DBGPROCESS *, LPPROCESS_STATE);
- void WINAPI ResetInterruptedThread (DBGPROCESS *, LPPROCESS_STATE);
- void WINAPI RecordException (DBGPROCESS *, DEBUG_EVENT *);
- HANDLE WINAPI FindThreadHandle (DBGPROCESS *, DWORD);
- /* start debug thread, and return event active handle */
- DBGPROCESS* WINAPI StartChildProcess (
- HWND hWnd,
- char *lpszModule,
- LPHANDLE lpDbgEvents)
- {
- DWORD TID;
- HANDLE hDebugHeap;
- DBGPROCESS *lpDbgProcess;
- int i;
- /* create unique debug events using debuggee process ID */
- if (!CreateDebugEvents (lpDbgEvents))
- return NULL;
- /* create serialized heap of dynamic size */
- if (!(hDebugHeap = HeapCreate (0, sizeof (DBGPROCESS) + sizeof (DBGTHREAD), 0)))
- {
- /* close all event handles */
- for (i=0; i<nDEBUGEVENTS; i++)
- CloseHandle (lpDbgEvents[i]);
- return NULL;
- }
- /* allocate and initialize debug heap structure */
- lpDbgProcess = (DBGPROCESS *)HeapAlloc (hDebugHeap, 0, sizeof (DBGPROCESS));
- lpDbgProcess->hDbgHeap = hDebugHeap;
- strcpy (lpDbgProcess->szModule, lpszModule);
- lpDbgProcess->hWnd = hWnd;
- lpDbgProcess->lpThreads = NULL;
- lpDbgProcess->lpSection = NULL;
- lpDbgProcess->lpERs = NULL;
- /* create debug thread */
- if (!(CreateThread ((LPSECURITY_ATTRIBUTES)NULL,
- 4096,
- (LPTHREAD_START_ROUTINE)DebugEventThread,
- (LPVOID)lpDbgProcess,
- 0,
- &TID)))
- return NULL;
- /* wait 15 seconds for debugger to complete initialization, else error */
- if (WAIT_TIMEOUT == WaitForSingleObject (lpDbgEvents[ACKNOWLEDGE], 15000))
- {
- HeapDestroy (lpDbgProcess->hDbgHeap);
- /* close all event handles */
- for (i=0; i<nDEBUGEVENTS; i++)
- CloseHandle (lpDbgEvents[i]);
- return NULL;
- }
- /* reset acknowledge event */
- ResetEvent (lpDbgEvents[ACKNOWLEDGE]);
- /* successfull thread and event start */
- return lpDbgProcess;
- }
- /* function notifies debug thread to terminate, frees handles, and destroys heap */
- void WINAPI CloseChildProcess (
- DBGPROCESS *lpDbgProcess,
- LPHANDLE lpDbgEvents)
- {
- int i;
- DBGTHREAD *pNode = lpDbgProcess->lpThreads;
- /* set close event for debug thread and wait for acknowledge */
- SetEvent (lpDbgEvents[CLOSEDEBUGGER]);
- WaitForSingleObject (lpDbgEvents[ACKNOWLEDGE], INFINITE);
- /* close all event handles */
- for (i=0; i<nDEBUGEVENTS; i++)
- CloseHandle (lpDbgEvents[i]);
- /* close all thread handles in the list */
- while (pNode != NULL)
- {
- RemoveThreadNode (lpDbgProcess, pNode->dwThreadID);
- pNode = lpDbgProcess->lpThreads;
- }
- /* destroy the debug heap */
- HeapDestroy (lpDbgProcess->hDbgHeap);
- }
- /* local function creates debug event objects for thread synchronization */
- BOOL WINAPI CreateDebugEvents (
- LPHANDLE lpDbgEvents)
- {
- char szEvent[MAX_PATH];
- LoadString (GetModuleHandle (NULL), IDS_DBGEVNTACTIVE, szEvent, sizeof (szEvent));
- if (!(lpDbgEvents[DEBUGACTIVE] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
- TRUE,
- TRUE,
- szEvent)))
- return FALSE;
- LoadString (GetModuleHandle (NULL), IDS_DBGEVNTCLOSE, szEvent, sizeof (szEvent));
- if (!(lpDbgEvents[CLOSEDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
- TRUE,
- FALSE,
- szEvent)))
- {
- CloseHandle (lpDbgEvents[DEBUGACTIVE]);
- return FALSE;
- }
- LoadString (GetModuleHandle (NULL), IDS_DBGEVNTSTOP, szEvent, sizeof (szEvent));
- if (!(lpDbgEvents[SUSPENDDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
- TRUE,
- FALSE,
- szEvent)))
- {
- CloseHandle (lpDbgEvents[DEBUGACTIVE]);
- CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
- return FALSE;
- }
- LoadString (GetModuleHandle (NULL), IDS_DBGEVNTSTART, szEvent, sizeof (szEvent));
- if (!(lpDbgEvents[RESUMEDEBUGGER] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
- TRUE,
- FALSE,
- szEvent)))
- {
- CloseHandle (lpDbgEvents[DEBUGACTIVE]);
- CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
- CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]);
- return FALSE;
- }
- LoadString (GetModuleHandle (NULL), IDS_DBGEVNTREAD, szEvent, sizeof (szEvent));
- if (!(lpDbgEvents[READMEMORY] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
- TRUE,
- FALSE,
- szEvent)))
- {
- CloseHandle (lpDbgEvents[DEBUGACTIVE]);
- CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
- CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]);
- CloseHandle (lpDbgEvents[RESUMEDEBUGGER]);
- return FALSE;
- }
- LoadString (GetModuleHandle (NULL), IDS_DBGEVNTWRITE, szEvent, sizeof (szEvent));
- if (!(lpDbgEvents[WRITEMEMORY] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
- TRUE,
- FALSE,
- szEvent)))
- {
- CloseHandle (lpDbgEvents[DEBUGACTIVE]);
- CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
- CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]);
- CloseHandle (lpDbgEvents[RESUMEDEBUGGER]);
- CloseHandle (lpDbgEvents[READMEMORY]);
- return FALSE;
- }
- LoadString (GetModuleHandle (NULL), IDS_DBGEVNTACK, szEvent, sizeof (szEvent));
- if (!(lpDbgEvents[ACKNOWLEDGE] = CreateEvent ((LPSECURITY_ATTRIBUTES)NULL,
- TRUE,
- FALSE,
- szEvent)))
- {
- CloseHandle (lpDbgEvents[DEBUGACTIVE]);
- CloseHandle (lpDbgEvents[CLOSEDEBUGGER]);
- CloseHandle (lpDbgEvents[SUSPENDDEBUGGER]);
- CloseHandle (lpDbgEvents[RESUMEDEBUGGER]);
- CloseHandle (lpDbgEvents[READMEMORY]);
- CloseHandle (lpDbgEvents[WRITEMEMORY]);
- return FALSE;
- }
- /* success */
- return TRUE;
- }
- /* main daddyo thread that is the debugger residing over a debuggee */
- BOOL WINAPI DebugEventThread (
- DBGPROCESS *lpDbgProcess)
- {
- DEBUG_EVENT de;
- HANDLE hDbgEvent[nDEBUGEVENTS];
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- HANDLE hChildProcess;
- BOOL bHooked, bUnHooked;
- // PROCESS_STATE ProcessState;
- bHooked = FALSE;
- bUnHooked = FALSE;
- /* initialize process startup information */
- si.cb = sizeof (si);
- si.lpReserved = NULL;
- si.lpDesktop = NULL;
- si.lpTitle = NULL;
- si.dwX = 0;
- si.dwY = 0;
- si.dwXSize = 0;
- si.dwYSize = 0;
- si.dwXCountChars = 0;
- si.dwYCountChars = 0;
- si.dwFillAttribute = 0;
- si.dwFlags = STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_SHOWNORMAL;
- si.cbReserved2 = 0;
- si.lpReserved2 = NULL;
- /* create debug process on module name */
- if (!CreateProcess (lpDbgProcess->szModule,
- NULL,
- (LPSECURITY_ATTRIBUTES)NULL,
- (LPSECURITY_ATTRIBUTES)NULL,
- FALSE,
- DEBUG_PROCESS,
- NULL,
- NULL,
- (LPSTARTUPINFO)&si,
- (LPPROCESS_INFORMATION)&pi))
- {
- ReportError (IDS_ERRCREATEPROCESS);
- return FALSE;
- }
- /* open process for all access */
- if ((hChildProcess = OpenProcess (PROCESS_ALL_ACCESS,
- FALSE,
- pi.dwProcessId)) == NULL)
- {
- ReportError (IDS_ERROPENPROCESS);
- TerminateProcess (pi.hProcess, 0);
- return FALSE;
- }
- /* store process info */
- lpDbgProcess->hProcess = hChildProcess;
- lpDbgProcess->dwPriority = GetPriorityClass (pi.hProcess);
- lpDbgProcess->dwProcessID = pi.dwProcessId;
- lpDbgProcess->bActive = TRUE;
- /* close process and thread handles in pi structure */
- CloseHandle (pi.hThread);
- CloseHandle (pi.hProcess);
- /* open debug events */
- CreateDebugEvents (hDbgEvent);
- /* signale completion of task */
- SetEvent (hDbgEvent[ACKNOWLEDGE]);
- /* start debug event loop */
- while (TRUE)
- {
- int nIndex;
- /* wait for debugger active */
- switch (nIndex = WaitForMultipleObjects (nDEBUGEVENTS, hDbgEvent, FALSE, INFINITE))
- {
- case CLOSEDEBUGGER:
- {
- int i;
- /* terminate debuggee process */
- TerminateProcess (lpDbgProcess->hProcess, 0);
- CloseHandle (lpDbgProcess->hProcess);
- /* signal completion of task */
- SetEvent (hDbgEvent[ACKNOWLEDGE]);
- /* close all debug events */
- for (i=0; i<nDEBUGEVENTS; i++)
- CloseHandle (hDbgEvent[i]);
- /* exit debugger now */
- return TRUE;
- }
- break;
- case SUSPENDDEBUGGER:
- SuspendDebuggeeProcess (lpDbgProcess);
- ResetEvent (hDbgEvent[DEBUGACTIVE]);
- ResetEvent (hDbgEvent[SUSPENDDEBUGGER]);
- break;
- case RESUMEDEBUGGER:
- ResumeDebuggeeProcess (lpDbgProcess);
- SetEvent (hDbgEvent[DEBUGACTIVE]);
- ResetEvent (hDbgEvent[RESUMEDEBUGGER]);
- break;
- case READMEMORY:
- {
- MEMORY_BASIC_INFORMATION mbi;
- DWORD Protect = 0;
- /* reset event so we don't do repeat */
- ResetEvent (hDbgEvent [READMEMORY]);
- /* if not committed memory abort */
- if (!VirtualQueryEx (lpDbgProcess->hProcess,
- PMAAddress,
- &mbi,
- sizeof (MEMORY_BASIC_INFORMATION)) ||
- mbi.State != MEM_COMMIT)
- {
- PMASize = 0;
- SetEvent (hDbgEvent [ACKNOWLEDGE]);
- break;
- }
- /* if guarded memory, change protection temporarily */
- if (!(mbi.Protect & PAGE_READONLY) &&
- !(mbi.Protect & PAGE_READWRITE))
- VirtualProtectEx (lpDbgProcess->hProcess,
- PMAAddress,
- PMASize,
- PAGE_READONLY,
- &Protect);
- if (!ReadProcessMemory (lpDbgProcess->hProcess,
- PMAAddress,
- PMABuffer,
- PMASize,
- NULL))
- {
- if (mbi.AllocationProtect != PAGE_READONLY &&
- mbi.AllocationProtect != PAGE_READWRITE)
- NotifyUser (NULL, IDS_ERROR, 0, "BaseProtect NOACCESS", 0);
- else
- {
- ReportError (IDS_ERRREADPROCESSMEMORY);
- PMASize = 0;
- }
- }
- /* reset protection if changed */
- if (Protect)
- VirtualProtectEx (lpDbgProcess->hProcess,
- PMAAddress,
- PMASize,
- Protect,
- &Protect);
- /* acknowledge success */
- SetEvent (hDbgEvent [ACKNOWLEDGE]);
- }
- break;
- case WRITEMEMORY:
- if (!WriteProcessMemory (lpDbgProcess->hProcess,
- PMAAddress,
- PMABuffer,
- PMASize,
- NULL))
- {
- ReportError (IDS_ERRWRITEPROCESSMEMORY);
- PMASize = 0;
- }
- ResetEvent (hDbgEvent [WRITEMEMORY]);
- SetEvent (hDbgEvent [ACKNOWLEDGE]);
- break;
- case DEBUGACTIVE:
- /* if debug active */
- if ((WaitForDebugEvent (&de, (DWORD)100)))
- {
- if (de.dwProcessId == lpDbgProcess->dwProcessID)
- {
- switch (de.dwDebugEventCode)
- {
- case EXIT_PROCESS_DEBUG_EVENT:
- SetStatusText (lpDbgProcess->hWnd, IDS_EXITPROCESS, 0);
- /* uninitialize probe dll */
- ResetProbe ();
- /* process is going away so notify main window */
- SendNotifyMessage (lpDbgProcess->hWnd,
- WM_COMMAND,
- IDM_PROCESSUNLOAD,
- 0);
- break;
- case LOAD_DLL_DEBUG_EVENT:
- SetStatusText (lpDbgProcess->hWnd, IDS_LOADDLL, 0);
- AddDllNode (lpDbgProcess,
- (LOAD_DLL_DEBUG_INFO *)&(de.u.LoadDll));
- break;
- case UNLOAD_DLL_DEBUG_EVENT:
- SetStatusText (lpDbgProcess->hWnd, IDS_UNLOADDLL, 0);
- RemoveDllNode (lpDbgProcess,
- (LOAD_DLL_DEBUG_INFO *)&(de.u.LoadDll));
- break;
- case CREATE_PROCESS_DEBUG_EVENT:
- SetStatusText (lpDbgProcess->hWnd, IDS_CREATEPROCESS, 0);
- /* add first thread to linked list of dbg structures */
- AddThreadNode (lpDbgProcess,
- de.dwThreadId,
- de.u.CreateProcessInfo.hThread,
- GetThreadPriority (de.u.CreateProcessInfo.hThread),
- de.u.CreateProcessInfo.lpStartAddress,
- de.u.CreateProcessInfo.hFile);
- lpDbgProcess->hFile = de.u.CreateProcessInfo.hFile;
- lpDbgProcess->lpImage = de.u.CreateProcessInfo.lpBaseOfImage;
- lpDbgProcess->dwDbgInfoOffset = de.u.CreateProcessInfo.dwDebugInfoFileOffset;
- lpDbgProcess->nDbgInfoSize = de.u.CreateProcessInfo.nDebugInfoSize;
- break;
- case CREATE_THREAD_DEBUG_EVENT:
- SetStatusText (lpDbgProcess->hWnd, IDS_CREATETHREAD, 0);
- /* add thread to linked list of dbg structures */
- AddThreadNode (lpDbgProcess,
- de.dwThreadId,
- de.u.CreateThread.hThread,
- GetThreadPriority (de.u.CreateThread.hThread),
- de.u.CreateThread.lpStartAddress,
- NULL);
- break;
- case EXIT_THREAD_DEBUG_EVENT:
- SetStatusText (lpDbgProcess->hWnd, IDS_EXITTHREAD, 0);
- /* remove thread record */
- RemoveThreadNode (lpDbgProcess,
- de.dwThreadId);
- break;
- case EXCEPTION_DEBUG_EVENT:
- switch (de.u.Exception.ExceptionRecord.ExceptionCode)
- {
- case EXCEPTION_BREAKPOINT:
- HandleBreakPoint(lpDbgProcess, de.dwThreadId);
- SetStatusText (lpDbgProcess->hWnd,
- IDS_BREAKPOINTEXCEPTION,
- RGB (0, 0xff, 0));
- /* post message to get ball rolling in main thread */
- PostMessage (lpDbgProcess->hWnd,
- WM_COMMAND,
- IDM_PROCESSREWALK,
- 0);
- break;
- case EXCEPTION_ACCESS_VIOLATION:
- /* record exception information */
- SetStatusText (lpDbgProcess->hWnd,
- IDS_ACCESSVIOLATIONEXCEPTION,
- RGB (0xff, 0, 0));
- RecordException (lpDbgProcess, &de);
- break;
- default:
- SetStatusText (lpDbgProcess->hWnd,
- IDS_UNHANDLEDEXCEPTION,
- RGB (0xff, 0, 0));
- RecordException (lpDbgProcess, &de);
- break;
- }
- break;
- case RIP_EVENT:
- SetStatusText (lpDbgProcess->hWnd,
- IDS_RIPEVENT,
- RGB (0, 0xff, 0));
- break;
- case OUTPUT_DEBUG_STRING_EVENT:
- SetStatusText (lpDbgProcess->hWnd,
- IDS_OUTPUTDEBUGSTRING,
- RGB (0, 0xff, 0));
- break;
- default:
- break;
- }
- }
- if(de.u.Exception.ExceptionRecord.ExceptionCode != EXCEPTION_BREAKPOINT)
- ContinueDebugEvent (de.dwProcessId, de.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
- else
- ContinueDebugEvent (de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
- }
- break;
- }
- }
- return TRUE;
- }
- void WINAPI SuspendDebuggeeProcess (
- DBGPROCESS *lppr)
- {
- DBGTHREAD *lpth = (DBGTHREAD *)lppr->lpThreads;
- while (lpth)
- {
- SuspendThread (lpth->hThread);
- lpth = (DBGTHREAD *)lpth->Next;
- }
- /* inform user via status bar */
- SetStatusText (lppr->hWnd, IDS_PROCESSSUSPENDED, RGB (0xff, 0, 0));
- lppr->bActive = FALSE;
- }
- void WINAPI ResumeDebuggeeProcess (
- DBGPROCESS *lppr)
- {
- DBGTHREAD *lpth = (DBGTHREAD *)lppr->lpThreads;
- while (lpth)
- {
- ResumeThread (lpth->hThread);
- lpth = (DBGTHREAD *)lpth->Next;
- }
- /* inform user via status bar */
- SetStatusText (lppr->hWnd, IDS_PROCESSRESUMED, RGB (0, 0xff, 0));
- lppr->bActive = TRUE;
- }
- void WINAPI AddThreadNode (
- DBGPROCESS *lppr,
- DWORD dwThreadID,
- HANDLE hThread,
- int nPriority,
- LPTHREAD_START_ROUTINE lpStart,
- HANDLE hFile)
- {
- DBGTHREAD *lpth;
- DBGTHREAD *pNode = lppr->lpThreads;
- /* allocate thread node off heap */
- lpth = (DBGTHREAD *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGTHREAD));
- /* initialize thread data */
- lpth->lpStartAddress = lpStart;
- lpth->nPriority = nPriority;
- lpth->dwThreadID = dwThreadID;
- lpth->hThread = hThread;
- lpth->Next = NULL;
- /* retieve section names for executable module if file handle passed */
- if (hFile)
- {
- RetrieveModuleName (lppr->szModule, hFile);
- lppr->lpSection = NULL;
- RetrieveSectionNames (lppr->hDbgHeap, hFile, &(lppr->lpSection));
- }
- /* set linked list pointers */
- while (pNode && pNode->Next)
- pNode = (DBGTHREAD *)pNode->Next;
- if (!pNode)
- lppr->lpThreads = lpth;
- else
- (DBGTHREAD *)pNode->Next = lpth;
- }
- void WINAPI RemoveThreadNode (
- DBGPROCESS *lppr,
- DWORD dwThreadID)
- {
- DBGTHREAD *pNode = lppr->lpThreads;
- DBGTHREAD *lpth;
- while (pNode->Next &&
- ((DBGTHREAD *)(pNode->Next))->dwThreadID != dwThreadID)
- pNode = (DBGTHREAD *)pNode->Next;
- if (pNode->Next)
- {
- lpth = (DBGTHREAD *)pNode->Next;
- pNode->Next = ((DBGTHREAD *)(pNode->Next))->Next;
- CloseHandle (lpth->hThread);
- HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpth);
- }
- else if (pNode->dwThreadID == dwThreadID)
- {
- lpth = pNode;
- lppr->lpThreads = NULL;
- CloseHandle (lpth->hThread);
- HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpth);
- }
- }
- /* find a thread's handle based on thread ID */
- HANDLE WINAPI FindThreadHandle (
- DBGPROCESS *lppr,
- DWORD dwThreadId)
- {
- DBGTHREAD *pNode = lppr->lpThreads;
- while (pNode != NULL)
- if (pNode->dwThreadID == dwThreadId)
- return (pNode->hThread);
- return NULL;
- }
- void WINAPI AddDllNode (
- DBGPROCESS *lppr,
- LOAD_DLL_DEBUG_INFO *lpdbgDll)
- {
- DBGDLL *lpdll;
- DBGDLL *pNode = lppr->lpDlls;
- /* allocate Dll node off heap */
- if ((lpdll = (DBGDLL *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGDLL))) == NULL)
- ReportError (IDS_ERRHEAPALLOC);
- /* initialize Dll structure */
- lpdll->hFile = lpdbgDll->hFile;
- lpdll->lpBaseOfDll = lpdbgDll->lpBaseOfDll;
- lpdll->dwDebugInfoFileOffset = lpdbgDll->dwDebugInfoFileOffset;
- lpdll->nDebugInfoSize = lpdbgDll->nDebugInfoSize;
- lpdll->fUnicode = lpdbgDll->fUnicode;
- lpdll->Next = NULL;
- lpdll->lpSection = NULL;
- RetrieveModuleName (lpdll->szImageName, lpdbgDll->hFile);
- /* get section names for DLL */
- RetrieveSectionNames (lppr->hDbgHeap, lpdbgDll->hFile, &(lpdll->lpSection));
- /* set linked list pointers */
- while (pNode && pNode->Next)
- pNode = (DBGDLL *)pNode->Next;
- if (!pNode)
- lppr->lpDlls = lpdll;
- else
- (DBGDLL *)pNode->Next = lpdll;
- }
- void WINAPI RemoveDllNode (
- DBGPROCESS *lppr,
- LOAD_DLL_DEBUG_INFO *lpdbgDll)
- {
- DBGDLL *pNode = lppr->lpDlls;
- DBGDLL *lpdll;
- SECTIONINFO *pSection, *pNext;
- while (pNode->Next &&
- ((DBGDLL *)(pNode->Next))->lpBaseOfDll != lpdbgDll->lpBaseOfDll)
- pNode = (DBGDLL *)pNode->Next;
- if (pNode->Next)
- {
- lpdll = (DBGDLL *)pNode->Next;
- pNode->Next = ((DBGDLL *)(pNode->Next))->Next;
- pSection = pNext = lpdll->lpSection;
- while (pNext)
- {
- pNext = (SECTIONINFO *)pSection->Next;
- HeapFree (lppr->hDbgHeap, 0, (LPSTR)pSection);
- pSection = pNext;
- }
- HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpdll);
- }
- else if (pNode->lpBaseOfDll == lpdbgDll->lpBaseOfDll)
- {
- lpdll = pNode;
- lppr->lpDlls = NULL;
- pSection = pNext = lpdll->lpSection;
- while (pNext)
- {
- pNext = (SECTIONINFO *)pSection->Next;
- HeapFree (lppr->hDbgHeap, 0, (LPSTR)pSection);
- pSection = pNext;
- }
- HeapFree (lppr->hDbgHeap, 0, (LPSTR)lpdll);
- }
- }
- void WINAPI RecordException (
- DBGPROCESS *lppr,
- DEBUG_EVENT *de)
- {
- DBGEXCEPTREC *lper;
- DBGEXCEPTREC *per = lppr->lpERs;
- HANDLE hThread;
- int i;
- /* allocate Dll node off heap */
- if ((lper = (DBGEXCEPTREC *)HeapAlloc (lppr->hDbgHeap, 0, sizeof (DBGEXCEPTREC))) == NULL)
- ReportError (IDS_ERRHEAPALLOC);
- /* initialize exception record structure */
- lper->dwThreadId = de->dwThreadId;
- lper->dwFirstChance = de->u.Exception.dwFirstChance;
- lper->ExceptRecord.ExceptionCode = de->u.Exception.ExceptionRecord.ExceptionCode;
- lper->ExceptRecord.ExceptionFlags = de->u.Exception.ExceptionRecord.ExceptionFlags;
- lper->ExceptRecord.ExceptionRecord = NULL;
- lper->ExceptRecord.ExceptionAddress = de->u.Exception.ExceptionRecord.ExceptionAddress;
- lper->ExceptRecord.NumberParameters = de->u.Exception.ExceptionRecord.NumberParameters;
- for (i=0; i<EXCEPTION_MAXIMUM_PARAMETERS; i++)
- lper->ExceptRecord.ExceptionInformation[i] =
- de->u.Exception.ExceptionRecord.ExceptionInformation[i];
- /* get exception thread handle */
- hThread = FindThreadHandle (lppr, de->dwThreadId);
- lper->Context.ContextFlags = CONTEXT_CONTROL;
- GetThreadContext (hThread, &(lper->Context));
- /* set linked list pointers */
- while (per && per->Next)
- per = (DBGEXCEPTREC *)per->Next;
- if (!per)
- lppr->lpERs = lper;
- else
- (DBGEXCEPTREC *)per->Next = lper;
- }
- /*
- * MIPS/ALPHA/PPC must increment the FIR/Iar on a breakpoint
- * in order to fetch the next instruction
- */
- int WINAPI HandleBreakPoint(
- DBGPROCESS *lppr,
- DWORD dwThreadID
- )
- {
- CONTEXT ThreadContext;
- DBGTHREAD *pNode = lppr->lpThreads;
- HANDLE hThread;
- while (pNode && pNode->dwThreadID != dwThreadID)
- pNode = (DBGTHREAD *)pNode->Next;
- if(!pNode)
- return(0);
- else
- {
- hThread = (HANDLE) pNode->hThread;
- ThreadContext.ContextFlags = CONTEXT_CONTROL;
- if (!GetThreadContext (hThread, &ThreadContext))
- {
- ReportError (IDS_ERRGETTHREADCONTEXT);
- return(0);
- }
- #ifdef _PPC_
- ThreadContext.Iar += 4;
- #elif !defined _X86_
- ThreadContext.Fir += 4;
- #endif
- if (!SetThreadContext (hThread, &ThreadContext))
- {
- ReportError (IDS_ERRSETTHREADCONTEXT);
- return (0);
- }
- return (1);
- }
- }
- int WINAPI WhereIsStack (
- HANDLE hThreadContext)
- {
- CONTEXT ThreadContext;
- ThreadContext.ContextFlags = CONTEXT_CONTROL;
- if (!GetThreadContext (hThreadContext, &ThreadContext))
- ReportError (IDS_ERRGETTHREADCONTEXT);
- #ifdef _X86_
- return ThreadContext.Esp;
- #elif defined (_PPC_)
- return (int) ThreadContext.Gpr1;
- #else /* _MIPS_ */
- return (int) ThreadContext.IntSp;
- #endif
- }
- /* function walks memory regions of process */
- int WINAPI WalkProcess (
- HANDLE hChildProcess,
- LPVOID *lpWalk,
- LPINT *lpObjects)
- {
- LPVMOBJECT lpList;
- LPVOID lpMem = 0;
- LPVOID lpStack = 0;
- int nCnt, i;
- SYSTEM_INFO si;
- /* if pointer exists, reset to no commit */
- if (*lpWalk)
- {
- if (!VirtualFree (*lpWalk, 0, MEM_DECOMMIT))
- ReportError (IDS_ERRVIRTUALFREE);
- }
- /* else perform initial reserve */
- else
- if ((*lpWalk = VirtualAlloc (NULL,
- TOTALVMRESERVE,
- MEM_RESERVE,
- PAGE_NOACCESS)) == NULL)
- ReportError (IDS_ERRVIRTUALALLOC);
- /* initialize list pointer to beginning of walker list */
- lpList = (LPVMOBJECT)*lpWalk;
- /* Get maximum address range from system info */
- GetSystemInfo(&si);
- /* walk process addresses */
- while (lpMem < si.lpMaximumApplicationAddress)
- {
- try /* virtual memory exception handler automatically commits mem */
- {
- /* touch memory in VMOBJECT structure that exists after mbi field to trigger
- access violation for a new page of memory. Do this here since VirtualQueryEx
- does not seem to generate exceptions, rather it just fails calls */
- *lpList->szObjType = 0;
- *lpList->szModule = 0;
- *lpList->szSection = 0;
- lpList->bNew = 0;
- VirtualQueryEx (hChildProcess,
- lpMem,
- &(lpList->mbi),
- sizeof (MEMORY_BASIC_INFORMATION));
- /* increment lpMem to next region of memory */
- lpMem = (LPVOID)((DWORD)lpList->mbi.BaseAddress +
- (DWORD)lpList->mbi.RegionSize);
- lpList++;
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
- {
- /* commit next page of walker list memory */
- if (((int)lpList + 4096) < (int)*lpWalk + TOTALVMRESERVE)
- VirtualAlloc ((LPVOID)((int)lpList + sizeof (VMOBJECT)),
- 4096,
- MEM_COMMIT,
- PAGE_READWRITE);
- else
- {
- NotifyUser (NULL,
- IDS_ERROR,
- IDS_NOTENOUGHMEM,
- " reserved for Objects",
- MB_OK);
- return 0;
- }
- }
- }
- /* allocate objects index array */
- if (*lpObjects)
- LocalFree (*lpObjects);
- nCnt = (((int)(LPVOID)lpList)-(int)*lpWalk)/sizeof (VMOBJECT);
- *lpObjects = LocalAlloc (LPTR, nCnt * sizeof (int));
- for (i=0; i<nCnt; i++)
- (*lpObjects)[i] = i;
- /* return number of item in list */
- return (nCnt);
- }
- void WINAPI AnalyzeProcess (
- DBGPROCESS *lpDbgProcess,
- LPVMOBJECT lpVMObject,
- int nObjects)
- {
- DBGTHREAD *pTh = lpDbgProcess->lpThreads;
- DBGDLL *pDll = lpDbgProcess->lpDlls;
- int nStack;
- int nThreadCnt = 0;
- char szNum[10];
- char szObjDesc[MAX_PATH];
- SECTIONINFO *pSection;
- int i;
- MEMORY_BASIC_INFORMATION mbi;
- LPPROBE lpProbe;
- /* name default heap in process if available */
- if (lpProbe = RetrieveProbeData ())
- {
- VirtualQueryEx (lpDbgProcess->hProcess, (PVOID)lpProbe->hDefHeap, &mbi, sizeof (mbi));
- /* ignore invalid regions with a base region of 0 */
- if (mbi.AllocationBase)
- {
- /* find all objects with same base region */
- for (i=0; i<nObjects; i++)
- {
- if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
- {
- strcpy (lpVMObject[i].szObjType, "heap");
- strcpy (lpVMObject[i].szModule, "process default");
- }
- }
- }
- }
- /* name stack object for each thread in process */
- while (pTh != NULL)
- {
- /* get stack location for thread */
- nStack = WhereIsStack (pTh->hThread);
- strcpy (szObjDesc, "Thread ");
- strcat (szObjDesc, itoa (nThreadCnt, szNum, 10));
- /* locate base region */
- VirtualQueryEx (lpDbgProcess->hProcess, (PVOID)nStack, &mbi, sizeof (mbi));
- /* ignore invalid regions with a base region of 0 */
- if (mbi.AllocationBase)
- {
- /* find all objects with same base region */
- for (i=0; i<nObjects; i++)
- {
- if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
- {
- strcpy (lpVMObject[i].szObjType, "stack");
- strcpy (lpVMObject[i].szModule, szObjDesc);
- }
- }
- }
- /* locate and identify the guard page in each stack.
- The guard page is a single page of committed memory at the lower end of
- committed memory and immediately adjacent to the stack's reserved memory.
- If there is no more reserved stack space left, the guard page will be the
- last page of committed memory. A stack cannot exist without a guard page.
- There will be at most three regions of memory in the stack: the actual stack
- space is committed, the guard page is committed and the remaining address
- space is marked reserved. */
- /* locate lowest region of stack, since objects array is not sorted until after
- this function, it is always in ascending address order :) */
- i=0;
- while (i<nObjects &&
- (int)lpVMObject[i].mbi.BaseAddress < nStack &&
- lpVMObject[i].mbi.AllocationBase != mbi.AllocationBase)
- i++;
- if (i<nObjects &&
- lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
- {
- if (lpVMObject[i].mbi.State == MEM_RESERVE)
- i++;
- /* identify guard page in section field */
- strcpy (lpVMObject[i].szSection, "guard");
- }
- /* increment thread count */
- nThreadCnt++;
- /* increment list pointer */
- pTh = (DBGTHREAD *)pTh->Next;
- }
- /* name DLL objects in process */
- while (pDll != NULL)
- {
- /* locate dll base region */
- VirtualQueryEx (lpDbgProcess->hProcess, pDll->lpBaseOfDll, &mbi, sizeof (mbi));
- /* ignore invalid regions with a base region of 0 */
- if (mbi.AllocationBase)
- {
- /* find all objects with same base region */
- for (i=0; i<nObjects; i++)
- {
- if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
- {
- strcpy (lpVMObject[i].szObjType, "dll");
- strcpy (lpVMObject[i].szModule, pDll->szImageName);
- }
- }
- }
- /* name dll sections */
- pSection = (SECTIONINFO *)pDll->lpSection;
- while (pSection != NULL)
- {
- i = 0;
- while (i++<nObjects)
- {
- if (lpVMObject[i].mbi.BaseAddress ==
- ((char *)pDll->lpBaseOfDll + pSection->uVirtualAddress))
- {
- strcpy (lpVMObject[i].szSection, pSection->szSection);
- break;
- }
- }
- pSection = (SECTIONINFO *)pSection->Next;
- }
- /* increment list pointer */
- pDll = (DBGDLL *)pDll->Next;
- }
- /* locate exe base region */
- VirtualQueryEx (lpDbgProcess->hProcess, lpDbgProcess->lpImage, &mbi, sizeof (mbi));
- /* ignore invalid regions with a base region of 0 */
- if (mbi.AllocationBase)
- {
- /* find all objects with same base region */
- for (i=0; i<nObjects; i++)
- {
- if (lpVMObject[i].mbi.AllocationBase == mbi.AllocationBase)
- {
- strcpy (lpVMObject[i].szObjType, "exe");
- strcpy (lpVMObject[i].szModule, lpDbgProcess->szModule);
- }
- }
- }
- /* name exe sections */
- pSection = lpDbgProcess->lpSection;
- while (pSection != NULL)
- {
- i = 0;
- while (i++<nObjects)
- {
- if (lpVMObject[i].mbi.BaseAddress ==
- ((char *)lpDbgProcess->lpImage + pSection->uVirtualAddress))
- {
- strcpy (lpVMObject[i].szSection, pSection->szSection);
- break;
- }
- }
- pSection = (SECTIONINFO *)pSection->Next;
- }
- }
- /* find all occurrances of objects having same base region */
- void WINAPI NameObjects (
- HANDLE hProcess,
- LPVOID lpAddress,
- LPVMOBJECT lpVMObj,
- int nObjects,
- char *lpszObjType,
- char *lpszModule)
- {
- int i;
- MEMORY_BASIC_INFORMATION mbi;
- /* locate base region */
- VirtualQueryEx (hProcess, lpAddress, &mbi, sizeof (mbi));
- /* ignore invalid regions with a base region of 0 */
- if (!mbi.AllocationBase)
- return;
- /* find all objects with same base region */
- for (i=0; i<nObjects; i++)
- {
- if (lpVMObj[i].mbi.AllocationBase == mbi.AllocationBase)
- {
- strcpy (lpVMObj[i].szObjType, lpszObjType);
- strcpy (lpVMObj[i].szModule, lpszModule);
- }
- }
- }
- void WINAPI IdentifyNewObjects (
- LPVMOBJECT lpVMObjectOld,
- int nObjectsOld,
- LPVMOBJECT lpVMObject,
- int nObjects)
- {
- int i, j;
- for (i=0; i<nObjects; i++)
- {
- for (j=0; j<nObjectsOld; j++)
- {
- if (VMCompare (lpVMObject+i, lpVMObjectOld+j))
- goto NEXT;
- }
- /* if not found must be a new item */
- lpVMObject[i].bNew = TRUE;
- NEXT:;
- }
- }
- BOOL WINAPI VMCompare (
- LPVMOBJECT lpVM1,
- LPVMOBJECT lpVM2)
- {
- /* compare memory info */
- if (lpVM1->mbi.AllocationBase != lpVM2->mbi.AllocationBase ||
- lpVM1->mbi.BaseAddress != lpVM2->mbi.BaseAddress ||
- lpVM1->mbi.RegionSize != lpVM2->mbi.RegionSize ||
- lpVM1->mbi.Protect != lpVM2->mbi.Protect ||
- lpVM1->mbi.AllocationProtect != lpVM2->mbi.AllocationProtect ||
- lpVM1->mbi.State != lpVM2->mbi.State ||
- lpVM1->mbi.Type != lpVM2->mbi.Type )
- return FALSE;
- /* compare character information */
- if (memcmp ((LPVOID)lpVM1->szObjType, (LPVOID)lpVM2->szObjType, 12) ||
- memcmp ((LPVOID)lpVM1->szSection,
- (LPVOID)lpVM2->szSection,
- IMAGE_SIZEOF_SHORT_NAME) ||
- memcmp ((LPVOID)lpVM1->szModule, (LPVOID)lpVM2->szModule, MAX_PATH))
- return FALSE;
- /* if still here, must be a match */
- return TRUE;
- }
- /* test to see if all memory objects in range are committed */
- BOOL WINAPI CommittedMemoryRange (
- int i,
- int j,
- LPVMOBJECT lpvm,
- int *Objects)
- {
- int k;
- /* test each memory object in range */
- for (k = min(i, j); k <= max (i, j); k++)
- /* report any non committed memory regions */
- if (lpvm[Objects[k]].mbi.State != MEM_COMMIT)
- return FALSE;
- /* report all committed range */
- return TRUE;
- }
- /* signal debugger thread to access process memory */
- BOOL WINAPI AccessProcessMemory (
- HANDLE hMemoryEvent,
- HANDLE hAckEvent,
- LPVOID lpAddress,
- LPVOID lpBuffer,
- DWORD *dwSize)
- {
- DWORD dwResult;
- /* copy data to module globals */
- PMAAddress = lpAddress;
- PMABuffer = lpBuffer;
- PMASize = *dwSize;
- /* signal debugger thread to read memory from process */
- SetEvent (hMemoryEvent);
- /* wait on debugger thread to signal completion of memory task */
- dwResult = WaitForSingleObject (hAckEvent, 100000);
- ResetEvent (hAckEvent);
- /* reset size accessed to verify operation */
- *dwSize = PMASize;
- return (dwResult == WAIT_OBJECT_0 &&
- PMASize != 0);
- }
- BOOL WINAPI InterruptThread_HookProcess (
- DBGPROCESS *lpDbgProcess,
- LPPROCESS_STATE lpState)
- {
- DBGDLL *pDlls = lpDbgProcess->lpDlls;
- int nBytes, nLen, i;
- MEMORY_BASIC_INFORMATION mbi;
- LPVOID lpLoadLibrary = NULL;
- char szKernel[] = "KERNEL32.DLL";
- char szFunction[] = "LoadLibraryA";
- BYTE pCode[PAGESIZE];
- BYTE pStack[PAGESIZE];
- HANDLE hDll;
- /* initialize stack and code pages */
- for (i=0; i<PAGESIZE; i++)
- {
- pStack[i] = 0;
- pCode[i] = 0;
- }
- /* find kernel32 Dll */
- while (pDlls != NULL)
- {
- if (!stricmp (pDlls->szImageName, szKernel))
- break;
- pDlls = (DBGDLL *)pDlls->Next;
- }
- /* if DLL not loaded abort */
- if (pDlls == NULL)
- return FALSE;
- /* load the dll in this process, find the function offset in this
- process and normalize to the offset in the child process */
- hDll = LoadLibrary (szKernel);
- lpLoadLibrary = GetProcAddress (hDll, szFunction);
- VirtualQuery (lpLoadLibrary, &mbi, sizeof (mbi));
- (int)lpLoadLibrary += ((int)pDlls->lpBaseOfDll - (int)mbi.AllocationBase);
- FreeLibrary (hDll);
- /* get thread context information and save for replacement */
- lpState->Context.ContextFlags = CONTEXT_FULL;
- if (!GetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context)))
- return FALSE;
- #ifdef _X86_
- lpState->Eip = (LPVOID)lpState->Context.Eip;
- lpState->Esp = (LPVOID)lpState->Context.Esp;
- #elif defined(_PPC_)
- lpState->Eip = (LPVOID)lpState->Context.Iar;
- lpState->Esp = (LPVOID)lpState->Context.Gpr1;
- #else /* MIPS */
- lpState->Eip = (LPVOID)lpState->Context.Fir;
- lpState->Esp = (LPVOID)lpState->Context.IntSp;
- #endif
- /* locate first writeable code page in exe module */
- lpState->pCodePage = lpDbgProcess->lpImage;
- VirtualQueryEx (lpDbgProcess->hProcess, lpState->pCodePage, &mbi, sizeof (mbi));
- while (!(mbi.Protect & PAGE_READWRITE) &&
- mbi.AllocationBase == lpDbgProcess->lpImage)
- {
- (int)lpState->pCodePage = (int)mbi.BaseAddress + mbi.RegionSize;
- VirtualQueryEx (lpDbgProcess->hProcess, lpState->pCodePage, &mbi, sizeof (mbi));
- }
- if (mbi.AllocationBase != lpDbgProcess->lpImage)
- return FALSE;
- /* save code page for reset process */
- ReadProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes);
- /* write DLL path to code page */
- strcpy ((char *)pCode, szCurPath);
- strcat ((char *)pCode, "\probe.dll");
- nLen = strlen ((char *)pCode) + 1;
- /* find current stack page and save */
- #ifdef _X86_
- lpState->pStackPage = (LPVOID)((((int)lpState->Context.Esp)/PAGESIZE) * PAGESIZE);
- #elif defined(_PPC_)
- lpState->pStackPage = (LPVOID)((((int)lpState->Context.Gpr1)/PAGESIZE) * PAGESIZE);
- #else /* MIPS */
- lpState->pStackPage = (LPVOID)((((int)lpState->Context.IntSp)/PAGESIZE) * PAGESIZE);
- #endif
- ReadProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes);
- /* push address of DLL string on stack */
- *((int *)(pStack+4092)) = (int)lpState->pCodePage;
- /* push return address on stack */
- *((int *)(pStack+4088)) = (int)lpState->pCodePage+nLen;
- /* return to Int 3 breakpoint instruction */
- pCode[nLen] = 0xCC;
- /* write new code and stack pages */
- WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, pCode, PAGESIZE, &nBytes);
- WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, pStack, PAGESIZE, &nBytes);
- /* update Eip to execute at actual LoadLibrary function */
- /* adjust stack pointer to point to return address */
- #ifdef _X86_
- lpState->Context.Eip = (UINT)lpLoadLibrary;
- lpState->Context.Esp = (UINT)lpState->pStackPage+4088;
- #elif defined(_PPC_)
- lpState->Context.Iar = (UINT)lpLoadLibrary;
- lpState->Context.Gpr1 = (UINT)lpState->pStackPage+4088;
- #else /* _MIPS_ */
- lpState->Context.Fir = (UINT)lpLoadLibrary;
- lpState->Context.IntSp = (UINT)lpState->pStackPage+4088;
- #endif
- if (!SetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context)))
- {
- ReportError (IDS_ERRSETTHREADCONTEXT);
- /* replace code and stack pages */
- WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes);
- WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes);
- return FALSE;
- }
- return TRUE;
- }
- void WINAPI ResetInterruptedThread (
- DBGPROCESS *lpDbgProcess,
- LPPROCESS_STATE lpState)
- {
- int nBytes;
- /* return thread context information */
- #ifdef _X86_
- lpState->Context.Eip = (UINT)lpState->Eip;
- lpState->Context.Esp = (UINT)lpState->Esp;
- #elif defined(_PPC_)
- lpState->Context.Iar = (UINT)lpState->Eip;
- lpState->Context.Gpr1 = (UINT)lpState->Esp;
- #else /* MIPS */
- lpState->Context.Fir = (UINT)lpState->Eip;
- lpState->Context.IntSp = (UINT)lpState->Esp;
- #endif
- SetThreadContext (lpDbgProcess->lpThreads->hThread, &(lpState->Context));
- /* return code and stack information */
- WriteProcessMemory (lpDbgProcess->hProcess, lpState->pCodePage, lpState->Code, PAGESIZE, &nBytes);
- WriteProcessMemory (lpDbgProcess->hProcess, lpState->pStackPage, lpState->Stack, PAGESIZE, &nBytes);
- }