Когда x86 и Windows уже приелись, а уютный x64dbg больше не радует глаз, пора переходить к настоящему хардкору. ARM, QNX, эмулятор QEMU и старый добрый GDB — вот инструменты для тех, кто не ищет легких путей. Сегодня мы запустим экзотическую ОС, подключимся к ней через виртуальный адаптер и шаг за шагом разберем логику программы прямо на лету, без лишнего комфорта, но с изрядной долей азарта.
Ты, вероятно, уже заметил, что большинство моих статей посвящено разбору задач под Windows на процессорах семейства Intel. Это нехорошо, и я изо всех сил стараюсь разнообразить тематику исследованием экзотических виртуальных машин и процессоров.
Виртуалки, каюсь, мною охвачены в меньшей степени по весьма уважительной причине: задачи под них очень неудобно отлаживать в динамике и приходится ограничиваться статическим анализом. Однако при желании всегда можно найти выход, даже такой нестандартный, как использование различных эмуляторов. Ты, вероятно, помнишь мои статьи, посвященные эмуляторам SheepShaver для Mac OS или BlueStacks под Android. На этот раз я хочу обратить твое внимание на легендарный эмулятор QEMU, при помощи которого мы будем анализировать приложения, реализованные под ARM QNX.
До этого мы уже сталкивались и с ARM, но исследовали его исключительно в дизассемблере, сегодня у нас появилась счастливая возможность прощупать его в динамике, причем на PC и даже из‑под Windows.
Возьмем в качестве пациента некое устройство, функционирующее под операционной системой QNX на процессоре ARM. Из этических соображений не будем раскрывать название программы и подробности о специфике ее работы, также оставим за скобками процесс снятия дампа с этого приложения. Кроме того, я не буду отвлекаться на процесс установки QEMU и загрузки образа, об этом написано много статей.
По условию нашей задачи файловая система устройства уже загружена в QEMU и успешно там функционирует. В окончательной формулировке наша цель выглядит так: путем патча или кейгена добиться валидности активационного кода (на скриншоте выделено голубым) в активационной строке (выделено красным), которую скармливают программе при помощи специального активационного Lua-скрипта. На представленном ниже изображении результат проверки выделен желтым.
Начнем с подключения отладчика GDB. Об этом тоже написано много разных статей, но почему‑то все они как‑то стыдливо умалчивают о настройке сетевого подключения. У неподготовленного пользователя может сложиться ложное впечатление, что опции -s -S вполне достаточно, чтобы GDB увидел QEMU по 1234-му порту.
На самом деле это, конечно, не так, поэтому чуть подробнее остановлюсь на подключении отладчика через виртуальный сетевой адаптер. Лично у меня получилось подключить только так. На сайте QEMU описанный способ показан в отдельной статье, я же попробую своими словами на пальцах объяснить пошаговую последовательность действий, необходимых для его реализации, поскольку она не совсем очевидна.
Для начала нам требуется создать новое сетевое подключение с именем tap0 (Панель управления → Сеть и Интернет → Сетевые подключения).
Создать его тоже не так‑то просто: лично у меня это получилось только путем установки OpenVPN. Создав виртуальный адаптер, мы прописываем у него в настройках следующую информацию.
После этого добавляем в командную строку QEMU опцию -nic tap,ifname=tap0,id=hub0, и можно тестировать подключение отладчиков к эмулятору. Я понимаю, что ты уже привык к удобному уютному x64dbg и, самое смешное, что с его помощью тоже можно отлаживать приложения в эмуляторе, но мы, наверное, оставим такую странную экзотику для какой‑нибудь следующей статьи. В этот раз мы начнем с самого удобного способа отладки — при помощи уже хорошо известного нам дизассемблера IDA.
Для тебя, вероятно, уже не новость, что этот дизассемблер оснащен собственным отладчиком. Хотя, конечно, все универсальное хуже специального, и он сильно проигрывает в удобстве и надежности x64dbg. Но в данном случае это самое меньшее из всех зол.
Вообще‑то процесс подключения IDA к QEMU через GDB подробно и с цветными картинками описан на сайте Hex-Rays, однако я снова попробую изложить его своими словами, поскольку там тоже есть нюансы.
Итак, после описанной выше настройки QEMU и его запуска мы вводим в его консоль команду pdebug 1234. Затем открываем в IDA меню Debugger → Attach → Remote GDB debugger и переходим к окну настроек подключения, в которое (исходя из выбранных выше настроек) вводим следующую информацию.
Далее в окне GDB configuration (Debugger options → Set specific options) нужно обязательно указать тип процессора (в нашем случае это ARM Little-endian), иначе IDA, скорее всего, рухнет при аттаче.
Однако при попытке подключения IDA просит имя или PID запущенного в эмуляторе процесса, а нам он неизвестен, и список выбора пустой.
При попытке выбрать процесс 0 IDA успешно коннектится к эмулятору, и хотя бы это радует: значит, мы всё сделали правильно.
Попробуем все‑таки определить, какой именно процесс обрабатывает наш запрос. Для начала посмотрим список запущенных в QEMU процессов. К сожалению, в QNX нет привычной команды ps, зато есть pidin ar, которая выводит искомое.
По счастью, процессов обнаружилось немного. Разберемся, какой из них нам нужен. На самом первом скриншоте желтым цветом выделен результат проверки валидности. Вероятно, подстрока validState: присутствует в нужном нам модуле. Начиная проверку снизу списка, мы сразу обнаруживаем его поиском grep. Вытаскиваем этот модуль и загружаем в IDA — искомая строка действительно там есть.
По идее, на этом нашу задачу уже можно было бы считать решенной, ведь достаточно закоротить проверку
на безусловный переход:
Но мы попробуем доискаться до исходной проверки, ведь эта функция может оказаться лишь отладочной печатью статуса. По листингу видно, что валидность кода зависит от параметра a2, передаваемого в функцию: если он указывает на 0 — код валидный. Параметр a2 передается в sub_1183F8 через регистр R1, однако непросто понять, откуда он берется: прямых ссылок на sub_1183F8 нет.
Хороший повод проверить отладчик! Ставим точку останова (F2) на адрес 1183F8 и нажимаем Debugger → Attach to process. Если мы всё сделали правильно, то IDA успешно подключится к процессу, который будет отображаться синим цветом в зеленой полоске наверху окна.
Если что‑то пойдет не так и IDA будет ругаться при подключении, ссылаясь на права доступа и прочую ерунду, просто проверь правильность адресов и настроек в окне Debugger → Process options.
Жмем Debugger → Continue process (F9), и на экране появится окошко Running с единственной кнопочкой Suspend. После этого в консоли QEMU запускаем активационный скрипт — процесс притормозит на нашей точке останова. По стеку (окно внизу справа) определяем адрес возврата 4FD1D4.
Попробуем преобразовать это место в псевдокод.
Функция sub_1183F8 вызывается из sub_4FD0DC, ее второй параметр тут называется v12. По этому указателю присваивается значение a2, по совпадению являющееся вторым параметром sub_4FD0DC. Судя по сообщению двумя строками выше этого присваивания, a2 — это результат активации, что выглядит вполне логично: 0 — успешная активация, иначе возвращается номер ошибки (в нашем случае — 2). Поднявшись чуть выше по стеку возвратов, мы находим место вызова sub_4FD0DC.
Похоже, мы отыскали обработчик ошибок активации и правильную ветку кода, на которой активация проходит успешно (sub_4FD0DC(a1, 0)
. В дальнейшее мы не будем углубляться, поскольку осталась чисто техническая часть: или закоротить данную функцию сразу на исполнение корректной ветки, или (что более правильно) искать и реверсировать алгоритм верификации активационного кода, чтобы сделать кейген.
К теме нашей статьи это уже отношения не имеет, поэтому в заключение я лучше расскажу тебе, как проходить эту последовательность в том случае, если IDA по какой‑либо причине не увидит QEMU. К сожалению, такая возможность вполне неиллюзорна, и внятных объяснений в сети я не нашел, поэтому тебе всегда нужно быть готовым к настоящему хардкору — отладке при помощи голого отладчика GDB. Попробуем пошагово повторить описанный процесс.
Сразу предупреждаю, что этот путь сложен и тернист, трудности подстерегают уже в самом его начале — получить сам отладчик GDB под ARM и QNX. Это свободное открытое программное обеспечение, распространяющееся в исходниках (скачать можно здесь), однако самому собрать бинарник из лежащих там исходников — тот еще квест, для решения которого рамки этой статьи тесны.
Начальное направление можно получить, например, на Stack Overflow, а мы предполагаем, что у нас уже имеется скомпилированный бинарник этого отладчика под нашу версию процессора. В этом случае после описанных выше настроек эмулятора QEMU, его запуска и ввода в консоль команды pdebug 1234 запускаем GDB в другом окне и в нем набираем команду подключения:
Если мы ничего не напутали, в окне GDB появится следующее сообщение.
Теперь нам снова требуется подключиться к нужному процессу из отладчика GDB. На скриншоте 7 мы определили PID нужного процесса — 512024. Для подключения к нему в консоли GDB набираем команду
Не обращаем внимания на многочисленные сообщения об ошибках, GDB успешно подключился к процессу 512024 и, так же как и в IDA, остановился на промежуточной точке останова 1037878. Эмулятор в момент останова тоже замерзнет, а мы воспользуемся паузой, чтобы (как было проделано выше) поставить точку останова на адрес 1183F8. Позволю себе маленькое лирическое отступление про особенности отладчика GDB.
Как я уже говорил, процесс отладки приложения в отладчике GDB достаточно экзотичен. GDB, как ты уже понял, полностью лишен гуя и управляется исключительно командами из консоли. В этом он больше всего напоминает DOS’овский отладчик debug.com, в котором мне, как хакеру старой школы, в свое время приходилось много и кропотливо работать. С полным справочником команд GDB можно ознакомиться на sourceware.org или opennet.ru, в данный момент нас интересуют команды останова.
Даже бегло ознакомившись с опциями точек останова GDB, ты понимаешь, что, несмотря на крайнюю недружественность к пользователю, это очень гибкий инструмент, возможности которого не уступают условным точкам останова x64dbg, а кое‑где даже превосходят их. Здесь на каждую точку останова можно повесить весьма сложные скрипты, настраивающие выполнение программы в отладчике по воле и фантазии пользователя. А из них даже можно вызывать функции и блоки кода, реализованные в приложении, однако это тоже тема для отдельной статьи. Сейчас нам нужно простые точки останова на адресе 1183F8:
Вроде все просто и понятно, звездочка перед адресом означает, что следующая за ней строка 0x1183F8 — это именно шестнадцатеричный адрес, а не идентификатор из таблицы отладочных символов, которую мы не подключили к отладчику, потому что у нас ее попросту нет. Далее командой c (continue) мы размораживаем QEMU (отладчик при этом, наоборот, замирает в ожидании точки останова) и в консоли QEMU запускаем активационный скрипт.
Как видишь, по достижении адреса 1183F8 точка останова сработала, мы остановились на ней в GDB, а выполнение программы в QEMU снова замерло. Приостановив программу, мы можем делать свои дела: например, посмотреть код, на котором мы остановились. Чтобы показать пять дизассемблированных команд по адресу из регистра PC, набираем в GDB x/5i $pc и получаем такой листинг:
Нам нужен был стек возвратов? Набираем x/4x $sp, получаем четыре верхних значения на стеке:
Посмотреть значение нужного регистра можно командой print $r0. Сделать шаг вперед — командами stepi или nexti (не путать с командами step и next, которые у нас не будут работать из‑за отсутствия подгруженной таблицы символов). Если же надо продолжить работу, остановившись на адресе 118408, не устанавливая на нее дополнительную точку останова, пишем
Краткий дайджест особо часто используемых команд можно посмотреть на «Xабре». Как видишь, при определенной сноровке и усидчивости можно прекрасно обойтись и без подключения к отладке IDA. Напоследок приведу пару статей, в которых отладчик GDB используется для анализа других задач.
Автор @JaboHack
источник xakep.ru
Ты, вероятно, уже заметил, что большинство моих статей посвящено разбору задач под Windows на процессорах семейства Intel. Это нехорошо, и я изо всех сил стараюсь разнообразить тематику исследованием экзотических виртуальных машин и процессоров.
Виртуалки, каюсь, мною охвачены в меньшей степени по весьма уважительной причине: задачи под них очень неудобно отлаживать в динамике и приходится ограничиваться статическим анализом. Однако при желании всегда можно найти выход, даже такой нестандартный, как использование различных эмуляторов. Ты, вероятно, помнишь мои статьи, посвященные эмуляторам SheepShaver для Mac OS или BlueStacks под Android. На этот раз я хочу обратить твое внимание на легендарный эмулятор QEMU, при помощи которого мы будем анализировать приложения, реализованные под ARM QNX.
До этого мы уже сталкивались и с ARM, но исследовали его исключительно в дизассемблере, сегодня у нас появилась счастливая возможность прощупать его в динамике, причем на PC и даже из‑под Windows.
Возьмем в качестве пациента некое устройство, функционирующее под операционной системой QNX на процессоре ARM. Из этических соображений не будем раскрывать название программы и подробности о специфике ее работы, также оставим за скобками процесс снятия дампа с этого приложения. Кроме того, я не буду отвлекаться на процесс установки QEMU и загрузки образа, об этом написано много статей.
По условию нашей задачи файловая система устройства уже загружена в QEMU и успешно там функционирует. В окончательной формулировке наша цель выглядит так: путем патча или кейгена добиться валидности активационного кода (на скриншоте выделено голубым) в активационной строке (выделено красным), которую скармливают программе при помощи специального активационного Lua-скрипта. На представленном ниже изображении результат проверки выделен желтым.
Начнем с подключения отладчика GDB. Об этом тоже написано много разных статей, но почему‑то все они как‑то стыдливо умалчивают о настройке сетевого подключения. У неподготовленного пользователя может сложиться ложное впечатление, что опции -s -S вполне достаточно, чтобы GDB увидел QEMU по 1234-му порту.
На самом деле это, конечно, не так, поэтому чуть подробнее остановлюсь на подключении отладчика через виртуальный сетевой адаптер. Лично у меня получилось подключить только так. На сайте QEMU описанный способ показан в отдельной статье, я же попробую своими словами на пальцах объяснить пошаговую последовательность действий, необходимых для его реализации, поскольку она не совсем очевидна.
Для начала нам требуется создать новое сетевое подключение с именем tap0 (Панель управления → Сеть и Интернет → Сетевые подключения).
Создать его тоже не так‑то просто: лично у меня это получилось только путем установки OpenVPN. Создав виртуальный адаптер, мы прописываем у него в настройках следующую информацию.
После этого добавляем в командную строку QEMU опцию -nic tap,ifname=tap0,id=hub0, и можно тестировать подключение отладчиков к эмулятору. Я понимаю, что ты уже привык к удобному уютному x64dbg и, самое смешное, что с его помощью тоже можно отлаживать приложения в эмуляторе, но мы, наверное, оставим такую странную экзотику для какой‑нибудь следующей статьи. В этот раз мы начнем с самого удобного способа отладки — при помощи уже хорошо известного нам дизассемблера IDA.
Для тебя, вероятно, уже не новость, что этот дизассемблер оснащен собственным отладчиком. Хотя, конечно, все универсальное хуже специального, и он сильно проигрывает в удобстве и надежности x64dbg. Но в данном случае это самое меньшее из всех зол.
Вообще‑то процесс подключения IDA к QEMU через GDB подробно и с цветными картинками описан на сайте Hex-Rays, однако я снова попробую изложить его своими словами, поскольку там тоже есть нюансы.
Итак, после описанной выше настройки QEMU и его запуска мы вводим в его консоль команду pdebug 1234. Затем открываем в IDA меню Debugger → Attach → Remote GDB debugger и переходим к окну настроек подключения, в которое (исходя из выбранных выше настроек) вводим следующую информацию.
Далее в окне GDB configuration (Debugger options → Set specific options) нужно обязательно указать тип процессора (в нашем случае это ARM Little-endian), иначе IDA, скорее всего, рухнет при аттаче.
Однако при попытке подключения IDA просит имя или PID запущенного в эмуляторе процесса, а нам он неизвестен, и список выбора пустой.
При попытке выбрать процесс 0 IDA успешно коннектится к эмулятору, и хотя бы это радует: значит, мы всё сделали правильно.
Попробуем все‑таки определить, какой именно процесс обрабатывает наш запрос. Для начала посмотрим список запущенных в QEMU процессов. К сожалению, в QNX нет привычной команды ps, зато есть pidin ar, которая выводит искомое.
По счастью, процессов обнаружилось немного. Разберемся, какой из них нам нужен. На самом первом скриншоте желтым цветом выделен результат проверки валидности. Вероятно, подстрока validState: присутствует в нужном нам модуле. Начиная проверку снизу списка, мы сразу обнаруживаем его поиском grep. Вытаскиваем этот модуль и загружаем в IDA — искомая строка действительно там есть.
По идее, на этом нашу задачу уже можно было бы считать решенной, ведь достаточно закоротить проверку
Код:
if ( *a2 )
Код:
v3 = 1;
Хороший повод проверить отладчик! Ставим точку останова (F2) на адрес 1183F8 и нажимаем Debugger → Attach to process. Если мы всё сделали правильно, то IDA успешно подключится к процессу, который будет отображаться синим цветом в зеленой полоске наверху окна.
Если что‑то пойдет не так и IDA будет ругаться при подключении, ссылаясь на права доступа и прочую ерунду, просто проверь правильность адресов и настроек в окне Debugger → Process options.
Жмем Debugger → Continue process (F9), и на экране появится окошко Running с единственной кнопочкой Suspend. После этого в консоли QEMU запускаем активационный скрипт — процесс притормозит на нашей точке останова. По стеку (окно внизу справа) определяем адрес возврата 4FD1D4.
Попробуем преобразовать это место в псевдокод.
Функция sub_1183F8 вызывается из sub_4FD0DC, ее второй параметр тут называется v12. По этому указателю присваивается значение a2, по совпадению являющееся вторым параметром sub_4FD0DC. Судя по сообщению двумя строками выше этого присваивания, a2 — это результат активации, что выглядит вполне логично: 0 — успешная активация, иначе возвращается номер ошибки (в нашем случае — 2). Поднявшись чуть выше по стеку возвратов, мы находим место вызова sub_4FD0DC.
Похоже, мы отыскали обработчик ошибок активации и правильную ветку кода, на которой активация проходит успешно (sub_4FD0DC(a1, 0)
К теме нашей статьи это уже отношения не имеет, поэтому в заключение я лучше расскажу тебе, как проходить эту последовательность в том случае, если IDA по какой‑либо причине не увидит QEMU. К сожалению, такая возможность вполне неиллюзорна, и внятных объяснений в сети я не нашел, поэтому тебе всегда нужно быть готовым к настоящему хардкору — отладке при помощи голого отладчика GDB. Попробуем пошагово повторить описанный процесс.
Сразу предупреждаю, что этот путь сложен и тернист, трудности подстерегают уже в самом его начале — получить сам отладчик GDB под ARM и QNX. Это свободное открытое программное обеспечение, распространяющееся в исходниках (скачать можно здесь), однако самому собрать бинарник из лежащих там исходников — тот еще квест, для решения которого рамки этой статьи тесны.
Начальное направление можно получить, например, на Stack Overflow, а мы предполагаем, что у нас уже имеется скомпилированный бинарник этого отладчика под нашу версию процессора. В этом случае после описанных выше настроек эмулятора QEMU, его запуска и ввода в консоль команды pdebug 1234 запускаем GDB в другом окне и в нем набираем команду подключения:
Код:
target qnx 192.168.1.200:1234
Теперь нам снова требуется подключиться к нужному процессу из отладчика GDB. На скриншоте 7 мы определили PID нужного процесса — 512024. Для подключения к нему в консоли GDB набираем команду
Код:
attach 512024
Не обращаем внимания на многочисленные сообщения об ошибках, GDB успешно подключился к процессу 512024 и, так же как и в IDA, остановился на промежуточной точке останова 1037878. Эмулятор в момент останова тоже замерзнет, а мы воспользуемся паузой, чтобы (как было проделано выше) поставить точку останова на адрес 1183F8. Позволю себе маленькое лирическое отступление про особенности отладчика GDB.
Как я уже говорил, процесс отладки приложения в отладчике GDB достаточно экзотичен. GDB, как ты уже понял, полностью лишен гуя и управляется исключительно командами из консоли. В этом он больше всего напоминает DOS’овский отладчик debug.com, в котором мне, как хакеру старой школы, в свое время приходилось много и кропотливо работать. С полным справочником команд GDB можно ознакомиться на sourceware.org или opennet.ru, в данный момент нас интересуют команды останова.
Даже бегло ознакомившись с опциями точек останова GDB, ты понимаешь, что, несмотря на крайнюю недружественность к пользователю, это очень гибкий инструмент, возможности которого не уступают условным точкам останова x64dbg, а кое‑где даже превосходят их. Здесь на каждую точку останова можно повесить весьма сложные скрипты, настраивающие выполнение программы в отладчике по воле и фантазии пользователя. А из них даже можно вызывать функции и блоки кода, реализованные в приложении, однако это тоже тема для отдельной статьи. Сейчас нам нужно простые точки останова на адресе 1183F8:
Код:
b *0x1183F8
Как видишь, по достижении адреса 1183F8 точка останова сработала, мы остановились на ней в GDB, а выполнение программы в QEMU снова замерло. Приостановив программу, мы можем делать свои дела: например, посмотреть код, на котором мы остановились. Чтобы показать пять дизассемблированных команд по адресу из регистра PC, набираем в GDB x/5i $pc и получаем такой листинг:
Код:
(gdb) x/5i $pc
0x1183f8: push {r4, r5, r6, r7, r8, r10, r11, lr}
0x1183fc: add r11, sp, #28 ; 0x1c
0x118400: sub sp, sp, #64 ; 0x40
0x118404: ldr r3, [pc, #324] ; 0x118550
0x118408: mov r4, r0
(gdb)
Код:
0xfffb18: 0x00fffb5c 0x004fd1d4 0x006c382c 0x005777b8
Код:
u *0x118408
- Пошаговая GDB-отладка ARM-процессора из консоли в Win10
- Хардкорный олдскул: QEMU и реверс образа флоппика
Автор @JaboHack
источник xakep.ru