Murasaki
-
Автор темы
- #1
Новогодний шалом.
Предисловие
Сегодня я хотел бы поведать о трюках, которые я встретил в лоадере AIMWARE. На этот отчаянный шаг меня сподвинуло то, что особо материал я и не готовил, но что-то выпускать до начала следующего года надо было. Затем я вспомнил, что многоуважаемый Rolzzandik (земля пухом человеку) кидал мне давным-давно лоадер. Мне никак не хотелось уже реверсить всячески лоадеры, но деваться уже некуда было.
Из-за того, что осталось мало времени, то я решил разделить разбор аимвара на две части, вторая соотвественно выйдет в январе.
Эта статья не будет столь длинной, я лишь опишу в ней некоторые трюки которые успел найти за пару часов ленивой отладки.
Лоадер
Так как наш лоадер на х32 и оснащен супер-технологиями VMProtect, то придется писать свой интернал патчер (экстернал не получится, так как при попытке запретить рандомизацию адресного пространства лоадер уходит в краш)
Удивительно, но факт, что сам протектор не выставлен на фулл-пресет, того же антидебага с чеками всяких PEB структур и NtAPI функции нет, системных вызовов тем более.
По поводу детекта виртуальной машины я не вкурсе, возможно её тоже нет, но вот виртуализация и мутация присутствует.
Проверки на время / Проверка на бряки
После того, как я победил трюк (который я опишу следующим) я столкнулся с неприятным казусом в виде чека на время. Он инициализируется в отдельном потоке с помощью NtCreateThreadEx на стадии рисовки своего окна, его суть заключается в том что он вначале вызывает GetTickCount64(), затем в бесконечном цикле будет постоянно замораживать поток и вычислять tick_start && tick_end.
Если после операции вычисления tick_start - tick_end результат будет меньше чем 600000 (не забываем, что дело имеем с миллисекундами), т.е. таймаутом для лоадера считается1 минута, после чего происходит вызов ExitProcess.
Есть много способов победить этот трюк, начиная от хука GetTickCount64, патчей в ручную, заканчивая патчем RET на начало функции. Но пока что я обхожусь лишь простым скипом самого создания потока без байт-патчинга.
Системные вызовы / Защита памяти
Ну что ж, переходим к моей любимой части, к системным вызовам. Начнём с того, что из себя представляют антидебаг методы в этом лоадере.
Шелл-код для защиты памяти
Казалось бы, вы видите такой колл и ваш SharpOD должен давать люлей такому трюку. Так-то оно так, но вот при срабатывании бряка приложение крашнулось и я понял, шо меня конкретно наебали с вызовом
Дело в том, что SharpOD действительно обходит прямой вызов, но когда ему попадается системный вызов тут уже беда...
Ну и вот, пока я дебажил я нашел целый остров пасхи, ведь тут была проверка на разрядность системы (могу ошибаться), в зависимости от одного байта вас могло отправить или на x32 системный вызов или же к x64 коду. В моём случае меня джампило на x64 код, который имеет такой вид:
Начало кода:
Конец кода:
Как быть? Шо делать? Мой комраде Arting уже разбирал крякми, у которого весь алгоритм уходил в х64 код, там он в приложении, которое имело х64 разрядность выделял память и вставлял байткод, тем самым спокойно трассируя.
Можете попросить у него ссылку на тему лично, но я пожалуй не буду упоминать другой форум :) В отличии от крякми Артинга у нас совсем иная ситуация. И такс, шо мы имеем:
Системный номер для вызова - 0xD: NtSetInformationThread
Один из параметров имеет вид: 0x11: ThreadHideFromDebugger
И самый первый параметр: 0xFFFFFFFFE, т.е. -2, т.е. под -2 подразмуевается нынешний поток, из которого идет вызов.
Суммируя все эти факторы мы получаем шелл-код с защитой памяти, по итогу у нас скрыт поток и при попытки бряков триггернуться мы получаем краш приложения.
Про х32 сисколл думаю нет смысла расписывать, он просто имеет такой вид:
Единственное скажу, что на удивление тут не используется вызов к Wow64Transition, но я уже говорил, что можно пользоваться и прямым sysenter и Wow64Transition.
Логика в том, что вначале идет прямой вызов NtAPI функции, если отладчик не обнаружен, то лоадер переходит к оружию из шеллкодов и системных вызовов. Как раз в эту ситуацию я и попал, SharpOD дернул простой вызов, но потом его вздернул сисколл.
Шелл-код с проверкой ProcessDebugPort
Вот ещё пример такого вызова на примере NtQueryInformationProcess, где проверяется ProcessDebugPort (параметр 0x7). Вначале вызываем напрямую
И затем шеллкодом вызываем системный вызов 0x19
По паттерну 80 3D 24 1F 68 00 00 я нашел 8 мест, где используются системные вызовы, можно расставить бряки и выявлять потенциального недоброжелателя и сверяя системный номер выдавать RET, что я кстати и сделал с трюком защиты памяти, поэтому в дальнейшем
все бряки у меня работали спокойно, однако будьте осторожны, потому что некоторым всё таки не стоит ставить RET, ибо это триггерит SEH аимвара.
Драйвер и удаление лоадера аимвара
Вот и перешли к последнему этапу первой части разбора защиты. После того, как я закрыл лоадер, то он магическим образом исчез у меня в папке. Я долго не мог понять в чём заключается загвоздка, ведь все импорты которые я знал и которые связанны с файлами не брякались вообще.
До той поры, пока я не пошел снова мониторить сисколлы, тогда мне попался товарищ NtLoadDriver.
Шо он тут забыл, казалось бы? Всё это время драйвер лежал у меня перед носом вместе с папкой где и находится экзешник аимвара, но на него внимания я никакого не обращал, потому что у него постоянно было 0 КБ.
Это был файлик с рандомным названием и абсолютно пустой по размерам. Но как только я начал мониторить NtUnloadDriver (тоже вызывается), то я обратил внимание на вес этого файла.
На этот раз он уже весил 768 кб, да и в реестре сам сервис указывал путь именно к этому файлу, чекаем первые два байта и видим: 4D 5A, понимаем шо это файлик PE формата
И по всей видимости именно он удалял мой лоадер. Представьте себе, вы наставили кучу меток и комментариев, закрываете приложуху и уходите куда-то там чиллить попивая чаек, а в это время драйвер аимвара удаляет его полностью.
Вообще, я думаю, что драйвер в дальнейшем сыграет большую роль в работе аимвара, пока без подписки я сказать точно ничего не могу.
Да и реверсить драйвера это пока дело не моё, особенно смотря на этот беспредел
Думаю, теперь понятно :D
Бонус:
Ссылка на драйвер:
Предисловие
Сегодня я хотел бы поведать о трюках, которые я встретил в лоадере AIMWARE. На этот отчаянный шаг меня сподвинуло то, что особо материал я и не готовил, но что-то выпускать до начала следующего года надо было. Затем я вспомнил, что многоуважаемый Rolzzandik (земля пухом человеку) кидал мне давным-давно лоадер. Мне никак не хотелось уже реверсить всячески лоадеры, но деваться уже некуда было.
Из-за того, что осталось мало времени, то я решил разделить разбор аимвара на две части, вторая соотвественно выйдет в январе.
Эта статья не будет столь длинной, я лишь опишу в ней некоторые трюки которые успел найти за пару часов ленивой отладки.
Лоадер
Так как наш лоадер на х32 и оснащен супер-технологиями VMProtect, то придется писать свой интернал патчер (экстернал не получится, так как при попытке запретить рандомизацию адресного пространства лоадер уходит в краш)
Удивительно, но факт, что сам протектор не выставлен на фулл-пресет, того же антидебага с чеками всяких PEB структур и NtAPI функции нет, системных вызовов тем более.
По поводу детекта виртуальной машины я не вкурсе, возможно её тоже нет, но вот виртуализация и мутация присутствует.
Проверки на время / Проверка на бряки
После того, как я победил трюк (который я опишу следующим) я столкнулся с неприятным казусом в виде чека на время. Он инициализируется в отдельном потоке с помощью NtCreateThreadEx на стадии рисовки своего окна, его суть заключается в том что он вначале вызывает GetTickCount64(), затем в бесконечном цикле будет постоянно замораживать поток и вычислять tick_start && tick_end.
Если после операции вычисления tick_start - tick_end результат будет меньше чем 600000 (не забываем, что дело имеем с миллисекундами), т.е. таймаутом для лоадера считается
Есть много способов победить этот трюк, начиная от хука GetTickCount64, патчей в ручную, заканчивая патчем RET на начало функции. Но пока что я обхожусь лишь простым скипом самого создания потока без байт-патчинга.
Системные вызовы / Защита памяти
Ну что ж, переходим к моей любимой части, к системным вызовам. Начнём с того, что из себя представляют антидебаг методы в этом лоадере.
Шелл-код для защиты памяти
Казалось бы, вы видите такой колл и ваш SharpOD должен давать люлей такому трюку. Так-то оно так, но вот при срабатывании бряка приложение крашнулось и я понял, шо меня конкретно наебали с вызовом
Дело в том, что SharpOD действительно обходит прямой вызов, но когда ему попадается системный вызов тут уже беда...
Ну и вот, пока я дебажил я нашел целый остров пасхи, ведь тут была проверка на разрядность системы (могу ошибаться), в зависимости от одного байта вас могло отправить или на x32 системный вызов или же к x64 коду. В моём случае меня джампило на x64 код, который имеет такой вид:
Начало кода:
Конец кода:
Как быть? Шо делать? Мой комраде Arting уже разбирал крякми, у которого весь алгоритм уходил в х64 код, там он в приложении, которое имело х64 разрядность выделял память и вставлял байткод, тем самым спокойно трассируя.
Можете попросить у него ссылку на тему лично, но я пожалуй не буду упоминать другой форум :) В отличии от крякми Артинга у нас совсем иная ситуация. И такс, шо мы имеем:
Системный номер для вызова - 0xD: NtSetInformationThread
Один из параметров имеет вид: 0x11: ThreadHideFromDebugger
И самый первый параметр: 0xFFFFFFFFE, т.е. -2, т.е. под -2 подразмуевается нынешний поток, из которого идет вызов.
Суммируя все эти факторы мы получаем шелл-код с защитой памяти, по итогу у нас скрыт поток и при попытки бряков триггернуться мы получаем краш приложения.
Про х32 сисколл думаю нет смысла расписывать, он просто имеет такой вид:
Код:
mov edx, esp
sysenter
ret
Логика в том, что вначале идет прямой вызов NtAPI функции, если отладчик не обнаружен, то лоадер переходит к оружию из шеллкодов и системных вызовов. Как раз в эту ситуацию я и попал, SharpOD дернул простой вызов, но потом его вздернул сисколл.
Шелл-код с проверкой ProcessDebugPort
Вот ещё пример такого вызова на примере NtQueryInformationProcess, где проверяется ProcessDebugPort (параметр 0x7). Вначале вызываем напрямую
И затем шеллкодом вызываем системный вызов 0x19
По паттерну 80 3D 24 1F 68 00 00 я нашел 8 мест, где используются системные вызовы, можно расставить бряки и выявлять потенциального недоброжелателя и сверяя системный номер выдавать RET, что я кстати и сделал с трюком защиты памяти, поэтому в дальнейшем
все бряки у меня работали спокойно, однако будьте осторожны, потому что некоторым всё таки не стоит ставить RET, ибо это триггерит SEH аимвара.
Драйвер и удаление лоадера аимвара
Вот и перешли к последнему этапу первой части разбора защиты. После того, как я закрыл лоадер, то он магическим образом исчез у меня в папке. Я долго не мог понять в чём заключается загвоздка, ведь все импорты которые я знал и которые связанны с файлами не брякались вообще.
До той поры, пока я не пошел снова мониторить сисколлы, тогда мне попался товарищ NtLoadDriver.
Шо он тут забыл, казалось бы? Всё это время драйвер лежал у меня перед носом вместе с папкой где и находится экзешник аимвара, но на него внимания я никакого не обращал, потому что у него постоянно было 0 КБ.
Это был файлик с рандомным названием и абсолютно пустой по размерам. Но как только я начал мониторить NtUnloadDriver (тоже вызывается), то я обратил внимание на вес этого файла.
На этот раз он уже весил 768 кб, да и в реестре сам сервис указывал путь именно к этому файлу, чекаем первые два байта и видим: 4D 5A, понимаем шо это файлик PE формата
И по всей видимости именно он удалял мой лоадер. Представьте себе, вы наставили кучу меток и комментариев, закрываете приложуху и уходите куда-то там чиллить попивая чаек, а в это время драйвер аимвара удаляет его полностью.
Вообще, я думаю, что драйвер в дальнейшем сыграет большую роль в работе аимвара, пока без подписки я сказать точно ничего не могу.
Да и реверсить драйвера это пока дело не моё, особенно смотря на этот беспредел
Думаю, теперь понятно :D
Бонус:
Ссылка на драйвер:
Пожалуйста, авторизуйтесь для просмотра ссылки.
В целом это всё, что я хотел описать в первой части. По началу у меня были некие сомнения по поводу аимвара, я думал, что не встречу уже подобных трюков, которые творил nelfo57 в своём крякми, но в целом я остался доволен.
Спасибо моей команде, шо иногда давали подсказки мне в затруднительных местах :D (easton гей №1 в СНГ, Dark_Bull, nelfo57, Arting)
Подписывайтесь на блог моей команды:
Всех с наступающим новым годом! Пока!
Team Enterial <3
Спасибо моей команде, шо иногда давали подсказки мне в затруднительных местах :D (easton гей №1 в СНГ, Dark_Bull, nelfo57, Arting)
Подписывайтесь на блог моей команды:
Пожалуйста, авторизуйтесь для просмотра ссылки.
Всех с наступающим новым годом! Пока!
Team Enterial <3
Последнее редактирование: