Results 1 to 2 of 2

Thread: Getting the base Address of a module

  1. #1
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default Getting the base Address of a module

    I put together this bit of code. The actual function I had some help with from someone (Tamimego - incase any of you know him) on a different forum, but this is very useful.

    Basically it can be used to get access to a process and if a process keeps changing it's offsets (a method known as ACLS if I'm not mistaken used to be more secure against modification) you can use this method to get the base.

    Code:
    // GetModuleBase.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <windows.h>
    #include <tlhelp32.h>
    #include <stdio.h>
    #include <string>
    
    #define executable "notepad.exe"
    #define classType "Notepad"
    using namespace std;
    
    /* These functions allow to find the correct Window & Class Name */
    //Needed for the FindWindowClassContains() & FindWindowTitleContains() Functions
    struct result_stru 
    {
        char* text;
        UINT (__stdcall*GET)(HWND,LPSTR,UINT);
        HWND hRet;
    };
    
    BOOL WINAPI StruEnumProc( HWND hwnd, result_stru* stru )
    {
        char loc_buf[128];
        stru->GET( hwnd, loc_buf, 127 );
        if( strstr( loc_buf, stru->text ) ) 
        {
            stru->hRet = hwnd;
            return FALSE;
        }
        return TRUE;
    }
    
    HWND FindWindowTitleContains( char* text )
    {
        result_stru res = { text, (UINT (__stdcall *)(HWND,LPSTR,UINT))GetWindowTextA, 0 };
        EnumWindows( (WNDENUMPROC)StruEnumProc, (LPARAM)&res );
        return res.hRet;
    }
    
    //case sensitive!
    HWND FindWindowClassContains( char* text )
    {
        result_stru res = { text, RealGetWindowClassA, 0 };
        EnumWindows( (WNDENUMPROC)StruEnumProc, (LPARAM)&res );
        return res.hRet;
    }
    
    HWND hWnd = FindWindow(classType,NULL);
    
    unsigned long GetProcessId( char* pszProcessName )
    {
        unsigned long dwResult = 0;
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 );
        if ( hSnapshot )
        {
            PROCESSENTRY32 processEntry = { sizeof( PROCESSENTRY32 ) };
            if ( Process32First( hSnapshot, &processEntry ) )
            {
                do
                {
                    if ( strcmp( processEntry.szExeFile, pszProcessName ) == 0 ) 
                    {
                        dwResult = processEntry.th32ProcessID;
                        break;
                    }
                }
                while ( Process32Next( hSnapshot, &processEntry ) );
            }
    
            if ( hSnapshot )
            {
                CloseHandle( hSnapshot );
                hSnapshot = NULL;
            }
        }
    
        return dwResult;
    }
    
    unsigned long GetModuleBase( unsigned long dwPID, char* pszModuleName, unsigned long* pdwSize )
    {
        unsigned long dwResult;
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
        if ( hSnapshot )
        {
            MODULEENTRY32 moduleEntry = { sizeof( MODULEENTRY32 ) };
            if ( Module32First( hSnapshot, &moduleEntry ) )
            {
                do
                {
                    if ( strcmp( moduleEntry.szModule, pszModuleName ) == 0 ) 
                    {
                        dwResult = (unsigned long)moduleEntry.modBaseAddr;
    
                        if ( pdwSize )
                            *pdwSize = moduleEntry.modBaseSize;
    
                        break;
                    }
                }
                while ( Module32Next( hSnapshot, &moduleEntry ) );
            }
    
            if ( hSnapshot )
            {
                CloseHandle( hSnapshot );
                hSnapshot = NULL;
            }
        }
    
        return dwResult;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        char szBuffer [512];
        
        if(!hWnd)
        {
            MessageBoxA(0, "Can't find the Process.\n Are you sure it's running?", "ERROR", MB_OK);
        }
        else
        {
            unsigned long dwPID = GetProcessId( executable );
            unsigned long dwSize;
            unsigned long dwBase = GetModuleBase( dwPID, executable, &dwSize );
    
            sprintf_s( szBuffer, sizeof( szBuffer ), "Base Address: 0x%X\n", dwBase );
            MessageBoxA(0, szBuffer, "Result o_0", MB_OK);
        }
        return 0;
    }

  2. #2
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    EDIT:
    It was brought to my attention that the previous code didn't work. Well I found out how much of an idiot I was because I left an important piece out. (custom getProcessId() function).

    Anywho, tested this out with several apps and now it's good to go. I hope this is helpful for some people because I know I was really struggling getting this to work properly at first.

    Let me break it down for everyone.

    These 2 functions make the findWindow & findClass... functions work properly.
    Code:
    struct result_stru 
    {
        char* text;
        UINT (__stdcall*GET)(HWND,LPSTR,UINT);
        HWND hRet;
    };
    
    BOOL WINAPI StruEnumProc( HWND hwnd, result_stru* stru )
    {
        char loc_buf[128];
        stru->GET( hwnd, loc_buf, 127 );
        if( strstr( loc_buf, stru->text ) ) 
        {
            stru->hRet = hwnd;
            return FALSE;
        }
        return TRUE;
    }
    The functions below are very helpful because sometimes the Window name or the Class name of an application is dynamic. (Changes based on the user or other parameters). So by passing the class or window name through the functions below, it will look for specific "static" keywords instead of the entire name. Alot of applications have a dynamic name that starts with Afx:******** (astericks replaced by numbers) these numbers change, so you can simply look for the letters "Afx:" as well as the Window name. This saves alot of hassle & time. Thanks to hummingbird for showing me the code above & below.
    Code:
    HWND FindWindowTitleContains( char* text )
    {
        result_stru res = { text, (UINT (__stdcall *)(HWND,LPSTR,UINT))GetWindowTextA, 0 };
        EnumWindows( (WNDENUMPROC)StruEnumProc, (LPARAM)&res );
        return res.hRet;
    }
    
    HWND FindWindowClassContains( char* text )
    {
        result_stru res = { text, RealGetWindowClassA, 0 };
        EnumWindows( (WNDENUMPROC)StruEnumProc, (LPARAM)&res );
        return res.hRet;
    }
    The code below is checking the class name.
    FindWindow() passes 2 arguments first one being the class and the second being the window name. You can check for both if you want to, but it's not necessary. Classname is what I'm passing through the code below and classname is defined above with "Notepad" which is the app I was using to test this with.
    Code:
    HWND hWnd = FindWindow(classType,NULL);
    The code below was introduced to be by Tamimego as I mentioned in my first post. He actually helped me get it working because for some unknown reason my code wasn't returning the correct values even though it compiled fine. The GetProcessId() function is actually also important because it's called before the GetModuleBase. If you don't include the GetProcessId() function, your code will still compile, however this function is modified from the original so you need to include it if you want it to work properly. This is what I missed in my initial release.
    Code:
    unsigned long GetProcessId( char* pszProcessName )
    {
        unsigned long dwResult = 0;
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 );
        if ( hSnapshot )
        {
            PROCESSENTRY32 processEntry = { sizeof( PROCESSENTRY32 ) };
            if ( Process32First( hSnapshot, &processEntry ) )
            {
                do
                {
                    if ( strcmp( processEntry.szExeFile, pszProcessName ) == 0 ) 
                    {
                        dwResult = processEntry.th32ProcessID;
                        break;
                    }
                }
                while ( Process32Next( hSnapshot, &processEntry ) );
            }
    
            if ( hSnapshot )
            {
                CloseHandle( hSnapshot );
                hSnapshot = NULL;
            }
        }
    
        return dwResult;
    }
    
    unsigned long GetModuleBase( unsigned long dwPID, char* pszModuleName, unsigned long* pdwSize )
    {
        unsigned long dwResult;
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
        if ( hSnapshot )
        {
            MODULEENTRY32 moduleEntry = { sizeof( MODULEENTRY32 ) };
            if ( Module32First( hSnapshot, &moduleEntry ) )
            {
                do
                {
                    if ( strcmp( moduleEntry.szModule, pszModuleName ) == 0 ) 
                    {
                        dwResult = (unsigned long)moduleEntry.modBaseAddr;
    
                        if ( pdwSize )
                            *pdwSize = moduleEntry.modBaseSize;
    
                        break;
                    }
                }
                while ( Module32Next( hSnapshot, &moduleEntry ) );
            }
    
            if ( hSnapshot )
            {
                CloseHandle( hSnapshot );
                hSnapshot = NULL;
            }
        }
    
        return dwResult;
    }
    The main portion of the code basically passes the variables of the executable (the executable is defined globally above) through the functions GetProcessID & GetModuleBase. It then returns the value and we use sprintf_s to put it into a buffer where it stores the information. Since the application is a console app, I could print to console by using printf() or cout, however I used messageboxs to return the value.

    Well hope this clears up any confusion.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •