Перейти к содержанию
Опубликовано
comment_2664

Установка и обнаружение VMT Хука (Виртуальная таблица методов класса)

 

В примере видно как легко детектится такой хук. Как обойти такую простую проверку!?

1. Для хука заходить во внутрь функции и установить хук в самой функции а не в vmt.

2. Записать код хука в пустом месте адресного пространства программы места там хватает чтоб записать хотябы редирект

тем самым адресс хука в vmt будет находится в адресном пространстве программы и условный античит пропустить такой код

 

 

1. Для теста создаем консольный проект на C++ и пропишем простой класс с VMT

class TestVMT//Простой класс с использованием VMT
{
public:

	virtual void Func1();
	virtual void Func2();
	virtual void Func3();
	virtual void Func4();
	virtual void Func5();

	DWORD64 ad = 0;

};

void TestVMT::Func1()
{
	MessageBoxA(0, "Func1", 0, 0);
}

void TestVMT::Func2()
{
	MessageBoxA(0, "Func2", 0, 0);
}

void TestVMT::Func3()
{
	MessageBoxA(0, "Func3", 0, 0);
}

void TestVMT::Func4()
{
	MessageBoxA(0, "Func4", 0, 0);
}

void TestVMT::Func5()
{
	MessageBoxA(0, "Func5", 0, 0);
}

2. Напишем функцию которая будет в роле хука

typedef int (WINAPI* MessageBoxS)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);// Прототип функции
MessageBoxS box = (MessageBoxS)0x7FFFB8B88120;// Адресс взят напрямую чтоб не заморачиваться


void hookfunc()//функция которая будет выполняться вместо оригинала
{	
	box(0, 0, 0, 0);
}

3. Напишем функцию которая будет устанавливать хук

LPVOID Hook(LPVOID pClass, LPVOID pHookFunc, int dwOffset)// Функция которая устанавливает хук в виртуальной таблице методов (VMT)
{
	LPVOID pVTable = *(LPVOID*)pClass;//Получаем адресс vmt таблица всегда находится по нулевому смещению
	LPVOID pAdressInTable = (LPVOID)((DWORD64)pVTable + dwOffset * 8);//Вычисляем адресс функции в таблице по ее порядковому номеру


	DWORD dwOldProtection;
	VirtualProtect((LPVOID)pAdressInTable, sizeof(pAdressInTable), PAGE_READWRITE, &dwOldProtection);// меняем параметры страницы установка флага чтение запись 

	memcpy(pAdressInTable, pHookFunc, 8);//Записываем наш адресс хука 

	VirtualProtect((LPVOID)pAdressInTable, sizeof(pAdressInTable), dwOldProtection, &dwOldProtection);// Восстановили параметры страницы

	return (LPVOID)pAdressInTable;// Вернули адресс из таблицы где установили хук
}

4. Пишем функцию для детекта хука

bool DetectVMT(LPVOID pClass, int MaxCount)// Простая функция для детекта хука. Проверяет таблицу VMT на изменения адрессов функций
{
	DWORD64 pVMT = *(DWORD64*)pClass;//Получаем адресс vmt таблица всегда находится по нулевому смещению

	MODULEINFO mInfo;// Структура которая будет получать информацию о модуле (конкретно наша программа)

	GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(0), &mInfo, sizeof(mInfo));// Можете в гугл заглянуть что делает эта функция
	printf("Base adress %llp\n", mInfo.lpBaseOfDll);

	DWORD64 EndFile = (DWORD64)mInfo.lpBaseOfDll + mInfo.SizeOfImage;// Вычисляем конец нашей программы базовый адресс + размер. Нужен для сравнения адрессов. Так как в основном адресса которые в таблице VMT не могут быть за пределами пространства программы

	for (int i = 0; i < MaxCount; i++)// Перебор таблицы методов
	{
		printf("VMT check %llp\n", *(DWORD64*)pVMT);
		if(*(DWORD64*)pVMT > EndFile)return 1;// Если адресс функции в таблице больше адресного пространства нашей программы то детект(То есть адресс ссылается на внешний код за пределами проги)
		if (*(DWORD64*)pVMT < (DWORD64)mInfo.lpBaseOfDll)return 1;// Если адресс функции в таблице меньше (для тех кто выделил память ниже нашей проги)

		pVMT += 8;//К первому адрессу в таблице прибавляем 8 байт это размер адрессов в х64 системе. Тем самым переходим на след функцию в таблице
	}


	return 0;// 0 если все адресса находятся в рамках пространства программы
}

5. Точка входа программы и использование функций

int main()
{
	TestVMT* pTestVMT = new TestVMT;

	printf("class adr %llp\n", pTestVMT);

	pTestVMT->Func4();// Проверка функции до хука

	if(DetectVMT(pTestVMT, 5))printf("VMT Detect hook\n");//Проверка таблицы перед хуком
	else
	{
		printf("VMT UNDetect hook\n");
	}

	system("pause");

	LPVOID vAdress = VirtualAlloc(0, 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);// Выделяем память для хука (Имитируем что мы заинжектили чит)
	memcpy(vAdress, (LPVOID)hookfunc, 100);// Запись кода hookfunc
	printf("vAdress %llp\n", vAdress);

	system("pause");

	LPVOID adresshook = Hook(pTestVMT, &vAdress, 3);// Установка хука в VMT (1 класс 2 адресс хука 3 номер функции в таблице)
	printf("adresshook %llp\n", adresshook);
	system("pause");

	pTestVMT->Func4();// Повторно вызывает функцию после хука для проверки

	if (DetectVMT(pTestVMT, 5))printf("VMT Detect hook\n");// Повторно проверяем наше таблицу VMT класса 
	else
	{
		printf("VMT UNDetect hook\n");
	}

	system("pause");

	return 1;
}

Дополнение:

- Как наглядно выглядит таблица (VMT) по нулевому смещению в классе https://prnt.sc/U72mdnLfdQGj

- После установки хука но номеру функции https://prnt.sc/qTUdUi3d7JYs

- Номер функции это порядковый номер https://prnt.sc/c4QilwUNh-Ys

 

Исходник:

 

 

#include <windows.h>
#include <stdio.h>
#include <Psapi.h>
 
class TestVMT//Простой класс с использованием VMT
{
public:
 
virtual void Func1();
virtual void Func2();
virtual void Func3();
virtual void Func4();
virtual void Func5();
 
DWORD64 ad = 0;
 
};
 
void TestVMT::Func1()
{
MessageBoxA(0, "Func1", 0, 0);
}
 
void TestVMT::Func2()
{
MessageBoxA(0, "Func2", 0, 0);
}
 
void TestVMT::Func3()
{
MessageBoxA(0, "Func3", 0, 0);
}
 
void TestVMT::Func4()
{
MessageBoxA(0, "Func4", 0, 0);
}
 
void TestVMT::Func5()
{
MessageBoxA(0, "Func5", 0, 0);
}
 
typedef int (WINAPI* MessageBoxS)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);// Прототип функции
MessageBoxS box = (MessageBoxS)0x7FFFB8B88120;// Адресс взят напрямую чтоб не заморачиваться
 
 
void hookfunc()//функция которая будет выполняться вместо  оригинала
{
box(0, 0, 0, 0);
}
 
LPVOID Hook(LPVOID pClass, LPVOID pHookFunc, int dwOffset)// Функция которая устанавливает хук в виртуальной таблице методов (VMT)
{
LPVOID pVTable = *(LPVOID*)pClass;//Получаем адресс vmt таблица всегда находится по нулевому смещению
LPVOID pAdressInTable = (LPVOID)((DWORD64)pVTable + dwOffset * 8);//Вычисляем адресс функции в таблице по ее порядковому номеру
 
 
DWORD dwOldProtection;
VirtualProtect((LPVOID)pAdressInTable, sizeof(pAdressInTable), PAGE_READWRITE, &dwOldProtection);// меняем параметры страницы установка флага чтение запись 
 
memcpy(pAdressInTable, pHookFunc, 8);//Записываем наш адресс хука 
 
VirtualProtect((LPVOID)pAdressInTable, sizeof(pAdressInTable), dwOldProtection, &dwOldProtection);// Восстановили параметры страницы
 
return (LPVOID)pAdressInTable;// Вернули адресс из таблицы где установили хук
}
 
bool DetectVMT(LPVOID pClass, int MaxCount)// Простая функция для детекта хука. Проверяет таблицу VMT на изменения адрессов функций
{
DWORD64 pVMT = *(DWORD64*)pClass;//Получаем адресс vmt таблица всегда находится по нулевому смещению
 
MODULEINFO mInfo;// Структура которая будет получать информацию о модуле (конкретно наша программа)
 
GetModuleInformation(GetCurrentProcess(), GetModuleHandleA(0), &mInfo, sizeof(mInfo));// Можете в гугл заглянуть что делает эта функция
printf("Base adress %llp\n", mInfo.lpBaseOfDll);
 
DWORD64 EndFile = (DWORD64)mInfo.lpBaseOfDll + mInfo.SizeOfImage;// Вычисляем конец нашей программы базовый адресс + размер. Нужен для сравнения адрессов. Так как в основном адресса которые в таблице VMT не могут быть за пределами пространства программы
 
for (int i = 0; i < MaxCount; i++)// Перебор таблицы методов
{
printf("VMT check %llp\n", *(DWORD64*)pVMT);
if(*(DWORD64*)pVMT > EndFile)return 1;// Если адресс функции в таблице больше адресного пространства нашей программы то детект(Тоесть адресс ссылается на внешний код за пределами проги)
if (*(DWORD64*)pVMT < (DWORD64)mInfo.lpBaseOfDll)return 1;// Если адресс функции в таблице меньше (для тех кто выделил память ниже нашей проги)
 
pVMT += 8;//К первому адрессу в таблице прибавляем 8 байт это размер адрессов в х64 системе. Тем самым переходим на след функцию в таблице
}
 
 
return 0;// 0 если все адресса находятся в рамках пространства программы
}
 
 
int main()
{
TestVMT* pTestVMT = new TestVMT;
 
printf("class adr %llp\n", pTestVMT);
 
pTestVMT->Func4();// Проверка функции до хука
 
if(DetectVMT(pTestVMT, 5))printf("VMT Detect hook\n");//Проверка таблицы перед хуком
else
{
printf("VMT UNDetect hook\n");
}
 
system("pause");
 
LPVOID vAdress = VirtualAlloc(0, 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);// Выделяем память для хука (Имитируем что мы заинжектили чит)
memcpy(vAdress, (LPVOID)hookfunc, 100);// Запись кода hookfunc
printf("vAdress %llp\n", vAdress);
 
system("pause");
 
LPVOID adresshook = Hook(pTestVMT, &vAdress, 3);// Установка хука в VMT (1 класс 2 адресс хука 3 номер функции в таблице)
printf("adresshook %llp\n", adresshook);
system("pause");
 
pTestVMT->Func4();// Повторно вызывает функцию после хука для проверки
 
if (DetectVMT(pTestVMT, 5))printf("VMT Detect hook\n");// Повторно проверяем наше таблицу VMT класса 
else
{
printf("VMT UNDetect hook\n");
}
 
system("pause");
 
return 1;
}

 

 

 

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

Опубликовано
comment_2666

Жирненько)

Продажи:


Здравствуйте!Я являюсь официальным посредником по данным читам:
1.[AltezaHack] – [Point Blank]
2.[AimNester] – [Point Blank,Warface]
3.[GlobalHack] – [CS:GO]
4.[sMARTHACK] – [CS:GO]
5.[AimJunkies] – [CS:GO,Warface,PUBG,S.T.A.L.K.E.R.GTA V и многое другое]

6.[FanHack] - [PUBG]
7.[FanHack] - [CS:GO]
8.[FanHack] - [APEX]

В России,Украине и других странах “СНГ”
У меня лучшие цены в России,Украине и остальных странах!

Мой профиль в ВК: Сергей Иванов (vk.com)
Моя группа в ВК: Буст чего то там (vk.com)
Логин Skype: doni-dakk
Отзывы покупателей: https://vk.com/topic-145854178_35682231
Telegramm:@Sedine



Покупая товары у меня,вы получаете:
* Тех.поддержку.
* Быструю активацию ключа.
* Решение ваших проблем.
* Так же,тех.поддержка с сайта.


Особенности товаров:
1.Не банят.
2.Большой функционал.
3.Поддержка.
4.Полность на Русском языке.(часть из них)

При покупке,вам гарантирована активация,скрин,о том что ваши деньги дошли по меня.

Звонки,я не принимаю!Даже не пытайтесь!

 

Гость
Эта тема закрыта для публикации ответов.