ProcessHacker 源码分析1

华温书
2023-12-01

ProcessHacker 的版本在不断更新,版本2.33相应的开发环境也于是俱进地更新到了VS2013.之前研究的是2.88版本相应的是VS2010.

 下定决心好好研究 ProcessHacker 和 ReatOS的代码。结合的参考资料有:毛德操的《windows 内核情景分析》还用潘爱民的《windows内核原理与实验》、经典的《Windows Internal》系列书籍、零散资料。

 

 ProcessHacker主要分为两部分,用户程序部分ProcessHacker.exe和一个驱动程序kprocesshacker.sys .分析工作也自然地分为两部分.

先贴出main函数。

INT WINAPI wWinMain(
    _In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ PWSTR lpCmdLine,
    _In_ INT nCmdShow
    ) 
{
    LONG result;
#ifdef DEBUG
    PHP_BASE_THREAD_DBG dbg;
#endif


CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);/*This function initializes the Component Object Model (COM) for use by the current thread. 
Applications are required to use CoInitializeEx before they make any other COM library calls except for memory allocation functions.


*/
//(struct _TEB *) (ULONG_PTR)__readfsdword(PcTeb);
pTeb = (struct _TEB *) (ULONG_PTR)__readfsdword(PcTeb);//线程环境块 地址
pPeb = pTeb->ProcessEnvironmentBlock;//进程环境块
PhInstanceHandle = pPeb->ImageBaseAddress;//进程主模块地址
   // PhInstanceHandle = (HINSTANCE)NtCurrentPeb()->ImageBaseAddress;//handle。线程环境块,进程环境块,值得认真看看。与CPU相关,编译器内部函数 __readfsdword 查看FS段中内容
//TEB 在FS段 0x18位置处
    if (!NT_SUCCESS(PhInitializePhLib()))
        return 1;
    if (!PhInitializeAppSystem())
        return 1;


    PhInitializeCommonControls();


    if (PhCurrentTokenQueryHandle)
    {
        PTOKEN_USER tokenUser;


        if (NT_SUCCESS(PhGetTokenUser(PhCurrentTokenQueryHandle, &tokenUser)))
        {
            PhCurrentUserName = PhGetSidFullName(tokenUser->User.Sid, TRUE, NULL);
            PhFree(tokenUser);
        }
    }


    PhLocalSystemName = PhGetSidFullName(&PhSeLocalSystemSid, TRUE, NULL);


    // There has been a report of the above call failing.
    if (!PhLocalSystemName)
        PhLocalSystemName = PhCreateString(L"NT AUTHORITY\\SYSTEM");//


    PhApplicationFileName = PhGetApplicationFileName();//是通过读取 LDR_DATA_TABLE_ENTRY(这些信息都在进程内存空间中)。参见 《LDR链调试手记》
    PhApplicationDirectory = PhGetApplicationDirectory();//\phlib\support.c


    // Just in case
    if (!PhApplicationFileName)
        PhApplicationFileName = PhCreateString(L"ProcessHacker.exe");
    if (!PhApplicationDirectory)
        PhApplicationDirectory = PhReferenceEmptyString();


    PhpProcessStartupParameters();


    PhpInitializeSettings();


    PhpEnablePrivileges();


    if (PhStartupParameters.RunAsServiceMode)//切为 服务模式。StartServiceCtrlDispatcher:Running the Program as a Local Server
    {
        RtlExitUserProcess(PhRunAsServiceStart(PhStartupParameters.RunAsServiceMode));//提供一个服务名。见《WINDOWS系统编程 Windows.System.Programming》
    }


    // Activate a previous instance if required.
    if (
        PhGetIntegerSetting(L"AllowOnlyOneInstance") &&
        !PhStartupParameters.NewInstance &&
        !PhStartupParameters.ShowOptions &&
        !PhStartupParameters.CommandMode &&
        !PhStartupParameters.PhSvc
        )
        PhActivatePreviousInstance();//通过发送 自定义的窗口消息,来实现激活。有所呼有所应。


    if (PhGetIntegerSetting(L"EnableKph") && !PhStartupParameters.NoKph)
        PhInitializeKph();


    if (
        PhStartupParameters.CommandMode &&
        PhStartupParameters.CommandType &&
        PhStartupParameters.CommandAction
        )
    {
        NTSTATUS status;


        status = PhCommandModeStart();


        if (!NT_SUCCESS(status) && !PhStartupParameters.Silent)
        {
            PhShowStatus(NULL, L"Unable to execute the command", status, 0);
        }


        RtlExitUserProcess(status);
    }


    if (PhStartupParameters.PhSvc)
    {
        MSG message;


        // Turn the feedback cursor off.????
        PostMessage(NULL, WM_NULL, 0, 0);//WM_NULL 空消息
//The WM_NULL message performs no operation. An application sends the WM_NULL message if it wants to post a message that the recipient window will ignore.
/*
For example, if an application has installed a WH_GETMESSAGE hook and wants to prevent a message from being processed, the GetMsgProc callback function can change the message number
to WM_NULL so the recipient will ignore it.
As another example, an application can check if a window is responding to messages by sending the WM_NULL message with the SendMessageTimeout function.
*/
        GetMessage(&message, NULL, 0, 0);


        RtlExitUserProcess(PhSvcMain(NULL, NULL, NULL));
    }


    // Create a mutant for the installer.
    {
        HANDLE mutantHandle;
        OBJECT_ATTRIBUTES oa;
        UNICODE_STRING mutantName;


        RtlInitUnicodeString(&mutantName, L"\\BaseNamedObjects\\ProcessHacker2Mutant");
        InitializeObjectAttributes(
            &oa,
            &mutantName,
            0,
            NULL,
            NULL
            );


        NtCreateMutant(&mutantHandle, MUTANT_ALL_ACCESS, &oa, FALSE);
    }


    // Set priority.
    {
        PROCESS_PRIORITY_CLASS priorityClass;


        priorityClass.Foreground = FALSE;
        priorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;


        if (PhStartupParameters.PriorityClass != 0)
            priorityClass.PriorityClass = (UCHAR)PhStartupParameters.PriorityClass;


        NtSetInformationProcess(NtCurrentProcess(), ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS));
    }


