[C++ Урок] Перехват данных

Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Шалом.
Сегодня детально поговорим про модификации функций и отдельных их частей.

Для начала, разберемся с терминологией:
Хук - модификация участка памяти приложения, принимающего участие в работе исполняемого кода на любом из этапов работы приложения.
Хук дубликат - подмена участка исполняемого кода с целью искажения конечных и промежуточных результатов выполнения. (подмена функции/части кода функции)

Для конкретного примера используем допотопную штуку.​
Код:
void* Create_Hook(
    BYTE *src,       //Адресс по которому будет установлен хук
    const BYTE *dst, //Адресс блока с дубликатом
    const int len)   //Размер нашего хука
{
BYTE *jmp;
DWORD dwback;
DWORD jumpto, newjump;
VirtualProtect(src,len,PAGE_READWRITE,&dwback);
if(src[0] == 0xE9)
{
jmp = (BYTE*)malloc(10);
jumpto = (*(DWORD*)(src+1))+((DWORD)src)+5;
newjump = (jumpto-(DWORD)(jmp+5));
jmp[0] = 0xE9;
*(DWORD*)(jmp+1) = newjump;
jmp += 5;
jmp[0] = 0xE9;
*(DWORD*)(jmp+1) = (DWORD)(src-jmp);
}
else
{
jmp = (BYTE*)malloc(5+len);
memcpy(jmp,src,len);
jmp += len;
jmp[0] = 0xE9;
*(DWORD*)(jmp+1) = (DWORD)(src+len-jmp)-5;
}
src[0] = 0xE9;
*(DWORD*)(src+1) = (DWORD)(dst - src) - 5;
for(int i = 5; i < len; i++)
src[i] = 0x90;
VirtualProtect(src,len,dwback,&dwback);
return (jmp-len);
}
Начнем работу с постановки задачи.
Допустим я взламываю игру и в ней есть функция, которая возвращает float, а я хочу возвращать свой float вместо того, который рассчитывает игра, хочу подменить функцию целиком.
Путем реверса машинного кода, про который поговорим в будущем, я выбрал для себя функцию
ее прототип выглядит так:
float __thiscall WeaponBase::GetDamage(bool)
Так как же написать свою функцию, которая заменит эту? очень просто.
Прописываем в коде, свой прототип.
Код:
typedef float (__thiscall* _getDamage)(WeaponBase*, bool);
Как это работает? почему аргументов стало два?

Начинается все с typedef, далее указывается тип данных, после указывают соглашение о вызовах, __thiscall, __stdcall, __fastcall, __cdecl и так далее, соглашение о вызовах нужно указывать то, которое соответствует оригинальной функции.
  • __thiscall - функция в классе (именно по этому и добавляется 1 аргумент, это указатель на тот самый класс к которому принадлежит функция)​
  • __fastcall - передает часть параметров и результат выполнения через регистры.​
  • __stdcall - для WINAPI функций.​
Если кратко, у всех свои фитчи (в конце урока ссылка). Далее следует имя (как у делегата на шарпе) и в скобках аргументы.
Общий шаблон:
typedef Тип (Соглашение * имя)(Аргументы);
Опытным путем, в удобном месте прописываем хук.​
Код:
//Наш прототип
typedef float (__thiscall* _getDamage)(WeaponBase*, bool);
//Экземпляр прототипа, на случай если захотим вернуть оригинальную функцию
_getDamage Damage;

//наш дамаг
float myDamage = 200.f;
bool Damage_enable;

//наша функция дубликат, которая заменит оригинал
float __thiscall  myGetDamage(WeaponBase* Weapon, bool b1)
{
    //если наша функция дамага в меню допустим, включена, возвращаем свой дамаг
   if(Damage_enable)
        return myDamage;
   //иначе код дойдет сюда, и мы вернем оригинал!
    return Damage(Weapon, b1);
}
Вроде прописали, теперь устанавливаем хук.
Код:
DWORD Адресс_начала_нашей_функции = 0x530D52;
Damage = (_getDamage)Create_Hook(
    (BYTE*)Адресс_начала_нашей_функции, //Адресс оригинальной функции в памяти приложения
    (BYTE*)myGetDamage,                 //наша функция-дубликат
     5);                                //Размер хука
