Base address of a process without DLL injection? - c++

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.

Related

A question about Windows process privilege escalation

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.

C++ TlHelp32.h program closes after being written to

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.

OpenProcess() Access_Denied with SeDebugPrivilege

This program enumerate all handles and get their names.
For pID 4 OpenProcess gets error 5 with SeDebugPrivilege.
UAC off. Running from Admin.
Enable SeDebugPrivilege
BOOL EnableDebugPrivilege(BOOL bEnable)
{
HANDLE hToken = nullptr;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) return FALSE;
TOKEN_PRIVILEGES tokenPriv;
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luid;
tokenPriv.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return FALSE;
_tprintf(_T("Privileges error: %d\n", GetLastError()));
return TRUE;
}
Enumerate handles
DWORD EnumerateFileHandles(ULONG pid)
{
HINSTANCE hNtDll = LoadLibrary(_T("ntdll.dll"));
assert(hNtDll != NULL);
PFN_NTQUERYSYSTEMINFORMATION NtQuerySystemInformation =
(PFN_NTQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll,
"NtQuerySystemInformation");
assert(NtQuerySystemInformation != NULL);
PFN_NTQUERYINFORMATIONFILE NtQueryInformationFile =
(PFN_NTQUERYINFORMATIONFILE)GetProcAddress(hNtDll,
"NtQueryInformationFile");
DWORD nSize = 4096, nReturn;
PSYSTEM_HANDLE_INFORMATION pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)
HeapAlloc(GetProcessHeap(), 0, nSize);
while (NtQuerySystemInformation(SystemExtendedHandleInformation, pSysHandleInfo,
nSize, &nReturn) == STATUS_INFO_LENGTH_MISMATCH)
{
HeapFree(GetProcessHeap(), 0, pSysHandleInfo);
nSize += 4096;
pSysHandleInfo = (SYSTEM_HANDLE_INFORMATION*)HeapAlloc(
GetProcessHeap(), 0, nSize);
}
DWORD dwFiles = 0;
_tprintf(_T("Handles Number: %d\n"), pSysHandleInfo->NumberOfHandles);
for (ULONG i = 0; i < pSysHandleInfo->NumberOfHandles; i++)
{
PSYSTEM_HANDLE pHandle = &(pSysHandleInfo->Handles[i]);
if (pHandle->ProcessId == 4)
{
HANDLE hProcess = OpenProcess(
PROCESS_DUP_HANDLE, FALSE, pHandle->ProcessId);
if (hProcess == NULL)
{
_tprintf(_T("OpenProcess failed w/err 0x%08lx\n"), GetLastError());
continue;
}
HANDLE hCopy;
if (!DuplicateHandle(hProcess, (HANDLE)pHandle->Handle,
GetCurrentProcess(), &hCopy, MAXIMUM_ALLOWED, FALSE, 0))
continue;
TCHAR buf[MAX_PATH];
if (GetFinalPathNameByHandle(hCopy, buf, sizeof(buf), VOLUME_NAME_DOS))
wprintf(L"p%d:h%d:t%d:\t%s\n", pHandle->ProcessId, pHandle->Handle, pHandle->ObjectTypeNumber, buf);
CloseHandle(hProcess);
CloseHandle(hCopy);
}
}
HeapFree(GetProcessHeap(), 0, pSysHandleInfo);
return dwFiles;
}
On windows 7 x64 it's work fine.
But on Windows 10 x64 OpenProcess returns error 5 with SeDebugPrivilege.
How open system process(pID 4) on windows 10.
You can't open a handle for it as the documentation for OpenProcess specifically says it'll fail:
If the specified process is the Idle process or one of the CSRSS
processes, this function fails and the last error code is
ERROR_ACCESS_DENIED because their access restrictions prevent
user-level code from opening them.
If you want to get system process names, you could try to use CreateToolhelp32Snapshot() to get the snapshot of the process, then use Process32First() and Process32Next() to enumerate the all process.
Here is an example:
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <string>
#include <TlHelp32.h>
using namespace std;
int main()
{
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//get the snapshot
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
cout << "CreateToolhelp32Snapshot Error!" << endl;
return false;
}
BOOL bResult = Process32First(hProcessSnap, &pe32);
int num(0);
while(bResult)
{
cout << "[" << ++num << "] : " << "Process Name:"<< pe32.szExeFile << " " << "ProcessID:" << pe32.th32ProcessID << endl;
bResult = Process32Next(hProcessSnap, &pe32);
}
CloseHandle(hProcessSnap);
}
Hope it could help you!

Get full path from a process in Windows

there's something wrong with this api. i already check return function. no error. but output nothing.
HANDLE hSnapProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
PROCESSENTRY32 process;
process.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnapProcess, &process);
do
{
if (process.th32ProcessID != 0)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process.th32ProcessID);
if (hProcess != NULL)
{
wchar_t filePath[MAX_PATH];
if (!GetModuleFileNameExW(hProcess, NULL, filePath, MAX_PATH))
{
std::wcout << filePath << std::endl;
}
}
CloseHandle(hProcess);
}
} while (Process32Next(hSnapProcess, &process));
CloseHandle(hSnapProcess);
Two clear mistakes can be seen in your code, both can be understood by reading the documentation.
Firstly, in GetModuleFileNameEx:
The handle must have the PROCESS_QUERY_INFORMATION and PROCESS_VM_READ access rights.
Your handle only has PROCESS_QUERY_INFORMATION.
Secondly, again in GetModuleFileNameEx:
If the function succeeds, the return value specifies the length of the string copied to the buffer.
If the function fails, the return value is zero.
Your logic is back-to-front. Replace:
if (!GetModuleFileNameExW(hProcess, NULL, filePath, MAX_PATH))
with
if (GetModuleFileNameExW(hProcess, NULL, filePath, MAX_PATH))
Nothing is wrong with this API, the only thing that's wrong here is your code.
The documentation clearly states that the return value of GetModuleFileNameExW is the length of the string copied to the buffer.
If the return value is 0, the function has failed.
So you simply need to write this:
...
if (GetModuleFileNameExW(hProcess, NULL, filePath, MAX_PATH) != 0)
{
// handle "success" case
}
...
BTW CloseHandle(hProcess); should be inside the if (hProcess != NULL) block.
Full working example with error checks
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
int main()
{
HANDLE hSnapProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (hSnapProcess != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 process;
process.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnapProcess, &process);
do
{
if (process.th32ProcessID != 0)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process.th32ProcessID);
if (hProcess != NULL)
{
wchar_t filePath[MAX_PATH];
if (GetModuleFileNameExW(hProcess, NULL, filePath, MAX_PATH))
{
std::wcout << filePath << std::endl;
}
else
{
std::wcout << L"GetModuleFileNameExW failed with error" << GetLastError() << std::endl;
}
CloseHandle(hProcess);
}
}
} while (Process32Next(hSnapProcess, &process));
CloseHandle(hSnapProcess);
}
else
{
std::wcout << L"CreateToolhelp32Snapshot failed with error" << GetLastError() << std::endl;
}
}

C++ Get the Base Address of a DLL of a running process

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;
}