• Ищем качественного (не новичок) разработчиков Xenforo для этого форума! В идеале, чтобы ты был фулл стек программистом. Если у тебя есть что показать, то свяжись с нами по контактным данным: https://t.me/DREDD

Гайд Как выгружать DLL / Unload

sg
Участник
Участник
Статус
Оффлайн
Регистрация
15 Янв 2021
Сообщения
507
Реакции
315
0. EntryPoint
Приветствую вас друзья. На связи ньюкамыч всея Руси. Сегодня оформим небольшом гайдик. Думаю он может быть полезен для новичков в сфере разработки читиксов для игр. Так как, находя какой-либо баг в своем mega-харош-хитаетвообщевсё продукте надо его отлаживать и изменять иногда по крупице в коде. А каждый раз компилить dll, закрывать игру, реинжектить, заходить в игру - занятие не из приятных.

Итак приступим же:

1. VMT

Даже сейчас, многие используют VMT хуки, что является небезопасным ( могу ошибаться, на ньюкамычах же ). Думаю, что вряд ли, среди тех, кто смотрит эту тему найдутся люди, которым не впадлу будет спастить VMT из лв или другого сурса. Так что, если вы такой, то в любом таком классе существует метод unhook. Называется в разных читах он по-разному, но вряд ли кто-то будет изъёбыаться и писать что-то иное.
Пример:
C++:
Expand Collapse Copy
    // Инициализируем
    vmthook* directx_hook;
  
    //
    // Что-то пишем
    //
  
    // Резко понадобилось отгрузить хук
    directx_hook->unhook();

2. Detour

Чуть сложнее, чем просто написать unload(). Для этого нам понадобится функция DetourRemove(). Которая включается в себя 2 аргумента типа PBYTE. Первый аргумент - наша оригинальная функция, которой мы присвоили значение, когда хукали функцию, и второй аргумент - наша хукнутая функция.
Пример:
C++:
Expand Collapse Copy
    // Инициализируем
    static auto setupbones = (DWORD)(util::FindSignature(crypt_str("client.dll"), "xy ?? ?? i xy i pi zd a ??"));
    DWORD original_setupbones = (DWORD)DetourFunction((PBYTE)setupbones, (PBYTE)hooked_setupbones);
  
    //
    // Жестко использовали наши хуки
    //
  
    // Понадобилось выгрузить
    DetourRemove((PBYTE)original_setupbones, (PBYTE)hooked_setupbones);

3. MinHook

Так же одна из простейших отгрузок, которая выполняется чисто одной строчкой:
MH_DisableHook(MH_ALL_HOOKS);
По хорошему, лучше ещё проверять, равен ли он MH_OK, т.е. завершилась ли отгрузка удачно.

4. Динамическая память

Ну просто ради хорошего тона надо освобождать динамическую память. "Если сделал malloc, будь добр, устрой и free". Нескладно ? Да и хуй с ним, никому не нужна утечка памяти же. Важно понимать, что если мы используем malloc, то надо делать освобождение памяти через free с аргументом в виде нашего поинтера. Так как это СИшная функция. А если вы умелец и сделали это как предполагают плюсы, то будет проще - delete и наш поинтер.

5. Возвращение оригинальных адресов

Звучит странно ? Ну щас поймёте на примере отгрузки меню из кс:
C++:
Expand Collapse Copy
    // При иницализации мы находим наше окно, где будем рисовать и так же
    // запоминаем ориг. WNDPROC ( неимоверно логично )
    do
        window = FindWindow(crypt_str("Valve001"), nullptr);
    while (window == NULL);
    oWndProc = (WNDPROC)SetWindowLongPtr(window, GWL_WNDPROC, (LONG_PTR)WndProc);
  
    //
    // Дальше хуки, отрисовка меню и т.п.
    //
  
    // Резко приспичило отгрузиться
    if (hooks::unhook) {
        // Отгружаем всё с помощью методов, описанных выше
        hooks::unload();
        pDevice->Release();
        // Снова запоминаем оригинал WNDPROC'а
        oWndProc = (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)(oWndProc));
        // ImGui moment...
        ImGui_ImplWin32_Shutdown();
        ImGui_ImplDX9_Shutdown();
        ImGui::DestroyContext();
        return 0;

6. Выгрузка DLL

Ну и наконец-то заключающаяся часть сего гайда, это простая выгрузка DLL. Так что приведу простенький и примитивный код:
C++:
Expand Collapse Copy
    // Ждем нажатия клавиши END и всё. В случае нажатия,
    // выходим из цикла и потока
    while (!GetAsyncKeyState(VK_END) & 1) {
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    FreeConsole();
    Sleep(2000);
    FreeLibraryAndExitThread(static_cast<HMODULE>(lpReserved), 0);
    return TRUE;


7. DLL_PROCESS_DETACH
Вот как-то так. Хочу сказать, чтобы вы не били меня камнями, т.к. это один из первых моих гайдов, собрал всю информацию с UC, GH ( noad ) и из своей головы. Пишите, что стоит исправить, буду рад любой адекватной критике)
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
А каждый раз компилить dll, закрывать игру, реинжектить, заходить в игру - занятие не из приятных.
Debug в mvs:
1637440807005.png
 
