Практическое моделирование

и другие вопросы разработки нефтяных месторождений
reversing

Qt Reversing Application

Мне захотелось немного повозится с реверсингом кода, написанного на С++ с применением великолепной библиотеки Qt. Как мне показалось, единственная путная статья, описывающая внутреннее устройство классов «Egg Hunt in Tesla Infotainment: A First Look at Reverse Engineering of Qt Binaries» 2023 года. Дело оказалось проще, чем казалось.

Открыв проект в IDA мы перейдем в Strings, чтобы посмотреть на текстовые ресурсы.

Qt использует механизм передачи событий, при помощи которого связываются сигналы и слоты объектов. Имена событий в программе начинаются с действия «add», «use», «init».

Проследим для примера за событием «doCharacterization», который находится в блоке состоящим из строк.

IDA подсказывает, что обращение к первой строке «PVTAnalysisDialog» происходит из sub_12766, тогда как к другим строкам прямого обращения не обнаружено. Такая ситуация напоминает таблицу, к элементам которой происходит косвенное обращение.

Проследим, как используется нулевой элемент таблицы. Единственная ссылка приводит к процедуре, в которой не происходит ничего интересного,

Поднимаясь выше по иерархии вызовов, мы попадаем на виртуальную таблицу класса PVTAnalysisDialog.

Источник подсказывает, что первые три функции для класса, который использует сигнально-слотовую систему Qt называются,

::metaObject()
::qt_metaCast()
::qt_metaCall()

Первая функция sub_6965 (metaObject) через один промежуточный прыжок приводит к функции sub_12442, из которой мы получим адрес структуры,

Структура называется staticMetaObject и состоит из четырех полей,

Первое поле dq offset qword_162078 хранит ссылку на родительский объект.
Второе поле dq offset unk_1168112 таблица хранения строчных данных
Третье поле dq offset unk_1168113 мета-данные объекта
Четвертое поле dq offset sub_3433 процедура обработки событий.

Разбор структуры начнем с таблицы строк. Однако по адресу не обнаруживаются сначала никакие строки.

Выбрав тип данных через Alt+D как Double word, можно заметить повторяющуюся комбинацию 0xFFFFFFFF. Источники упоминают, что второе после 0xFFFFFFFF значение отвечает за длину строковой переменной.

Информация о длине строки мне не пригодилась и мы можем листать дальше, до появления наконец то самой таблицы строк, которая и есть та таблица с которой всё началось.

Копируем строковые переменные в excel и индексируем,

Нулевой элемент таблицы всегда отвечает за имя класса, что упрощает изучение внутренней структуры программы. Вернемся назад на шаг и перейдем к структуре хранящей мета-данные объекта.

Мета данные состоят из двух частей.

Первый блок это описательный блок, где первая цифра 8 отвечает за внутренний номер версии Qt. Для разных версий Qt используется разная логика, в целом похожая, но отличная в деталях, поэтому трудной найти версию статьи, которая посвящена именно текущей версии.

Следующий блок представлен как массив из пяти элементов. Чтобы понять с какого элемента начинать формировать массив, можно обратить внимание на последнее число, которое обычно 6 или 8. Это флаговое число, которым обозначаются сигналы, слоты и другие элементы. Таблица продолжается до следующей метки.

Полученную мета таблицу копируем в excel, индексацию начинаем с единицы.

Первое число в мета таблице это номер строки. Таким образом формируется соответствие внутреннего кода сигнальной системы и текстового имени.

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

Сверяясь с таблицей excel, находим, что код 2 отвечает за updateNParaffinCutsStatus. Можно переименовать sub_6918, но предварительно конечно поставив точку прерывания внутри функции, пытаясь с gui активировать сигнал.

Обнаружив интересующий класс в программе, можно также поставить точку прерывания на ключе переменной a3 блока switch и прочитать какой код поступил на обработку.

Так у меня получилось переходить от нажатий в интерфейсе к местам обработки событий и у вас я думаю всё получится.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *