Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Help with understanding "base address"

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
dreamlane
How do I cheat?
Reputation: 0

Joined: 13 Mar 2013
Posts: 3
Location: United States

PostPosted: Wed Mar 13, 2013 3:52 pm    Post subject: Help with understanding "base address" Reply with quote

Hey guys. I've been playing around with Cheat Engine, mostly as an exercise to augment an OS class I am currently taking as part of a CS degree.

I've tracked a multilevel pointer to its base address, but I am a little confused on one thing.

The first level of the pointer is
Code:
"Client.exe"+0069C25C.


How do i figure out in CE what the hex value of "Client.exe" is?

I understand the offsets and pointer arithmetic, but I'm lost in regards to getting the address of "Client.exe" wand what CE evaluates that string to be.



pointerss.png
 Description:
 Filesize:  8.46 KB
 Viewed:  16315 Time(s)

pointerss.png


Back to top
View user's profile Send private message AIM Address
SteveAndrew
Master Cheater
Reputation: 30

Joined: 02 Sep 2012
Posts: 323

PostPosted: Thu Mar 14, 2013 12:08 am    Post subject: This post has 1 review(s) Reply with quote

Well that's easy, "Client.exe" is the base address of "Client.exe" when its loaded in memory...

In previous versions of Windows the base address used to be pretty consistently located at: 0x00400000... So addresses used to be based off that and they would still work for everyone. In more recent versions of Windows: 7, 8, etc.. It's no longer the case...

So instead of using VA's (virtual addresses [image base included]) We use RVA's(relative virtual addresses)... As we know with the same version of the game (say your using v1.0), if everyone's using v1.0 the code/data is going to be located at the same offset from the start of the module/exe...

If you're working from the inside of the process it's really easy to get the base address of any module (a loaded DLL, or the process itself)

//Note this is C/C++ code
Code:

ULONG EXEBaseAddr = (ULONG)GetModuleHandleW(0);

ULONG DLLBaseAddr = (ULONG)GetModuleHandleW(L"whatever.dll");


It's really that simple if on the inside of the process (with an injected dll for example) (don't get confused about a module handle [with that function] being the base address, a process handle is different as you'll see below (the handle you get from OpenProcess for example))


If working from the outside (externally, like CE)

There are several ways, but one easy way is to use the toolhelp APIs

Code:

#include <tlhelp32.h>

//Get process ids/handles/modules functions
HANDLE GetProcessHandle(wchar_t *ProcessName, ULONG *ReturnedProcessId)
{
   PROCESSENTRY32W *pe = new PROCESSENTRY32W;
   HANDLE Snap;

   pe->dwSize = sizeof(PROCESSENTRY32W);
   Snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

   if(Snap == INVALID_HANDLE_VALUE)
   {
      delete pe;
      return 0;
   }

   BOOL bProcess = Process32FirstW(Snap, pe);
   while(bProcess)
   {
      if(_wcsicmp(pe->szExeFile, ProcessName) == 0)
      {
         HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pe->th32ProcessID);
         
         if(ReturnedProcessId)
            *ReturnedProcessId = pe->th32ProcessID;

         CloseHandle(Snap);
         delete pe;
         return ProcessHandle;
      }

      bProcess = Process32NextW(Snap, pe);
   }

   CloseHandle(Snap);
   delete pe;
   return 0;
}

ULONG GetModuleBase(wchar_t *ModuleName, ULONG ProcessId)
{
   MODULEENTRY32W *me = new MODULEENTRY32W;

   HANDLE Snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);

   me->dwSize = sizeof(MODULEENTRY32W);
   if(Snap == INVALID_HANDLE_VALUE)
   {
      delete me;
      return 0;
   }

   BOOL bModule = Module32First(Snap, me);
   while(bModule)
   {
      if(!ModuleName|| _wcsicmp(me->szModule, ModuleName) == 0)
      {
         CloseHandle(Snap);
         return (ULONG)me->modBaseAddr;
      }

      bModule = Module32Next(Snap, me);
   }

   CloseHandle(Snap);
   delete me;
   return 0;
}
///.... I'm using Crysis 3 as an example usage of those functions, lol!

ULONG RemoteProcessId = 0;
HANDLE RemoteProcessHandle = GetProcessHandle(L"Crysis3.exe", &RemoteProcessId);

 //if 'ModuleName' passed is NULL just return EXE Base
ULONG EXEModuleBase = GetModuleBase(0, RemoteProcessId);

//or for a specific DLL of that process
ULONG DLLModuleBase = GetModuleBase(L"SomeDll.dll", RemoteProcessId);

printf("Remote EXE Base: %p; Remote DLL Base: %p\n", EXEModuleBase, DLLModuleBase);



However you said you're going to school so you may be interested in knowing the way Windows itself has that information stored... (how the toolhelp API's probably work internally)

It's part of the PEB of a process where this information can be accessed...

