G
G
Gleb Genken2021-01-21 19:36:30
C++ / C#
Gleb Genken, 2021-01-21 19:36:30

Why does CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID) return INVALID_HANDLE_VALUE when accessing a non-own process?

Here is the code:

#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;

DWORD GetPID(const char* ProcessName) {...}

MODULEENTRY32 GetModule(const char* moduleName, unsigned long long ProcessID) {
    MODULEENTRY32 modEntry = { 0 };
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, ProcessID);

    cout << "Started looking for module " << moduleName << " with PID " << ProcessID << "..." << endl;

    if (hSnapshot == NULL || hSnapshot == INVALID_HANDLE_VALUE) {
        cout << GetLastError() << endl;
        Module32First(hSnapshot, &modEntry);
        cout << "Taking snapshot failed. 4" << endl << "Last error:" << GetLastError() << endl; ;
    }
    else {
        cout << "Modules snapshot had been took successfully!" << endl;
        cout << "Starting modulelist scan..." << endl;

        MODULEENTRY32 curr = { 0 };

        curr.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &curr)) {
            do {
                if (!strcmp(curr.szModule, moduleName)) {
                    cout << "Found " << curr.szModule << " at " << curr.th32ModuleID << " (PID: " << curr.th32ProcessID << ")" << endl;
                    modEntry = curr;
                    break;
                }
                cout << "Found " << curr.szModule << " at " << curr.th32ModuleID << " (PID: " << curr.th32ProcessID << ")" << endl;
            } while (Module32Next(hSnapshot, &curr));
        }
        CloseHandle(hSnapshot);
    }
    return modEntry;
}
int main() {
     unsigned long long pid = GetPID("Process.exe");
     MODULEENTRY32 module = GetModule("process.exe", pid);
}

The GetPID function works fine, checked through the task manager; moduleName is also correctly assigned. So why am I getting INVALID_HANDLE_VALUE?

I added the output to the console of those modules that the algorithm passes through, if it does run. And if you call GetModule with the argument ProcessID=0, then the output will be as follows:
Started looking for module Minecraft.Windows.exe with PID 0...
Modules snapshot had been took successfully!
Starting modulelist scan...
Found MCBEBot.exe at 1 (PID: 20732)
Found ntdll.dll at 1 (PID: 20732)
Found KERNEL32.DLL at 1 (PID: 20732)
Found KERNELBASE.dll at 1 (PID: 20732)
Found ucrtbase.dll at 1 (PID: 20732)
Found MSVCP140.dll at 1 (PID: 20732)
Found VCRUNTIME140.dll at 1 (PID: 20732)
Found sechost.dll at 1 (PID: 20732)
Found RPCRT4.dll at 1 (PID: 20732)

That is, instead of 0 in PID, the function CreateToolhelp32Snapshot()substitutes the PID of the process in which it is running. If you substitute any value in the PID (both the real PID of the process and a random number). Thus, for some reason, this function can only refer to its modules. What to do in this case? And why access to processes (in GetPID()called
HANDLE ProcessesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL)
without any problems) happens normally, but to the modules - no?

Thanks in advance for any help!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anvar Shakhmaev, 2021-01-21
@RxR

I don’t remember exactly, but it seems that each process has its own descriptor table, and memory is allocated for it in the heap for this process. Therefore, access to the table of descriptors and memory from another process is needed.
Perhaps DuplicateHandle?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question