Се­год­ня мы раз­берем­ся, как устро­ены дис­три­бути­вы на базе Wise Installer — того самого вин­тажно­го инстал­лятора родом из девянос­тых. Мы возь­мем ста­рую ути­литу, которая отка­зыва­ется уста­нав­ливать­ся без «глав­ной прог­раммы», и шаг за шагом иссле­дуем скрип­ты и фун­кции инстал­лятора с исполь­зовани­ем отладчи­ков и IDA, что­бы понять логику про­вер­ки и зас­тавить ути­литу уста­нав­ливать­ся без допол­нитель­ных усло­вий.

Се­год­ня мы оку­нем­ся в исто­рию и приль­нем к ее анна­лам. Те, кто зас­тал конец прош­лого века, ког­да компь­юте­ры были боль­шими, а тра­ва зеленой, прек­расно пом­нят, как уста­нав­ливали себе на компь­ютер игры и при­ложе­ния с куп­ленных на рын­ке ком­пакт‑дис­ков: для это­го исполь­зовал­ся инстал­лятор Wise Installer.

Эта раз­работ­ка коман­ды Wise Solution (что в перево­де озна­чает «Муд­рые решения») в те вре­мена была прак­тичес­ки монопо­лис­том сре­ди инстал­ляторов все­воз­можно­го соф­та. При всем богатс­тве зоопар­ка сов­ремен­ных ана­логов акту­аль­ных дис­три­бути­вов на этой плат­форме прак­тичес­ки не оста­лось, но мы поп­робу­ем вспом­нить прош­лое и поковы­рять­ся во внут­реннос­тях такого дис­три­бути­ва.

Итак, пос­танов­ка задачи. Пред­положим, мы наш­ли на ста­ром дис­ке дис­три­бутив неко­ей жиз­ненно важ­ной ути­литы, но она катего­ричес­ки отка­зыва­ется уста­нав­ливать­ся, пока не уста­нов­лена дру­гая, основная прог­рамма (отсутс­тву­ющая у тебя и совер­шенно тебе ненуж­ная). В пакет той самой «боль­шой прог­раммы» эта ути­лита изна­чаль­но вхо­дила. Сооб­щение об ошиб­ке, пос­ле которо­го инстал­лятор зак­рыва­ется, выг­лядит вот так.

Тре­бует­ся най­ти спо­соб, как инстал­лировать ути­литу без основной прог­раммы.

Иден­тифици­ровать защиту даже и не нуж­но — она сама при запус­ке корявы­ми синими бук­вами выда­ет, что это Wise Installer Wizard. Detect It Easy тоже сог­лаша­ется с этим.

За­пус­каем инстал­лятор из отладчи­ка x32dbg и при появ­лении окна сооб­щения пре­рыва­ем прог­рамму. Смот­рим стек вызовов.

Вид­но, что окно сооб­щения реали­зова­но с исполь­зовани­ем фун­кции DialogBoxParamA, которая вызыва­ется из загадоч­ной биб­лиоте­ки glcb36c.tmp. А она, в свою оче­редь, находит­ся во вре­мен­ном под­катало­ге сис­темы.

Лег­ко убе­дить­ся, что при каж­дом новом запус­ке инстал­лятора наз­вание у нее раз­ное, но файл один и тот же. Вытас­кива­ем его из вре­мен­ного катало­га наружу и пре­пари­руем при помощи IDA. Самый ниж­ний адрес воз­вра­та 10001EA8 при­над­лежит основной фун­кции WiseMain, из нее вызыва­ется фун­кция sub_10003C7C, в свою оче­редь вызыва­ющая диало­говое окно сооб­щения. И этот вызов выг­лядит весь­ма инте­рес­но.

Очень похоже на обра­бот­чик опко­дов интер­пре­тато­ра. Ука­затель на текущую коман­ду которо­го IDA почему‑то называ­ет nLength. Поп­робу­ем пот­расси­ровать шитый код покоман­дно в нашем любимом отладчи­ке x64dbg.

Нас нем­ного огор­чает то обсто­ятель­ство, что биб­лиоте­ка glcb36c.tmp мало того что не заг­ружа­ется сра­зу, так вдо­бавок матери­али­зует­ся в про­цес­се работы во вре­мен­ном катало­ге под раз­ными име­нами, а это зат­рудня­ет уста­нов­ку на нее точек оста­нова. Но мы уже опыт­ные хакеры и зна­ем, как с этим бороть­ся.

В парамет­рах x64dbg на вклад­ке «События» ста­вим гал­ку на «Пре­рывать­ся на точ­ке вхо­да DLL», пос­ле чего запус­каем инстал­лятор. Пока что нам силь­но везет — пер­вая же оста­нов­ка выводит нас на точ­ку вхо­да в биб­лиоте­ку со зна­комым наз­вани­ем glc60fb.tmp, у которой вдо­бавок и экспор­ты иден­тичны тре­буемым.

Те­перь и точ­ку оста­нова мож­но ста­вить на выбор­ку команд, бла­го биб­лиоте­ка еще и на фик­сирован­ные адре­са садит­ся. Оста­новив­шись на ней, пос­мотрим в окне дам­па, отку­да счи­тыва­ется текущая коман­да.

На пер­вый взгляд все выг­лядит как типич­ный откомпи­лиро­ван­ный шитый код инстал­ляци­онно­го скрип­та. Если в свой­ствах нашей точ­ки оста­нова пос­тавить в поле усло­вия 0, а в поле тек­ста жур­нала {eax}: {cl}, то в жур­нале мож­но получить лог пос­ледова­тель­нос­ти выпол­нения команд с их адре­сами сле­дующе­го вида:

...
460BE1: 0
460C29: 9
460C8C: 9
460CDB: 9
460D5C: 9
460DDD: 9
460E31: 9
460EDA: 1B
460EDB: 9
460F3E: 9
460F92: 9
460FF0: 9
46104E: 9
461169: 9
461203: C
46121B: 9
46126F: 9
4612DC: D
461918: 9
461AB1: 9
461C81: 9 | ...

Все это очень замеча­тель­но, но пока что мы не зна­ем ни наз­ваний команд, ни син­такси­са, ни их реаль­ного дей­ствия. Мы и сам скрипт видели толь­ко в окне отладчи­ка, поэто­му нач­нем с его извле­чения.

По­гуг­лив, мы к сво­ему удив­лению обна­ружи­ваем, что, нес­мотря на свою вин­тажность, фор­мат Wise Installer прак­тичес­ки не докумен­тирован и очень беден на ути­литы для ревер­са. Сущес­тву­ет нес­коль­ко прак­тичес­ки одно­тип­ных ути­лит‑рас­паков­щиков: WiseUnpacker, ExWise, HWUN и E_WISE (к сожале­нию, за дав­ностью лет эти про­екты, похоже, канули в Лету, я их смог най­ти лишь на архивных сай­тах).

Как я уже говорил, все это прак­тичес­ки одно­тип­ные рас­паков­щики инстал­ляци­онных архи­вов, даже без вос­ста­нов­ления имен фай­лов, содер­жащих­ся в пакете. Конеч­но, инстал­ляци­онный скрипт без осо­бого тру­да обна­ружи­вает­ся в рас­пакован­ных фай­лах, но есть и кое‑что поин­терес­нее.

Соз­датели ути­литы REWise попыта­лись пой­ти чуть даль­ше и ревер­сировать инстал­ляци­онный скрипт. К сожале­нию, похоже, им надо­ело это без­бла­годат­ное дело еще на самом пер­воначаль­ном эта­пе, поэто­му опция деком­пиляции скрип­та -z сох­ранилась толь­ко в отла­доч­ном вари­анте, который по умол­чанию отклю­чен. Поп­робу­ем вос­поль­зовать­ся их наработ­ками для луч­шего понима­ния струк­туры и фун­кци­они­рова­ния интер­пре­тато­ра инстал­ляци­онно­го скрип­та.

Итак, нат­равив REWize на наш инстал­ляци­онный модуль, получа­ем в кон­соль огромную прос­тыню даже не деком­пилиро­ван­ного кода, а, ско­рее, отла­доч­ного лога покоман­дной раз­борки инстал­ляци­онно­го скрип­та. Он име­ет сле­дующий вид:

...
0x16 'W32INST_PATH_'
0x00 2440 0x00000000 0x000011B4 1999-01-21 14:40:08 9728 0000000000000000000000000000000000000000 20CC89C5 'TEMP/W32INST_PATH_' "(null)" "(null)" "(null)" "(null)" "(null)" "(null)"
0x09 09 '(null)' 'f16' '(null)' '(null)'
- "0_x7FBB_FILEVERSION_x7F"
- "0_x7FBB_FILEVERSION_x7F"
- "0_x7FBB_FILEVERSION_x7F"
- "0_x7FBB_FILEVERSION_x7F"
- "0_x7FBB_FILEVERSION_x7F"
0x09 09 '(null)' 'f16' '(null)' '(null)'
- "0_x7FBB_VERSION_x7F"
- "0_x7FBB_VERSION_x7F"
- "0_x7FBB_VERSION_x7F"
- "0_x7FBB_VERSION_x7F"
- "0_x7FBB_VERSION_x7F"
0x09 09 '(null)' 'f16' '(null)' '(null)'
...

По‑преж­нему ни фига не понят­но, кро­ме того, что пер­вое сле­ва Hex-чис­ло — это код опе­рации, а сле­дующая за ним мешани­на строк и чисел — ее парамет­ры.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии