CreateToolHelp32Snapshot Question

I recently started to learn about the windows API for Memory editing purposes.

This game I am trying to write memory to requires you to get the module address first before you edit memory in the game. When a dll file is loaded into memory it gets a new base address everytime the game starts. So windows has the CreateToolHelp32Snapshot function, with Module32First and Module32Next. Basically scans through the modules loaded into memory associated with that game.

So my question is, how do I scan through the module list and ONLY get the ONE module I want. (Client.dll)


I tried messing around with this earlier and this is what I came up with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// MessingAround.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <TlHelp32.h>

using namespace std;





int main()
{
	HWND hWnd = FindWindowA(0, "Garry's Mod");
	MODULEENTRY32 me32;

	me32.dwSize = sizeof(MODULEENTRY32);



	if (hWnd == 0)
	{
		std::cout << "Window not found." << std::endl;
		Sleep(3000);
		return main();
	}
	else
	{
		std::cout << "window found." << endl;

		DWORD pID;
		GetWindowThreadProcessId(hWnd, &pID);

		HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);

		if (!Module32First(hSnap, &me32))
		{
			std::cout << "Error.";
			return (FALSE);
		}


		do 
		{
			cout << "Module Name: " << (DWORD) me32.modBaseAddr << endl;
			cout << "Process ID: " << me32.th32ProcessID << endl;
			cout << "Pid: " << pID << endl;

		} while (Module32Next(hSnap, &me32));

		CloseHandle(hSnap);



	}

    return 0;
}
Last edited on
Using PSAPI https://msdn.microsoft.com/en-us/library/windows/desktop/ms684884(v=vs.85).aspx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
#include <psapi.h>
#include <cctype>

#pragma comment ( lib, "psapi.lib" ) // link with psapi.lib (psapi.dll)

HANDLE open_process( std::string window_title )
{
    const auto window = ::FindWindowA( nullptr, window_title.c_str() ) ;
    if(window)
    {
        DWORD pid = 0 ;
        ::GetWindowThreadProcessId( window, std::addressof( pid ) ) ;

        static constexpr auto required_access = PROCESS_ALL_ACCESS ; // adjust as required
        return ::OpenProcess( required_access, false, pid ) ;
    }

    return nullptr ;
}

std::vector<HMODULE> module_list( HANDLE process )
{
    std::vector<HMODULE> modules(2048) ; // a sufficiently large size

    DWORD nbytes = 0 ;
    ::EnumProcessModules( process, std::addressof( modules.front() ),
                          DWORD( modules.size() * sizeof( HMODULE ) ), std::addressof(nbytes) ) ;

    modules.resize( nbytes / sizeof( HMODULE ) ) ;
    return modules ;
}

std::string& to_lower( std::string& str )
{
    for( char& c : str ) c = char( std::tolower(c) ) ;
    return str ;
}

const void* base_address( HANDLE process, std::string module_name )
{
    char fname[MAX_PATH] {};
    for( auto module : module_list(process) )
    {
        ::GetModuleFileNameExA( process, module, fname, sizeof(fname) ) ;
        const std::string full_name = fname ;
        std::string file_name = full_name.substr( full_name.find_last_of( "/\\" ) + 1 ) ;
        if( to_lower(file_name) == to_lower(module_name) ) return module ;
    }

    return nullptr ; // not found
}

int main()
{
    const std::string window_title = "Garry's Mod" ;
    const auto process = open_process(window_title) ;

    const std::string module_name = "Client.dll" ;
    const void* address = base_address( process, module_name ) ;

    if(address)
    {
        std::cout << "module '" << module_name << "' is loaded at base address " << address
            << "\n\t in process " << process << " which owns a window with title '" << window_title << "'\n" ;
    }

    // ...

    // CloseHandle(process) ; // once we are done 
}
Last edited on
I did it another way without messing with psapi.lib. Used strcmp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
DWORD_PTR dwGetModuleBaseAddress(DWORD pID, TCHAR *szModuleName)
{
	DWORD_PTR dwModuleBaseAddress = 0;
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pID);
	if (hSnapshot != INVALID_HANDLE_VALUE)
	{
		MODULEENTRY32 ModuleEntry32;
		ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
		if (Module32First(hSnapshot, &ModuleEntry32))
		{
			do
			{
				if (strcmp(ModuleEntry32.szModule, szModuleName) == 0)
				{
					dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
					break;
				}
			} while (Module32Next(hSnapshot, &ModuleEntry32));
		}
		CloseHandle(hSnapshot);
	}
	return dwModuleBaseAddress;
}




int main()
{
	HWND hWnd = FindWindowA(0, "Garry's Mod");
	if (hWnd == 0)
	{
		std::cout << "Window not found." << std::endl;
		Sleep(3000);
		return main();
	}
	else
	{
		std::cout << "window found." << endl;

		DWORD pID;
		GetWindowThreadProcessId(hWnd, &pID);

		DWORD clientdllBaseAddress = 0;
		clientdllBaseAddress = dwGetModuleBaseAddress(pID, _T("client.dll"));
Registered users can post here. Sign in or register to post.