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; 
}