0

I'm writing application that would display PID and base address of some other application. I'm getting error with id 5 so it's Access Denied and my question is why? I'm opening as admin, building as release (not debug) and someone told me that I should set this but even with that It's still same error.

IDE is Code::Blocks with compiler GNU GCC 64x

Console output:

Process ID = 2656
err: 5
INVALID_HANDLE_VALUE returned
BaseAddr = 0

Full code:

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

DWORD GetProcId(const char* procName)
{
    DWORD procId = 0;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap != INVALID_HANDLE_VALUE)
    {
        PROCESSENTRY32 procEntry;
        procEntry.dwSize = sizeof(procEntry);

        if (Process32First(hSnap, &procEntry))
        {
            do
            {
                if (lstrcmpi(procEntry.szExeFile, procName) == 0) {
                    procId = procEntry.th32ProcessID;
                    break;
                }
            } while (Process32Next(hSnap, &procEntry));

        }
    }
    CloseHandle(hSnap);
    return procId;
}

uintptr_t GetModuleBaseAddress(DWORD procId, const char* modName)
{
    uintptr_t modBaseAddr = 0;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, procId);
    std::cout << "err: " << GetLastError() << std::endl;
    if (hSnap != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 modEntry;
        modEntry.dwSize = sizeof(modEntry);
        if (Module32First(hSnap, &modEntry))
        {
            do
            {
                if (!stricmp(modEntry.szModule, modName))
                {
                    modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnap, &modEntry));
        }
    } else {
        std::cout << "INVALID_HANDLE_VALUE returned" << std::endl;
    }
    CloseHandle(hSnap);
    return modBaseAddr;
}

int main()
{
    DWORD procId = GetProcId("Game.exe");

    std::cout << "Process ID = " << procId << std::endl;

    uintptr_t baseAddr = GetModuleBaseAddress(procId, "Game.exe");

    std::cout << "BaseAddr = " << baseAddr << std::endl;

    std::getchar();
    return 0;
}
  • Are you mixing 32 and 64 bit? – drescherjm Apr 05 '20 at 21:58
  • I'm compiling using GNU GCC x64 and also I tried both `TH32CS_SNAPMODULE` alone and `TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32` together. All fails. – Miłosz Tomkiel Apr 05 '20 at 21:59
  • If your application is x64 Is game.exe a 64 bit application? – drescherjm Apr 05 '20 at 22:00
  • It's 32bit but I want this to be working both for 32 and 64bit. – Miłosz Tomkiel Apr 05 '20 at 22:01
  • I think they need to match. – drescherjm Apr 05 '20 at 22:02
  • Then how would you do it for 32bit? – Miłosz Tomkiel Apr 05 '20 at 22:02
  • You would need to build your application as a 32 bit one. I think the -m32 compiler flag would do that. [https://stackoverflow.com/questions/2426478/when-should-m32-option-of-gcc-be-used](https://stackoverflow.com/questions/2426478/when-should-m32-option-of-gcc-be-used) – drescherjm Apr 05 '20 at 22:03
  • I just tried using 32x and 64x compilers with and without flag you mentioned. All scenarios failed. – Miłosz Tomkiel Apr 05 '20 at 22:08
  • _I'm getting error with id 5_ Which call is failing? You're not checking error codes in your code... – Paul Sanders Apr 05 '20 at 22:22
  • I am, recheck my code. – Miłosz Tomkiel Apr 05 '20 at 22:23
  • What I mean is, you're not calling `GetLastError` anywhere. – Paul Sanders Apr 05 '20 at 22:32
  • 1
    Then you've missed this line `std::cout << "err: " << GetLastError() << std::endl;` and also check console output I attached to post. – Miłosz Tomkiel Apr 05 '20 at 22:33
  • Sorry, missed that. What happens if you run your code as Administrator? – Paul Sanders Apr 05 '20 at 22:38
  • Same thing, access denied. – Miłosz Tomkiel Apr 05 '20 at 22:38
  • Can you try this on some other program? Perhaps the game has some type of technology that blocks this. – drescherjm Apr 05 '20 at 22:39
  • This game is Diablo II and it was made around 20 years ago and there are many programs that can read memory thus finding base address of this game. But I'll try on notepad. – Miłosz Tomkiel Apr 05 '20 at 22:40
  • Notepad gives correct PID also but different error: `299` which is `ERROR_PARTIAL_COPY` – Miłosz Tomkiel Apr 05 '20 at 22:44
  • Even opening as admin gives this error. – Miłosz Tomkiel Apr 05 '20 at 23:21
  • You are calling [GetLastError](https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror) too late. By that time the value returned is meaningless. As documented, *"you should call the `GetLastError` function **immediately** when a function's return value indicates that such a call will return useful data"*. The fact that the code works with Notepad implies, that the observed behavior is peculiar to the intended target process. – IInspectable Apr 06 '20 at 05:44
  • But it doesn’t work with notepad. Just different error. – Miłosz Tomkiel Apr 06 '20 at 08:50
  • It works with Notepad. It just wasn't able to retrieve the full information. You'll have to retry for it to succeed. Unless you hit the [documented](https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot) error mode: *"If the specified process is a 64-bit process and the caller is a 32-bit process, this function fails and the last error code is `ERROR_PARTIAL_COPY` (299)."* We don't know whether you are building a 32-bit or 64-bit executable. Merely using a 64-bit compiler doesn't automagically produce a 64-bit binary. – IInspectable Apr 06 '20 at 09:19

0 Answers0