C/C++ 进程线程操作技术

手动创建单进程: 下面通过一个实例来分别演示进程的创建函数.

#include <windows.h>
#include <stdio.h>

BOOL WinExec(char *pszExePath, UINT uiCmdShow)
{
    UINT uiRet = 0;
    uiRet = ::WinExec(pszExePath, uiCmdShow);
    if (31 < uiRet)
    {
        return TRUE;
    }
    return FALSE;
}

BOOL ShellExecute(char *pszExePath, UINT uiCmdShow)
{
    HINSTANCE hInstance = 0;
    hInstance = ::ShellExecute(NULL, NULL, pszExePath, NULL, NULL, uiCmdShow);
    if (32 < (DWORD)hInstance)
    {
        return TRUE;
    }
    return FALSE;
}

BOOL Exec_Run(LPCSTR exe_file)
{
    PROCESS_INFORMATION pi = { 0 };
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);

    BOOL bRet = CreateProcessA(exe_file,
        NULL, NULL, NULL, FALSE,
        NULL, NULL, NULL, &si, &pi);

    if (bRet != FALSE)
    {
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return TRUE;
    }
    return FALSE;
}

int main(int argc, char * argv[])
{
    int ret = 0;
    ret = Exec_Run("c:\\windows\\system32\\notepad.exe");
    printf("执行状态: %d \n", ret);

    system("pause");
    return 0;
}

手动创建多线程: 多线程的创建需要使用CreateThread()其内部应该传递进去ThreadProc()线程执行函数,运行结束后恢复.

#include <Windows.h>
#include <iostream>

int Global_One = 0;
CRITICAL_SECTION g_cs;

// 定义一个线程函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
    // 加锁防止线程数据冲突
    EnterCriticalSection(&g_cs);
    for (int x = 0; x < 10; x++)
    {
        Global_One++;
        Sleep(1);
    }
    // 执行完修改以后,需要释放锁
    LeaveCriticalSection(&g_cs);
    return 0;
}

int main()
{
    // 初始化锁
    InitializeCriticalSection(&g_cs);

    HANDLE hThread[10] = { 0 };

    for (int x = 0; x < 10; x++)
    {
        // 循环创建线程
        hThread[x] = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
    }
    // 等待多个线程执行结束.
    WaitForMultipleObjects(10, hThread, TRUE, INFINITE);

    // 最后循环释放资源
    for (int x = 0; x < 10; x++)
    {
        CloseHandle(hThread[x]);
    }

    printf("Global: %d \n", Global_One);
    DeleteCriticalSection(&g_cs);

    system("pause");
    return 0;
}

强制终止一个进程: 在进程正常进行退出时,会调用ExitProcess()正常关闭程序,也可以调用TerminateProcess()强制销毁进程.

#include <windows.h>
#include <stdio.h>

int Get_ProcessID(LPCSTR path)
{
    HWND hWnd = FindWindow(NULL, path);
    if (hWnd != NULL)
    {
        DWORD dwPid = 0;
        GetWindowThreadProcessId(hWnd, &dwPid);
        if (dwPid != 0)
            return dwPid;
    }
    return -1;
}

int main(int argc,char * argv [])
{
    int pid = 0;

    pid = Get_ProcessID("新建文本文档.txt - 记事本");
    printf("进程PID为: %d \n", pid);

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (hProcess != NULL)
    {
        TerminateProcess(hProcess, 0);   // 终止进程
    }

    system("pause");
    return 0;
}

判断进程是否存在: 通过循环遍历所有进程,并对比szExeFile名称是否与pName一致,来实现判断进程是否正在运行中.

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

int Get_Process_Status(const char *procressName)
{
    char pName[MAX_PATH];
    strcpy(pName, procressName);                           // 拷贝数组
    CharLowerBuff(pName, MAX_PATH);                        // 将名称转换为小写

    PROCESSENTRY32 currentProcess;                                    // 存放快照进程信息的一个结构体
    currentProcess.dwSize = sizeof(currentProcess);                   // 在使用这个结构之前,先设置它的大小
    HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 给系统内的所有进程拍一个快照

    if (INVALID_HANDLE_VALUE != hProcess)
    {
        BOOL bMore = Process32First(hProcess, &currentProcess);
        while (bMore)
        {
            CharLowerBuff(currentProcess.szExeFile, MAX_PATH);        // 将进程名转换为小写
            if (strcmp(currentProcess.szExeFile, pName) == 0)         // 比较是否存在此进程
            {
                CloseHandle(hProcess);
                return 1;
            }
            bMore = Process32Next(hProcess, &currentProcess);
        }
        CloseHandle(hProcess);
    }
    return -1;
}

int main(int argc,char * argv [])
{
    int ret = Get_Process_Status("qq.exe");

    if (ret == 1)
        printf("正在运行. \n");
    else
        printf("没有运行. \n");

    system("pause");
    return 0;
}

遍历获取进程PID:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

DWORD FindProcessID(LPCTSTR szProcessName)
{
    DWORD dwPID = 0xFFFFFFFF;
    HANDLE hSnapShot = INVALID_HANDLE_VALUE;
    PROCESSENTRY32 pe;
    pe.dwSize = sizeof(PROCESSENTRY32);
    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
    Process32First(hSnapShot, &pe);
    do
    {
        if (!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile))
        {
            dwPID = pe.th32ProcessID;
            break;
        }
    } while (Process32Next(hSnapShot, &pe));
    CloseHandle(hSnapShot);
    return dwPID;
}

int main(int argc,char *argv[])
{
    DWORD PID = FindProcessID(L"qq.exe");
    printf("该进程PID是: %d \n", PID);

    system("pause");
    return 0;
}

枚举系统中所有进程:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int EnumProcess()
{
    PROCESSENTRY32 pe32 = { 0 };
    pe32.dwSize = sizeof(PROCESSENTRY32);

    // 获取全部进程快照
    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE != hProcessSnap)
    {
        // 获取快照中第一条信息
        BOOL bRet = Process32First(hProcessSnap, &pe32);
        while (bRet)
        {
            printf("进程ID: %-5d --> 进程名: %s \n", pe32.th32ProcessID, pe32.szExeFile);
            // 获取快照中下一条信息
            bRet = Process32Next(hProcessSnap, &pe32);
        }
        CloseHandle(hProcessSnap);
    }
    return -1;
}

int main(int argc,char * argv [])
{
    EnumProcess();

    system("pause");
    return 0;

}

枚举指定进程中的DLL模块: 枚举出指定PID进程中所加载的DLL

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int EnumProcessModule(DWORD Pid)
{
    MODULEENTRY32 me32 = { 0 };
    me32.dwSize = sizeof(MODULEENTRY32);
    // 获取指定进程全部模块的快照
    HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Pid);

    if (INVALID_HANDLE_VALUE != hModuleSnap)
    {
        // 获取快照中第一条信息
        BOOL bRet = Module32First(hModuleSnap, &me32);
        while (bRet)
        {
            printf("模块基址: 0x%p --> 大小: %-8d --> 模块名: %-25s -> 路径: %s \n",
                me32.modBaseAddr, me32.modBaseSize, me32.szModule,me32.szExePath);

            // 获取快照中下一条信息
            bRet = Module32Next(hModuleSnap, &me32);
        }
        CloseHandle(hModuleSnap);
        return 0;
    }
    return -1;
}

int main(int argc,char * argv [])
{
    EnumProcessModule(1920);

    system("pause");
    return 0;
}

枚举进程中线程ID:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int EnumThread(DWORD Pid)
{
    THREADENTRY32 te32 = { 0 };
    te32.dwSize = sizeof(THREADENTRY32);
    int index = 0;

    // 获取全部线程快照
    HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (INVALID_HANDLE_VALUE != hThreadSnap)
    {
        // 获取快照中第一条信息
        BOOL bRet = Thread32First(hThreadSnap, &te32);
        while (bRet)
        {
            // 只过滤出 Owner Process ID = pid 的线程ID
            if (Pid == te32.th32OwnerProcessID)
            {
                printf("线程ID: %6d --> 大小: %d \n", te32.th32ThreadID,te32.dwSize);
                ++index;
            }

            // 获取快照中下一条信息
            bRet = Thread32Next(hThreadSnap, &te32);
        }
        CloseHandle(hThreadSnap);
        return index;
    }
    return -1;
}

int main(int argc,char * argv [])
{
    int tid_count = EnumThread(9868);
    printf("线程数: %d \n", tid_count);

    system("pause");
    return 0;
}

