Понадобилась мне одна программка, которая, почему-то не захотела ставиться на мою систему, причем не захотела без всяких ошибок и вылетаний. Инсталлятор просто висел на 1% и дальше двигаться не хотел. Зная, что поддержка винды у этой софтины зависит исключительно от бодуна разработчиков (то они винду вообще не поддерживали, потом прошлая версия прекрасно ставилась и работала, а тут вдруг опять нет), решил я в софтине поковыряться, небось, софтина-то работает, а инсталлятор кривой. Но о том, как я возился с софтиной, напишу как-нибудь позже. А тут будет такой простенький заметк про реверсинг инсталлятора.
Я уже как-то упоминал (копия), что инсталляторов и упаковщиков есть туева хуча на свете, и для начала надо определить, с каким именно инсталлером мы имеем дело. Для этого воспользуюсь программкой Detect It Easy (DiE), которая по своей базе сигнатур может определять тип экзешника, чем он упакован, чем скомпилирован, а если это инсталлятор — определить и его тип. Программка работает примерно также, как антивирусный сканер, определяя по сигнатурам, с чем мы имеем дело. Благо, почти все упаковщики, компиляторы или сборщики инсталляционных пакетов, так или иначе оставляют свою сигнатуру в файле.
Итак, скармливаю DiE исследуемый инсталлятор.
Видим тип — QT installer.
Естественно, о ней я и подумал сразу же, не изобретать же велосипед, до нас его более умные люди изобрели. А не тут-то было! Автоматического распаковщика не нашел, так что стал думать… Qt проект открытый, значит, скорее всего, они особо не заморачивались, и инсталлятор представляет из себя самораспаковывающийся архив, который по структуре выглядит как-то так, как выглядят самораспаковывающиеся архивы RAR WinZip или 7Zip — в начале файла EXE-модуль, а после него данные, которые EXE-модуль распаковывает:
В принципе, что я иду верным путем, можно было понять из главного окна DiE, тот недвусмысленно сообщал про overlay (оверлей), в котором находятся QT installer data, т.е. данные QT-установщика.
На то, что представляют собой данные установщика (оверлей) можно посмотреть, собственно, из DiE, нажав кнопку Overlay в главном окне программы. У DiE есть встроенный небольшой HEX-редактор, в котором оверлей и откроется.
А почему бы не поковырять оверлей отдельно от экзешника? Вряд ли в самом SFX-модуле найдется что-то полезное. Подумав так, я решил отделить оверлей от SFX-модуля, т.е. сдампить его в отдельный файл. Благо, функция дампа у DiE тоже была, достаточно нажать правой клавишей мыши на ту часть окна, где представлена информация в RAW-виде и нажать пункт меню Dump (или комбинацию Ctrl+D)
Сохраняю его в файл Dump.bin
.
Первое, что бросается в глаза, когда посмотришь на дамп, это сигнатура qres
, с которой начинается файл. QRes, соответственно, сокращение от Qt Resources, оказалось, я прав — это бинарный формат ресурсов фреймворка Qt.
Примечание: до этого момента я с Qt никогда плотно не сталкивался, сам не пользовался, писать под него меня никто не просил, и вообще — раз проект открытый, наверное, стоило бы задачу решать без бубна, ознакомившись с документацией. Оно может быть и да, но в данной заметке я показываю ход рассуждений, будто бы встречаюсь с каким-то неведомым форматом, и на простом примере показываю, как его разобрать.
Опять же, у меня возникла мысль о том, что ну явно же кому-то надо было расковыривать бинарные ресурсы Qt, значит, умные люди уже сделали какой-нибудь распаковщик ресурсов…
Нашел, но, к дикому моему сожалению, он оказался только под Linux, а у меня вокруг одна винда. Решил собрать его в Cygwin, так что, как я его собирал, описываю тезисно:
— Устанавливаем сам Cygwin
— Добавляем пакеты gcc (я просто в поиске менеджера пакетов ввел gcc и поставил все, до чего руки дотянулись)
— Добавляем поддержку Qt5 (аналогичным образом)
— Добавляем git, если еще не установлен.
Далее выполняем:
git clone https://github.com/tatokis/qresExtract
Ответ должен быть примерно таким:
Cloning into 'qresExtract'...
remote: Enumerating objects: 12, done.
remote: Total 12 (delta 0), reused 0 (delta 0), pack-reused 12
Receiving objects: 100% (12/12), 11.70 KiB | 520.00 KiB/s, done.
Resolving deltas: 100% (3/3), done.
далее переходим в директорию qresExtract
:
cd qresExtract
И выполняем компиляцию. Тут немножко пришлось поковыряться, т.к. стандартные qmake && make
из инструкции к программе в Cygwin не сработали, оказалось, надо так:
qmake-qt5
Ответ:
Info: creating stash file /home/Nigger/tst/qresExtract/.qmake.stash
и далее:
make
Соберется экзешник qresExtract.exe
. Впрочем, кому лень собирать, готовый экзешник со всеми DLL будет в ссылках в разделе «Инструменты».
Итак, скармливаем qresExtractor.exe
наш Dump.bin
.
qresExtract.exe Dump.bin
И я-то, дурак, думал, что на этом все. А вот хуй тебе, Толян!
Экстрактор наделал кучу директорий в папке с Dump.bin
, но, блин, нам досталась только мета-информация: некий скрипт install.js
с инструкциями по установке софта, config-internal.ini
, в котором, впрочем, обнаруживался обнадеживающий параметр offlineOnly=true
, т.е., скорее всего, установщик оффлайновый, и бинарники не качаются из интернетов, и они где-то с нами.
Впрочем, в одном из конфигов оказалась интересная информация, в XML-файле перечислялись названия 7zip-архивов:
<DownloadableArchives>bearer.7z,iconengines.7z,imageformats.7z,platforms.7z,
qmltooling.7z,Qt.7z,QtGraphicalEffects.7z,QtQml.7z,QtQuick.7z,
QtQuick.2.7z,styles.7z,translations.7z,content.7z</DownloadableArchives>
Это, конечно, надо будет потом автоматизировать, но тут покажу, как я сделал это вручную.
Итак, что такое архив 7z (7zip), это архив, начинающийся с определенной сигнатуры:
37 7A BC AF 27 1C
.
Откроем файл дампа в шестнадцатеричном редакторе WinHex и попытаемся выполнить поиск по сигнатруре. В меню: Search —> Find HEX Values, вводим значения сигнатуры архива без пробелов (377ABCAF271C
).
Я их последовательно нашел вручную (продолжение поиска по F3) и в результате составил такую вот таблицу:
Адрес обнаружения сигнатуры | Конец архива |
2513 |
ABDE |
ABDF |
113DE |
113DF |
9642C |
9642D |
15D369 |
15D36A |
19E04D |
19E04E |
1C0868 |
1C0869 |
1D670C |
1D670D |
1E6AAC |
1E6AAD |
3C6FA7 |
3C6FA8 |
3CFCD0 |
3CFCD1 |
3E4392 |
3E4393 |
46FC7F |
46FC80 |
01F20307 |
Я предположил, что 7z-архивы идут подряд, один за другим, потому вычислял конец предыдущего архива, как -1
байт с начала сигнатуры следующего, а за конец предыдущего архива взял конец файла. 7z-архиву пофиг, если после самого архива окажется какой-то мусор. Так что последний архив все равно должен был открыться. Так и получилось.
Сдампил архивы я тоже с помощью WinHex. На руках у меня была таблица с начальными и конечными адресами архивов, оставалось ввести их в окно Edit—>Define Block и ввести в окне начальный и конечный адрес, например, 9642D
и 15D369
и установить радиокнопку в End:
Можно пойти, проверить, нужный ли блок выделило (Navigation —> Go to —>Beginning of block), если немножко покрутить полосами прокрутки, то явно будет виден заголовок архива:
А можно выделенный блок сдампить в отдельный файл (Edit —> Copy Block —> Into New File), в общем, я так и сдампил архивы, а потом еще их и распаковал. Вот вам два, как пример:
Detect It Easy (DiE):
— На Exe-Lab
— На Mega.nz
qresExtract:
— Binary for Windows x86
— Sources
WinHex 19.9: