stihl не предоставил(а) никакой дополнительной информации.
Когда x86 и Windows уже приелись, а уютный x64dbg больше не радует глаз, пора переходить к настоящему хардкору. ARM, QNX, эмулятор QEMU и старый добрый GDB — вот инструменты для тех, кто не ищет легких путей. Сегодня мы запустим экзотическую ОС, подключимся к ней через виртуальный адаптер и шаг за шагом разберем логику программы прямо на лету, без лишнего комфорта, но с изрядной долей азарта.
Ты, вероятно, уже заметил, что большинство моих статей посвящено разбору задач под Windows на процессорах семейства Intel. Это нехорошо, и я изо всех сил стараюсь разнообразить тематику исследованием экзотических виртуальных машин и процессоров.
Виртуалки, каюсь, мною охвачены в меньшей степени по весьма уважительной причине: задачи под них очень неудобно отлаживать в динамике и приходится ограничиваться статическим анализом. Однако при желании всегда можно найти выход, даже такой нестандартный, как использование различных эмуляторов. Ты, вероятно, помнишь мои статьи, посвященные эмуляторам Для просмотра ссылки Войдиили Зарегистрируйся или Для просмотра ссылки Войди или Зарегистрируйся. На этот раз я хочу обратить твое внимание на легендарный Для просмотра ссылки Войди или Зарегистрируйся, при помощи которого мы будем анализировать приложения, реализованные под ARM QNX.
До этого мы уже Для просмотра ссылки Войдиили Зарегистрируйся, но исследовали его исключительно в дизассемблере, сегодня у нас появилась счастливая возможность прощупать его в динамике, причем на PC и даже из‑под Windows.
Возьмем в качестве пациента некое устройство, функционирующее под операционной системой QNX на процессоре ARM. Из этических соображений не будем раскрывать название программы и подробности о специфике ее работы, также оставим за скобками процесс снятия дампа с этого приложения. Кроме того, я не буду отвлекаться на процесс установки QEMU и загрузки образа, об этом написано Для просмотра ссылки Войдиили Зарегистрируйся.
По условию нашей задачи файловая система устройства уже загружена в QEMU и успешно там функционирует. В окончательной формулировке наша цель выглядит так: путем патча или кейгена добиться валидности активационного кода (на скриншоте выделено голубым) в активационной строке (выделено красным), которую скармливают программе при помощи специального активационного Lua-скрипта. На представленном ниже изображении результат проверки выделен желтым.
Для просмотра ссылки Войдиили Зарегистрируйся
Начнем с подключения отладчика GDB. Об этом тоже написано Для просмотра ссылки Войдиили Зарегистрируйся Для просмотра ссылки Войди или Зарегистрируйся статей, но почему‑то все они как‑то стыдливо умалчивают о настройке сетевого подключения. У неподготовленного пользователя может сложиться ложное впечатление, что опции -s -S вполне достаточно, чтобы GDB увидел QEMU по 1234-му порту.
На самом деле это, конечно, не так, поэтому чуть подробнее остановлюсь на подключении отладчика через виртуальный сетевой адаптер. Лично у меня получилось подключить только так. На сайте QEMU описанный способ показан Для просмотра ссылки Войдиили Зарегистрируйся, я же попробую своими словами на пальцах объяснить пошаговую последовательность действий, необходимых для его реализации, поскольку она не совсем очевидна.
Для начала нам требуется создать новое сетевое подключение с именем tap0 (Панель управления → Сеть и Интернет → Сетевые подключения).
Для просмотра ссылки Войдиили Зарегистрируйся
Создать его тоже не так‑то просто: лично у меня это получилось только путем установки Для просмотра ссылки Войдиили Зарегистрируйся. Создав виртуальный адаптер, мы прописываем у него в настройках следующую информацию.
Для просмотра ссылки Войдиили Зарегистрируйся
После этого добавляем в командную строку QEMU опцию -nic tap,ifname=tap0,id=hub0, и можно тестировать подключение отладчиков к эмулятору. Я понимаю, что ты уже привык к удобному уютному x64dbg и, самое смешное, что с его помощью тоже можно отлаживать приложения в эмуляторе, но мы, наверное, оставим такую странную экзотику для какой‑нибудь следующей статьи. В этот раз мы начнем с самого удобного способа отладки — при помощи уже хорошо известного нам дизассемблера IDA.
Для тебя, вероятно, уже не новость, что этот дизассемблер оснащен собственным отладчиком. Хотя, конечно, все универсальное хуже специального, и он сильно проигрывает в удобстве и надежности x64dbg. Но в данном случае это самое меньшее из всех зол.
Вообще‑то процесс подключения IDA к QEMU через GDB подробно и с цветными картинками описан на сайте Для просмотра ссылки Войдиили Зарегистрируйся, однако я снова попробую изложить его своими словами, поскольку там тоже есть нюансы.
Итак, после описанной выше настройки 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, которая выводит искомое.
Скриншот 7
По счастью, процессов обнаружилось немного. Разберемся, какой из них нам нужен. На самом первом скриншоте желтым цветом выделен результат проверки валидности. Вероятно, подстрока 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. Это свободное открытое программное обеспечение, распространяющееся в исходниках (скачать можно Для просмотра ссылки Войдиили Зарегистрируйся), однако самому собрать бинарник из лежащих там исходников — тот еще квест, для решения которого рамки этой статьи тесны.
Начальное направление можно получить, например, Для просмотра ссылки Войдиили Зарегистрируйся, а мы предполагаем, что у нас уже имеется скомпилированный бинарник этого отладчика под нашу версию процессора. В этом случае после описанных выше настроек эмулятора QEMU, его запуска и ввода в консоль команды pdebug 1234 запускаем GDB в другом окне и в нем набираем команду подключения:
Если мы ничего не напутали, в окне GDB появится следующее сообщение.
Для просмотра ссылки Войдиили Зарегистрируйся
Теперь нам снова требуется подключиться к нужному процессу из отладчика GDB. На скриншоте 7 мы определили PID нужного процесса — 512024. Для подключения к нему в консоли GDB набираем команду
Для просмотра ссылки Войдиили Зарегистрируйся
Не обращаем внимания на многочисленные сообщения об ошибках, GDB успешно подключился к процессу 512024 и, так же как и в IDA, остановился на промежуточной точке останова 1037878. Эмулятор в момент останова тоже замерзнет, а мы воспользуемся паузой, чтобы (как было проделано выше) поставить точку останова на адрес 1183F8. Позволю себе маленькое лирическое отступление про особенности отладчика GDB.
Как я уже говорил, процесс отладки приложения в отладчике GDB достаточно экзотичен. GDB, как ты уже понял, полностью лишен гуя и управляется исключительно командами из консоли. В этом он больше всего напоминает DOS’овский отладчик debug.com, в котором мне, как хакеру старой школы, в свое время приходилось много и кропотливо работать. С полным справочником команд GDB можно ознакомиться на Для просмотра ссылки Войдиили Зарегистрируйся или Для просмотра ссылки Войди или Зарегистрируйся, в данный момент нас интересуют Для просмотра ссылки Войди или Зарегистрируйся.
Даже бегло ознакомившись с опциями точек останова GDB, ты понимаешь, что, несмотря на крайнюю недружественность к пользователю, это очень гибкий инструмент, возможности которого не уступают условным точкам останова x64dbg, а кое‑где даже превосходят их. Здесь на каждую точку останова можно повесить весьма сложные скрипты, настраивающие выполнение программы в отладчике по воле и фантазии пользователя. А из них даже можно вызывать функции и блоки кода, реализованные в приложении, однако это тоже тема для отдельной статьи. Сейчас нам нужно простые точки останова на адресе 1183F8:
b *0x1183F8
Вроде все просто и понятно, звездочка перед адресом означает, что следующая за ней строка 0x1183F8 — это именно шестнадцатеричный адрес, а не идентификатор из таблицы отладочных символов, которую мы не подключили к отладчику, потому что у нас ее попросту нет. Далее командой c (continue) мы размораживаем QEMU (отладчик при этом, наоборот, замирает в ожидании точки останова) и в консоли QEMU запускаем активационный скрипт.
Для просмотра ссылки Войдиили Зарегистрируйся
Как видишь, по достижении адреса 1183F8 точка останова сработала, мы остановились на ней в GDB, а выполнение программы в QEMU снова замерло. Приостановив программу, мы можем делать свои дела: например, посмотреть код, на котором мы остановились. Чтобы показать пять дизассемблированных команд по адресу из регистра PC, набираем в GDB x/5i $pc и получаем такой листинг:
Нам нужен был стек возвратов? Набираем x/4x $sp, получаем четыре верхних значения на стеке:
Посмотреть значение нужного регистра можно командой print $r0. Сделать шаг вперед — командами stepi или nexti (не путать с командами step и next, которые у нас не будут работать из‑за отсутствия подгруженной таблицы символов). Если же надо продолжить работу, остановившись на адресе 118408, не устанавливая на нее дополнительную точку останова, пишем
Краткий дайджест особо часто используемых команд можно Для просмотра ссылки Войдиили Зарегистрируйся. Как видишь, при определенной сноровке и усидчивости можно прекрасно обойтись и без подключения к отладке IDA. Напоследок приведу пару статей, в которых отладчик GDB используется для анализа других задач.
Ты, вероятно, уже заметил, что большинство моих статей посвящено разбору задач под Windows на процессорах семейства Intel. Это нехорошо, и я изо всех сил стараюсь разнообразить тематику исследованием экзотических виртуальных машин и процессоров.
Виртуалки, каюсь, мною охвачены в меньшей степени по весьма уважительной причине: задачи под них очень неудобно отлаживать в динамике и приходится ограничиваться статическим анализом. Однако при желании всегда можно найти выход, даже такой нестандартный, как использование различных эмуляторов. Ты, вероятно, помнишь мои статьи, посвященные эмуляторам Для просмотра ссылки Войди
До этого мы уже Для просмотра ссылки Войди
Возьмем в качестве пациента некое устройство, функционирующее под операционной системой QNX на процессоре ARM. Из этических соображений не будем раскрывать название программы и подробности о специфике ее работы, также оставим за скобками процесс снятия дампа с этого приложения. Кроме того, я не буду отвлекаться на процесс установки QEMU и загрузки образа, об этом написано Для просмотра ссылки Войди
По условию нашей задачи файловая система устройства уже загружена в QEMU и успешно там функционирует. В окончательной формулировке наша цель выглядит так: путем патча или кейгена добиться валидности активационного кода (на скриншоте выделено голубым) в активационной строке (выделено красным), которую скармливают программе при помощи специального активационного Lua-скрипта. На представленном ниже изображении результат проверки выделен желтым.
Для просмотра ссылки Войди
Начнем с подключения отладчика GDB. Об этом тоже написано Для просмотра ссылки Войди
На самом деле это, конечно, не так, поэтому чуть подробнее остановлюсь на подключении отладчика через виртуальный сетевой адаптер. Лично у меня получилось подключить только так. На сайте QEMU описанный способ показан Для просмотра ссылки Войди
Для начала нам требуется создать новое сетевое подключение с именем tap0 (Панель управления → Сеть и Интернет → Сетевые подключения).
Для просмотра ссылки Войди
Создать его тоже не так‑то просто: лично у меня это получилось только путем установки Для просмотра ссылки Войди
Для просмотра ссылки Войди
После этого добавляем в командную строку QEMU опцию -nic tap,ifname=tap0,id=hub0, и можно тестировать подключение отладчиков к эмулятору. Я понимаю, что ты уже привык к удобному уютному x64dbg и, самое смешное, что с его помощью тоже можно отлаживать приложения в эмуляторе, но мы, наверное, оставим такую странную экзотику для какой‑нибудь следующей статьи. В этот раз мы начнем с самого удобного способа отладки — при помощи уже хорошо известного нам дизассемблера IDA.
Для тебя, вероятно, уже не новость, что этот дизассемблер оснащен собственным отладчиком. Хотя, конечно, все универсальное хуже специального, и он сильно проигрывает в удобстве и надежности x64dbg. Но в данном случае это самое меньшее из всех зол.
Вообще‑то процесс подключения IDA к QEMU через GDB подробно и с цветными картинками описан на сайте Для просмотра ссылки Войди
Итак, после описанной выше настройки 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;
Но мы попробуем доискаться до исходной проверки, ведь эта функция может оказаться лишь отладочной печатью статуса. По листингу видно, что валидность кода зависит от параметра 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. Это свободное открытое программное обеспечение, распространяющееся в исходниках (скачать можно Для просмотра ссылки Войди
Начальное направление можно получить, например, Для просмотра ссылки Войди
target qnx 192.168.1.200:1234
Если мы ничего не напутали, в окне GDB появится следующее сообщение.
Для просмотра ссылки Войди
Теперь нам снова требуется подключиться к нужному процессу из отладчика GDB. На скриншоте 7 мы определили PID нужного процесса — 512024. Для подключения к нему в консоли GDB набираем команду
attach 512024
Для просмотра ссылки Войди
Не обращаем внимания на многочисленные сообщения об ошибках, GDB успешно подключился к процессу 512024 и, так же как и в IDA, остановился на промежуточной точке останова 1037878. Эмулятор в момент останова тоже замерзнет, а мы воспользуемся паузой, чтобы (как было проделано выше) поставить точку останова на адрес 1183F8. Позволю себе маленькое лирическое отступление про особенности отладчика GDB.
Как я уже говорил, процесс отладки приложения в отладчике GDB достаточно экзотичен. GDB, как ты уже понял, полностью лишен гуя и управляется исключительно командами из консоли. В этом он больше всего напоминает DOS’овский отладчик debug.com, в котором мне, как хакеру старой школы, в свое время приходилось много и кропотливо работать. С полным справочником команд GDB можно ознакомиться на Для просмотра ссылки Войди
Даже бегло ознакомившись с опциями точек останова GDB, ты понимаешь, что, несмотря на крайнюю недружественность к пользователю, это очень гибкий инструмент, возможности которого не уступают условным точкам останова x64dbg, а кое‑где даже превосходят их. Здесь на каждую точку останова можно повесить весьма сложные скрипты, настраивающие выполнение программы в отладчике по воле и фантазии пользователя. А из них даже можно вызывать функции и блоки кода, реализованные в приложении, однако это тоже тема для отдельной статьи. Сейчас нам нужно простые точки останова на адресе 1183F8:
b *0x1183F8
Вроде все просто и понятно, звездочка перед адресом означает, что следующая за ней строка 0x1183F8 — это именно шестнадцатеричный адрес, а не идентификатор из таблицы отладочных символов, которую мы не подключили к отладчику, потому что у нас ее попросту нет. Далее командой c (continue) мы размораживаем QEMU (отладчик при этом, наоборот, замирает в ожидании точки останова) и в консоли QEMU запускаем активационный скрипт.
Для просмотра ссылки Войди
Как видишь, по достижении адреса 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)
Нам нужен был стек возвратов? Набираем x/4x $sp, получаем четыре верхних значения на стеке:
0xfffb18: 0x00fffb5c 0x004fd1d4 0x006c382c 0x005777b8
Посмотреть значение нужного регистра можно командой print $r0. Сделать шаг вперед — командами stepi или nexti (не путать с командами step и next, которые у нас не будут работать из‑за отсутствия подгруженной таблицы символов). Если же надо продолжить работу, остановившись на адресе 118408, не устанавливая на нее дополнительную точку останова, пишем
u *0x118408
Краткий дайджест особо часто используемых команд можно Для просмотра ссылки Войди
www
- Для просмотра ссылки Войди
или Зарегистрируйся - Для просмотра ссылки Войди
или Зарегистрируйся