1. 程式人生 > >windows遍歷程序與殺死程序

windows遍歷程序與殺死程序

windows下遍歷程序有多種方式:

程序快照:CreateToolhelp32Snapshot;

程序狀態API:PSAPI;

在psapi中主要使用到的方法有:

EnumProcesses——列舉程序;

EnumProcessModules——列舉程序內模組;

GetModuleFileNameEx——獲取模組名;

通過這3個方法就可以遍歷程序以及程序內各個模組;

其中基本資料結構QString、QList是基於Qt的,如果用的不是Qt庫,換成C++對應STL標準庫List、String的即可;

    //Win32Api:
    void AdjustPrivilege()
    {
        HANDLE hToken;
        if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
        {
            TOKEN_PRIVILEGES tp;
            tp.PrivilegeCount = 1;
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))
            {
                AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
            }
            CloseHandle(hToken);
        }
    }
	
    //根據程序所在的路徑查詢程序,並返回程序的ID列表
    QList<DWORD> CheckProcess(const QString &processPath)
    {
        AdjustPrivilege();
        QList<DWORD> pIDList;
        DWORD dwProcessId[1024];
        DWORD bytesRet;
        if (EnumProcesses(dwProcessId, sizeof(dwProcessId), &bytesRet))
        {
            HANDLE hProcess = NULL;
            HMODULE hModus[1024];
            DWORD bytesModuRet;
            TCHAR szModuleName[MAX_PATH];
            QStringList tempPathList = processPath.toLower()
                    .split(QRegExp("[/\\\\]"), QString::SkipEmptyParts);
            QString processPathWinStd;//轉成windows標準的路徑
            int listLength = tempPathList.length();
            for (int idx = 0; idx < listLength; ++idx)
            {
                if (idx != 0)
                    processPathWinStd.push_back("\\");
                processPathWinStd.push_back(tempPathList[idx]);
            }
            int ProcessNum = (bytesRet/sizeof(DWORD));
            for (int i = 0, j = 0; i < ProcessNum; ++i)
            {
                hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessId[i]);
                if (hProcess)
                {
                    //Do not call CloseHandle on any of the handles returned by this function.
                    //The information comes from a snapshot, so there are no resources to be freed.
                    if (EnumProcessModules(hProcess, hModus, sizeof(hModus), &bytesModuRet))
                    {
                        int ModuleNum = (bytesRet/sizeof(DWORD));
                        for (j = 0; j < ModuleNum; ++j)
                        {
                            if (GetModuleFileNameEx(hProcess, hModus[j], szModuleName, sizeof(szModuleName))
                             && processPathWinStd == QString::fromWCharArray(szModuleName, _tcslen(szModuleName)).toLower())
                            {
                                pIDList.push_back(dwProcessId[i]);
                            }
                        }
                    }
                    CloseHandle(hProcess);
                }
            }
        }
        return pIDList;
    }
注意其中的EnumProcessModules中的hModus控制代碼不能使用CloseHandle(因為這些控制代碼來自一個快照snapshot,不是實際的資源):

Do not call CloseHandle on any of the handles returned by this function.
The information comes from a snapshot, so there are no resources to be freed.

windows下殺死程序也有兩種方式:

TerminateProcess——系統API;

NtTerminateProcess——ntdll.dll中未公開匯出方法;

TerminateProcess實際上也是呼叫NtTerminateProcess實現具體功能的;

正常情況下,呼叫這兩個任何一個都可以終結或者殺死一個程序(誇使用者殺程序需要先提權,提權見“windows提權方法”),但是在有些情況下有些應用程式為了防止自己被殺,會hook系統的TerminateProcess方法,導致TerminateProcess失效;所以用NtTerminateProcess可以使殺死程序的成功率更高一些;

    void Terminate(const QString &processPath)
    {
        AdjustPrivilege();
        //================TerminateProcess================//遍歷程序列表與程序模組,匹配路徑後強殺
        DWORD dwProcessId[1024];
        DWORD bytesRet;
        if (EnumProcesses(dwProcessId, sizeof(dwProcessId), &bytesRet))
        {
            HANDLE hProcess = NULL;
            HMODULE hModus[1024];
            DWORD bytesModuRet;
            TCHAR szModuleName[MAX_PATH];
            QStringList tempPathList = processPath.toLower()
                    .split(QRegExp("[/\\\\]"), QString::SkipEmptyParts);
            QString processPathWinStd;//轉成windows標準的路徑
            int listLength = tempPathList.length();
            for (int idx = 0; idx < listLength; ++idx)
            {
                if (idx != 0)
                    processPathWinStd.push_back("\\");
                processPathWinStd.push_back(tempPathList[idx]);
            }
            int ProcessNum = (bytesRet/sizeof(DWORD));
            for (int i = 0, j = 0; i < ProcessNum; ++i)
            {
                hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessId[i]);
                if (hProcess)
                {
                    //Do not call CloseHandle on any of the handles returned by this function.
                    //The information comes from a snapshot, so there are no resources to be freed.
                    if (EnumProcessModules(hProcess, hModus, sizeof(hModus), &bytesModuRet))
                    {
                        int ModuleNum = (bytesRet/sizeof(DWORD));
                        for (j = 0; j < ModuleNum; ++j)
                        {
                            if (GetModuleFileNameEx(hProcess, hModus[j], szModuleName, sizeof(szModuleName))
                             && processPathWinStd == QString::fromWCharArray(szModuleName, _tcslen(szModuleName)).toLower())
                            {
                                TerminateProcess(hProcess, 4);
                            }
                        }
                    }
                    CloseHandle(hProcess);
                }
            }
        }
    }

    void Terminate(const DWORD &pID)
    {
        AdjustPrivilege();
        //================TerminateProcess================//根據程序ID強殺
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pID);
        if (hProcess)
        {
            TerminateProcess(hProcess, 4);
            CloseHandle(hProcess);
        }
    }

