📖 учебник Руководство по подключению для начинающих

Sbenny.com доверяют 1,330,761 XNUMX XNUMX счастливых пользователей с 2014 года.
Зарегистрируйтесь

PixelYT

Ученик Уровень 2️⃣
Участник 5 лет
Я знаю отличный учебник по подключению уже существует здесь, но этот учебник более подробный и, на мой взгляд, более полезен для новичков.

Отказ от ответственности: я нашел этот учебник где-то еще и решил поделиться им здесь, потому что он действительно полезен! Я НЕ НАПИСАЛ ЭТО РУКОВОДСТВО, ДАННОЕ РУКОВОДСТВО БЫЛО НАПИСАНО криоатомизатор



Название игры: Пуля Force
Язык кодирования: C + +

Что вам нужно, чтобы следовать этому руководству по подключению функций Android:

• Знание C ++
• Базовые знания по созданию мод-меню для Android.
• Должен уже знать, как исправлять функции с помощью шестнадцатеричных кодов. Если нет, вернись, когда сможешь.
DnSpy
Android-студия

Шаблон Octowolves
Or
ШАБЛОН LGLS

(если вы предпочитаете другой шаблон, это тоже нормально)

• Мозг


Если они у вас есть, можете продолжать читать. В противном случае это руководство слишком сложное, чтобы вы могли понять и применить его в других играх.

Пожалуйста, не задавайте мне в комментариях вопросов, не относящихся к этому руководству. Если вы хотите узнать о создании меню для Android, прочтите другие темы в этом разделе.

Я предоставлю готовую копию учебника по подключению с Шаблон Octowolves. Вы несете ответственность за обновление смещений, когда это необходимо, поскольку я уже привожу имена функций в этом руководстве.

В этом руководстве по подключению функций Android я буду использовать Шаблон Octowolves демонстрировать.

Итак, вы знаете, как патчить, но хотите вывести все на новый уровень. Но какой следующий уровень? С чего начать?

Что ж, этот туториал IS следующий уровень.

Что это такое?

Зацепление.

Что зацепляет?


Перехват - более эффективный и лучший способ модификации функций.

Это позволяет нам возвращать все, что мы хотим функции, создавая функцию и подключая ее, вызывая ее в нашем основном потоке со смещением.

Почему я должен использовать его вместо патчей?

• Более эффективным

• Можете вернуть все, что захотите

• Может настраивать функции для вызова указателей при обновлении

• Любое исправление, используемое в меню, легко понять, и ваши смещения при исправлении подвергаются риску.

• Прицепление труднее пиявки, чем пятно, и, во-первых, реже.


Теперь, когда вы знаете, что такое перехват и почему вы должны его использовать, приступим к уроку.

Я разделю этот поток на 5 разделов, по одному для каждого основного типа данных, который вы можете подключить, а также на дополнительный раздел.

Раздел 1. Основы подключения к Android

Итак, перехват происходит примерно так:

Сначала мы создаем функцию и возвращаем в нее то, что хотим, следуя приведенному ниже шаблону:
C ++:
(datatype) (*old_function)(void *instance);
(datatype) function(void *instance) {
    if (instance != NULL) {
        if (boolean) {
            return (whatever suitable for datatype);
        }
    }
    return old_function(instance);
}
Затем нам нужно вызвать его в нашем hack_thread со смещением следующим образом:
C ++:
octo_hook((void*)getAbsoluteAddress(0xOFFSET), (void*)Function, (void**)&old_Function);
Ваш полный hack_thread будет выглядеть примерно так:
C ++:
void* hack_thread(void*) {
    LOGI("I have been loaded. Mwuahahahaha");
    do {
        sleep(1);
    } while (!isLibraryLoaded(libName));
    LOGI("I found the il2cpp lib. Address is: %p", (void*)findLibrary(libName));
    octo_hook((void*)getAbsoluteAddress(0xOFFSET), (void*)Function, (void**)&old_Function);
    return NULL;
}
Вот оно!


Раздел 2: Перехват логических функций.

В Bullet Force есть интересная функция, которую мы можем довольно легко найти.

Если мы поищем CanShoot в dnspy, мы увидим, что это функция в классе PlayerScript, о котором я упоминал в предыдущих руководствах, что это ваш класс игрока. В нем все самое хорошее.
C ++:
private bool CanShoot(bool checkRPM = true)
Эта функция, кажется, проверяет, можем ли мы стрелять или нет.

Мы могли бы легко исправить это до true и двигаться дальше, но мы здесь для того, чтобы подключиться, верно?

Вы можете вернуть только тип данных типа данных функции. (да), так что мы можем вернуть только истину или ложь.

Все, что нам нужно сделать, это вернуть true, и это позволит нам стрелять, даже если у нас закончились патроны или перезарядка.

Как ни странно, когда вы изменяете эту функцию, она также останавливает задержку пули, позволяя вам стрелять больше пуль, поэтому эта функция также является читерской скоростью стрельбы.

Следуя шаблону, который я упомянул в разделе 1 выше, мы можем создать нашу функцию перехвата и вернуть true.
C ++:
bool (*old_CanShoot)(void *instance);
bool CanShoot(void *instance) {
    if (instance != NULL) {
        if (isAmmoandFirerate) {
            return true;
        }
    }
    return old_CanShoot(instance);
}
Теперь нам нужно вызвать его в вашем хакерском потоке и ввести смещение с помощью getabsoluteaddress.
C ++:
octo_hook((void*)getAbsoluteAddress(0x4ED460), (void*)CanShoot, (void**)&old_CanShoot);
Теперь ваша ветка взлома должна выглядеть так:
C ++:
void* hack_thread(void*) {
    LOGI("I have been loaded. Mwuahahahaha");
    do {
        sleep(1);
    } while (!isLibraryLoaded(libName));
    LOGI("I found the il2cpp lib. Address is: %p", (void*)findLibrary(libName));
    octo_hook((void*)getAbsoluteAddress(0x4ED460), (void*)CanShoot, (void**)&old_CanShoot);
    return NULL;
}
Теперь нам нужно сделать новый переключатель для этой функции. Найдите функции const char * в массиве заданий getListFT.

Как только вы его нашли, удалите все, что находится внутри {};

Ваш список функций теперь должен выглядеть так:
C ++:
const char *features[]= {};
Затем добавьте "" и поместите в него название вашей функции вашего переключателя. Мы делаем скорострельность и неограниченное количество боеприпасов, так что назовите переключатель как хотите. Я назову это «Скорострельность и неограниченные боеприпасы».

Ваш список функций теперь должен выглядеть так:
C ++:
const char *features[]= {"Unlimited Ammo And Firerate"};
Затем перейдите к функциям changeSeekBar, changeSpinner, changeEditText и удалите там кейсы, поскольку они нам не нужны, потому что мы используем только переключатели.

Теперь функции должны выглядеть так:
C ++:
void changeSeekBar(JNIEnv *env, jclass clazz, jint i, jint seekbarValue) {
    int li = (int) i;
    switch (li) {
        default:
            break;
    }
    return;
}

void changeSpinner(JNIEnv *env, jclass clazz, jint i, jstring value) {
    int li = (int) i;
    switch (li) {
        default:
            break;
    }
}

void changeEditText(JNIEnv *env, jclass clazz, jint i, jstring value){
    int li = (int) i;
    switch (li){
        default:
            break;
    }
    return;
}
В вашей функции changetoggles удалите регистры и добавьте регистр 0: а затем прервите; в конце. (не забывайте ломаться после каждого дела)

После этого делаем, isAmmoandFirerate =! isAmmoandFirerate; внутри вашего футляра.

Вот как это должно выглядеть сейчас:
C ++:
void changeToggle(JNIEnv *env, jclass thisObj, jint number) {
    int i = (int) number;
    switch (i) {
        case 0:
            isAmmoandFirerate = ! isAmmoandFirerate;
            break;
        default:
            break;
    }
    return;
}
Мы рассматриваем случай 0 как первую функцию, нашей второй функцией будет случай 1 и так далее.

Вот и все, готово!

Вы только что успешно подключили свою первую функцию! Похлопайте себя по спине.

Не будем слишком дерзкими, мы все еще не знаем, как подключать другие базовые типы данных.



Раздел 3. Перехват целочисленных функций Android.

Итак, я нашел очень интересную целочисленную функцию.
C ++:
public int getGrenadesLeft();
Сначала создайте логическое значение.
C ++:
bool isUnlimitedGrenades = false;
Чтобы перехватить это, нам нужно вернуть целое число. Следуя шаблону из первого раздела, давайте сделаем нашу функцию.
C ++:
int (*old_getGrenadesLeft)(void *instance);
int getGrenadesLeft(void *instance) {
    if(instance!=NULL) {
        if (isUnlimitedGrenades) {
            return 3;
        }
    }
    return old_getGrenadesLeft(instance);
}
Почему вы вернули только 3? Разве нам не нужно больше гранат, вроде 999?

Достаточно просто. Когда я впервые попытался использовать эту функцию, игра проверяет, превышает ли количество гранат максимальное количество гранат.

Вместо того, чтобы искать проверку и отключать ее, мы можем просто привязать ее к низкому числу. Он всегда будет оставаться на 3 гранатах, что дает нам неограниченное количество гранат.

Совет: если вас все еще выгоняют из игры, также подключите функцию GetMaxGrenades к 3.

Теперь вызовем наш хук в нашем хакерском потоке со смещением.
C ++:
octo_hook((void*)getAbsoluteAddress(0x8FD818), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
Ваш hack_thread теперь должен выглядеть так:
C ++:
void* hack_thread(void*) {
    LOGI("I have been loaded. Mwuahahahaha");
    // loop until our target library is found
    do {
        sleep(1);
    } while (!isLibraryLoaded(libName));
    LOGI("I found the il2cpp lib. Address is: %p", (void*)findLibrary(libName));

    octo_hook((void*)getAbsoluteAddress(0x8FD818), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
    octo_hook((void*)getAbsoluteAddress(0x4ED460), (void*)CanShoot, (void**)&old_CanShoot);
    return NULL;
}
Затем добавьте «Неограниченное количество гранат» как функцию в свой список функций.

Добавьте это в ChangeToggles после случая 0:
C ++:
case 1:
   isUnlimitedGrenades = ! isUnlimitedGrenades;
break;
Сделанный! Вы только что успешно подключили свою первую функцию int.



Раздел 4: Перехват поплавковых функций.

Итак, мы снова видим еще одну особенную функцию.
C ++:
public extern float get_fieldOfView();
Эта функция управляет вашим игровым полем обзора (fov).

Мы должны вернуть к нему 100, так как мы хотим получить высокий fov, верно?

Во-первых, давайте сделаем наше логическое значение.
C ++:
bool isFov = false;
Затем давайте сделаем нашу функцию.
C ++:
float (*old_get_fieldOfView)(void *instance);
float get_fieldOfView(void *instance) {
    if(instance!=NULL) {
        if (isFov) {
            return 100.0f;
        }
    }
    return old_get_fieldOfView(instance);
}
}
Почему мы вернули 100.0f вместо 100.0?

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

Что ж, если мы вернем 100.0, игра сочтет это двойным, что может или не может вызвать сбой или проблемы с функциями.

Когда мы помещаем f в конец, игра узнает, что это число с плавающей точкой.

Лучше перестраховаться, чем сожалеть!

Теперь мы можем вызвать нашу функцию в нашем хакерском потоке со смещением.
C ++:
octo_hook((void*)getAbsoluteAddress(0x1133710), (void*)get_fieldOfView, (void**)&old_get_fieldOfView);
Ваша завершенная хак-ветка должна выглядеть примерно так:
C ++:
void* hack_thread(void*) {
    LOGI("I have been loaded. Mwuahahahaha");
    // loop until our target library is found
    do {
        sleep(1);
    } while (!isLibraryLoaded(libName));
    LOGI("I found the il2cpp lib. Address is: %p", (void*)findLibrary(libName));

    octo_hook((void*)getAbsoluteAddress(0x8FD818), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
    octo_hook((void*)getAbsoluteAddress(0x4ED460), (void*)CanShoot, (void**)&old_CanShoot);
    octo_hook((void*)getAbsoluteAddress(0x8FD818), (void*)get_fieldOfView, (void**)&old_get_fieldOfView);
    return NULL;
}
Затем перейдите к своим функциям и добавьте «Fov» как функцию.

Ваши окончательные функции должны выглядеть примерно так:
C ++:
const char *features[]= {"Ammo And Firerate", "Unlimited Grenades", "Fov Changer"};
Зайдите в свою функцию changetoggles и добавьте:
C ++:
case 2:
   isFov = ! isFov;
   break;
Ваша последняя функция changetoggle должна выглядеть так:
C ++:
void changeToggle(JNIEnv *env, jclass thisObj, jint number) {
    int i = (int) number;
    switch (i) {
        case 0:
            isAmmoandFirerate = ! isAmmoandFirerate;
            break;
        case 1:
            isUnlimitedGrenades = ! isUnlimitedGrenades;
            break;
        case 2:
            isFov = ! isFov;
            break;
        default:
            break;
    }
    return;
}
Вот и все! Это 3 типа данных, которые вы чаще всего увидите, и теперь вы знаете, как их всех перехватить! Похлопайте себя по спине (снова).

Раздел 5: Привязка обновления для использования указателей на функции и прочего

Я как бы уже упоминал об этом во многих других своих уроках, но я не буду повторять здесь в образовательных целях.

Что такое обновление?

Краткое резюме:

Обновление вызывается 60 раз в секунду и необходимо, если вы используете такие вещи, как указатели на функции. Это полезно для таких вещей, как получение позиций игроков, так как вам нужна самая текущая позиция игрока.

Правильно?

Лучше всего просто подключить update.

Итак, давайте сделаем функцию обновления.
C ++:
void(*old_PlayerScript_UpdateFast)(void *player);
void PlayerScript_UpdateFast(void *player) {
    if(player != nullptr){
        //your stuff goes here
    }
    old_PlayerScript_UpdateFast(player);
}
Теперь просто подключите его к нашей ветке хакерских атак.
C ++:
octo_hook((void*)getAbsoluteAddress(0x507AE8), (void*)PlayerScript_UpdateFast, (void**)&old_PlayerScript_UpdateFast);
Это оно! Теперь вы можете вызывать все, что захотите, в своей функции обновления. Повеселись! (я оставлю функцию обновления в исходном коде, который я предоставляю, на случай, если кто-то собирается ее использовать).

Раздел 6. Использование заголовков для смещений и функций Android-перехватчиков (необязательно)

Использование заголовков для таких вещей, как смещения или функции перехвата, в основном используется только для поддержания чистого кода в вашем main.cpp.

Сделаем заголовок смещения. Обычно это упрощает обновление смещений, если они находятся в одном файле только по порядку.
C ++:
#ifndef OFFSETS_H
#define OFFSETS_H

namespace Offsets {
    enum Offsets {
   
        CanShootOffset = 0x4ED460,
        getGrenadesLeftOffset = 0x8FD818,
        get_fieldOfViewOffset = 0x8FD818,
        PlayerScriptUpdateFastOffset = 0x507AE8

    };
}

#endif
Теперь мы можем включить наш заголовок и заменить наши смещения крючка на те, что в заголовке.

Теперь ваши крючки должны выглядеть так:
C ++:
octo_hook((void*)getAbsoluteAddress(Offsets::getGrenadesLeftOffset), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
octo_hook((void*)getAbsoluteAddress(Offsets::CanShootOffset), (void*)CanShoot, (void**)&old_CanShoot);
octo_hook((void*)getAbsoluteAddress(Offsets::get_fieldOfViewOffset), (void*)get_fieldOfView, (void**)&old_get_fieldOfView);
octo_hook((void*)getAbsoluteAddress(Offsets::PlayerScriptUpdateFastOffset), (void*)PlayerScript_UpdateFast, (void**)&old_PlayerScript_UpdateFast);
Теперь давайте поместим наши функции-хуки в другой заголовок, чтобы сделать наш main.cpp немного чище.

Мы можем поместить в заголовок наши логические значения, функции-перехватчики и многое другое.

Мы также можем создать функцию, которая вызывает все наши перехватчики в потоке взлома из заголовка, еще больше очищая main.cpp.

Вот как должен выглядеть заголовок вашего хука:
C ++:
bool isAmmoandFirerate = false;
bool isUnlimitedGrenades = false;
bool isFov = false;



bool (*old_CanShoot)(void *instance);
bool CanShoot(void *instance) {
    if (instance != NULL) {
        if (isAmmoandFirerate) {
            return true;
        }
    }
    return old_CanShoot(instance);
}

int (*old_getGrenadesLeft)(void *instance);
int getGrenadesLeft(void *instance) {
    if(instance!=NULL) {
        if (isUnlimitedGrenades) {
            return 3;
        }
    }
    return old_getGrenadesLeft(instance);
}

float (*old_get_fieldOfView)(void *instance);
float get_fieldOfView(void *instance) {
    if (instance != NULL) {
        if (isFov) {
            return 100.0f;
        }
    }
    return old_get_fieldOfView(instance);
}

void(*old_PlayerScript_UpdateFast)(void *player);
void PlayerScript_UpdateFast(void *player) {
    if(player != nullptr){
        //your stuff goes here
    }
    old_PlayerScript_UpdateFast(player);
}

void CallHooks() {
    octo_hook((void*)getAbsoluteAddress(Offsets::getGrenadesLeftOffset), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
    octo_hook((void*)getAbsoluteAddress(Offsets::CanShootOffset), (void*)CanShoot, (void**)&old_CanShoot);
    octo_hook((void*)getAbsoluteAddress(Offsets::get_fieldOfViewOffset), (void*)get_fieldOfView, (void**)&old_get_fieldOfView);
    octo_hook((void*)getAbsoluteAddress(Offsets::PlayerScriptUpdateFastOffset), (void*)PlayerScript_UpdateFast, (void**)&old_PlayerScript_UpdateFast);
}
Не забудьте вызвать CallHooks (); в вашем hack_thread, иначе это не сработает.

Что ж, это почти все основы подключения, и это довольно просто, как только вы освоите его. Вам не нужно будет что-либо исправлять снова и снова! (кроме, может быть, отсутствия античит-функций).

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

Гуров

Дмитрий Петренко
✌️ Команда сообщества
Участник 5 лет
Большое спасибо за эту ценную информацию ????
 

PixelYT

Ученик Уровень 2️⃣
Участник 5 лет
Спасибо за чтение учебника :)
Если вам нужна помощь, просто спросите меня, и я помогу вам, или если вам нужен еще один пример взлома, как этот, тогда я предоставлю вам один :)
 

Гуров

Дмитрий Петренко
✌️ Команда сообщества
Участник 5 лет
Спасибо за чтение учебника :)
Если вам нужна помощь, просто спросите меня, и я помогу вам, или если вам нужен еще один пример взлома, как этот, тогда я предоставлю вам один :)
Большое спасибо, приятель. Это отличная помощь для таких новичков, как мы. Я постучу, если мне понадобится помощь :любовь:
 

PixelYT

Ученик Уровень 2️⃣
Участник 5 лет
@Gourov Потрясающие! :)
Сообщение автоматически объединяется:

@RockingRivu Я мог бы сделать видеоурок, но на самом деле это было бы то же самое, просто спросите меня, с чем у вас проблемы. и у меня нет микрофона, поэтому я не знаю, поможет ли это сделать видео без моего голоса?

Я посмотрю на это, и если я сделаю видеоурок, я обязательно напомню вам, а также ссылку на видео здесь, как только я опубликую его
 

комикс8

Lurker Уровень 0️⃣
Участник 3 лет
хм @PixelYTЯ никогда не пробовал реверс-инжиниринг раньше, хорошо
 
Последнее редактирование:

хххманоксхх

Ученик Уровень 2️⃣
Участник 4 лет
PixelYT
пожалуйста, я не получил его, и я видел этот тавер раньше на многих сайтах, но ему действительно нужно видео, чтобы объяснить больше деталей и стать проще, так что если вы сделаете видео, которое было бы хорошо, спасибо, человек
 

PixelYT

Ученик Уровень 2️⃣
Участник 5 лет
возможно, я сам сделаю видеоурок или напишу более пояснительный туториал (хотя этот урок от Shmoo объясняет все намного лучше, чем я могу)
 

PixelYT

Ученик Уровень 2️⃣
Участник 5 лет
Учебник немного устарел и не очень полезен для тех, кто плохо знаком с подключением, поэтому, возможно, я попытаюсь создать лучший (если смогу; p) учебник, который показывает, как изменять поля и взламывать с помощью указателей на функции!
 

Полярный медведь

Начинающий Уровень 1️⃣
Участник 2 лет
PixelYT
почему мы добавляем эти логические значения
isAmmoandFirerate
isUnlimitedГранаты
я имею в виду, что эти функции существуют в игре или мы их делаем???
откуда вы их взяли??????
и что я должен использовать
Шаблон Octowolves или LGLS TEMPLATE или MSHookFunction???? я имею в виду, что проще всего?
 
Топовое