Перейти к содержанию

Динамический базовый указатель


Рекомендуемые сообщения

У меня такая проблема - в СЕ самый нижний указатель (который должен быть статическим ) имеет вид "xxx.exe+160B8D0", так вот, сам xxx.exe  - динамический и каждый раз меняется.

Как его можно занести в код на с++? Был бы он статическим, записал бы так:

        ReadProcessMemory(phandle, (LPVOID)(0x13F8D0000 + 0x160B8D0), &address, 8, NULL);        ReadProcessMemory(phandle, (LPVOID)(address + 0xd0), &address, 8, NULL);        ReadProcessMemory(phandle, (LPVOID)(address + 0x490), &address, 8, NULL);        ReadProcessMemory(phandle, (LPVOID)(address + 0x1c6), &BlueRank, 2, NULL);

Но увы, стоит перезрузить систему и уже не работает из-за измененного базового адреса (0x13F8D0000).

Ссылка на комментарий
Поделиться на другие сайты

сделай скриншот модулей(CreateToolhelp32Snapshot), в цикле сравни все имена модулей с нужным именем(strcmp) и верни адрес с помощью MODULEENTRY32

Изменено пользователем partoftheworlD
Ссылка на комментарий
Поделиться на другие сайты

А где именно в той структуре адрес лежит? Я сделал так

	INT64 address;		snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);		pInfo.dwSize = sizeof(PROCESSENTRY32);		if (Process32First(snapshot, &pInfo)){			while (Process32Next(snapshot, &pInfo)){				if (!strcmp(name, pInfo.szExeFile)){					HANDLE hSnap;					hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pInfo.th32ProcessID);					MODULEENTRY32 mod;					if (Module32First(hSnap, &mod))					{																	}					CloseHandle(hSnap);				}			}		}

В mod оказывается экзешник игры (если верить mod.szExePath), но как адрес вытащить?

modBaseAddr мне 0 возвращает
Ссылка на комментарий
Поделиться на другие сайты

szExePath возвращает путь модуля, если не изменяет память, а не адрес.Лучше раздели на 2 функции. А то, пока читал твой код запутался. :-D Вот готовый рабочий код, переделаешь под себя если надо. MSDN 

 

 

void Process(char *Processname){	HANDLE hPID = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);	PROCESSENTRY32 ProcEntry;	ProcEntry.dwSize = sizeof(ProcEntry);	do		if (!strcmp(ProcEntry.szExeFile, Processname))		{			PID = ProcEntry.th32ProcessID;			CloseHandle(hPID);			hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);			return;		}	while (Process32Next(hPID, &ProcEntry));	system("pause");	exit(0);} 
DWORD GetModule(char* ModuleName){	HANDLE hModule = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PID);	MODULEENTRY32 mEntry;	mEntry.dwSize = sizeof(mEntry);	do		if (!strcmp(mEntry.szModule, ModuleName))		{			CloseHandle(hModule);			return (DWORD)mEntry.modBaseAddr;		}	while (Module32Next(hModule, &mEntry));	return 0;} 
Изменено пользователем partoftheworlD
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

Спасибо) Забыл размерность (mEntry.dwSize = sizeof(mEntry) ) указать, из-за этого адрес и возвращался нулевым)

Изменено пользователем Abraham08
Ссылка на комментарий
Поделиться на другие сайты

Ещё такой вопрос: у меня есть байтовый адрес инструкции (48 8B 58 38 48 85 DB 74 * F6), есть сама инструкция (mov rbx,[rax+38]), в регистре rax хранится нужный мне адрес (тот самый, который был получен вчера через MODULEENTRY32), как можно на с++ добраться до этого регистра и считать из него информацию? Дело в том, что вчерашний вариант работает исключительно на в7, этот же вариант будет работать и на в10.

Ссылка на комментарий
Поделиться на другие сайты

Сигнатуру и маску для адреса в rax сделай и ищи.(SignMaker используй или вручную)

Изменено пользователем partoftheworlD
Ссылка на комментарий
Поделиться на другие сайты

  • 2 недели спустя...
В 29.01.2016в15:35, partoftheworlD сказал:

 

А вы трейнеры для 64 битных игр делали под windows 10? Тут такое дело, чтобы функции ReadProcessMemory и подобные принимали в качестве параметров 8 байтовые значения (я имею в виду второй параметр, в который заносится адрес из которого нужно считать данные, а в 64 битной игре и адреса 64 битные), необходимо перевести проект в Visual Studio 2013 в 64 битный режим (Project-> Project Properties->Configuration Manager->Active Solution Platform->x64), но вот в чем беда, на Windows 7 при таком раскладе всё продолжает работать, а в Windows 10 не создается окно (функция CreateWindow возвращает 0), я даже без трейнера попытался его создать, банальный шаблон программы HelloWorld, где просто создается окно и более ничего, в 32 битной версии нормально всё, а в 64 окно не хочет создаваться (проблема только на Windows 10), не знаете в чём дело?

 

 

Ссылка на комментарий
Поделиться на другие сайты

Ничего подобного. В моем пятом уроке (про сканер сигнатур) по созданию движка для трейнеров как раз используется 10 винда, и все нормально создается. Проверяй структуру WNDCLASSEX и параметры создаваемого окна.

 

Показывай код создания окна (включая код заполнения вышеупомянутой структуры).

Ссылка на комментарий
Поделиться на другие сайты

Вот полный код программы:

Скрытый текст

//Main.cpp

#include <Windows.h>
#include <string>
#include "resource.h"
#include <TlHelp32.h>
#include <fstream>
#include "MemReader.h"



using namespace std;

HWND hwnd;
HINSTANCE hInstance2;
DWORD64 var;
fstream Logs;

LRESULT CALLBACK DS2ZERO(HWND, UINT, UINT, LONG);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int nCmdShow){


	MSG Msg;
	WNDCLASSEX WndClass;
	char name[] = "ClassName";
	hInstance2 = hInstance;

	WndClass.style = CS_HREDRAW | CS_VREDRAW;
	WndClass.lpfnWndProc = (WNDPROC)DS2ZERO;
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hInstance = hInstance;
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	WndClass.lpszMenuName = NULL;
	WndClass.lpszClassName = name;
	WndClass.cbSize = sizeof(WNDCLASSEX);
	WndClass.hIconSm = NULL;

	if (!RegisterClassEx(&WndClass)){
		MessageBox(NULL, "Cant register class", "Error", MB_OK);
		exit(1);
	}
	HDC hDCScreen = GetDC(NULL);
	int Horres = GetDeviceCaps(hDCScreen, HORZRES);
	int Vertres = GetDeviceCaps(hDCScreen, VERTRES);
	ReleaseDC(NULL, hDCScreen);



	hwnd = CreateWindow(name, "DS2RANK", WS_OVERLAPPED | WS_SYSMENU, (Horres / 2) - 300, (Vertres / 2) - 300, 600, 600, NULL, NULL, hInstance, NULL);

	if (!hwnd){
		MessageBox(NULL, to_string(GetLastError()).c_str(), "Error", MB_OK);//
		exit(1);
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	
	while (GetMessage(&Msg, NULL, 0, 0)){

		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}

	return Msg.wParam;


}

LRESULT CALLBACK DS2ZERO(HWND hwnd, UINT Message, UINT wParam, LONG lParam){
	
	static HANDLE background;
	static Trainer ReadRank;
	HDC hDC, hCompatibleDC;
	PAINTSTRUCT PaintStruct;
	RECT Rect, Rect2, Rect3;
	
	

	switch (Message){

	case WM_CREATE:

		background = LoadBitmap(hInstance2, MAKEINTRESOURCE(IDB_BITMAP1)); //Фоновое изображение, загружаемое из RC файла

		return 0;

	case WM_PAINT:
		GetClientRect(hwnd, &Rect);
		hDC = BeginPaint(hwnd, &PaintStruct);
		hCompatibleDC = CreateCompatibleDC(hDC);
		SelectObject(hCompatibleDC, (HANDLE)background);
		BitBlt(hDC, 0, 0, Rect.right, Rect.bottom, hCompatibleDC, 0, 0, SRCCOPY);

		ReadRank.GetProcess();
		ReadRank.GetModule();
		ReadRank.OpenProc();


		Rect2.left = 0;
		Rect2.right = 192;
		Rect2.top = 0;
		Rect2.bottom = 367;

		Rect3.left = 807;
		Rect3.right = 192;
		Rect3.top = 0;
		Rect3.bottom = 367;

		DrawText(hDC, to_string(ReadRank.GetBloodRank()).c_str(), -1, &Rect2, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
		DrawText(hDC, to_string(ReadRank.GetBlueRank()).c_str(), -1, &Rect3, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
		

		DeleteDC(hCompatibleDC);
		EndPaint(hwnd, &PaintStruct);


		return 0;
		
	case WM_DESTROY:
		DeleteObject(background);
		PostQuitMessage(1);
		return 0;

	case WM_KEYDOWN:
		if (wParam == 27) SendMessage(hwnd, WM_CLOSE, wParam, lParam);
		InvalidateRect(hwnd, NULL, false);
		return 0;
	case WM_LBUTTONDOWN:
		InvalidateRect(hwnd, NULL, false);
		return DefWindowProc(hwnd, Message, wParam, lParam);
	case WM_RBUTTONDOWN:
		InvalidateRect(hwnd, NULL, false);
		return DefWindowProc(hwnd, Message, wParam, lParam);
	case WM_ERASEBKGND:
		return 0;
	}



	return DefWindowProc(hwnd, Message, wParam, lParam);
}

 

 

Скрытый текст

//MemReader.cpp
#pragma once

#include <Windows.h>
#include <TlHelp32.h>
#include <cstring>
#include "MemReader.h"
#include <string>



Trainer::Trainer(){
	ProcessName = new char[16];
	BloodRank = 0;
	BlueRank = 0;
	strcpy_s(ProcessName, 16, "Game.exe");
	pHandle = 0;
}

Trainer::~Trainer(){
	delete[] ProcessName;
}

DWORD Trainer::GetProcess(){
	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	PROCESSENTRY32 pInfo;
	pInfo.dwSize = sizeof(PROCESSENTRY32);
	if (Process32First(snapshot, &pInfo)){
		do{
			if (!strcmp(ProcessName, pInfo.szExeFile)){
				pID = pInfo.th32ProcessID;
				CloseHandle(snapshot);
				return pInfo.th32ProcessID;
			}
		} while (Process32Next(snapshot, &pInfo));
	}
}

MODULEENTRY32 Trainer::GetModule(){
	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
	MODULEENTRY32 mInfo;
	mInfo.dwSize = sizeof(MODULEENTRY32);
	Module32First(snapshot, &mInfo);
	AddressBase = (INT64)mInfo.modBaseAddr;
	//MessageBox(NULL, std::to_string(AddressBase).c_str(), "33", MB_OK);
	CloseHandle(snapshot);
	return mInfo;

}

HANDLE Trainer::OpenProc(){
	return pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pID);

}

short int Trainer::GetBloodRank(){
	ReadProcessMemory(pHandle, (LPVOID)(AddressBase + 0x160B8D0), &AddressOffset, 8, NULL);
	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0xd0), &AddressOffset, 8, NULL);
	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0x490), &AddressOffset, 8, NULL);
	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0x1c8), &BloodRank, 2, NULL);
	return BloodRank;
}

short int Trainer::GetBlueRank(){
	ReadProcessMemory(pHandle, (LPVOID)(AddressBase + 0x160B8D0), &AddressOffset, 8, NULL);
	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0xd0), &AddressOffset, 8, NULL);
	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0x490), &AddressOffset, 8, NULL);
	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0x1c6), &BlueRank, 2, NULL);
	return BlueRank;
}

DWORD64 Trainer::FindSignature(DWORD64 base, DWORD64 size, byte* sign, char* mask){
	MEMORY_BASIC_INFORMATION mbi = { 0 };
	DWORD64 offset = 0;
	while (offset < size){
		VirtualQueryEx(pHandle, (LPCVOID)(base + offset), &mbi, sizeof(MEMORY_BASIC_INFORMATION));
		if (mbi.State != MEM_FREE){
			byte* buffer = new byte[mbi.RegionSize];
			ReadProcessMemory(pHandle, mbi.BaseAddress, buffer, mbi.RegionSize, NULL);
			for (int i = 0; i < mbi.RegionSize; i++){
				if (DataCompare(buffer + i, sign, mask)){
					delete[] buffer;
					return (DWORD64)mbi.BaseAddress + i;
				}
			}
			delete[] buffer;
		}
		offset += mbi.RegionSize;
		//MessageBox(NULL, std::to_string(mbi.RegionSize).c_str(), "33", MB_OK);
	}
	return 0;
}

bool Trainer::DataCompare(byte* data, byte* sign, char* mask){
	for (; *mask; data++, mask++, sign++){
		if (*mask == 'x' && *data != *sign) return false;
	}
	return true;
}

void Trainer::SetAddressBase(DWORD64 addr){
	AddressBase = addr;
}

 

 

Скрытый текст

//Memreader.h

#pragma once

#include <Windows.h>
#include <TlHelp32.h>

class Trainer{
public:
	Trainer();
	~Trainer();
	DWORD GetProcess();
	MODULEENTRY32 GetModule();
	HANDLE OpenProc();
	short int GetBloodRank();
	short int GetBlueRank();
	DWORD64 FindSignature(DWORD64 base, DWORD64 size, byte* sign, char* mask);
	bool DataCompare(byte* data, byte* sign, char* mask);
	void SetAddressBase(DWORD64);
private:
	short int BloodRank;
	short int BlueRank;
	char*	  ProcessName;
	HWND	  hWndDS;
	DWORD	  pID;
	HANDLE    pHandle;
	INT64     AddressBase;
	INT64     AddressOffset;
};

 

 

Как уже говорил, проблема только на windows 10 и только в режиме x64 (в режиме x32 на w10 окно создается, но программа не работает т.к. функции принимают 4 байтовые значения)

Может нужно какие-то ещё параметры изменить в Project Properties? Или версия студии неподходит?

Изменено пользователем Abraham08
Ссылка на комментарий
Поделиться на другие сайты

Прочитай про недокументированные функции.(NtWow64QueryInformationProcess64
NtWow64ReadVirtualMemory64) Инфы по ним мало.
 Для чтения из игры x64 можно использовать NtWow64ReadVirtualMemory64 в 32 битном трейнере и окошко будет работать, придется функции руками импортировать из ntdll. И вот статейку глянь.

Изменено пользователем partoftheworlD
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

11 час назад, partoftheworlD сказал:

Прочитай про недокументированные функции.(NtWow64QueryInformationProcess64
NtWow64ReadVirtualMemory64) Инфы по ним мало.
 Для чтения из игры x64 можно использовать NtWow64ReadVirtualMemory64 в 32 битном трейнере и окошко будет работать, придется функции руками импортировать из ntdll. И вот статейку глянь.

Вот спасибо, знать бы о них раньше)

И, к слову, таки удалось запустить окно х64 проекта в в10, воспользовался этой шапкой:

Скрытый текст


HINSTANCE hInstance2;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND hWnd;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	hInstance2 = hInstance;
	WNDCLASSEX wc;
	ZeroMemory(&wc, sizeof(WNDCLASSEX));
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.hCursor = LoadCursor(0, IDC_ARROW);

	wc.lpszClassName = "WindowClass";
	RegisterClassEx(&wc);
	hWnd = CreateWindow("WindowClass", "DS2RANK", WS_SYSMENU | WS_MINIMIZEBOX, (GetSystemMetrics(SM_CXSCREEN) / 2) - 300, (GetSystemMetrics(SM_CYSCREEN) / 2) - 300, 600, 600, 0, 0, hInstance, 0);
	ShowWindow(hWnd, nCmdShow);
	
	MSG msg;

	while (1)
	{
		while (PeekMessage(&msg, 0, 0, 0, 1))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		if (msg.message == WM_QUIT) break;
	}
	return (int)msg.wParam;
}

 

В итоге так и не понял почему мой вариант не работал. Вроде и тут и там одно и то же - создается, заполняется и регистриуется класс окна, создается окно с учетом разрешения, запускается цикл сообщений. Но мой вариант на х64 в10 не работал, а этот работает. Мистика.

Ссылка на комментарий
Поделиться на другие сайты

Не мистика. В твоем варианте ты забыл обнулить структуру после ее создания. А в новом - там есть обнуление. Скорее всего, причина как раз в этом - функция создания окна обращалась к какому-то параметру в структуре, а там был "мусор" (ведь структура не была обнулена после создания). Отсюда и ошибка.

Ссылка на комментарий
Поделиться на другие сайты

  • 5 месяцев спустя...

В уроках у Xipho есть функция FindProcessByName:

Скрытый текст

BOOL ProcessManager::FindProcessByName(LPCTSTR ProcessName)
{
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
	if (hSnapshot == INVALID_HANDLE_VALUE) return FALSE;

	PROCESSENTRY32 pe = { 0 };
	pe.dwSize = sizeof(PROCESSENTRY32);

	if (Process32First(hSnapshot, &pe))
	{	
		while (Process32Next(hSnapshot, &pe))
		{
			if (!lstrcmp(pe.szExeFile, ProcessName))
			{
				m_PID = pe.th32ProcessID;
				break;
			}
		}
	}

	CloseHandle(hSnapshot);
	return TRUE;
}

 

Подскажите, пожалуйста, как из данной функции можно получить\вытащить значение DWORD m_PID для функции:

wsprintf(text, L"%u", m_PID);

 

Ссылка на комментарий
Поделиться на другие сайты

partoftheworlD, спасибо! Удалось получить BaseAddres, дальше пытаюсь получить нужный адрес из адреса указателя:

75ecc8afaddbt.jpg

Для этого использую функцию из уроков Xipho:

Скрытый текст

BOOL ProcessManager::ReadMemory(DWORD64 addr, LPVOID buffer, int sz)
{
	BOOL res = false;
	SIZE_T bytesRead = 0;
	HANDLE hProc = OpenProcess(PROCESS_VM_READ | PROCESS_VM_OPERATION, FALSE, m_PID);
	if (hProc)
	{
		res = ReadProcessMemory(hProc, (LPVOID)addr, buffer, sz, &bytesRead);
		if (!res)
		{
			int err = GetLastError();
		}
		CloseHandle(hProc);
		res = true;
	}

	return res;
}
...
  	case WM_RBUTTONUP:
	{
      pm.ReadMemory(0x00419BA5, &outta, 4);
      wsprintf(text, L"0x%X", outta);
      MessageBox(hWnd, text, L"INFO", MB_OK | MB_ICONINFORMATION);
    }
	break;

 

Функция замечательно работает при чтении значений из конечных адресов, но при попытке прочитать нужный адрес из адреса указателя возвращает пустое значение. Подскажите, пожалуйста, как доработать функцию ReadMemory или что я делаю не так?

Ссылка на комментарий
Поделиться на другие сайты

Попробуй сначала получить базовый адрес, а потом работать от него с указателями. Т.е 


pm.ReadMemory(0x40000000, &baseaddress, 4); //получил базовый адрес
pm.ReadMemory(baseaddress + 0x10, &outta, 4); //получил значение которое хранится в baseaddress->0x10
wsprintf(text, L"0x%X", outta);

получится что ты прочитаешь значение из baseaddress->0x10 и выводишь его.

 

Вот пример из исходников старого чита

Packetbase = memory->ReadMem<DWORD>(Engine + 0x4416B8); //получаем базовый адрес
Packetbase = memory->ReadMem<DWORD>(Packetbase + 0x634); //baseaddress->0x634
Packetbase = memory->ReadMem<DWORD>(Packetbase + 0x110); //baseaddress->0x634->0x110
memory->WriteMem(Packetbase + 0x6a8, &value); //тут записываем в конечное значение baseaddress->0x634->0x110->0x6A8 наш value

 

Скрытый текст

void Functions::RadarHack()
{
    bool value = false;
	bool value2 = true;
	auto Packetbase = 0;
	auto old = 0;
	for (auto index_player = 1; index_player < MAX_PLAYERS; ++index_player)
	{
		entity->getPlayer(index_player);
		switch (local_player->getTeam())
		{
		case Side::T:
			entity->getHealth() >= 1 ? Draw(index_player, true, false) : Draw(index_player, false, false);
			break;
		case Side::CT:
			entity->getHealth() >= 1 ? Draw(index_player, true, true) : Draw(index_player, false, true);
			break;
		}
	}
	if(old + 0x32 == GetTickCount())
	{
		Packetbase = memory->ReadMem<DWORD>(Engine + 0x4416B8);
		Packetbase = memory->ReadMem<DWORD>(Packetbase + 0x634);
		Packetbase = memory->ReadMem<DWORD>(Packetbase + 0x110);
		memory->WriteMem(Packetbase + 0x6a8, &value);
		printf("%u\n", memory->ReadMem<int>(Packetbase + 0x6a8));
	}
	else memory->WriteMem(Packetbase + 0x6a8, &value2);
	old = GetTickCount();
	Sleep(1);
}

 

Изменено пользователем partoftheworlD
Ссылка на комментарий
Поделиться на другие сайты

Нашёл ещё способ, как получить адрес из адреса указателя, под катом, вдруг кому пригодится:

Скрытый текст

		int value = 0;
		HANDLE phandle;
		DWORD address = 0x0040E300; //BaseAddress + Offset = PointAddress
		
		phandle = OpenProcess(PROCESS_VM_READ, 0, m_PID);

		if (phandle)
		{
			ReadProcessMemory(phandle, (void*)address, &value, sizeof(value), 0);
			wsprintf(text, L"%X", value);
			MessageBox(hWnd, text, L"INFO", MB_OK | MB_ICONINFORMATION);
		}

 

 

Изменено пользователем Merlin
Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.