Шалом. Я довольно давно не активничал тут, и решил заново пройтись по лоадеру своего камраде :)
Сам по себе лоадер имел интересные трюки, на которых можно было затупить на пару минут.
1. Архитектура файла
Сам файл имеет x64 разрядность и накрыт VMProtect, однако она тут играет малую роль, из всего функционала там используется только антидебаг из юзермода и мутация кода. Импорты никак не защищены, будем иметь это в виду =)
2. Проверка на валидный пароль
Из моей последней статьи на BROKENCORE можно понять, что пароль в лоадере генерировался за счёт никнейма. В дебаггере в два регистра передавались две переменные: Пароль и ник, и после этого вызывалась функция с генерацией и проверки пароля, если функция возвращала 0, значит пароль был невалидным.
На пароль сейчас не будем обращать внимание, ибо мы хотели сломать всю защиту =)
3. Архитектура защиты
В этой части я столкнулся с неприятными антидебаг трюками, которые я разделю на подпункты.
3.1. Антидебаг с помощью VEH
А эта проверка была написана исключительно для меня :D
В прошлых версиях лоадера я обходил всю защиту меняя адрес RIP на начало функции инжекта и деттачился, чтобы не наткнуться на антидебаг функцию во время инжекта. В этой версии кодер это зафиксил добавив переменные, которые будут меняться в других функциях, да бы я просто так не прошел уже меняя адрес, ну и что-то по типу PAGE_GUARD хуков но с другим назначением.
Суть в том чтобы вызвать PAGE_GUARD исключение и схватить его, в адресе на котором установлен VEH идет проверка на значение исключение, т.е. если исключение == 80000001 (PAGE_GUARD), то лоадер прекращает свою работу, все это выглядит так:
Если же джамп не произошел, то идет проверка уже на C0000005. Просто нопаем JNE проверку и антидебаг трик побежден :)
3.2. Хитрый трюк против ScyllaHide
Этот трюк выполняется уже во время вызова TLS Callback. Все мы знаем про хуки сциллыхайд и её проверки на параметры вызывающей функции. Тут трюк состоял в том чтобы патчить проверку у сциллыхайд на хук NtSetInformationThread, т.е. оригинальный хук проверял ThreadInformationClass на наличие 0x11 (ThreadHideFromDebugger) с помощью JNE, если они не были равны, то он просто скипал и шел дальше, но тут QHide просто меняет JNE на JMP и из-за этого хук сциллыхайд перестает работать и поток по итогу всё равно скрывается :) Довольно интересный трюк, который сразу и не заметишь, если не обратить внимание на вызов TLS Callback и завершающий код процесса (0x80000003).
До TLS каллбэка:
После TLS каллбэка:
Просто ставим RET в начало функции и этот трик побежден.
3.3. Поток с проверкой на анти-дебаг
По своей невнимательности на этот трюк я потратил больше всего времени, ибо не совсем понимал почему вызывался NtCreateThreadEx, а адреса в регистре не было :) Затем заметив функцию с которой стартовал поток я начал её листать и понял что это детект memory бряков. Этот трюк довольно распространенный и обходится он все также хуками от сциллыхайд.
Исходный код проверки:
3.4. Проверки на Breakpoints и на патч RET
В этом подпункте QHide сделал проверки на байты на важные функции, список байтов которые он проверял:
Проверки на байты:
Уже ничего не мешало составить паттерны для нахождения других мест с проверками.
Паттерны:
Патчим все это дело и переходим к последнему подпункту.
3.5. Анти-дебаг трюки во время инжекта
В ранних версиях QHide никак не защищал дллку, а лишь просто держал её в репозитории гитхаба делая хттп реквест чтобы скачать. Теперь же в этой версии она сидит там уже зашифрованной, и в функции инжекта сидят антидебаг трюки, здесь уже было тяжело трассировать по той причине, что любой колл мог привести к антидебаг трюку и по итогу не загрузить длл полностью. Но тем не менее этот трюк переставал работать из-за хуков сциллыхайд. А именно лоадер вызывал NtQueryInformationProcess с параметром Debug Port (можно понять по 0x7 параметру)
Нопаем проверку и на этом отключение защиты подходит к концу.
Затем нопаем саму проверку авторизации и получаем нашу заветную длл, которая будет находится в регионе памяти лоадера с правами RWX :)
На этом у меня всё, возможно я упустил некоторые детали, но тем не менее защита отключена, дллка чистая у меня. Сама статья по содержанию кажется не очень длинной, но вот дебажить это чудо было затратно по времени. Спасибо кто решился почитать эту статью, мне и самому было весело это сидеть и патчить :D
Подписывайтесь на мой блог: https://t.me/colby5engineering
Всего хорошего!
Сам по себе лоадер имел интересные трюки, на которых можно было затупить на пару минут.
1. Архитектура файла
Сам файл имеет x64 разрядность и накрыт VMProtect, однако она тут играет малую роль, из всего функционала там используется только антидебаг из юзермода и мутация кода. Импорты никак не защищены, будем иметь это в виду =)
2. Проверка на валидный пароль
Из моей последней статьи на BROKENCORE можно понять, что пароль в лоадере генерировался за счёт никнейма. В дебаггере в два регистра передавались две переменные: Пароль и ник, и после этого вызывалась функция с генерацией и проверки пароля, если функция возвращала 0, значит пароль был невалидным.
Код:
QWORD PTR SS:[RSP+140] - Пароль
QWORD PTR SS:[RSP+1B0] - Ник
CALL 00007FF746B52AF0 - Вызов генерации и проверки
На пароль сейчас не будем обращать внимание, ибо мы хотели сломать всю защиту =)
3. Архитектура защиты
В этой части я столкнулся с неприятными антидебаг трюками, которые я разделю на подпункты.
3.1. Антидебаг с помощью VEH
А эта проверка была написана исключительно для меня :D
В прошлых версиях лоадера я обходил всю защиту меняя адрес RIP на начало функции инжекта и деттачился, чтобы не наткнуться на антидебаг функцию во время инжекта. В этой версии кодер это зафиксил добавив переменные, которые будут меняться в других функциях, да бы я просто так не прошел уже меняя адрес, ну и что-то по типу PAGE_GUARD хуков но с другим назначением.
Суть в том чтобы вызвать PAGE_GUARD исключение и схватить его, в адресе на котором установлен VEH идет проверка на значение исключение, т.е. если исключение == 80000001 (PAGE_GUARD), то лоадер прекращает свою работу, все это выглядит так:
Если же джамп не произошел, то идет проверка уже на C0000005. Просто нопаем JNE проверку и антидебаг трик побежден :)
3.2. Хитрый трюк против ScyllaHide
Этот трюк выполняется уже во время вызова TLS Callback. Все мы знаем про хуки сциллыхайд и её проверки на параметры вызывающей функции. Тут трюк состоял в том чтобы патчить проверку у сциллыхайд на хук NtSetInformationThread, т.е. оригинальный хук проверял ThreadInformationClass на наличие 0x11 (ThreadHideFromDebugger) с помощью JNE, если они не были равны, то он просто скипал и шел дальше, но тут QHide просто меняет JNE на JMP и из-за этого хук сциллыхайд перестает работать и поток по итогу всё равно скрывается :) Довольно интересный трюк, который сразу и не заметишь, если не обратить внимание на вызов TLS Callback и завершающий код процесса (0x80000003).
До TLS каллбэка:
После TLS каллбэка:
Просто ставим RET в начало функции и этот трик побежден.
3.3. Поток с проверкой на анти-дебаг
По своей невнимательности на этот трюк я потратил больше всего времени, ибо не совсем понимал почему вызывался NtCreateThreadEx, а адреса в регистре не было :) Затем заметив функцию с которой стартовал поток я начал её листать и понял что это детект memory бряков. Этот трюк довольно распространенный и обходится он все также хуками от сциллыхайд.
Исходный код проверки:
3.4. Проверки на Breakpoints и на патч RET
В этом подпункте QHide сделал проверки на байты на важные функции, список байтов которые он проверял:
Код:
0xC3 - RET
0xCC - INT3 (Software Breakpoint)
Проверки на байты:
Уже ничего не мешало составить паттерны для нахождения других мест с проверками.
Паттерны:
Код:
3D C3 00 00 00 - cmp eax, 0xC3
3D CC 00 00 00 - cmp eax, 0xCC
Патчим все это дело и переходим к последнему подпункту.
3.5. Анти-дебаг трюки во время инжекта
В ранних версиях QHide никак не защищал дллку, а лишь просто держал её в репозитории гитхаба делая хттп реквест чтобы скачать. Теперь же в этой версии она сидит там уже зашифрованной, и в функции инжекта сидят антидебаг трюки, здесь уже было тяжело трассировать по той причине, что любой колл мог привести к антидебаг трюку и по итогу не загрузить длл полностью. Но тем не менее этот трюк переставал работать из-за хуков сциллыхайд. А именно лоадер вызывал NtQueryInformationProcess с параметром Debug Port (можно понять по 0x7 параметру)
Нопаем проверку и на этом отключение защиты подходит к концу.
Затем нопаем саму проверку авторизации и получаем нашу заветную длл, которая будет находится в регионе памяти лоадера с правами RWX :)
На этом у меня всё, возможно я упустил некоторые детали, но тем не менее защита отключена, дллка чистая у меня. Сама статья по содержанию кажется не очень длинной, но вот дебажить это чудо было затратно по времени. Спасибо кто решился почитать эту статью, мне и самому было весело это сидеть и патчить :D
Подписывайтесь на мой блог: https://t.me/colby5engineering
Всего хорошего!
Последнее редактирование: