Как узнать, какие dll использует процесс?

184
31 июля 2021, 02:30

Опираясь на это,хочу получить список dll, которые использует каждый процесс. Я использую stl list, где каждая нода имеет вот такие поля:

struct info
{
     wchar_t name_PID[100]; // the name of process
     //maybe DWORD not unsigned
    unsigned num_PID; // the id of the proc
     char* path;// the way like C://
     char par_name[100]; // the name of parent
    unsigned num_par_PID;// the id of the parent
     char ownerName[256]="\0"; // host/adm/elv
     char* SID;
    unsigned x_bit;
    //bool DEP;
    char DEP[4];
    //bool ASLR;
    char ASLR[4];
};

На момент выполнения этой функции(которая ищет dll у процесса), все представленные поля заполнены. Вот так выглядит вариант из документации Microsoft:

int main( void )
{
    DWORD aProcesses[1024]; 
    DWORD cbNeeded; 
    DWORD cProcesses;
    unsigned int i;
    // Get the list of process identifiers.
    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
        return 1;
    // Calculate how many process identifiers were returned.
    cProcesses = cbNeeded / sizeof(DWORD);
    // Print the names of the modules for each process.
    for ( i = 0; i < cProcesses; i++ )
    {
        PrintModules( aProcesses[i] );
    }
    return 0;
}

По аналогии и я пишу свою функцию:

void about_dll(list <info>& gqlist)
{
    list <info> ::iterator lit;
    DWORD* mass;
    DWORD cbNeeded, cProcesses;
    mass = (DWORD*)malloc(1*sizeof(DWORD));
    int i = 0;
    for (lit = gqlist.begin(); lit != gqlist.end(); ++lit)
    {
        mass[i] = lit->num_PID;
        mass = (DWORD*)realloc(mass, sizeof(DWORD)*(i + 2));
        i++;
    }
    int k = 0;
    EnumProcesses(mass, sizeof(mass)*i, &cbNeeded);
    // Calculate how many process identifiers were returned.
        cProcesses = cbNeeded / sizeof(DWORD);
        for (i = 0; i < cProcesses; i++)
        {
            //PrintModules(aProcesses[i]);
            about_dll2(mass[i]);
        }
}

Я пробегаю по каждому элементу списка, чтобы записать в новый массив mass(который динамический) номер процесса. Это нужно для функции EnumProcesses, которая после исполнения изменит содержимое cbNeeded. Его я использую, для цикла (ровно как и в примере).

В документации вызывают из цикла функцию(в их примере из сайта):

int PrintModules( DWORD processID )
{
    HMODULE hMods[1024];
    HANDLE hProcess;
    DWORD cbNeeded;
    unsigned int i;
    // Print the process identifier.
    printf( "\nProcess ID: %u\n", processID );
    // Get a handle to the process.
    hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
                            PROCESS_VM_READ,
                            FALSE, processID );
    if (NULL == hProcess)
        return 1;
   // Get a list of all the modules in this process.
    if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
    {
        for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
        {
            TCHAR szModName[MAX_PATH];
            // Get the full path to the module's file.
            if ( GetModuleFileNameEx( hProcess, hMods[i], szModName,
                                      sizeof(szModName) / sizeof(TCHAR)))
            {
                // Print the module name and handle value.
                _tprintf( TEXT("\t%s (0x%08X)\n"), szModName, hMods[i] );
            }
        }
    }
    // Release the handle to the process.
    CloseHandle( hProcess );
    return 0;
}

Теперь и я вызываю about_dll2 каждый раз из цикла.

void about_dll2(DWORD processID)
{
    HMODULE hMods[1024];
    HANDLE hProcess;
    DWORD cbNeeded;
    unsigned int i;
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, processID);
    // Get a list of all the modules in this process.
    if (NULL == hProcess)
        return;
    //GetModuleHandleExA(NULL, "chrome.exe", hMods);
    if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
    {
        for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
        {
            TCHAR szModName[MAX_PATH];
            // Get the full path to the module's file.
            if (GetModuleFileNameEx(hProcess, hMods[i], szModName,sizeof(szModName) / sizeof(TCHAR)))
            {
                // Print the module name and handle value.
                _tprintf(TEXT("\t%s (0x%08X)\n"), szModName, hMods[i]);
            }
        }
    }
}

Но возникает несколько трудностей:

  1. Не всегда hProcess получает валидное значение - соответственно завершаю функцию на этой итерации.
  2. if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) никогда не выполняется.

Последнее и есть причина моего вопроса - почему эта функция в if возвращает 0? Я подумал, что дело может быть в неинициализированном hMods. Поэтому захотел инициализировать её(неудачно). Мне показалось, что GetModuleHandleExA должен иницилизировать этот hMods, но вышло так , что приходится самому называть эту dll, а я наоборот хочу узнать dll.

Таким образом, более общий вопрос задать так: Как узнать, какие dll использует процесс? А поконкретнее - описал выше. Может я вообще не в ту сторону иду с описанной выше идеей?

Answer 1

Вопрос решился использованием Module32First и Module32Next. Всё оказалось очень тривиально, даже мануал нашел тут. В общем решение у меня выглядит так:

void about_dll(list <info>& gqlist)
{
    list <info> ::iterator it;
    HANDLE hSnap;
    for (it = gqlist.begin(); it != gqlist.end(); ++it)
    {
        int i = 0;
        hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, it->num_par_PID);
        if (hSnap == NULL)
        {
            continue;
        }
        else
        {
            memset(it->DLL[i], 0, 30);
            MODULEENTRY32 mod;
            if (Module32First(hSnap, &mod))
            {
                //m_List1.AddString(mod.szExePath);
                char k1[30]="\0";
                sprintf(k1, "%s", mod.szModule);
                if (!strstr(k1, "exe"))
                {
                    sprintf(it->DLL[i], "%s", mod.szModule);
                    i++;
                    memset(it->DLL[i], 0, 30);
                }
                while (Module32Next(hSnap, &mod))
                {
                    //m_List1.AddString(mod.szExePath);
                    if (strstr(mod.szModule, "exe"))
                        continue;
                    sprintf(it->DLL[i], "%s", mod.szModule);
                    i++;
                    memset(it->DLL[i], 0, 30);
                }
            }
            CloseHandle(hSnap);
        }
    }
}
READ ALSO
С чем связано определение равенства потоковых итераторов?

С чем связано определение равенства потоковых итераторов?

Почему 2 std::istream_iterator считаются одинаковыми, даже если они указывают на разные элементы одного потока? С чем связано такое определение?

190
Как Подготовить запрос sql QT?

Как Подготовить запрос sql QT?

есть такой вопрос, хочу сделать UPDATE запрос к базе данных, для этого нужно подготовить запрос, но помимо подстановки данных, я хочу подставить...

351
как разыменовать двойной указатель на класс

как разыменовать двойной указатель на класс

есть указатель на массив объектов s и указатель на s

110
ofstream. Записать char в начало файла

ofstream. Записать char в начало файла

Собственно, есть std::ofstream file

110