So I have been trying to get into memory reading in C++ and I thought a cool project would be to read all addresses a process is using (similar to how Cheat Engine works).
I started by reading
Link1: Read Memory of Process C++
Link2: Read memory of 64bit process address
Link3: http://www.cplusplus.com/forum/general/42132/
And I also watched a tutorial on youtube where he explained how a process (game) worked with addresses. Link to youtube video: https://www.youtube.com/watch?v=wiX5LmdD5yk
This resulted in me making three different methods:
DWORD GetProcId(const wchar_t* procName) {
DWORD pid = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hSnap != INVALID_HANDLE_VALUE) {
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if(Process32First(hSnap, &procEntry)) {
do {
if(!_wcsicmp(procEntry.szExeFile, procName)) {
pid = procEntry.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &procEntry));
}
}
CloseHandle(hSnap);
return pid;
}
This method is to get the process-id which I could also just type manually by finding the same PID in task-manager (which gave me the same baseaddress later on).
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName) {
uintptr_t modBaseAddr = 0;
//I use 0x10 instead of TH32CS_SNAPMODULE32 since it didnt work and according to documentation
// this is the value it should have.
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | 0x10, procId);
if(hSnap != INVALID_HANDLE_VALUE) {
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if(Module32First(hSnap, &modEntry)) {
do {
if(!_wcsicmp(modEntry.szModule, modName)) {
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while(Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
This method (I assume) will return the base address of the process. Which for example in my code I tried to find the base address of the discord.exe process. When discord.exe wasn't running I got 0 and when it was running I got an address (which I believe is the correct base address, correct me if I am wrong).
And my main method:
int main() {
DWORD procId = GetProcId(L"Discord.exe");
uintptr_t moduleBase = GetModuleBaseAddress(procId, L"Discord.exe");
HANDLE hProcess = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);
uintptr_t dynamicPtrBaseAddr = moduleBase;
std::cout << "Dynamic: " << dynamicPtrBaseAddr << std::endl;
int value = 0;
int arr [10000] = {};
for (int i = 0; i < 100000; i++) {
ReadProcessMemory(hProcess, (BYTE*)dynamicPtrBaseAddr, &value, sizeof(value),0);
dynamicPtrBaseAddr += 1;
arr[i] = value;
}
}
Where I try to put all the values of all 100000 addresses in an array.
So my questions are:
Have I retrieved the base address of the process correctly?
For reading the other addresses I just increase dynamicPtrBaseAddr by 1, is there a better way to implement an offset? Or is this the correct way?
Now I increase the base address by 100000. Can I find the last address of the process instead?
I compile with g++ main.cpp -o test -lpsapi -DUNICODE (MinGW).
You must run as administrator and you must compile for the same bitness as the target process.
You should not be reading 1 byte at a time, especially in an external hack.
You should be using VirtualQueryEx() to properly loop through only proper memory regions:
DWORD procid = GetProcId("ac_client.exe");
unsigned char* addr = 0;
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procid);
MEMORY_BASIC_INFORMATION mbi;
while (VirtualQueryEx(hProc, addr, &mbi, sizeof(mbi)))
{
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && mbi.Protect != PAGE_GUARD)
{
std::cout << "base : 0x" << std::hex << mbi.BaseAddress << " end : 0x" << std::hex << (uintptr_t)mbi.BaseAddress + mbi.RegionSize << "\n";
}
addr += mbi.RegionSize;
}
This ensures you're only reading proper memory. Next you would reach each region into a local buffer in one go, this will increase speed dramatically as you won't have the overhead of calling the API for each byte.
What you're looks like you're trying to do is pattern scanning. You can find our pattern scanning tutorials in the same place you found the original tutorial you were following.
Related
Basically am trying to iterate through function address's from a running process which is a dummy program that I have created so what I do is this
IMAGE_THUNK_DATA first_thunk = { 0 };
if(!ReadProcessMemory(handle,process_base_address + import_desc.FirstThunk,&first_thunk,sizeof(first_thunk),0))
return false;
std::cout << "Function address :" << std::hex << "0x" << first_thunk.u1.Function << '\n';
Now everything you see is correct and I read it from the target process without a problem but now
when I try to print first_thunk.u1.Function I get an address that will land inside MessageBoxA function.
But I want the address of it and not an address inside that function anyways if I do this auto address = process_base_address + import_desc.FirstThunk; I get what I want which is the address of MessageBoxA
So I am so confused. Why doing process_base_address + import_desc.FirstThunk works and using the struct that I read doesn't which is my big problem regarding this question when I try to read the sizeof(IMAGE_THUNK_DATA) I read 8 bytes which is understandable since its inside a union which shares the address space for 4 variables inside there but how would I get each variable address or access each var address or rva using ReadProcessMemory since its only reading 8 bytes I can't do that.
Which you mean is ReadProcessMemory with auto address = process_base_address + import_desc.FirstThunk works for you but doesn't work with process_base_address + import_desc.FirstThunk directly, I recommend to use (PBYTE) Conversion.
According to your description sizeof(IMAGE_THUNK_DATA) = 8, I assume you use the x64 version.
typedef struct _IMAGE_THUNK_DATA64 {
union {
ULONGLONG ForwarderString; // PBYTE
ULONGLONG Function; // PDWORD
ULONGLONG Ordinal;
ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME
} u1;
} IMAGE_THUNK_DATA64;
typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64;
When the highest value of IMAGE_THUNK_DATA is 1, it means that the function is imported in the form of a serial number, otherwise, the function is imported in the form of a function name, and it is an RVA, pointing to an IMAGE_IMPORT_BY_NAME structure. We can use constant IMAGE_ORDINAL_FLAG to test whether the highest bit is 1.
The following sample work for me:
#include <Windows.h>
#include <iostream>
#include <psapi.h>
#pragma warning(disable : 4996)
using namespace std;
void main()
{
int i;
HMODULE hModule;
DWORD dwOffset, cbneeded;
SIZE_T dwRet;
DWORD dwPid = 8752; // PID of process to be hooked
TCHAR szModName[MAX_PATH];
TCHAR szHookModName[MAX_PATH] = { "user32.dll" };
TCHAR szFuncName[MAX_PATH] = { "MessageBoxA" };
IMAGE_DOS_HEADER DOSHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
IMAGE_DATA_DIRECTORY DataDirectory;
IMAGE_IMPORT_DESCRIPTOR ImportDesc;
IMAGE_THUNK_DATA OrigThunkData;
IMAGE_THUNK_DATA RealThunkData;
PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)malloc(255); //function name length;
MEMORY_BASIC_INFORMATION mbi;
LPVOID lpBaseAddress;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwPid);
if (hProcess == NULL)
{
printf("Fail to open process!\n");
return;
}
if (!EnumProcessModules(hProcess, &hModule, sizeof(hModule), &cbneeded))
{
printf("Fail to enum process modules!\n");
return;
}
if (!ReadProcessMemory(hProcess, hModule, (void*)&DOSHeader, sizeof(IMAGE_DOS_HEADER), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
dwOffset = DOSHeader.e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + dwOffset, (void*)&OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
DataDirectory = OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
i = 0;
do
{
dwOffset = DataDirectory.VirtualAddress + sizeof(IMAGE_IMPORT_DESCRIPTOR) * i;
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + dwOffset, (void*)&ImportDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + ImportDesc.Name, (void*)szModName, MAX_PATH, &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (stricmp(szModName, szHookModName) == 0)
break;
i++;
} while (ImportDesc.Name);
i = 0;
do
{
lpBaseAddress = (PBYTE)hModule + ImportDesc.OriginalFirstThunk + sizeof(IMAGE_THUNK_DATA) * i;
if (!ReadProcessMemory(hProcess, lpBaseAddress, (void*)&OrigThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + ImportDesc.FirstThunk + sizeof(IMAGE_THUNK_DATA) * i, (void*)&RealThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
std::cout << "Function address :" << std::hex << "0x" << RealThunkData.u1.Function << '\n';
lpBaseAddress = (PBYTE)hModule + ImportDesc.FirstThunk + sizeof(IMAGE_THUNK_DATA) * i;
if (!ReadProcessMemory(hProcess, lpBaseAddress, (void*)&RealThunkData, sizeof(IMAGE_THUNK_DATA), &dwRet))
{
printf("Fail to read memory in remote process!\n");
return;
}
std::cout << "Function address :" << std::hex << "0x" << RealThunkData.u1.Function << '\n';
if ((OrigThunkData.u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
if (!ReadProcessMemory(hProcess, (PBYTE)hModule + OrigThunkData.u1.AddressOfData, (void*)pImportByName, sizeof(WORD) + strlen(szFuncName) + 1, &dwRet))
{
if (GetLastError() == ERROR_PARTIAL_COPY)
{
i++;
continue;
}
else
{
printf("Fail to read memory in remote process!\n");
return;
}
}
if (pImportByName->Name[0] == '\0')
{
printf("Function not located!\n");
break;
}
if (strcmpi((char*)pImportByName->Name, szFuncName) == 0)
{
printf("Function: %s \n ", pImportByName->Name);
break;
}
}
i++;
} while (OrigThunkData.u1.Function);
free(pImportByName);
}
It should be noted that the contents pointed to by OriginalFirstThunk and FirstThunk in the PE file are exactly the same, but when the file is loaded into memory, the difference appears: the contents of OriginalFirstThunk will not change, but the data in FirstThunk will change to the entry address of the function.
target process:
#include <windows.h>
#include <iostream>
int main()
{
printf("child\n");
VOID *p = (VOID*)MessageBoxA;
MessageBoxA(NULL,"TEST","TEST",0);
getchar();
return 0;
}
Result:
I was learning how to interact with processes from a channel called "null". I wrote his program and tried to understand how everything worked. But when i executed it the wpm function did work but then the target program immediately closed after it incremented the same variable I was writing to.
Anyways here's the code.
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
HANDLE hProc = NULL;
DWORD ProcId;
bool attatchProc(const char* ProcName)
{
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(PROCESSENTRY32);
auto hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcSnap == INVALID_HANDLE_VALUE)
return false;
while (Process32Next(hProcSnap, &procEntry)) {
std::cout << procEntry.szExeFile << std::endl;
if (!strcmp(ProcName, procEntry.szExeFile)) {
std::cout << "Process Found!\n Heres the Process ID" << procEntry.th32ProcessID << std::endl;
ProcId = procEntry.th32ProcessID;
hProc = OpenProcess(PROCESS_ALL_ACCESS, false, ProcId);
if (hProc == NULL)
std::cout << "Sike you thought lmao" << std::endl;
CloseHandle(hProcSnap);
return true;
}
}
std::cout << "Process not found or other issue";
}
template <class DataType>
void wpm(DataType VarToWrite, DWORD addressToWrite)
{
WriteProcessMemory(hProc, (PVOID)addressToWrite, &VarToWrite, sizeof(DataType), 0);
}
int main()
{
DWORD memAddr = 0x012FF848;
attatchProc((char*)"Testing.exe");
while (1)
{
wpm<int>(68, memAddr);
}
}
You are not using Process32First to get the first entry in the snapshot. Microsoft Docs has a tutorial on how to do it correctly here
If you use the tutorial you can come up with your own version like mine, which includes exactly what you need and nothing else. I use TCHAR in this example so you can either include tchar.h or you can change it to match your coding style.
#include
DWORD GetProcId(const TCHAR* 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 (!_tcsicmp(procEntry.szExeFile, procName))
{
procId = procEntry.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &procEntry));
}
}
CloseHandle(hSnap);
return procId;
}
After calling this function you would check if the return is nonzero and then call OpenProcess() using the process id and the memory access permissions you require. If the process handle is nonzero you may then continue to write to the process memory. If you write to the incorrect memory address you will crash the program, so ensure you have the correct address by using the Visual Studio Debugger and comparing what you see against what you see in the target process using another debugger like Cheat Engine.
With DLL injection, grabbing the base address of the process was as easy as using
GetModuleHandleW(0);
So I'm trying to grab the address without injection and I can't seem to get it to work. I've Googled some solutions and found others from stackoverflow but they don't seem to work. Here's what I'm using right now. I have the right headers and it compiles. It just doesn't work.
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))
{
do
{
if (_tcsicmp(ModuleEntry32.szModule, szModuleName) == 0)
{
dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
break;
}
} while (Module32Next(hSnapshot, &ModuleEntry32));
}
CloseHandle(hSnapshot);
}
return dwModuleBaseAddress;
}
I try to cout this address and it just gives me 0. I think it might be the fact that I don't understand the second parameter. I'm just copying what I saw. Here's my main function.
int main() {
HWND hwnd = FindWindowA(NULL, gameName);
int x;
if (hwnd == NULL) {
cout << "Cannot find " << (string)gameName << " window" << endl;
cin >> x;
exit(-1);
}
DWORD procID;
GetWindowThreadProcessId(hwnd, &procID);
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
DWORD playerAddr = 0;
playerAddr = dwGetModuleBaseAddress(procID, _T("starbound.exe"));
cout << hex << playerAddr;
}
Some of this may be redundant because I'm just adding it to what I had before. I'm just not sure why it's not working.
Your code is correct, there is nothing wrong with it, I just tested it on x86 and x64.
Your problem is you need to run as administrator so you have correct security permissions to access the other process and you also should build your project as the same architecture, x86 or x64, as the target process.
If neither of those solutions fix it, then your 'gameName' variable or your module name are defined incorrectly.
If you use your dwModuleBaseAddress as a debug tool, it may be easier to spot the call that fails...
DWORD_PTR dwGetModuleBaseAddress(DWORD dwProcID, TCHAR *szModuleName)
{
DWORD_PTR dwModuleBaseAddress = (DWORD_PTR)-1; // unlikely value...
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, dwProcID);
if (hSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 ModuleEntry32;
ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
dwModuleBaseAddress = (DWORD_PTR)-2;
if (Module32First(hSnapshot, &ModuleEntry32))
{
do
{
--dwModuleBaseAddress;
if (_tcsicmp(ModuleEntry32.szModule, szModuleName) == 0)
{
dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
break;
}
} while (Module32Next(hSnapshot, &ModuleEntry32));
}
CloseHandle(hSnapshot);
}
return dwModuleBaseAddress;
}
You can also check the error that caused the issue using GetLastError()
void PrintLastError()
{
LPTSTR psz;
DWORD dwError = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwError,
0,
(LPTSTR)&psz,
1024,
NULL);
_tprintf(_T("Windows reports error: (0x%08X): %s\n"), dwError, (psz) ? psz : _T("(null)"));
if (psz)
{
LocalFree(psz);
}
}
If all else fails, try running this example from msdn https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms686849(v=vs.85).aspx
It will print the exact string you want to match, the problem may come from there.
i'm trying to read the memory of a game called: "Prison Architect",
but i always have this value: "Money :-858993460"
I lost 2 days without have found any solutions.
I hope you can help me.
Pointer Info:
BaseAddress: "prison architect.exe"+00075140
Pointer1: 300
Pointer2: 88
Pointer3: 26c
Pointer4: 70
Pointer5: 328
int FindPointer(int offset, HANDLE pHandle, int baseaddr, int offsets[])
{
int Address = baseaddr;
int total = offset;
for (int i = 0; i < total; i++) //Loop trough the offsets
{
ReadProcessMemory(pHandle, (LPCVOID)Address, &Address, 4, NULL);
Address += offsets[i];
}
return Address;
}
int main()
{
int value = 0; // This will store our value. In my case, its an integer, which is the timer
DWORD pid; //This will store our Process ID, used to read/write into the memory
HWND hwnd; //Finally a handle to our window
hwnd = FindWindow(NULL, L"Prison Architect"); //Finds the Window
if (!hwnd) //If none, display an error
{
cout << "Window not found!\n";
cin.get();
}
GetWindowThreadProcessId(hwnd, &pid); //Get the process id and place it in pid
HANDLE phandle = OpenProcess(PROCESS_VM_READ, 0, pid); //Get permission to read
if (!phandle) //Once again, if it fails, tell us
{
cout << "Could not get handle!\n";
cin.get();
}
int baseAddress = 0x00197BE8;
int offsets[] = { 0x300, 0x88, 0x26c, 0x70, 0x328 };
while (1) {
int moneyRead = FindPointer(5, phandle, baseAddress, offsets); //number of offsets, HANDLE, base address, offsets
//reading
int money;
ReadProcessMemory(phandle, (LPVOID)moneyRead, &money, sizeof(money), 0);
cout << "\nMoney :" << money;
Sleep(3000);
}
return 0;
}
int baseAddress = 0x00197BE8;
You're using a hard coded address, which is bad practice because it may only work for this one instance of running the game process. When you re-open the game it probably will change.
The pointer must begin with an address that has a relative offset from a module. You then add the relative offset to the address of the module which you have calculated at run time. This will make it so your final address that is calculated always works correctly, regardless of ASLR.
You can use this function to find the base address of a module
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
Add the relative offset to the return value and use this as the base address of the pointer you pass into your FindPointer() function.
I am trying to read an address from a running process. In order to do this, I have determined the offset of the address from a certain dll of the running process.
So far what I have done is I find the window, I than find the PID of the program and get the handle of it. From there I create a snapshot of the program using CreateToolhelp32Snapshot(), which allows me to loop through the modules of the program. From there I would like to get the base address of a specific module by name, however I am not sure how to get the name of the modules, this is my current code and where I am stuck. Is there a simple way I can get the name of the module based on the information I have?
// Find the window
hwnd = FindWindow(NULL, L"calculator");
if (!hwnd) {
cout << "window not found\n";
cin.get();
}
//Get Process ID
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_VM_OPERATION, 0, pid);
if (!phandle) {
cout << "could not get handle\n";
cin.get();
}
if (snapshot_test != INVALID_HANDLE_VALUE) {
// First module
MODULEENTRY32 mod_entry;
mod_entry.dwSize = sizeof(mod_entry);
if (Module32First(snapshot_test, &mod_entry)) {
do {
DWORD test = (DWORD)(mod_entry.modBaseAddr + 0x46F68 + 10);
cout << ReadProcessMemory(phandle, (void*)(test), &health, sizeof(health), 0);
} while (Module32Next(snapshot_test, &mod_entry));
}
else (cout << "module32first error");
}
else (cout << "snapshot error")
The MODULEENTRY32.szModule variable contains the name of the module, and MODULEENTRY32.modBaseAddr contains the address of the module itself. You can use this function to get the address of a module by passing in it's name. It will loop through the modules and find the one with the matching name
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}