判断进程是否重复运行:

#include <Windows.h>
#include <stdio.h>

// 判断是否重复运行
BOOL IsAlreadyRun()
{
    HANDLE hMutex = NULL;
    hMutex = CreateMutex(NULL, FALSE, "RUN");
    if (hMutex)
    {
        if (ERROR_ALREADY_EXISTS == GetLastError())
            return TRUE;
    }
    return FALSE;
}

int main(int argc, const char * argv[])
{
    if (IsAlreadyRun() == TRUE)
        printf("重复运行 \n");
    else
        printf("没有重复运行 \n");

    system("pause");
    return 0;
}

循环干掉特定进程: 该方式只能干掉普通的检测程序,无法干掉带有自保护的杀软,需要加载驱动。

#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>

int Kill_AV_Process(char *kill_list[],int Count)
{
    PROCESSENTRY32 currentProcess;
    currentProcess.dwSize = sizeof(currentProcess); 
    HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (INVALID_HANDLE_VALUE != hProcess)
    {
        BOOL bMore = Process32First(hProcess, &currentProcess);
        while (bMore)
        {
            CharLowerBuff(currentProcess.szExeFile, MAX_PATH);

            for (int each = 0; each < Count; each++)
            {
                if (strcmp(currentProcess.szExeFile, kill_list[each]) == 0)
                {
                    // printf("干掉进程 --> %s \n", kill_list[each]);
                    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, currentProcess.th32ProcessID);
                    TerminateProcess(hProcess, 0);
                }
            }
            bMore = Process32Next(hProcess, &currentProcess);
        }
        CloseHandle(hProcess);
    }
    return -1;
}

int main(int argc, char * argv[])
{
    // 填写杀毒软件的进程名称,然后循环干掉进程
    char *fuck[10] = { "chrome.exe", "360.exe","qqpctray.exe","qqpcrtp.exe","qmdl.exe" };
    Kill_AV_Process(fuck,5);

    system("pause");
    return 0;
}

暂停/恢复指定的线程:

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>

int Start_Stop_Thread(DWORD Pid,DWORD ThreadID)
{
    THREADENTRY32 te32 = { 0 };
    te32.dwSize = sizeof(THREADENTRY32);

    // 获取全部线程快照
    HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (INVALID_HANDLE_VALUE != hThreadSnap)
    {
        // 获取快照中第一条信息
        BOOL bRet = Thread32First(hThreadSnap, &te32);
        while (bRet)
        {
            // 只过滤出 pid 里面的线程
            if (Pid == te32.th32OwnerProcessID)
            {
                // 判断是否为ThreadID,暂停指定的TID
                if (ThreadID == te32.th32ThreadID)
                {
                    // 打开线程
                    HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);

                    SuspendThread(hThread);     // 暂停线程
                    //ResumeThread(hThread);    // 恢复线程
                    CloseHandle(hThreadSnap);
                }
            }
            // 获取快照中下一条信息
            bRet = Thread32Next(hThreadSnap, &te32);
        }
        return 0;
    }
    return -1;
}

int main(int argc, char * argv[])
{
    // 暂停或恢复进程ID = 4204 里面的线程ID = 10056
    int ret = Start_Stop_Thread(4204,10056);
    printf("状态: %d \n", ret);

    system("pause");
    return 0;
}

枚举进程内存权限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h>

