Win32:进程相关的API

文章目录

 

获取所有进程的进程ID和EXE文件名

方式1:通过进程快照CreateToolhelp32Snapshot(),获取所有进程的ID和进程EXE名(不是路径)

    #include <tlHelp32.h>
    #include <vector>
    //**
    // Method:     GetPEntryList 
    // Description:获取进程ENTRY32列表(CreateToolhelp32Snapshot进程快照方式),获取进程ID和EXE名
    // Parameter:  OUT std::vector<char  > & list - 
    // Returns:    void - 
    //**
    void MyTools::GetPEntryList(OUT std::vector<PROCESSENTRY32>& list)
    {
        HANDLE handle;
        handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //调用CreatToolhelp32Snapshot来获取快照,用THREADENTRY32来获取线程信息等 就会用到'tlHelp32.h'头文件
        PROCESSENTRY32 info = new PROCESSENTRY32;
        info->dwSize = sizeof(PROCESSENTRY32);
        Process32First(handle, info);
        while (Process32Next(handle, info) != FALSE)
        {
            DWORD PID = info->th32ProcessID;    //获取进程ID  
            wchar_t ExeName = info->szExeFile;    //获取进程的EXE名(注意不是全路径)   
            PROCESSENTRY32 copyInfo = new PROCESSENTRY32;    //将造成内存泄漏
            copyInfo = info;
            list.push_back(copyInfo);    //进程结构体PROCESSENTRY32存入vector
        }
        delete(info);

        CloseHandle(handle);

        return;
    }

方式2:通过枚举进程EnumProcesses(),只能获取所有进程的ID

    //**
    // Method:     GetPIDList 
    // Description:获取进程ID列表(EnumProcesses方式)
    // Parameter:  OUT std::vector<int  > & PIDList - 
    // Returns:    void - 
    //**
    void GetPIDList(OUT std::vector<int>& PIDList)
    {
        //获取PID数组
        DWORD PIDs[500];    //PID数组
        DWORD NeededSize;    //数组有效字节数
        EnumProcesses(OUT PIDs, sizeof(PIDs), OUT & NeededSize);

        //计算PID个数
        int numberOfPID = (NeededSize / sizeof(DWORD));

        //遍历PID数组
        for (int i = 0; i < numberOfPID; i++)
        {
            PIDList.push_back(PIDs[i]);  //写入vector
        }
        return;
    }
  • 注意,不论是CreateToolhelp32Snapshot()还是EnumProcesses(),得到的进程数量都是一样的。盲猜CreateToolhelp32Snapshot的内部是调用了EnumProcesses()。

打开进程句柄(通过进程ID)

  • OpenProcess() 打开某进程,且声明需要的权限,一般可以声明PROCESS_ALL_ACCESS即所有权限。
  • 有的进程无法打开,尝试用管理员身份运行EXE后可以打开一部分进程(如svhost.exe),但仍有一些进程无法打开(如System、smss.exe等)。
    //**
    // Method:     OpenProcessByPID 
    // Description:
    // Parameter:  int PID - 
    // Parameter:  HANDLE & hProcess - 
    // Returns:    void - 
    //**
    void OpenProcessByPID(int PID,OUT HANDLE& hProcess)
    {
        hProcess = 0;
        //打开进程
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);
        if (hProcess == 0)
        {
            MessageBox(0, L"打开进程失败:是否开启管理员身份?是否在32位进程中尝试打开64位进程?", 0, 0);
        }
        return;
    }
    
  • 打开当前进程的句柄
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,GetCurrentProcessId());
    
    •  
  • 32位进程中无法打开64位进程,而64位进程既可以打开32位进程也可以打开64位进程。
  • 可以使用IsWow64Process宏判断目标进程的位数。
            //判断是32位还是64位进程,isWow64Process用于判断某进程是否运行在WOW64下。
            //对于64位程序,Wow64Process参数会返回FALSE!
            BOOL Wow64Process;
            IsWow64Process(hProcess, &Wow64Process);
            if(Wow64Process==TRUE){printf("目标进程是32位进程");}
    
    
  • 提权函数:经测试发现没有任何效果,可能win10不再需要提权令牌了?只需管理员权限就够了?
    //**
    // Method:     UpPrivileges 
    // Description:提权函数,但暂时看不到效果,很多进程提权后仍打不开:
    // Returns:    bool - 
    //**
    bool UpPrivileges()
    {
        HANDLE hToken;
        TOKEN_PRIVILEGES tp;
        TOKEN_PRIVILEGES oldtp;
        DWORD dwSize = sizeof(TOKEN_PRIVILEGES);
        LUID luid;
    
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
        {
            MessageBox(0, L"OpenProcessToken is FALSE ", 0, 0);
            if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
            {
                printf("OpenProcessToken GetLastError() == ERROR_CALL_NOT_IMPLEMENTED \n");
                return true;
            }
            else
            {
                printf("OpenProcessToken GetLastError() ==Others \n");
                return false;
            }
        }
        if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
        {
            CloseHandle(hToken);
            MessageBox(0, L"LookupPrivilegeValue is FALSE ", 0, 0);
            return false;
        }
        ZeroMemory(&tp, sizeof(tp));
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = luid;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        / Adjust Token Privileges /
        if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) {
            CloseHandle(hToken);
            MessageBox(0, L"AdjustTokenPrivileges == FALSE ", 0, 0);
            return false;
        }
        // close handles
        printf("UpPrivileges Success ! \n");
        CloseHandle(hToken);
        return true;
    
    }
    

打开模块句柄/基址(根据进程句柄、模块名)

  • 通过GetModuleHandle(NULL)只能获取当前进程的模块基址,参数为NULL表示获取主模块基址
  • 通过EnumProcessModulesEx()可以枚举任意进程的所有模块句柄,其中首个模块句柄就是主模块的基址。
    //**
    // Method:     OpenModuleByName 
    // Description:获取模块基址(根据进程句柄、模块名称)
    // Parameter:  HANDLE hProcess - 
    // Parameter:  wchar_t  destModuleName - 
    // Parameter:  OUT HMODULE hModule - 
    // Returns:    void - 
    //**
    void OpenModuleByName(HANDLE hProcess, wchar_t destModuleName, OUT HMODULE& hModule)
    {
        if (hProcess == 0) { hModule = 0; return; }
    
        //枚举进程的所有模块的句柄
        HMODULE moduleArray[500] = { 0 };
        DWORD neededSize = 0;
        EnumProcessModulesEx(hProcess, OUT moduleArray, sizeof(moduleArray), OUT & neededSize, LIST_MODULES_ALL);
    
        //获取主模块基址:进程第0个模块的句柄就是进程主模块的句柄/基址/载入地址
        if (destModuleName == NULL)
        {
            hModule = moduleArray[0];
        }
        //获取指定模块名称的模块基址
        else
        {
            int NumOfModule = neededSize / sizeof(HMODULE); //计算模块个数
            for (int i = 0; i < NumOfModule; i++)
            {
                WCHAR moduleFileName[50] = { 0 };
                MyTools::GetModuleName(hProcess, moduleArray[i], moduleFileName);
                if (wcscmp(moduleFileName, destModuleName) == 0) { hModule = moduleArray[i]; return; }
            }
    
        }
    }
    

获取模块的文件全路径(根据进程句柄、模块句柄)

  • 获取目标进程的主模块全路径(根据模块句柄)
  • 参数hModule表示模块的在目标进程的载入地址/基址+
  • 如果传入hModule=NULL,则表示获取主模块全路径,即进程全路径
            WCHAR filePath[200] = { 0 };
            GetModuleFileNameEx(hProcess, hModule,OUT filePath, sizeof(filePath) ); 
    
    • 1
    • 2

获取模块的文件名(根据进程句柄、模块句柄)

  • 通过截取模块的文件全路径可以得到模块文件名
  • 传入模块句柄=NULL表示主模块的文件名,即’进程名’。
//**
// Method:     GetModuleName 
// Description:获取模块的文件名(根据进程句柄、模块句柄)
// Parameter:  HANDLE hProcess - 
// Parameter:  HMODULE hModule - 参数为NULL时表示获取主模块的文件名
// Parameter:  OUT WCHAR  ModuleFileName - 是文件名,不是全路径
// Returns:    void - 
//**
void MyTools::GetModuleName(HANDLE hProcess, HMODULE hModule, OUT WCHAR ModuleFileName)
{
    if (hProcess == 0)return;
    //获取进程全路径:进程主模块(第0个模块)的全路径
    WCHAR fullPath[200] = { 0 };
    DWORD bufferSize = GetModuleFileNameEx(hProcess, hModule, OUT fullPath, sizeof(fullPath));
    //从全路径中截取EXE文件名
    int len = wcslen(fullPath);
    for (int i = len - 1; i >= 0; i--)
    {
        if (fullPath[i] == L'\')
        {
            wcscpy(ModuleFileName, &fullPath[i + 1]);
            break;
        }
    }
}

获取模块的镜像大小、入口地址(通过进程句柄、模块起始地址)

  • GetModuleInformation()实际上是通过分析模块的PE头结构,从而返回ImageSize和EntryPoint的,所以参数hModule必须是模块的起始镜像地址,所以传入hModule=NULL并不能得到主模块的信息。
        MODULEINFO moduleInfo = { 0 };
        GetModuleInformation(hProcess, hModule, OUT & moduleInfo, sizeof(moduleInfo));
        moduleInfo.lpBaseOfDll;//模块基址,实际上就是传入的hModule参数值
        moduleInfo.SizeOfImage;//模块镜像大小
        moduleInfo.EntryPoint; //模块入口地址
    

读取进程的内存

//打开进程(读取权限)
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);
//读取内存
LPVOID destAddr=(LPVOID)0x7ff7e1e40000;
BYTE buffer[1024] = { 0 };
unsigned __int64 numberOfReadedByte = 0;    //成功读取的内存字节数
ReadProcessMemory(hProcess, destAddr, OUT buffer, sizeof(buffer), &numberOfReadedByte );

if (numberOfReadedByte == 0) 
{ 
     DWORD code = GetLastError();
    MessageBox(0, L"读取进程内存失败", 0, 0);
    return false; 
}

获取进程的所有模块的句柄

  • 获取其他进程的所有模块
    HMODULE moduleArray[500] = { 0 };
    DWORD neededSize = 0;
    //枚举进程的模块
    EnumProcessModulesEx(hProcess, OUT moduleArray, sizeof(moduleArray), OUT & neededSize, LIST_MODULES_ALL);
  • 获取当前进程的所有模块
    HMODULE moduleArray[500] = { 0 };
    DWORD neededSize = 0;
    //打开当前进程的句柄
    HANDLE hCurrentProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,GetCurrentProcessId());
    //枚举当前进程的模块
    EnumProcessModulesEx(hCurrentProcess , OUT moduleArray, sizeof(moduleArray), OUT & neededSize, LIST_MODULES_ALL);
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值