#ifdef DEBUG
    dbg.ClientId = NtCurrentTeb()->ClientId;
    dbg.StartAddress = wWinMain;
    dbg.Parameter = NULL;
    InsertTailList(&PhDbgThreadListHead, &dbg.ListEntry);
    TlsSetValue(PhDbgThreadDbgTlsIndex, &dbg);
#endif


    PhInitializeAutoPool(&BaseAutoPool);


    PhEmInitialization();
    PhGuiSupportInitialization();
    PhTreeNewInitialization();//树形控件
    PhGraphControlInitialization();
    PhHexEditInitialization();//16进制编辑器实现
    PhColorBoxInitialization();


    PhSmallIconSize.X = GetSystemMetrics(SM_CXSMICON);//不采用 硬编码
    PhSmallIconSize.Y = GetSystemMetrics(SM_CYSMICON);


    if (PhStartupParameters.ShowOptions)
    {
        // Elevated options dialog for changing the value of Replace Task Manager with Process Hacker.
        PhShowOptionsDialog(PhStartupParameters.WindowHandle);
        RtlExitUserProcess(STATUS_SUCCESS);
    }


    PhPluginsEnabled = PhGetIntegerSetting(L"EnablePlugins") && !PhStartupParameters.NoPlugins;


    if (PhPluginsEnabled)
    {
        PhPluginsInitialization();
        PhLoadPlugins();
    }


    if (!PhMainWndInitialization(nCmdShow))
    {
PhShowError(NULL, L"无法初始主窗口.");//PhShowError(NULL, L"Unable to initialize the main window.");
        return 1;
    }


    PhDrainAutoPool(&BaseAutoPool);


    result = PhMainMessageLoop();//主循环
    RtlExitUserProcess(result);
}

 类似资料: