Обратный AutoIt. Декомпилируем и деобфусцируем скрипт, снимаем лимиты без пересборки проекта

Да­вай раз­берем­ся, как вытащить исходни­ки из «ском­пилиро­ван­ного» скрип­та AutoIt, обой­ти обфуска­цию и снять три­аль­ные огра­ниче­ния без перес­борки про­екта. Я покажу, как работа­ет деком­пилятор myAutToExe, где скры­ты стро­ки и как под­ловить клю­чевую перемен­ную, что­бы обма­нуть про­вер­ку регис­тра­ции, — по шагам, от ревер­са до финаль­ного пат­ча.

Се­год­ня мы будем сочетать при­ятное с полез­ным, а имен­но пог­рузим­ся в две наши любимые темы — раз­ные экзо­тичес­кие интер­пре­тато­ры и деоб­фуска­ция. Я уже дос­таточ­но злос­ловил на тему того, сколь­ко в пос­леднее вре­мя понап­ридумы­вали средств раз­работ­ки для чай­ников, что­бы каж­дый школь­ник пос­ле прос­мотра озна­коми­тель­ного тик­токов­ско­го ролика мог закодить свою пер­вую прог­рамму.

На­вер­ное, ты уди­вил­ся, почему я до сих пор не упо­минал такое рас­простра­нен­ное условно‑бес­плат­ное поделие, как AutoIt? Судя по все­му, он задумы­вал­ся как меч­та любой дрес­сирован­ной обезь­яны — ничего не надо прог­рамми­ровать, прос­то вози мыш­кой по экра­ну и тыкай по кноп­кам, все твои дей­ствия авто­мати­чес­ки скрип­туют­ся, при­чем совер­шенно без­возмез­дно, то есть даром. Для тех, кто чуть поум­нее, нас­коро при­дума­ли уре­зан­ную вер­сию бей­сика для добав­ления в скрип­ты прос­тень­кой логики.

Даль­ше, по мере рос­та популяр­ности тех­нологии, ее соз­датели пош­ли по накатан­ной схе­ме — при­дума­ли механизм ком­понов­ки из прос­тецких тек­сто­вых скрип­тов исполня­емых фай­лов, и вот уже целые ком­мерчес­кие про­екты пишут­ся исклю­читель­но на AutoIt. При­чем изна­чаль­но в полити­ке кон­торы сох­ранялось некое фри­вар­но‑опен­сор­сное фрон­дерс­тво: пакет, помимо «ком­пилято­ра» Aut2Exe, пре­обра­зовы­вающе­го скрипт в исполня­емый модуль, содер­жал «деком­пилятор», про­вора­чива­ющий фарш назад, — Exe2Aut.

Од­нако с вер­сии 3.2.5.1 эти вред­ные веяния упраз­дни­ли и теперь гро­зят вся­чес­кими карами наг­лецам, пос­мевшим заик­нуть­ся о вос­ста­нов­лении кода из «ском­пилиро­ван­ного» исполня­емо­го фай­ла. Конеч­но же, угро­зами дело не огра­ничи­лось — была пред­при­нята и прог­рам­мная защита исходно­го кода (мес­тами доволь­но забав­ная): пре­ком­пиляция исходни­ков в байт‑код, который потом упа­ковы­вали, зашиф­ровыва­ли и даже навеши­вали свер­ху UPX, а кро­ме того, исполь­зовали весь­ма при­митив­ную обфуска­цию. Естес­твен­но, такая защита эффектив­на исклю­читель­но от чес­тных людей, точ­нее, от школь­ников, нез­накомых с осно­вами реверс‑инжи­нирин­га.

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

Exeinfo PE более кон­крет­но называ­ет вер­сию — AutoIt v3.3.13.15. Пакет работа­ет, но без регис­тра­ции сущес­тву­ет ряд раз­дра­жающих огра­ниче­ний: при опре­делен­ных дей­стви­ях прог­рамма выда­ет сооб­щения вида «Unregistered version can not …, to register?» с пред­ложени­ем, понят­ное дело, зарегис­три­ровать­ся.

Ли­цен­зион­ный ключ прог­рамма зап­рашива­ет на сай­те раз­работ­чика, там же этот ключ и валиди­рует, что допол­нитель­но харак­теризу­ет авто­ров с не очень хорошей сто­роны. Раз так, поп­робу­ем сами вытащить исходни­ки из исполня­емо­го фай­ла. Пос­коль­ку вер­сия нашего AutoIt выше 3.2.5.1, штат­ного деком­пилято­ра для нее не сущес­тву­ет.

По счастью, име­ются и сто­рон­ние деком­пилято­ры, и деоб­фуска­торы AutoIt, и Exeinfo PE даже ука­зыва­ет нам на них: это Exe2Aut decomp. v0.10 2014 и AU3Stripper v19.x 2019 or myAutToExe 2.15 [email protected].

Пер­вая ссыл­ка уже мер­тва, а со вто­рой явно что‑то не то, одна­ко про­ект myAutToExe впол­не сущес­тву­ет и под­держи­вает­ся на GitHub. Мож­но нагуг­лить еще, к при­меру, питонов­ский скрипт AutoIt-Ripper, но нам впол­не под­ходит и myAutToExe — он самый акту­аль­ный, да еще и со мно­жес­твом заяв­ленных допол­нитель­ных фич, поэто­му им и вос­поль­зуем­ся.

Дей­стви­тель­но, этот инс­тру­мент вос­ста­новил нам исходный au3-файл, сэконо­мив кучу вре­мени и нер­вов на раз­бор вир­туаль­ной машины и сис­темы команд AutoIt, которых мы на этот раз касать­ся не будем. Воз­можно, у нас ког­да‑нибудь появит­ся задача, для которой это будет необ­ходимо, но пока что для даль­нейших дей­ствий впол­не дос­таточ­но и вос­ста­нов­ленно­го кода. Жела­ющие могут самос­тоятель­но углу­бить­ся в эту тему, более деталь­но иссле­довав исходни­ки при­веден­ных выше гит­хабов­ских про­ектов.

У нас же, даже нес­мотря на наличие вос­ста­нов­ленно­го кода, веселье толь­ко начина­ется. При пер­вом взгля­де ста­новит­ся оче­вид­но, что получен­ный код совер­шенно нечита­ем.

На­чис­то отсутс­тву­ют име­на иден­тифика­торов, чис­ленные и стро­ковые кон­стан­ты. Судя по оби­лию фун­кций EXECUTE(), веро­ятно, зашиф­рованы осо­бо кри­тич­ные фраг­менты кода — налицо явная обфуска­ция с целью осложнить нам жизнь. При­чем обфуска­ция какая‑то самопис­но‑кас­томная, пос­коль­ку в исполь­зован­ном нами myAutToExe деоб­фуска­ция извес­тных инс­тру­мен­тов заяв­лена пря­мо «из короб­ки». В readme.txt даже перечис­лен спи­сок под­держи­ваемых обфуска­торов:

Supported Obfuscators:
‘Jos van der Zande AutoIt3 Source Obfuscator v1.0.14 [June 16, 2007]’ ,
‘Jos van der Zande AutoIt3 Source Obfuscator v1.0.15 [July 1, 2007]’ ,
‘Jos van der Zande AutoIt3 Source Obfuscator v1.0.20 [Sept 8, 2007]’ ,
‘Jos van der Zande AutoIt3 Source Obfuscator v1.0.22 [Oct 18, 2007]’ ,
‘Jos van der Zande AutoIt3 Source Obfuscator v1.0.24 [Feb 15, 2008]’ ,
‘EncodeIt 2.0’ and
‘Chr() string encode’

При­чем содер­жащи­еся в при­мерах обфусци­рован­ные фай­лы этим самым Jos van der Zande AutoIt3 Source Obfuscator до боли напоми­нают наш код, но что‑то неуло­вимое меша­ет myAutToExe кор­рек­тно его детек­тировать и деоб­фусци­ровать. Не будем искать ответ на воп­рос, что имен­но и как починить myAutToExe, — у нас сей­час есть кон­крет­ная цель, и нет смыс­ла отвле­кать­ся на побоч­ные квес­ты. Поп­робу­ем при­дать прог­рамме читабель­нос­ти сво­ими руками.

Бла­го мы уже изрядно под­наторе­ли в гораз­до более мрач­ной деоб­фуска­ции. В качес­тве при­меров можешь пос­мотреть дру­гие мои статьи:

  • Зелье для Zelix. Изу­чаем обфуска­тор для Java и при­думы­ваем собс­твен­ный деоб­фуска­тор
  • Раз­гадай­ка. Пишем собс­твен­ный деоб­фуска­тор для JavaScript
  • JSFuck. Раз­бира­ем уни­каль­ный метод обфуска­ции JS-кода

Вдо­бавок умные люди уже дав­но занима­ются делом деоб­фуска­ции скрип­тов AutoIt и пи­шут об этом статьи. В общем, как говорит­ся, гла­за боят­ся, а руки дела­ют.

Нач­нем с вос­ста­нов­ления тек­сто­вых строк. По оби­лию в вос­ста­нов­ленном коде прис­ваива­ний выраже­ний вида A2E00001A18($OS[...]) мож­но пред­положить, что стро­ковые кон­стан­ты каким‑то обра­зом закоди­рова­ны через эти фун­кции и мас­сив. Находим фун­кцию A2E00001A18 в самом кон­це кода:

FUNC A2E00001A18($A2E00001A18) LOCAL $A2E00001A18_ FOR $X=1 TO STRINGLEN($A2E00001A18)STEP 2 $A2E00001A18_&=CHR(DEC(STRINGMID($A2E00001A18,$X,2))) NEXT RETURN $A2E00001A18_ ENDFUNC

Ни­чего слож­ного, типич­ная крип­тогра­фия для млад­ших школь­ников: каж­дый сим­вол закоди­рован дву­мя Hex-сим­волами сво­его 8-бит­ного шес­тнад­цатерич­ного кода. Оста­лось понять, как фор­миру­ется огромный (нес­коль­ко тысяч эле­мен­тов) мас­сив исходных строк для этой фун­кции $OS[]. Если гля­нуть на пре­дыду­щий скрин­шот, то ста­новит­ся оче­вид­но, что его запол­няет фун­кция A2E00001A18_(), тоже рас­положен­ная в кон­це кода.

В ней так­же нет ничего слож­ного: она зачем‑то целых пять раз под­ряд сох­раня­ет в файл вре­мен­ного катало­га со слу­чай­ным наз­вани­ем (генери­руемым фун­кци­ей a2e00001a18x_()) огромный мас­сив тек­сто­вых дан­ных, захар­дко­жен­ный в пред­шес­тву­ющей фун­кции _igrf4d27dqc(). Нем­ного сму­щают вот эти «зашиф­рован­ные» стро­ки кода:

Global $a2e00001a18, $os = Execute(BinaryToString("0x457865637574652842696E617279746F737472696E672827...

И вот такие:

Execute(BinaryToString("0x457865637574652842696E617279746F737472696E672827307834353738363536333735373...

Пер­вая из них запол­няет иско­мый мас­сив $OS, но, судя по исполь­зованию фун­кции BinaryToString(), дру­гих крип­тоал­горит­мов автор обфуска­тора пока не выучил, поэто­му пишем прос­тень­кую прог­рам­мку на шар­пе и рас­кодиру­ем пер­вую стро­ку:

string newline = "";for (int j = 0; j < sline.Length; j += 2){ string charcode = sline.Substring(j, 2); try { byte bt = Convert.ToByte(charcode, 16); newline += (char)(bt); } catch (Exception e) { break; }}

Источник: xakep.ru

Ответить

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