void ScanMemoryAttribute()
{
    DWORD Addres = 0, Size = 0;
    MEMORY_BASIC_INFORMATION Basicinfo = {};

    // 遍历进程所有分页, 输出内容
    while (VirtualQuery((LPCVOID)Addres, &Basicinfo, sizeof(MEMORY_BASIC_INFORMATION)))
    {
        Size = Basicinfo.RegionSize;
        printf("地址: %08p 类型: %7d 大小: %7d 状态: ", Basicinfo.BaseAddress,Basicinfo.Type,Basicinfo.RegionSize);
        switch (Basicinfo.State)
        {
        case MEM_FREE:      printf("空闲 \n"); break;
        case MEM_RESERVE:   printf("保留 \n"); break;
        case MEM_COMMIT:    printf("提交 \n"); break;
        default: printf("未知 \n"); break;
        }

        // 如果是提交状态的内存区域,那么遍历所有块中的信息
        if (Basicinfo.State == MEM_COMMIT)
        {
            // 遍历所有基址是 Address
            LPVOID BaseBlockAddress = (LPVOID)Addres;
            DWORD BlockAddress = Addres;
            DWORD dwBlockSize = 0;
            // 遍历大内存块中的小内存块
            while (VirtualQuery((LPVOID)BlockAddress, &Basicinfo, sizeof(Basicinfo)))
            {
                if (BaseBlockAddress != Basicinfo.AllocationBase)
                {
                    break;
                }
                printf("--> %08X", BlockAddress);
                // 查看内存状态,映射方式
                switch (Basicinfo.Type)
                {
                case MEM_PRIVATE:   printf("私有  "); break;
                case MEM_MAPPED:    printf("映射  "); break;
                case MEM_IMAGE:     printf("镜像  "); break;
                default: printf("未知  "); break;
                }

                if (Basicinfo.Protect == 0)
                    printf("---");
                else if (Basicinfo.Protect & PAGE_EXECUTE)
                    printf("E--");
                else if (Basicinfo.Protect & PAGE_EXECUTE_READ)
                    printf("ER-");
                else if (Basicinfo.Protect & PAGE_EXECUTE_READWRITE)
                    printf("ERW");
                else if (Basicinfo.Protect & PAGE_READONLY)
                    printf("-R-");
                else if (Basicinfo.Protect & PAGE_READWRITE)
                    printf("-RW");
                else if (Basicinfo.Protect & PAGE_WRITECOPY)
                    printf("WCOPY");
                else if (Basicinfo.Protect & PAGE_EXECUTE_WRITECOPY)
                    printf("EWCOPY");
                printf("\n");

                // 计算所有相同块大小
                dwBlockSize += Basicinfo.RegionSize;
                // 累加内存块的位置
                BlockAddress += Basicinfo.RegionSize;
            }
            // 内有可能大小位空
            Size = dwBlockSize ? dwBlockSize : Basicinfo.RegionSize;
        }
        // 下一个区域内存信息
        Addres += Size;
    }
}

int main(int argc, char * argv[])
{
    ScanMemoryAttribute();
    system("pause");
    return 0;
}

查询进程所具备的权限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h>

BOOL QueryPrivileges()
{
    // 1. 获得本进程的令牌
    HANDLE hToken = NULL;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
        return false;

    // 2. 获取提升类型
    TOKEN_ELEVATION_TYPE ElevationType = TokenElevationTypeDefault;
    BOOL  bIsAdmin = false;
    DWORD dwSize = 0;

    if (GetTokenInformation(hToken, TokenElevationType, &ElevationType, sizeof(TOKEN_ELEVATION_TYPE), &dwSize))
    {
        // 2.1 创建管理员组的对应SID
        BYTE adminSID[SECURITY_MAX_SID_SIZE];
        dwSize = sizeof(adminSID);
        CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID, &dwSize);

        // 2.2 判断当前进程运行用户角色是否为管理员
        if (ElevationType == TokenElevationTypeLimited)
        {
            // a. 获取连接令牌的句柄
            HANDLE hUnfilteredToken = NULL;
            GetTokenInformation(hToken, TokenLinkedToken, (PVOID)&hUnfilteredToken, sizeof(HANDLE), &dwSize);
            // b. 检查这个原始的令牌是否包含管理员的SID
            if (!CheckTokenMembership(hUnfilteredToken, &adminSID, &bIsAdmin))
                return false;
            CloseHandle(hUnfilteredToken);
        }
        else
        {
            bIsAdmin = IsUserAnAdmin();
        }
    }

    // 3. 判断具体的权限状况
    BOOL bFullToken = false;
    switch (ElevationType) 
    {
        case TokenElevationTypeDefault: /* 默认的用户或UAC被禁用 */
            if (IsUserAnAdmin())
                bFullToken = true;      // 默认用户有管理员权限
            else
                bFullToken = false;     // 默认用户不是管理员组
            break;

        case TokenElevationTypeFull:    /* 已经成功提高进程权限 */
            if (IsUserAnAdmin())
                bFullToken = true;      // 当前以管理员权限运行
            else
                bFullToken = false;     // 当前未以管理员权限运行
            break;

        case TokenElevationTypeLimited: /* 进程在以有限的权限运行 */
            if (bIsAdmin)
                bFullToken = false;     // 用户有管理员权限,但进程权限有限
            else
                bFullToken = false;     // 用户不是管理员组,且进程权限有限
            break;
    }
    return bFullToken;
}

