Статья [Reverse-Engineering] Ломаем всю защиту лоадера QHide

  • colby57
  • UNEXPECTED_KERNEL_MODE_TRAP_M (1000007f)
  • 155
  • 2
  • 240
Шалом. Я довольно давно не активничал тут, и решил заново пройтись по лоадеру своего камраде :)
Сам по себе лоадер имел интересные трюки, на которых можно было затупить на пару минут.

1. Архитектура файла

Сам файл имеет x64 разрядность и накрыт VMProtect, однако она тут играет малую роль, из всего функционала там используется только антидебаг из юзермода и мутация кода. Импорты никак не защищены, будем иметь это в виду =)

2. Проверка на валидный пароль

Из моей последней статьи на BROKENCORE можно понять, что пароль в лоадере генерировался за счёт никнейма. В дебаггере в два регистра передавались две переменные: Пароль и ник, и после этого вызывалась функция с генерацией и проверки пароля, если функция возвращала 0, значит пароль был невалидным.

1631308826485.png


Код:
QWORD PTR SS:[RSP+140] - Пароль
QWORD PTR SS:[RSP+1B0] - Ник

CALL 00007FF746B52AF0 - Вызов генерации и проверки

На пароль сейчас не будем обращать внимание, ибо мы хотели сломать всю защиту =)

3. Архитектура защиты

В этой части я столкнулся с неприятными антидебаг трюками, которые я разделю на подпункты.

3.1. Антидебаг с помощью VEH

А эта проверка была написана исключительно для меня :D

В прошлых версиях лоадера я обходил всю защиту меняя адрес RIP на начало функции инжекта и деттачился, чтобы не наткнуться на антидебаг функцию во время инжекта. В этой версии кодер это зафиксил добавив переменные, которые будут меняться в других функциях, да бы я просто так не прошел уже меняя адрес, ну и что-то по типу PAGE_GUARD хуков но с другим назначением.
1631309037746.png


Суть в том чтобы вызвать PAGE_GUARD исключение и схватить его, в адресе на котором установлен VEH идет проверка на значение исключение, т.е. если исключение == 80000001 (PAGE_GUARD), то лоадер прекращает свою работу, все это выглядит так:
1631309073880.png


Если же джамп не произошел, то идет проверка уже на C0000005. Просто нопаем JNE проверку и антидебаг трик побежден :)

3.2. Хитрый трюк против ScyllaHide

Этот трюк выполняется уже во время вызова TLS Callback. Все мы знаем про хуки сциллыхайд и её проверки на параметры вызывающей функции. Тут трюк состоял в том чтобы патчить проверку у сциллыхайд на хук NtSetInformationThread, т.е. оригинальный хук проверял ThreadInformationClass на наличие 0x11 (ThreadHideFromDebugger) с помощью JNE, если они не были равны, то он просто скипал и шел дальше, но тут QHide просто меняет JNE на JMP и из-за этого хук сциллыхайд перестает работать и поток по итогу всё равно скрывается :) Довольно интересный трюк, который сразу и не заметишь, если не обратить внимание на вызов TLS Callback и завершающий код процесса (0x80000003).

До TLS каллбэка:
1631309120718.png


После TLS каллбэка:
1631309140433.png


Просто ставим RET в начало функции и этот трик побежден.

3.3. Поток с проверкой на анти-дебаг

По своей невнимательности на этот трюк я потратил больше всего времени, ибо не совсем понимал почему вызывался NtCreateThreadEx, а адреса в регистре не было :) Затем заметив функцию с которой стартовал поток я начал её листать и понял что это детект memory бряков. Этот трюк довольно распространенный и обходится он все также хуками от сциллыхайд.
1631309185757.png


Исходный код проверки:
1631309197861.png


3.4. Проверки на Breakpoints и на патч RET

В этом подпункте QHide сделал проверки на байты на важные функции, список байтов которые он проверял:

Код:
0xC3 - RET
0xCC - INT3 (Software Breakpoint)

Проверки на байты:
1631309297156.png


Уже ничего не мешало составить паттерны для нахождения других мест с проверками.
Паттерны:
Код:
3D C3 00 00 00 - cmp eax, 0xC3
3D CC 00 00 00 - cmp eax, 0xCC

Патчим все это дело и переходим к последнему подпункту.

3.5. Анти-дебаг трюки во время инжекта

В ранних версиях QHide никак не защищал дллку, а лишь просто держал её в репозитории гитхаба делая хттп реквест чтобы скачать. Теперь же в этой версии она сидит там уже зашифрованной, и в функции инжекта сидят антидебаг трюки, здесь уже было тяжело трассировать по той причине, что любой колл мог привести к антидебаг трюку и по итогу не загрузить длл полностью. Но тем не менее этот трюк переставал работать из-за хуков сциллыхайд. А именно лоадер вызывал NtQueryInformationProcess с параметром Debug Port (можно понять по 0x7 параметру)

1631309505305.png


Нопаем проверку и на этом отключение защиты подходит к концу.

Затем нопаем саму проверку авторизации и получаем нашу заветную длл, которая будет находится в регионе памяти лоадера с правами RWX :)

1631309531838.png


На этом у меня всё, возможно я упустил некоторые детали, но тем не менее защита отключена, дллка чистая у меня. Сама статья по содержанию кажется не очень длинной, но вот дебажить это чудо было затратно по времени. Спасибо кто решился почитать эту статью, мне и самому было весело это сидеть и патчить :D

Подписывайтесь на мой блог: https://t.me/colby5engineering

Всего хорошего!
 
Последнее редактирование:
Сверху Снизу