获得进程完整路径的第二种方法

第一次发的博客是用PEB获得进程完整路径,这几天在学一种新方法。进程下有多个模块,而通过windbg调试发现第一模块即进程完整路径。直接看代码把。

#include <TlHelp32.h>
#include <Psapi.h>
char* GetProcessList(ULONG& BufferLength)  
{
    HANDLE   SnapshotHandle = NULL;
    HANDLE   ProcessHandle  = NULL;
    DWORD           Offset = 0;
    DWORD           v7 = 0;
    PROCESSENTRY32  ProcessEntry32; //快照
    char  ProcessFullPath[MAX_PATH] = { 0 };

    
    if (EnableDebugPrivilege()==FALSE)
    {
        return NULL;
    }


    ProcessEntry32.dwSize = sizeof(PROCESSENTRY32); //结构体中有dwSize的时候dwSize一般要初始化为自己结构体的大小。
    
    SnapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (SnapshotHandle == INVALID_HANDLE_VALUE)
    {
        return NULL;
    }

    char* BufferData = (char*)LocalAlloc(LPTR, 1024);       //暂时分配一下缓冲区   --->虚拟内存   malloc 

    if (BufferData==NULL)
    {
        CloseHandle(SnapshotHandle);
        return NULL;
    }
    if (Process32First(SnapshotHandle, &ProcessEntry32))             //得到第一个进程顺便判断一下系统快照是否成功
    {

        //ProcessID  ProcessImageName  ProcessFullPath    //C:WindowsSystem32Calc.exe
        do
        {
            //打开进程并返回句柄
            ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,  
                FALSE, ProcessEntry32.th32ProcessID);   //打开目标进程  
                                                  //        (ProcessEntry32.th32ProcessID !=4))
            if (ProcessHandle == NULL)// 权限太高 - 降低打开
            {
                ProcessHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
                    FALSE, ProcessEntry32.th32ProcessID);   //打开目标进程

                if (ProcessHandle == NULL)
                {
                    strcpy(ProcessFullPath, "打开进程失败");

                    goto Label1;

                }
            }
                //获得进程下的第一个模块
            HMODULE ModuleHandle = NULL;
            
            DWORD ReturnLength = GetModuleFileNameEx(ProcessHandle, ModuleHandle,  
                ProcessFullPath,
                sizeof(ProcessFullPath));  //进程下的第一模块就是本身的进程所在地址

            if (ReturnLength == 0)
            {
                RtlZeroMemory(ProcessFullPath, MAX_PATH);

                QueryFullProcessImageName(ProcessHandle, 0, ProcessFullPath, &ReturnLength);    // 更推荐使用这个函数
                if (ReturnLength == 0)
                {
                    strcpy(ProcessFullPath, "枚举信息失败");
                }
            }
            //BufferData[[20][calc.exe][              ][20][calc.exe][              ][20][calc.exe][              ]                          ]
Label1:
            v7 = sizeof(DWORD) +
                lstrlen(ProcessEntry32.szExeFile) + lstrlen(ProcessFullPath) + 2;  //ID + ImageName + 1 + FullPath + 1
            // 缓冲区太小,再重新分配下
            if (LocalSize(BufferData) < (Offset + v7))
                BufferData = (char*)LocalReAlloc(BufferData, (Offset + v7),
                    LMEM_ZEROINIT | LMEM_MOVEABLE);
            //接下来三个memcpy就是向缓冲区里存放数据 数据结构是 
            //进程ID+进程名+0+进程完整名+0  进程
            //因为字符数据是以0 结尾的
            memcpy(BufferData + Offset, &(ProcessEntry32.th32ProcessID), sizeof(DWORD));
            Offset += sizeof(DWORD);
            memcpy(BufferData + Offset, ProcessEntry32.szExeFile, lstrlen(ProcessEntry32.szExeFile) + 1);
            Offset += lstrlen(ProcessEntry32.szExeFile) + 1;
            memcpy(BufferData + Offset, ProcessFullPath, lstrlen(ProcessFullPath) + 1);
            Offset += lstrlen(ProcessFullPath) + 1;
            if (ProcessHandle!=NULL)
            {
                CloseHandle(ProcessHandle);
                ProcessHandle = NULL;
            }
                
        } while (Process32Next(SnapshotHandle, &ProcessEntry32));
    }
    else
    {
        CloseHandle(SnapshotHandle);
        LocalFree(BufferData);

        return NULL;
    }

    BufferLength = Offset;
    CloseHandle(SnapshotHandle);
    return BufferData;

}

顺带着挖个坑,ListCtrl这个控件贼坑,咋写都不出来。。。。

原文地址:https://www.cnblogs.com/Anony-WhiteLearner/p/6562391.html