Что произойдет?
Когда игра вызовет нужную нам функцию, в самом ее начале будет стоять наш хук, который заставит исполняемый код сделать безусловный прыжок на нашу функцию-дубликат, которая при нужных нам условиях вернет коду игры нужное нам значение.
Почему размер хука 5 байт?
5 байт, это минимум который нужен для совершения того самого безусловного прыжка на нашу функцию-дубликат. То есть 0xE9 = jmp и 4 байта адресс.
Меняем задачу:
Я не хочу подменить всю функцию, хочу изменить лишь кусок.
Для этого придется возится с асм инструкциями и регистрами, чтобы достичь понимания работы функции и понять в каком месте правильней всего подменить данные. В моем случае, это произойдет в конце функции:​
Код:
.text:005310F6                 fld     dword ptr [ebp-10h] 
.text:005310F9                 mov     ecx, [ebp-0Ch]
.text:005310FC                 pop     ebx
.text:005310FD                 mov     large fs:0, ecx
.text:00531104                 mov     esp, ebp
.text:00531106                 pop     ebp
.text:00531107                 retn    4
Анализируя псевдокод в IDA Pro я понял что результат запишется по адресу регистра ebp - 0x10, в инструкции fld dword ptr [ebp-10h] следовательно опишу свою функцию для подмена этой инструкции.
Теперь смотрю, сколько байт в памяти занимает нужная мне инструкция, fld dword ptr [ebp-10h] , 3 байта, для хука нужно минимум 5, следовательно, хук будет подменять сразу две инструкции, чтобы часть кода не была утеряна.
То есть, подменим две инструкции,
и следующую за ней:
Сумарно получится 6 байт. (просто посчитать число байт инструкций в хексе, D9 45 F0 8B 4D F4)
То бишь, мы прыгнем на инструкцию pop ebx (берем ее адресс, и отнимаем от адреса инструкции fld dword ptr [ebp-10h])
Получится 005310FC - 005310F6, ставим калькулятор Windows в режим программист, тип в hex и считаем, ура, вышло 6 байт.
Из этого выходит:
Код:
//Наш дамаг
float myDamage = 200.f;
//Включена ли функция?
bool Damage_enable;
//Адресс нужной нам инструкции:
DWORD dwDamage_address = 0x005310F6;
//Адресс кода на который мы вернемся после изменения промежуточного результата выполнения
DWORD dwReturnDamage_address = dwDamage_address + 0x6;

_declspec(naked)int Damage_hook(void)
{
    //Если наша функция включена
    if (Damage_enable)
    {
        //выполняем нужные нам инструкции
        _asm fld     dword ptr[myDamage]
            _asm mov     ecx, [ebp - 0Ch]
            _asm jmp dword ptr[dwReturnDamage_address]
    }
    else //если нет
    {
        //Выполняем оригинальные
        _asm fld     dword ptr[ebp - 10h]
            _asm mov     ecx, [ebp - 0Ch]
            _asm jmp dword ptr[dwReturnDamage_address]
    }
}
Ставим хук:
Create_Hook((BYTE*)dwDamage_address, (BYTE*)Damage_hook, 6);
Почему ретурн через 6 байт?
По тому что мы подменяем 6 байт, нам не нужно чтобы поток ушел в рекурсию, снова и снова прыгая на наш хук.
Общий шаблон:
Код:
//Адресс подменяемой инструкции
DWORD someAddress = 0;
//someAddress + Точное число байт, размер всех подменяемых инструкций приложения минимум 5,
//если 5 не хватает берем больше, однако не забываем добавить инструкции которые взяли, чтобы исполняемый код не терялся.
DWORD returnSomeAddress = someAddress + 5;
//состояние функци
bool state;
//хук-дубликат учатска кода
_declspec(naked)int someName(void)
{
    //Если наша функция включена
    if (state)
    {
        //выполняем измененные инструкции
        //и прыгаем на адресс, который сразу после подменяемых нами инструкций в оригинальной памяти
        //чтобы продолжить выполнение функции
            _asm jmp dword ptr[returnSomeAddress]
    }
    else //если нет
    {
        //Выполняем оригинальные
        //и делаем тоже самое. (прыгаем на продолжение)
            _asm jmp dword ptr[returnSomeAddress]
    }
}
Что нам дает это знание?
Возможности изменять результат выполнения кода в различных приложениях. Вариантов применения миллиарды. На пример, у вас есть конкурент, у которого лаунчер с привязкой. Вы копаясь в его лаунчере, нашли функцию генерации ключа, который проверяется в бд, зная как работают хуки вы сможете подменить ключ на уже активированный и постебать паренька.
Хукая винапи, можно даже вытягивать указатели из экстернал читов. Если самому обновлять лень)
Это только несколько вариантов применения этих знаний из бесконечного множества.
Все зависит от вашей фантазии и желания разьебать что нибудь.

Все вопросы и замечания выслушаю в комментариях.

Дополнительные обучающие материалы из внешних источников: (кликабельные ссылки)
Пожалуйста, авторизуйтесь для просмотра ссылки.

Пожалуйста, авторизуйтесь для просмотра ссылки.

Пожалуйста, авторизуйтесь для просмотра ссылки.


Писалось на скорую руку и без компилятора, если что-то интересно, кидайте свои примеры, помогу разобраться подробней. Спасибо за внимание.​
 
Эксперт
Статус
Оффлайн
Регистрация
12 Июн 2014
Сообщения
991
Реакции[?]
1,209
Поинты[?]
3K
магия:
Код:
_declspec(naked)int Damage_hook(void)
{
    //Если наша функция включена
    if (Damage_enable)
        //выполняем нужные нам инструкции
         __asm fld     dword ptr[myDamage] 
    else //если нет
        //Выполняем оригинальные
      __asm fld     dword ptr[ebp - 10h]
        
    
     __asm mov     ecx, [ebp - 0Ch]
     __asm jmp dword ptr[dwReturnDamage_address]
}
 
//Экземпляр прототипа, на случай если захотим вернуть оригинальную функцию _getDamage Damage;
не "если", а для возврата
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
магия:
Код:
_declspec(naked)int Damage_hook(void)
{
    //Если наша функция включена
    if (Damage_enable)
        //выполняем нужные нам инструкции
         __asm fld     dword ptr[myDamage]
    else //если нет
        //Выполняем оригинальные
      __asm fld     dword ptr[ebp - 10h]
      
  
     __asm mov     ecx, [ebp - 0Ch]
     __asm jmp dword ptr[dwReturnDamage_address]
}
 

не "если", а для возврата
По поводу магии, можно и на асме условие написать и прописать label для возврата оригинала. по типу goto, будет еще красивей выглядеть.а про поводу "если", возврат оригинала не всегда нужен, только по своему желанию или необходимости в случае с винапи тем же.
 
Пользователь
Статус
Оффлайн
Регистрация
26 Окт 2017
Сообщения
520
Реакции[?]
95
Поинты[?]
2K
а теперь по факту. 95% людей и 1% не поймут что тут написано
ибо аудитория чисто дайте готовый билд длл или кфг
или как собрать сурс и сделать так чтобы я мог дать его другу с привязкой они даже разбираться не станут.
ну а так вроде годно мб кому пригодится, но скорее люди кто хотят найдут другие источники, да и тем более это не такая уж сложная задача как по мне
==============
ты им лучше про VAC расскажи как он работает как его частично обойти или максимально скрыться чтобы не получить бан
думаю кто то да прочтёт мб чаго да выйдет
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
а теперь по факту. 95% людей и 1% не поймут что тут написано
ибо аудитория чисто дайте готовый билд длл или кфг
или как собрать сурс и сделать так чтобы я мог дать его другу с привязкой они даже разбираться не станут.
ну а так вроде годно мб кому пригодится, но скорее люди кто хотят найдут другие источники, да и тем более это не такая уж сложная задача как по мне
==============
ты им лучше про VAC расскажи как он работает как его частично обойти или максимально скрыться чтобы не получить бан
думаю кто то да прочтёт мб чаго да выйдет
про вак долго расказывать, у него больше миллиона наборов конфигураций, и от обновления до обновления могут применять самые разные, их могут даже менять в режиме реального времени. у них банальный бот для автоотсчетов и хорошие аналитики.
 
Забаненный
Статус
Оффлайн
Регистрация
27 Сен 2016
Сообщения
237
Реакции[?]
144
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
про вак долго расказывать, у него больше миллиона наборов конфигураций, и от обновления до обновления могут применять самые разные, их могут даже менять в режиме реального времени. у них банальный бот для автоотсчетов и хорошие аналитики.
Но тем не менее, чтобы его обойти, ты можешь обойтись лишь обфускацией :smirk:
 
Эксперт
Статус
Оффлайн
Регистрация
12 Июн 2014
Сообщения
991
Реакции[?]
1,209
Поинты[?]
3K
Но тем не менее, чтобы его обойти, ты можешь обойтись лишь обфускацией :smirk:
нет . полноценно обойти VAC мало кто может. по крайней мере я знаю только одного человека который смог отключить большую часть античита
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Но тем не менее, чтобы его обойти, ты можешь обойтись лишь обфускацией :smirk:
только вот, 90% вака на серверной части, клиентские дополнения нужны исключительно для сбора данных при "пороге вхождения", весь анализ и выводы делает сервер на основе найденных индикаторов, это значит что твоя "обфускация", это пердеж в лужу, зазнайки вроде тебя думают, что разрабам есть дело до твоего говно-чита и они будут детектировать вот именно его, и надо защитить код обфускацией чтобы систему не выпалили. Спустись на землю чувак, вак один, а читов на игры сервера которых защищаются ваком сотни тысяч без приуменьшений, ваку абсолютно похуй на твой чит и твой код, он ориентирован совсем на другое.
 
Новичок
Статус
Оффлайн
Регистрация
8 Авг 2019
Сообщения
1
Реакции[?]
1
Поинты[?]
0
Специально тут зарегистрировался, чтобы лайк поставить, а не могу. Даже не думал, что найду ответ на свой вопрос на подобном сайте с читами. Спасибо, хоть и старая тема.
 
Забаненный
Статус
Оффлайн
Регистрация
7 Авг 2019
Сообщения
18
Реакции[?]
3
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Очень полезная тема, спасибо

Жаль что лайк поставить не могу(
 
Coder [C++]
Начинающий
Статус
Оффлайн
Регистрация
22 Июн 2019
Сообщения
53
Реакции[?]
14
Поинты[?]
0
Здорова Дрим) Спасибо многое вычитал для себя, лайк к сожалению не получилось поставить, точнее кнопки нет(
 
#define VOID void
Начинающий
Статус
Оффлайн
Регистрация
13 Май 2017
Сообщения
120
Реакции[?]
24
Поинты[?]
13K
возможно на момент инжекта твоей длл целевой модуль не подгружен.
100% информация, что он подгружен.
после инжекта приложение зависает и спустя 5 секунд крашится
 
Я лучше тебя
Участник
Статус
Оффлайн
Регистрация
31 Июл 2017
Сообщения
383
Реакции[?]
448
Поинты[?]
1K
Похожие темы
Сверху Снизу