ntdll.dll匯出方式:
    const unsigned long SE_DEBUG_PRIVILEGE = 0x14;
    typedef int (__stdcall *fRtlAdjustPrivilege)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN);
    typedef DWORD (__stdcall *fNtTerminateProcess)(HANDLE, UINT);
    HMODULE hNtDll = NULL;
    fRtlAdjustPrivilege funcAdjustPrivilege = NULL;
    fNtTerminateProcess funcTerminateProcess = NULL;

    //================
    //NtDll方式:
    //================
    bool NtInit()
    {
        hNtDll = LoadLibrary(_T("ntdll.dll"));
        if (!hNtDll)
            return false;
        funcAdjustPrivilege =
                (fRtlAdjustPrivilege)GetProcAddress(hNtDll, "RtlAdjustPrivilege");
        funcTerminateProcess =
                (fNtTerminateProcess)GetProcAddress(hNtDll, "NtTerminateProcess");
        return true;
    }

    void NtFree()
    {
        if (hNtDll)
            FreeLibrary(hNtDll);
    }

    void NtAdjustPrivilege()
    {
        if (funcAdjustPrivilege)
        {
            BOOLEAN oldStatus;
            funcAdjustPrivilege(SE_DEBUG_PRIVILEGE, true, false, &oldStatus);
        }
    }

    void NtTerminate(const QString &processPath)
    {
        NtAdjustPrivilege();
        //================TerminateProcess================//遍歷程序列表與程序模組,匹配路徑後強殺
        if (funcTerminateProcess)
        {
            DWORD dwProcessId[1024];
            DWORD bytesRet;
            if (EnumProcesses(dwProcessId, sizeof(dwProcessId), &bytesRet))
            {
                HANDLE hProcess = NULL;
                HMODULE hModus[1024];
                DWORD bytesModuRet;
                TCHAR szModuleName[MAX_PATH];
                QStringList tempPathList = processPath.toLower()
                        .split(QRegExp("[/\\\\]"), QString::SkipEmptyParts);
                QString processPathWinStd;//轉成windows標準的路徑
                int listLength = tempPathList.length();
                for (int idx = 0; idx < listLength; ++idx)
                {
                    if (idx != 0)
                        processPathWinStd.push_back("\\");
                    processPathWinStd.push_back(tempPathList[idx]);
                }
                int ProcessNum = (bytesRet/sizeof(DWORD));
                for (int i = 0, j = 0; i < ProcessNum; ++i)
                {
                    hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessId[i]);
                    if (hProcess)
                    {
                        //Do not call CloseHandle on any of the handles returned by this function.
                        //The information comes from a snapshot, so there are no resources to be freed.
                        if (EnumProcessModules(hProcess, hModus, sizeof(hModus), &bytesModuRet))
                        {
                            int ModuleNum = (bytesRet/sizeof(DWORD));
                            for (j = 0; j < ModuleNum; ++j)
                            {
                                if (GetModuleFileNameEx(hProcess, hModus[j], szModuleName, sizeof(szModuleName))
                                 && processPathWinStd == QString::fromWCharArray(szModuleName, _tcslen(szModuleName)).toLower())
                                {
                                    funcTerminateProcess(hProcess, 4);
                                }
                            }
                        }
                        CloseHandle(hProcess);
                    }
                }
            }
        }
    }

    void NtTerminate(const DWORD &pID)
    {
        NtAdjustPrivilege();
        //================TerminateProcess================//根據程序ID強殺
        if (funcTerminateProcess)
        {
            HANDLE hProcess = NULL;
            hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pID);
            if (hProcess)
            {
                funcTerminateProcess(hProcess, 4);
                CloseHandle(hProcess);
            }
        }
    }