How To Get Module Base Address

All .exe and .dll files when loaded into memory are referred to as "modules".

When adding addresses to your Cheat Engine table, and especially when using pointers you will often find the address listed like this:

Or maybe like this:
client.dll + 004EE83

This is using relative offset from the address of a module. Too see if an address is offset from a certain module make sure you enable this:

Then in memory viewer use "Go To Address" to the address. Regardless of if it is data or code, this will tell you what module it is offset from.

To view all the modules loaded by the process in Cheat Engine and view their addresses do this:

Also you can use Dissect PE Headers to view relative information:

MZ-Start is the address of the module as it is currently loaded into memory. Preferred ImageBase is parsed straight from the PE Header and is the location that it prefers to be loaded into. If this memory address is already taken, it will relocate.

"client.dll + 004EE83" works in Cheat Engine because Cheat Engine evaluates the address of client.dll. CE will get the address of client.dll and replace it with the adress that the module is loaded.
So lets say the address of module client.dll is 0x10000000, cheat Engine will evaluate:

client.dll + 004EE83
0x10000000 + 004EE83

The above evaluation is done by cheat engine while the program is running.

But when you are trying to use this in an external trainer you need to evaluate "client.dll" + 004EE83 yourself. There are multiple ways of doing this and we will discuss one of them now.

To do this externally you can use this function that has been widely used named dwGetModuleBaseAddress.

Basically it uses the windows API CreateToolhelp32Snapshot to get a snapshot of all loaded modules for the given process, it then iterates through all the loaded modules and finds the module with the module name you give it. It returns a DWORD_PTR to the module address. You input the ProcessID and the name of the module and it ouputs the address of the module.

//Place these with your other includes
#include <tlhelp32.h>
#include <tchar.h>
Function Prototype:
//Place this in the global namespace anywhere before the function is defined and called.
DWORD_PTR dwGetModuleBaseAddress(DWORD dwProcID, TCHAR *szModuleName);
Function Definition:
//Place this anywhere in the global namespace
DWORD_PTR dwGetModuleBaseAddress(DWORD dwProcID, TCHAR *szModuleName)
    DWORD_PTR dwModuleBaseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, dwProcID);
    if (hSnapshot != INVALID_HANDLE_VALUE)
        MODULEENTRY32 ModuleEntry32;
        ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &ModuleEntry32))
                if (_tcsicmp(ModuleEntry32.szModule, szModuleName) == 0)
                    dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
            } while (Module32Next(hSnapshot, &ModuleEntry32));
    return dwModuleBaseAddress;
The Function Call
DWORD clientdllBaseAddress = 0;
clientdllBaseAddress = dwGetModuleBaseAddress(dwProcId, _T("client.dll"));
1) You will need to FindWindow() to get the HANDLE to the window and pass it to GetWindowThreadProcessId() to get the dwProcId.