www.pudn.com > PEMonitor_0.10_src.zip > PEMonitor.c
/////////////////////////////////////////////////////////////////////////////// // // FileName : PEMonitor.c // Version : 0.10 // Author : Luo Cong // Date : 2004-09-02 (yyyy-mm-dd) // Comment : // /////////////////////////////////////////////////////////////////////////////// #include#include #include "Misc.h" #include "PEMonitor.h" #include "PEServ.h" #include "FileServ.h" #include "BreakPointServ.h" #include "StackServ.h" #include "MemServ.h" #include "LogServ.h" #include "disasm.h" #ifdef _DEBUG #include "tib.h" PTIB pTib; #endif long g_lFileSize = 0; char *g_FileContents = NULL; unsigned long g_ulImageBase = 0; int ProcessFile(char *szCmdLine) { int nRetResult = 0; int nRetCode; CONTEXT ct; STARTUPINFO si; DEBUG_EVENT de; PROCESS_INFORMATION pi; LPVOID lpAddr; int nSetBPIndex = 1; int nCurBPIndex; FUNCTION_NAME fnPrevFuncName; unsigned long ulPrevEIP; #ifdef _MY_DEBUG char szPrevFuncName[FUNCTIONNAMELEN]; #endif GetStartupInfo(&si); nRetCode = CreateProcess( NULL, // name of executable module szCmdLine, // command line string NULL, // ProcessAttributes NULL, // ThreadAttributes FALSE, // handle inheritance option DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, // creation flags NULL, // new environment block NULL, // current directory name &si, // startup information &pi // process information ); MY_PROCESS_ERROR(nRetCode); for (;;) { nRetCode = WaitForDebugEvent(&de, INFINITE); MY_PROCESS_ERROR(nRetCode); if (EXIT_PROCESS_DEBUG_EVENT == de.dwDebugEventCode) { printf("\n**** PE Monitor: Debug Process finished! ****\n"); #ifdef _DEBUG MessageBox(NULL, "Process finished!", "PE Monitor", MB_ICONINFORMATION); #endif break; } else if (CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode) { nRetCode = SetFunctionsBreakPoint(pi.hProcess); MY_PROCESS_ERROR(nRetCode); } else if (EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode) { if ( EXCEPTION_BREAKPOINT ==\ de.u.Exception.ExceptionRecord.ExceptionCode ) { lpAddr = de.u.Exception.ExceptionRecord.ExceptionAddress; nCurBPIndex = GetBreakPointIndex(lpAddr); if (nCurBPIndex) { #ifdef _MY_DEBUG printf( "Break '%s' at address: 0x%08X\n", g_bpData[nCurBPIndex].szFuncName, lpAddr ); #endif #ifdef _MY_DEBUG strcpy(szPrevFuncName, g_bpData[nCurBPIndex].szFuncName); #endif fnPrevFuncName = g_bpData[nCurBPIndex].fnFuncName; nRetCode = RemoveBreakPoint(pi.hProcess, nCurBPIndex); MY_PROCESS_ERROR(nRetCode); ct.ContextFlags = CONTEXT_FULL; nRetCode = GetThreadContext(pi.hThread, &ct); MY_PROCESS_ERROR(nRetCode); nRetCode = AnalyzeBreakPointAndWriteToLog( pi.hProcess, ct.Esp, fnPrevFuncName ); MY_PROCESS_ERROR(nRetCode); --ct.Eip; // Set single step flag to Re-SetBreakPoint on this // existing breakpoint. ct.EFlags |= TRAPFLAG; // set single step flag nRetCode = SetThreadContext(pi.hThread, &ct); MY_PROCESS_ERROR(nRetCode); ulPrevEIP = ct.Eip; } } // EXCEPTION_BREAKPOINT else if ( EXCEPTION_SINGLE_STEP ==\ de.u.Exception.ExceptionRecord.ExceptionCode ) { // Re-SetBreakPoint on the last existing breakpoint. nRetCode = SetBreakPoint( pi.hProcess, (unsigned long *)ulPrevEIP, #ifdef _MY_DEBUG szPrevFuncName, #endif fnPrevFuncName, nCurBPIndex ); MY_PROCESS_ERROR(nRetCode); } // EXCEPTION_SINGLE_STEP } nRetCode = ContinueDebugEvent( de.dwProcessId, de.dwThreadId, DBG_CONTINUE ); MY_PROCESS_ERROR(nRetCode); } // for (;;) nRetResult = 1; Exit0: CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return nRetResult; } int Initialize(const char *szPEFileName) { int nRetResult = 0; int nRetCode; IMAGE_NT_HEADERS nt_header; nRetCode = ReadFileContents(szPEFileName); MY_PROCESS_ERROR(nRetCode); nRetCode = InitLogFile(szPEFileName); MY_PROCESS_ERROR(nRetCode); nRetCode = GetNTHeader(&nt_header); MY_PROCESS_ERROR(nRetCode); g_ulImageBase = nt_header.OptionalHeader.ImageBase; nRetResult = 1; Exit0: return nRetResult; } void Finalize() { FreeFileContents(); FinalizeLogFile(); } void Usage(const char *szExecFileName) { printf( "PE Monitor v%d.%02d, Compiled on " __DATE__ ", " __TIME__ "\n" "Copyleft (C) Luo Cong at Kingsoft, Duba\n" "Usage:\n\t" "%s FileName [Parameter 1] [Parameter 2] ... [Parameter N]\n", VERSIONHI, VERSIONLO, szExecFileName ); } /** * Attention: * szCmdLine's size must not greater than MAX_PATH, * Here has an hidden trouble. */ void GetStartupCmdLine(int argc, char *argv[], char *szCmdLine) { int i; szCmdLine[0] = '\0'; strcat(szCmdLine, "\""); strcat(szCmdLine, argv[1]); strcat(szCmdLine, "\" "); for (i = 2; i < argc; ++i) { strcat(szCmdLine, argv[i]); strcat(szCmdLine, " "); } szCmdLine[strlen(szCmdLine) - 1] = '\0'; } int main(int argc, char *argv[]) { int nRetResult = 0; int nRetCode; char szCmdLine[MAX_PATH]; if (argc < 2) { Usage(argv[0]); goto Exit0; } nRetCode = IsPEFile(argv[1]); MY_PROCESS_ERROR(nRetCode); nRetCode = Initialize(argv[1]); MY_PROCESS_ERROR(nRetCode); GetStartupCmdLine(argc, argv, szCmdLine); nRetCode = ProcessFile(szCmdLine); MY_PROCESS_ERROR(nRetCode); nRetResult = 1; Exit0: Finalize(); return nRetResult; }