Code:
// main.cpp
//
#include "stdafx.h"
#include <stdlib.h>
#include <windows.h>
#include <Winternl.h>
#include <tlhelp32.h>
#include <string>
#include <map>
typedef NTSTATUS (__stdcall *NTQUERY)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG );
HMODULE hmod = LoadLibraryA("ntdll.dll");
NTQUERY _NtQueryInformationThread = (NTQUERY)GetProcAddress( hmod,"NtQueryInformationThread");
struct THREAD_BASIC_INFORMATION
{
bool ExitStatus;
int * TebBaseAddress;
unsigned int processid;
unsigned int threadid;
unsigned int AffinityMask;
unsigned int Priority;
unsigned int BasePriority;
};
struct TPlayer{
// OFFSETS
// 0x0
__int64 GUID;
// 0x8
DWORD dummy0[20];
// 0x58
DWORD health;
// 0x5C
DWORD mana;
// 0x60
DWORD dummy1[4];
// 0x70
DWORD healthmax;
// 0x74
DWORD manamax;
// 0x2AC
DWORD dummy2[141];
//STATS//
// 0x2B0
DWORD strength;
// 0x2B4
DWORD agility;
// 0x2B8
DWORD stamina;
// 0x2BC
DWORD intellect;
// 0x2BC
DWORD spirit;
// 0x2C0
DWORD dummy3[10];
// 0x2EC
DWORD armor;
// 0x2F0
DWORD dummy4;
// 0x2F4
DWORD resistance[5];
};
struct TWoWObject{
DWORD dummy0;
DWORD dummy2;
DWORD UnitData;
DWORD dummy3;
DWORD dummy4;
DWORD ObjectType;
DWORD dummy5;
DWORD dummy6;
DWORD dummy7;
DWORD dummy8;
DWORD dummy10;
DWORD dummy11;
__int64 GUID;
DWORD dummy12;
DWORD NextPtr;
};
void _error()
{
if( GetLastError() ){
DWORD err = GetLastError();
WCHAR b[80];
ZeroMemory( b, (sizeof(WCHAR))*80 );
int a = (sizeof(WCHAR))*80;
if( FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, b, a, NULL) ){
wprintf(L"nSYSTEM ERROR %d: %sn",err, b );
}else{
throw( L"FORMAT MESSAGE ERROR" );
}
SetLastError(0);
}
}
class CMemoryReader{
public:
CMemoryReader();
~CMemoryReader();
bool openProcess( const std::wstring & );
bool _char(const DWORD &, char *, SIZE_T * = NULL);
bool _uchar(const DWORD &, unsigned char *, SIZE_T * = NULL);
bool _int(const DWORD &, int *, SIZE_T * = NULL);
bool int64(const DWORD &, __int64 *, SIZE_T * = NULL);
bool _uint(const DWORD &,unsigned int *, SIZE_T * = NULL);
bool _long(const DWORD &, long *, SIZE_T * = NULL);
bool _ulong(const DWORD &, unsigned long *, SIZE_T * = NULL);
bool _float(const DWORD &, float *, SIZE_T * = NULL);
bool _double(const DWORD &, double *, SIZE_T * = NULL);
bool _bool(const DWORD &, bool *, SIZE_T * = NULL);
bool _dword(const DWORD &, DWORD *, SIZE_T * = NULL);
bool read(const DWORD &, void *, const DWORD &, SIZE_T * = NULL);
DWORD getPID();
HANDLE getProcess();
private:
DWORD pid;
HANDLE gHandle;
std::wstring name;
};
CMemoryReader::CMemoryReader(){
}
CMemoryReader::~CMemoryReader(){
CloseHandle( gHandle );
}
bool CMemoryReader::openProcess( const std::wstring &name ){
HANDLE hToken;
OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );
TOKEN_PRIVILEGES tp = { 0 };
LUID luid;
DWORD cb = sizeof(TOKEN_PRIVILEGES);
if( !LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid ) ) return FALSE;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges( hToken, FALSE, &tp, cb, NULL, NULL );
_error();
CloseHandle(hToken);
this->name = name;
HWND wnd = FindWindowW(NULL, (LPCWSTR)name.c_str() );
_error();
if( !wnd ) return false;
DWORD thread = GetWindowThreadProcessId( wnd, &this->pid );
_error();
gHandle = OpenProcess(PROCESS_ALL_ACCESS, false, this->pid);
_error();
return true;
}
bool CMemoryReader::_char(const DWORD &addr, char * v, SIZE_T * r)
{ return read(addr,v,sizeof(char),r); }
bool CMemoryReader::_uchar(const DWORD &addr, unsigned char * v, SIZE_T * r)
{ return read(addr,v, sizeof(unsigned char) ,r); }
bool CMemoryReader::_int(const DWORD &addr, int * v, SIZE_T * r)
{ return read(addr, v, sizeof(int), r); }
bool CMemoryReader::_uint(const DWORD &addr, unsigned int * v, SIZE_T * r)
{ return read(addr, v, sizeof(unsigned int), r); }
bool CMemoryReader::_long(const DWORD &addr, long * v, SIZE_T * r)
{ return read(addr, v, sizeof(long), r); }
bool CMemoryReader::_ulong(const DWORD &addr, unsigned long * v, SIZE_T * r)
{ return read(addr, v, sizeof(unsigned long), r); }
bool CMemoryReader::_float(const DWORD &addr, float * v, SIZE_T * r)
{ return read(addr, v, sizeof(float), r); }
bool CMemoryReader::_double(const DWORD &addr, double * v, SIZE_T * r)
{ return read(addr, v, sizeof(double), r); }
bool CMemoryReader::_bool(const DWORD &addr, bool * v, SIZE_T * r)
{ return read(addr, v, sizeof(bool), r); }
bool CMemoryReader::_dword(const DWORD &addr,DWORD * v, SIZE_T * r)
{ return read(addr, v, sizeof(DWORD), r); }
bool CMemoryReader::int64(const DWORD &addr, __int64 * v, SIZE_T * r)
{ return read(addr, v, sizeof(__int64), r); }
bool CMemoryReader::read(const DWORD &addr, void * value, const DWORD &size_, SIZE_T * total)
{
if( this->gHandle == INVALID_HANDLE_VALUE ) return false;
BOOL ok = false;
ok = ReadProcessMemory(this->gHandle, (LPCVOID)addr, value, size_, total);
_error();
return ok;
}
DWORD CMemoryReader::getPID(){
return this->pid;
}
HANDLE CMemoryReader::getProcess(){
return this->gHandle;
}
class wowMemoryReader{
public:
wowMemoryReader();
~wowMemoryReader();
bool GetWoWBaseInfo(void);
bool GetPlayerInfo(void);
bool GetByGUID( __int64, TWoWObject & );
TPlayer player;
private:
CMemoryReader * mem;
__int64 playerGUID;
DWORD ObjectBasePtr;
};
wowMemoryReader::wowMemoryReader(){
mem = new CMemoryReader();
}
wowMemoryReader::~wowMemoryReader(){
delete mem;
}
bool wowMemoryReader::GetByGUID( __int64 guid, TWoWObject & o ){
DWORD CurrentPtr;
TWoWObject WoWObject;
int counter = 0;
if( !mem->_dword(ObjectBasePtr + 0xc, &CurrentPtr ) ) return false;
while( mem->read(CurrentPtr, &WoWObject, sizeof(WoWObject) ) )
{
if( WoWObject.GUID == guid)
{
o = WoWObject;
return true;
}
CurrentPtr = WoWObject.NextPtr;
counter++;
}
return false;
}
bool wowMemoryReader::GetPlayerInfo()
{
TWoWObject playerptr;
if( !GetByGUID( playerGUID, playerptr ) ) return 0;
if( !mem->read( playerptr.UnitData, &player, sizeof(TPlayer) ) ) return 0;
return true;
}
bool wowMemoryReader::GetWoWBaseInfo()
{
if( !mem->openProcess( L"World of Warcraft" ) ) return false;
HANDLE ThreadHandle;
THREADENTRY32 ThreadEntry;
HANDLE SnapHandle;
THREAD_BASIC_INFORMATION BasicInformation;
SnapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
_error();
if( SnapHandle == INVALID_HANDLE_VALUE ) return false;
ThreadEntry.dwSize = sizeof(THREADENTRY32);
_error();
if( !Thread32First(SnapHandle, &ThreadEntry) ) return false;
bool found = false;
while( Thread32Next(SnapHandle, &ThreadEntry) )
{
_error();
if( ThreadEntry.th32OwnerProcessID != mem->getPID() ) continue;
ThreadHandle = OpenThread(THREAD_QUERY_INFORMATION, false, ThreadEntry.th32ThreadID);
_error();
Sleep(100);
if( !ThreadHandle ) continue;
THREADINFOCLASS * tic = new THREADINFOCLASS();
NTSTATUS ThreadQueryResult = _NtQueryInformationThread(ThreadHandle, *tic, &BasicInformation, sizeof(THREAD_BASIC_INFORMATION), NULL);
_error();
CloseHandle( ThreadHandle );
_error();
if( ThreadQueryResult ) continue;
found = true;
break;
ThreadEntry.dwSize = sizeof(THREADENTRY32);
}
CloseHandle( SnapHandle );
_error();
if( !found ) return false;
const DWORD TIB_ptr = (int)BasicInformation.TebBaseAddress;
DWORD TLS_index;
DWORD TLS_ptr;
DWORD TSL_slot;
if( !mem->_dword(0xE7DA2C, &TSL_slot ) ) return false;
if( !mem->_dword(TIB_ptr+0x2c, &TLS_ptr ) ) return false;
if( !mem->_dword(TLS_ptr+(TSL_slot*4), &TLS_index) ) return false;
if( !mem->_dword(TLS_index+16, &ObjectBasePtr) ) return false;
if( !mem->int64(TLS_index+8, &playerGUID) ) return false;
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
wowMemoryReader wow;
if( !wow.GetWoWBaseInfo() ) return 0;
printf( "WOW base object found.n" );
if( !wow.GetPlayerInfo() ) return false;
printf( "Player info:ntHealth: %d/%dn", wow.player.health, wow.player.healthmax);
printf( "tMana: %d/%dn", wow.player.mana, wow.player.manamax);
printf( "tStrength: %dn", wow.player.strength);
printf( "tAgility: %dn", wow.player.agility);
printf( "tStamina: %dn", wow.player.stamina);
printf( "tIntellect: %dn", wow.player.intellect);
printf( "tSpirit: %dn", wow.player.spirit);
printf( "tArmor: %dn", wow.player.armor);
printf( "tResistance:nttArcane: %d, Fire: %d, Nature: %d, Frost: %d, Shadow: %dn",
wow.player.resistance[0],
wow.player.resistance[1],
wow.player.resistance[2],
wow.player.resistance[3],
wow.player.resistance[4]
);
while(1){
Sleep(100);
}
return 0;
}