Ну, если я правильно тебя понял, то гайд рассчитан на то, что, если человек не умеет нормально юзать дебаг ( бред, но такие бывают ), или надо фиксануть баг, который просто муторно отлаживать, по типу не в том порядке рисуешь чамсы за стеной ( первое че в голову пришло :).

up: я как бы человек-гений, не понял аббревиатуру mvs XD
 
Ну, если я правильно тебя понял, то гайд рассчитан на то, что, если человек не умеет нормально юзать дебаг ( бред, но такие бывают ), или надо фиксануть баг, который просто муторно отлаживать, по типу не в том порядке рисуешь чамсы за стеной ( первое че в голову пришло :).

up: я как бы человек-гений, не понял аббревиатуру mvs XD
Гайд полезный, но функцию UnHook приложи, чтобы потом лишних вопросов не было))
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Гайд полезный, но функцию UnHook приложи, чтобы потом лишних вопросов не было))
почему этот "гайд" полезен, если его лет 100 назад мамонты придумали и давно валяется на юц или на том же югейме
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
И ? Что ты мне этим сказать хочешь ? Либо ты не выкупил рофла, либо я хуй его знает. Поясняй
"каждый раз компилить dll, закрывать игру, реинжектить, заходить в игру".
Далее ты хочешь написать *рофл* на тему тех, кто работает c кодом в vs, что якобы каждый раз этим нужно заниматься.
Мой же ответ был лишь как помощь, если ты не знаешь, что каждый раз рекомпилить длл не нужно, можно изменить код за секунду без реинжекта, так-как действительно многие об этом не знают, что мне тебе тут пояснить еще?
 
"каждый раз компилить dll, закрывать игру, реинжектить, заходить в игру".
Далее ты хочешь написать *рофл* на тему тех, кто работает c кодом в vs, что якобы каждый раз этим нужно заниматься.
Мой же ответ был лишь как помощь, если ты не знаешь, что каждый раз рекомпилить длл не нужно, можно изменить код за секунду без реинжекта, так-как действительно многие об этом не знают, что мне тебе тут пояснить еще?
эта хуйня практически 98% времени отваливается и/или не работает по каким то причинам
 
эта хуйня практически 98% времени отваливается и/или не работает по каким то причинам
Не идеально, но в целом нормально всё работает. Главное проект настроить правильным образом, единственная проблема - глобальные переменные не сможешь инициализировать новые таким образом. Но да, действительно, эта функция может отвалиться, но я перед этим так могу уже под сотку изменений кода успеть сделать, это лучше чем реинжектить было бы эти 100 раз, так-что грех жаловать когда только через несколько часов отваливается и приходится сделать 1 реинжект
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
"каждый раз компилить dll, закрывать игру, реинжектить, заходить в игру".
Далее ты хочешь написать *рофл* на тему тех, кто работает c кодом в vs, что якобы каждый раз этим нужно заниматься.
Мой же ответ был лишь как помощь, если ты не знаешь, что каждый раз рекомпилить длл не нужно, можно изменить код за секунду без реинжекта, так-как действительно многие об этом не знают, что мне тебе тут пояснить еще?
Ты не выкупил рофла,дядь.
 
"каждый раз компилить dll, закрывать игру, реинжектить, заходить в игру".
Далее ты хочешь написать *рофл* на тему тех, кто работает c кодом в vs, что якобы каждый раз этим нужно заниматься.
Мой же ответ был лишь как помощь, если ты не знаешь, что каждый раз рекомпилить длл не нужно, можно изменить код за секунду без реинжекта, так-как действительно многие об этом не знают, что мне тебе тут пояснить еще?
Для этого нужны нормальные настройки проекта и это лишь начало ограничений будем так говорить например
 
Не идеально, но в целом нормально всё работает. Главное проект настроить правильным образом, единственная проблема - глобальные переменные не сможешь инициализировать новые таким образом. Но да, действительно, эта функция может отвалиться, но я перед этим так могу уже под сотку изменений кода успеть сделать, это лучше чем реинжектить было бы эти 100 раз, так-что грех жаловать когда только через несколько часов отваливается и приходится сделать 1 реинжект
тогда уже лучше захукать вндпроц и на альт-таб сделать запуск инжектора.exe и выгрузку длл, тем самым когда альт табаешься у тебя длл выгружается
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
тогда уже лучше захукать вндпроц и на альт-таб сделать запуск инжектора.exe и выгрузку длл, тем самым когда альт табаешься у тебя длл выгружается
это че за марсианские технологии? Нахуя?
 
это че за марсианские технологии? Нахуя?
если ты кодишь длл и делаешь пару изменений в коде, а применение изменений без остановки дебага не работает по каким то там причинам, это будет являться самым быстрым и эффективным методом разработки кода, все что тебе будет нужно для применения изменений это альт+таб, ребилд проекта и разворот игры
 
почему этот "гайд" полезен, если его лет 100 назад мамонты придумали и давно валяется на юц или на том же югейме
Нигде не видел подобного гайда, где собраны способы анлоада для всех разнообразных библиотек. В основном пишут, либо про опредленную библиотеку и вообще нигде не встречал, где был бы сразу обговорен момент с возвращением ориг. адресов, на чем и лично у меня постоянно крашилась игра, при анлоаде менюшки.
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Нигде не видел подобного гайда, где собраны способы анлоада для всех разнообразных библиотек. В основном пишут, либо про опредленную библиотеку и вообще нигде не встречал, где был бы сразу обговорен момент с возвращением ориг. адресов, на чем и лично у меня постоянно крашилась игра, при анлоаде менюшки.
симпл - есть анлоад
осирис - есть анлоад
qu0 -есть анлоад
дохуя где это все реализвано из коробки
А,ну и еще,если ты на бряке дебажишь,то после f5 мвс тебе все сама собирает без проблем,нахуя юзать альты и т.д. - неизвестно
 
симпл - есть анлоад
осирис - есть анлоад
qu0 -есть анлоад
дохуя где это все реализвано из коробки

А,ну и еще,если ты на бряке дебажишь,то после f5 мвс тебе все сама собирает без проблем,нахуя юзать альты и т.д. - неизвестно
Речь вообще про гайды была. Но в любом случае, эта тема создана для тех, кто по каким-то соображениям пишет свою базу, пастит её и т.п. Но, неожиданно, у него нет никакого анлоада, да и просто тон хорошего программиста - знать как это работает, а не бездумно пастить, как это делает наверное 70% ЮГ
 
Во первых, не понимаю как связана выгрузка dll с анхуком. Но да ладно.

Во вторых FreeLibraryAndExitThread не высвобождает dll , а уменьшает количество ссылок на либу и завершает поток.

В третьих , зачем вы в FreeLibraryAndExitThread передаете static_cast<HMODULE>(lpReserved) ? Вы вообще знаете что это за параметр который вы кастуете в HMODULE? Я не знаю, может быть вы определили lpReserved как HMODULE вашей либы, но я очень сомневаюсь, и скорее всего это обычный параметр точки входа dll.

Зачем постить какой то контент, когда вы сами не понимаете что делаете? Обычно когда вы загружаете dll, количество ссылок становится равной 1, а когда создаете поток, она увеличивается на 1, по этому когда вы из потока вызываете FreeLibraryAndExitThread, счетчик ссылок не становится равным 0. Надо чтоб загружавший dll модуль тоже уменьшил количество ссылок на 1.

По этому этот пост не несет никакой полезной нагрузки.

P.S. Есть одна хитрость как можно высвободить dll саму себя, нужно уменьшить счетчик ссылок до 1 и вызвать FreeLibraryAndExitThread. Счетчик ссылок находится в структуре LDR_DDAG_NODE::LoadCount, которую можно найти с помощью структуры PEB процесса.
 
Во первых, не понимаю как связана выгрузка dll с анхуком. Но да ладно.

Во вторых FreeLibraryAndExitThread не высвобождает dll , а уменьшает количество ссылок на либу и завершает поток.

В третьих , зачем вы в FreeLibraryAndExitThread передаете static_cast<HMODULE>(lpReserved) ? Вы вообще знаете что это за параметр который вы кастуете в HMODULE? Я не знаю, может быть вы определили lpReserved как HMODULE вашей либы, но я очень сомневаюсь, и скорее всего это обычный параметр точки входа dll.

Зачем постить какой то контент, когда вы сами не понимаете что делаете? Обычно когда вы загружаете dll, количество ссылок становится равной 1, а когда создаете поток, она увеличивается на 1, по этому когда вы из потока вызываете FreeLibraryAndExitThread, счетчик ссылок не становится равным 0. Надо чтоб загружавший dll модуль тоже уменьшил количество ссылок на 1.

По этому этот пост не несет никакой полезной нагрузки.

P.S. Есть одна хитрость как можно высвободить dll саму себя, нужно уменьшить счетчик ссылок до 1 и вызвать FreeLibraryAndExitThread. Счетчик ссылок находится в структуре LDR_DDAG_NODE::LoadCount, которую можно найти с помощью структуры PEB процесса.
Определенно, я тут не гуру языка, но разве освободить всю память и анхункуть != выгрузить длл ? Так как физически длл в процессе больше нет и всё работает так же, будто её и не было. Я перечислил основные "правила", как произвести анлоад для новичков ( тех, кто хоть слегка шарит в плюсах и умеет думать головой, им то это вполне моет быть полез ).

Про остальное я промолчу, потому что ясное дело я тут не хвх биг бой кодер с 2013. Но единственный момент не очень понятен. По поводу кастования в HMODULE. Аргумент для основного потока - LPVOID lpReserved, а при создании потока через CreateThread(0, 0, main, hModule, 0, 0) В качестве аргумента для функции main идёт тот HMODULE hModule из DllMain'а. Порывшись в интернете можно найти объяснение этого самого типа LPVOID - указатель на любой тип. Соответственно передавая в качестве аргумента HMODULE и потом кастуя его обрано в него же мы не получим хлопка вселенной и всё будет нормально
 
Назад
Сверху Снизу