Hello,
First of all: this tutorial describes the very earliest phase of programming an own bot/hack/tool/whatever. Most of you do already know this info or don't have to know it due to the libraries which are out there in the net. Although, it would be nice if you could fly over the code and post suggestions for improvements that I could make. (may it be coding style or bad performance or something else...)
Since I'm also pretty new to memory editing, I want to build things by hand instead of taking a library. I want to understand what the single steps are which are processed in the background. Therefore, I've started to write some little program from scratch.
The first action you have to do to begin with reading / writing memory, is to get a process handle via the OpenProcess() function from psapi.dll. OpenProcess requires the process' ID.
You can't get this ID that easy, since there could be multiple WoW's running and therefore you can't simply enter "WoW.exe" into some magic function and get the process ids from them.
The solution is to enumerate over all active processes regardless of them being wow processes or not, and to get their process names. Then, it's a simple string comparison with "WoW.exe" and you are done.
Note that you need to add the "SeDebugPrivilege" to the own processes ProcessToken to access some processes, including the WoW process. This requires the process to be elevated to administrator rights in Windows Vista and up. The privilege has to be set as soon as you access the process with OpenProcess(); The second function takes care of setting the flag.
To elevate the process, just go to the Linker => Manifest settings in the project properties and choose requireAdministrator in the UAC dropdown field.
The attachment contains my implementation of the mentioned functions, which automates this process of getting the process ID.
sample usage:
Code:
#include <windows.h>
#include <psapi.h>
#include <stdio.h>
#include <tchar.h>
#include <vector>
#include "process.h"
#include <exception>
int main () {
try {
Process::SetDebugPrivileges();
std::vector<DWORD> processPIDs = Process::GetPidsByProcessName(std::basic_string<TCHAR>(TEXT("Wow.exe")));
_tprintf(TEXT("Found %d WoW processes.\n"), processPIDs.size());
} catch (std::exception& e) {
_tprintf(TEXT("ERROR: %s\n"), e.what());
} catch (...) {
_tprintf(TEXT("UNKNOWN EXCEPTION\n"));
}
getchar();
return 0;
}
source:
process.h
Code:
#ifndef process_h_included
#define process_h_included
#include <tchar.h>
#include <vector>
#include <string>
class Process {
public:
static void SetDebugPrivileges ();
static std::vector<DWORD> GetPidsByProcessName (const std::basic_string<TCHAR> &processName);
};
#endif
process.cpp
Code:
#include <windows.h>
#include <tchar.h>
#include <vector>
#include <exception>
#include "process.h"
#include <Tlhelp32.h>
#include <string>
#include <memory.h>
void Process::SetDebugPrivileges () {
// Get own process token
HANDLE hToken_unsafe;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken_unsafe)) {
throw std::runtime_error("setDebugPrivileges: OpenProcessToken failed");
}
const std::tr1::shared_ptr<void> hToken (hToken_unsafe, CloseHandle);
TOKEN_PRIVILEGES tPrivileges;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tPrivileges.Privileges[0].Luid)) {
throw std::runtime_error("setDebugPrivileges: LookupPrivilegeValue failed");
}
// Set SeDebugPrivilege flag
tPrivileges.PrivilegeCount = 1;
tPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken.get(), FALSE, &tPrivileges, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)) {
throw std::runtime_error("setDebugPrivileges: AdjustTokenPrivileges failed");
}
if (GetLastError() != ERROR_SUCCESS) {
throw std::runtime_error("setDebugPrivileges: AdjustTokenPrivileges didn't adjust all specified privileges");
}
};
std::vector<DWORD> Process::GetPidsByProcessName (const std::basic_string<TCHAR> &processName) {
// Make snapshot of process list
const std::tr1::shared_ptr<void> hProcessSnapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL), CloseHandle);
if (hProcessSnapshot.get() == INVALID_HANDLE_VALUE) {
throw std::runtime_error("Process::GetPidsByProcessName: CreateToolhelp32Snapshot failed");
}
// Go through the list and search for processes with a matching process name
std::vector<DWORD> result;
PROCESSENTRY32 pEntry;
pEntry.dwSize = sizeof(PROCESSENTRY32);
for (BOOL success = Process32First(hProcessSnapshot.get(), &pEntry);
success && GetLastError() != ERROR_NO_MORE_FILES;
success = Process32Next(hProcessSnapshot.get(), &pEntry))
{
if (processName == pEntry.szExeFile) {
result.push_back(pEntry.th32ProcessID);
}
}
return result;
};
Enjoy!