Hi all,
Don't currently have time for this as a video (may do tomorrow), but wanted to share it as I now have this knowledge, so what I've been working on lately is a C++ version of JAPI (hopefully), which I'm doing solely for the purpose of learning. I've never really used C++ that extensively, only to do some fundamental calculations and what not, but here is some code which may help some of you along:
Code:
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <string>
#include <Psapi.h>
using namespace std;
int _tmain(int argc, _TCHAR* argv [])
{
// First off we grab a handle to Tibia via FindWindow()
HWND hwnd = FindWindow(L"TibiaClient", NULL);
// Dump the handle to console
cout << "HWND: " << hwnd << endl;
// These variables are self explanitory except cbNeeded, which I still don't fully get... Ah well
DWORD cbNeeded;
DWORD processID;
DWORD address = 0x3BE1E0;
// This is the MODULES handle, for the Tibia.exe module in the Tibia process (long story, basically we get a window, find the process linked to it, find the modules in
//the process, then we finally have the handle - which is also the base address!)
HMODULE hModule;
// Declare a wstring to hold the location of the Tibia client, bare in mind this won't always be the same, 32 bit will not have (x86)!
wstring fileName = L"C:\\Program Files (x86)\\Tibia\\Tibia.exe";
// A buffer to hold the value we read
int buffer;
// This gets the process ID of the process linked to the handle we obtained using FindWindow - Getting the ID from the window handle
GetWindowThreadProcessId(hwnd, &processID);
// Dump it to console
cout << "Process ID: " << processID << endl;
// This will get us a handle to the process itself, allowing us to enumerate it's modules!
HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, processID);
// Dump it to the console
cout << "Process Handle: " << handle << endl;
// Declare an array to store the modules in
HMODULE hMods[1024];
// Check the enumeration is legit (if the process doesn't exist or whatever, it will fail at this point!
if (EnumProcessModules(handle, hMods, sizeof(hMods), &cbNeeded))
{
// Inform the user that the enumeration worked fine, useful for debugging
cout << "Enumerated: " << "Success!" << endl;
// Cycle through the list of enumerations
for (int i = 0; i < (cbNeeded / sizeof(hwnd)); i++)
{
// Tell the user which cycle we are on, so we can monitor easily
cout << "Round " << i << ": ";
// Declare a TCHAR to hold the module name (szModName) of the required length
TCHAR szModName[MAX_PATH];
// If we can get the module file name, if the module denies us access it will fail here
if (GetModuleFileNameEx(handle, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
// Print the module name (stored as wstring, hence wcout instead of cout), and it's address from hMods
cout << "Module Name: ";
wcout << szModName;
cout << ". Entry Number: " << hMods[i];
// If the modules name is the same as the path we declared earlier then assign hModule to that module, and add the base address to the address to read.
if (szModName == fileName)
{
hModule = hMods[i];
address += (DWORD)hMods[i];
}
}
// Inform the user we finished the loop
cout << ". " << endl;
}
// Inform the user of the module handle (to confirm it is correct against the above list)
cout << "Module Handle: " << hModule << endl;
}
// Attempt to read memory, this will print 1 if success, 2 if failure
cout << "Read Success: " << ReadProcessMemory(handle, (void*)address, &buffer, sizeof(buffer), 0) << endl;
// Print the last error, incase of failure.
cout << "Last error: " << GetLastError() << endl;
// Print the data we read
cout << "Read: " << buffer << endl;
// Clean up a little
CloseHandle(handle);
// Inform the user that we've finished and wait for input.
cout << "End" << endl;
cin.get();
return 0;
}
Any comments or suggestions on how to make this easier are appreciated, I will make a tutorial about this tomorrow, explaining more as to why I took this route.
Thanks