int main(int argc, char * argv[])
{
    BOOL ret = QueryPrivileges();
    printf("具备权限: %d \n", ret);

    system("pause");
    return 0;
}

枚举指定进程权限:

#include <stdio.h>
#include <ShlObj.h>
#include <Windows.h>

void ShowPrviliges(HANDLE process)
{
    // 通过进程句柄获取到进程令牌
    HANDLE hToken;
    OpenProcessToken(process, TOKEN_QUERY, &hToken);

    // 获取查询道德令牌信息
    DWORD dwSize;
    GetTokenInformation(hToken,TokenPrivileges, NULL, NULL, &dwSize);

    // 根据令牌中的大小分配空间
    char *pBuf = new char[dwSize] {};
    GetTokenInformation(hToken,TokenPrivileges, pBuf, dwSize, &dwSize);

    // 将内存中的内容用要查询数据结构体解析
    TOKEN_PRIVILEGES* pTp = (TOKEN_PRIVILEGES*)pBuf;
    DWORD dwCount = pTp->PrivilegeCount;               // 解析出权限个数
    LUID_AND_ATTRIBUTES* pluid = pTp->Privileges;      // 具备的权限类型

    for (int i = 0; i < dwCount; i++, pluid++)
    {
        char szName[100] = {};
        DWORD dwLen = sizeof(szName);
        LookupPrivilegeNameA(0, &pluid->Luid, szName, &dwLen);
        switch (pluid->Attributes)
        {
        case 0:
            printf("[ID: %3d] ---> [关闭]      ---> %s \n", i,szName); break;
        case 1:
            printf("[ID: %3d] ---> [默认]      ---> %s \n", i,szName); break;
        case 2:
            printf("[ID: %3d] ---> [开启]      ---> %s \n", i,szName); break;
        case 3:
            printf("[ID: %3d] ---> [默认开启]  ---> %s \n", i,szName); break;
        }
    }
    delete pBuf;
}

int main(int argc ,char *argv[])
{
    // 拿到PID为9656程序的句柄
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 9656);
    ShowPrviliges(hProcess);

    // 拿到自身程序的句柄
    HANDLE LocalProcess = GetCurrentProcess();
    ShowPrviliges(LocalProcess);

    system("pause");
    return 0;
}

提升指定进程权限:

#include <windows.h>
#include <stdio.h>

int EnbalePrivileges(HANDLE hProcess, char *pszPrivilegesName)
{
    HANDLE hToken = NULL;
    LUID luidValue = { 0 };
    TOKEN_PRIVILEGES tokenPrivileges = { 0 };
    BOOL bRet = FALSE;
    DWORD dwRet = 0;

    // 打开进程令牌并获取具有 TOKEN_ADJUST_PRIVILEGES 权限的进程令牌句柄
    bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
    if (bRet != FALSE)
    {
        // 获取本地系统的 pszPrivilegesName 特权的LUID值
        bRet = LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue);
        if (bRet == FALSE)
            return -1;
    }

    // 设置提升权限信息
    tokenPrivileges.PrivilegeCount = 1;
    tokenPrivileges.Privileges[0].Luid = luidValue;
    tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    // 提升进程令牌访问权限
    bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL);
    if (bRet != FALSE)
    {
        // 根据错误码判断是否特权都设置成功
        dwRet = GetLastError();
        if (ERROR_SUCCESS == dwRet)
        {
            return 1;
        }
    }
    return -1;
}

int main(int argc,char * argv [])
{
    // 获取当前自身进程句柄
    HANDLE Local_Pid = GetCurrentProcess();

    // 修改当前进程令牌访问权限
    if (FALSE != EnbalePrivileges(Local_Pid, SE_DEBUG_NAME))
        printf("提权成功 \n");

    system("pause");
    return 0;
}

原文链接: https://www.cnblogs.com/LyShark/p/12976302.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C/C++ 进程线程操作技术

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/351071

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午6:40
下一篇 2023年3月2日 上午6:40

相关推荐