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;
}
Related
I try to use OpenProcess() function to read some information from the "System" process. But I always get the error code 5 which means ERROR_ACCESS_DENIED.
I have used AdjustTokenPrivileges() function to get the debug privilege and it still not works. I just don't know what's wrong with my code. Here is part of my code:
int GetInfo()
{
PROCESSENTRY32 pe32{ sizeof(PROCESSENTRY32) };
THREADENTRY32 th32{ sizeof(THREADENTRY32) };
MODULEENTRY32 md32{ sizeof(MODULEENTRY32) };
PWCHAR Name;
DWORD id = 0;
int err = 0;
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return -1;
}
BOOL pResult = Process32First(hProcessSnap, &pe32);
while (pResult)
{
Name = pe32.szExeFile;
if (lstrcmpW(Name, L"System") == 0)
{
id = pe32.th32ProcessID;
PrivilegeEscalation();
HANDLE ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, false, pe32.th32ProcessID);
err = GetLastError();
cout << err << endl;
cout << "The thread number of System is : " << pe32.cntThreads << endl;
CloseHandle(ProcessHandle);
break;
}
pResult = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
return 0;
BOOL PrivilegeEscalation()
{
HANDLE hToken;
TOKEN_PRIVILEGES Tp;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
return FALSE;
}
Tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Tp.Privileges[0].Luid);
Tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &Tp, sizeof(Tp), NULL, NULL);
//int err = GetLastError();
CloseHandle(hToken);
return TRUE;
}
The System process is not a real process, it represents the kernel. You can't expect all process related functions to work on it.
If you are cloning something like Process Explorer, call the undocumented NT API like the Windows Task manager has been doing all its life.
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.
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.