The following is a sort of 'undocumented' way of achieving the same thing... It requires a little bit of setup therefore, but this way is cooler Wink

In your header file: .h
Code:

typedef void** PPVOID;

typedef struct _UNICODE_STRING
{
    WORD Length;
    WORD MaximumLength;
    WORD *Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _LDR_DATA_TABLE_ENTRY
{
     LIST_ENTRY InLoadOrderLinks;
     LIST_ENTRY InMemoryOrderLinks;
     LIST_ENTRY InInitializationOrderLinks;
    PVOID ModuleBase;
     PVOID EntryPoint;
     ULONG SizeOfImage;
     UNICODE_STRING FullModuleName;
     UNICODE_STRING BaseModuleName;
     ULONG Flags;
     WORD LoadCount;
    WORD TlsIndex;
    union
    {
        LIST_ENTRY HashLinks;
        struct
        {
            PVOID SectionPointer;
            ULONG CheckSum;
        };
    };
    union
    {
        ULONG TimeDateStamp;
        PVOID LoadedImports;
    };
    DWORD EntryPointActivationContext; //_ACTIVATION_CONTEXT * EntryPointActivationContext;
     PVOID PatchInformation;
     LIST_ENTRY ForwarderLinks;
     LIST_ENTRY ServiceTagLinks;
     LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;


typedef struct _PEB_LDR_DATA {
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;

} PEB_LDR_DATA, *PPEB_LDR_DATA;


typedef struct _PEB {

BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
BOOLEAN Spare;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA LoaderData;
DWORD ProcessParameters; //PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
DWORD FastPebLockRoutine; //PPEBLOCKROUTINE FastPebLockRoutine;
DWORD FastPebUnlockRoutine; //PPEBLOCKROUTINE FastPebUnlockRoutine;
ULONG EnvironmentUpdateCount;
PPVOID KernelCallbackTable;
PVOID EventLogSection;
PVOID EventLog;
DWORD FreeList; //PPEB_FREE_BLOCK FreeList;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[0x2];
PVOID ReadOnlySharedMemoryBase;
PVOID ReadOnlySharedMemoryHeap;
PPVOID ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
BYTE Spare2[0x4];
LARGE_INTEGER CriticalSectionTimeout;
ULONG HeapSegmentReserve;
ULONG HeapSegmentCommit;
ULONG HeapDeCommitTotalFreeThreshold;
ULONG HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PPVOID *ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
PVOID GdiDCAttributeList;
PVOID LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
ULONG OSBuildNumber;
ULONG OSPlatformId;
ULONG ImageSubSystem;
ULONG ImageSubSystemMajorVersion;
ULONG ImageSubSystemMinorVersion;
ULONG GdiHandleBuffer[0x22];
ULONG PostProcessInitRoutine;
ULONG TlsExpansionBitmap;
BYTE TlsExpansionBitmapBits[0x80];
ULONG SessionId;
} PEB, *PPEB;


typedef struct _PROCESS_BASIC_INFORMATION {
      long    ExitStatus;
      PPEB    PebBaseAddress;
      unsigned long    AffinityMask;
      long    BasePriority;
      unsigned long    UniqueProcessId;
        unsigned long    InheritedFromUniqueProcessId;
}PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

typedef enum _PROCESSINFOCLASS {
   ProcessBasicInformation = 0
} PROCESSINFOCLASS;

typedef ULONG (NTAPI *NTQUERYINFORMATIONPROCESS)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);

HANDLE GetProcessHandle(wchar_t *ProcessName, ULONG *ReturnedProcessId); //lol still using toohelp to get the processid and handle
BOOL GetProcessPEB(HANDLE hProcess, PPEB pPeb);
BOOL GetProcessLoaderData(HANDLE hProcess, PEB peb, PPEB_LDR_DATA pPebLdrData);
ULONG GetModuleBaseEx(wchar_t *ModuleName, HANDLE hProcess);


In the source file (.cpp)
Code:

BOOL GetProcessPEB(HANDLE hProcess, PPEB pPeb)
{
    SetLastError(0);

    NTQUERYINFORMATIONPROCESS NtQueryInformationProcess = 0;

    PROCESS_BASIC_INFORMATION pbi = {0};
    NTSTATUS NtStatus;
    ULONG dwLength;
    HMODULE NtDll;

   NtDll = GetModuleHandleA("ntdll.dll");
    if(!NtDll) return 0;

    NtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)GetProcAddress(NtDll, "NtQueryInformationProcess");
    if(!NtQueryInformationProcess) return 0;

    NtStatus = NtQueryInformationProcess(hProcess, ProcessBasicInformation, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), &dwLength);

    if(NtStatus != 0) return 0; //0 == STATUS_SUCCESS

    ULONG dwBytesRead = 0;
   if(!ReadProcessMemory(hProcess, pbi.PebBaseAddress, pPeb, sizeof(PEB), &dwBytesRead) || dwBytesRead < sizeof(PEB)) return 0;

    //Successfully Got PEB!
    return 1;
}

BOOL GetProcessLoaderData(HANDLE hProcess, PEB peb, PPEB_LDR_DATA pPebLdrData)
{
     ULONG dwBytesRead = 0;

     if(!ReadProcessMemory(hProcess, peb.LoaderData, pPebLdrData, sizeof(PEB_LDR_DATA), &dwBytesRead) || dwBytesRead < sizeof(PEB_LDR_DATA)) return 0;

     return 1;
}

ULONG GetModuleBaseEx(wchar_t *ModuleName, HANDLE hProcess)
{
   LDR_DATA_TABLE_ENTRY LoaderTable;
   PLIST_ENTRY pCurrentList = 0, pStart = 0;
   PEB ThePeb;
   PEB_LDR_DATA PebLoaderData;

   if(!GetProcessPEB(hProcess, &ThePeb)) return 0;
   if(!GetProcessLoaderData(hProcess, ThePeb, &PebLoaderData)) return 0;

    pStart = PebLoaderData.InLoadOrderModuleList.Blink;
    pCurrentList = PebLoaderData.InLoadOrderModuleList.Flink;

   wchar_t *RemoteModuleName = 0;
    while(pCurrentList != pStart) //It's a doublely linked list
   {
      if(!ReadProcessMemory(hProcess, pCurrentList, &LoaderTable, sizeof(LDR_DATA_TABLE_ENTRY), 0)) return 0;
      
      RemoteModuleName = new wchar_t[LoaderTable.BaseModuleName.Length+1];
      ZeroMemory(RemoteModuleName, LoaderTable.BaseModuleName.Length+1);

      if(!ReadProcessMemory(hProcess, LoaderTable.BaseModuleName.Buffer, RemoteModuleName, LoaderTable.BaseModuleName.Length, 0))
      {
         VirtualFree(RemoteModuleName, 0, MEM_RELEASE);
         return 0;
      }

      if(!ModuleName || _wcsicmp(ModuleName, RemoteModuleName) == 0)
      {   
         delete[] RemoteModuleName;
         return (ULONG)LoaderTable.ModuleBase;
      }

      delete[] RemoteModuleName;
      pCurrentList = LoaderTable.InLoadOrderLinks.Flink;
    }

   return 0;
}


Then where you're writing your code, usage is similar:

Code:

ULONG RemoteProcessId = 0;
HANDLE RemoteProcessHandle = GetProcessHandle(L"Crysis3.exe", &RemoteProcessId);

ULONG EXEBaseFromPEB = GetModuleBaseEx(0, RemoteProcessHandle); //Will get Crysis3.exe's base address

//Gets the base address of the dll named 'WhateverTheDllIsCalled.dll'
ULONG DLLBaseFromPEB = GetModuleBaseEx(L"WhateverTheDllIsCalled.dll", RemoteProcessHandle);

printf("Remote EXE Base From PEB: %p; Remote Module: %08x", EXEBaseFromPEB, DLLBaseFromPEB);


Now it's probably better to use the toolhelp APIs or some other documented way... as it isn't depending on those structures being exactly the same in every version of windows as this is here, but these in particular don't really change very often so it's still pretty safe to use. If you did want to use some undocumented way of doing things and wanted to be safer about it you could just not even use defined structures! The just wouldn't look as pretty but you would have offsets into structures and sizes of structures defined for different versions of windows and play around with them in the code to get what you needed...

Man I guess I can't just explain something simply can I!! lol That's enough for now...

_________________
Back to top
View user's profile Send private message
dreamlane
How do I cheat?
Reputation: 0

Joined: 13 Mar 2013
Posts: 3
Location: United States

PostPosted: Thu Mar 14, 2013 4:16 pm    Post subject: Reply with quote

Excellent answer SteveAndrew. If this were StackOverflow, you'd have earned yourself some points.

Thank you for taking the time to explain both the high level and low level parts!
Back to top
View user's profile Send private message AIM Address
Crashix
How do I cheat?
Reputation: 0

Joined: 10 Dec 2013
Posts: 1

PostPosted: Tue Dec 10, 2013 8:41 am    Post subject: Reply with quote

Thank you Steve Andrew and dreamlane this post really helped me =)

But i have one problem since a long time with this base adress! and i just registered to tell you that...

Your code below seems to work only for 32bit process and dll...

When i try to execute your code with 64bit process it didn't work and he send me a base adress of 0.

I know that CreateToolhelp32Snapshot( work only for 32bit. So, is there a way to make it work with 64 bit ? or am i missing something ?

thanks in advance =)
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25796
Location: The netherlands

PostPosted: Tue Dec 10, 2013 9:00 am    Post subject: Reply with quote

Also or in
TH32CS_SNAPMODULE32 to createtoolhelp32snapshof

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites