Как распаковать upx файл
Перейти к содержимому

Как распаковать upx файл

  • автор:

PE Explorer

главная программы pe explorer обзорный тур

Распаковщик UPX

Автоматическая распаковка файлов, сжатых UPX

В состав PE Explorer входит плагин для распаковки UPX. Этот плагин вызывается при каждом открытии файла и анализирует, не является ли открываемый файл сжатым при помощи UPX. Поддерживаются все версии UPX, начиная с самых ранних версий (до 0.80) и заканчивая самыми новыми 3.9x версиями.

Кроме того, PE Explorer поддерживает распаковку файлов, которые после сжатия UPX подверглись модификации с использованием так называемых UPX-скрэмблеров: Advanced UPX Scrambler, UPoLyX, UPX Lock. Так же PE Explorer поддерживает распаковку Upack и NSPack.

Теперь вы можете открывать файлы, сжатые UPX, и даже не заметить, что они были сжаты!

В случае, если открываемый исполняемый файл оказывается запакован UPX, плагин для распаковки UPX автоматически распаковывает файл и воссоздаёт его в его оригинальной несжатой форме, что позволяет вам проводить дальнейший анализ файла в PE Explorer.

При сохранении на диск файл записывается так же в распакованном виде. PE Explorer не запаковывает файл обратно. По этой причине размер файла до и после открытия может существенно отличатся, даже если вы не вносили в него никаких изменений.

Плагин для распаковки UPX отображает всю информацию о ходе процесса декомпрессии файла в нижней панели лога:

Распаковка вредоносных программ

Плагин для распаковки UPX содержит механизм распаковки файлов, которые подверглись модификации после сжатия. Такие файлы не могут быть распакованы стандартными средствами самого UPX, поскольку была изменена внутренняя структура файла. Например, имя секции UPX переименовано в XYZ, или версия формата UPX исправлено с 1.20 на 3.21. Эта техника часто используется вирусмейкерами для маскировки и защиты от распаковки.

Чтобы распаковать такой EXE файл самостоятельно, вам бы пришлось запустить его и снять дамп запакованных участков памяти с последующей записью на жёсткий диск после того, как файл полностью распакуется в памяти компьютера.

PE Explorer полностью избавляет вас от необходимости этим заниматься. Всё, что нужно, чтобы распаковать подобный обфусцированный файл — это просто открыть его в PE Explorer. Все операции по распаковке происходят автоматически.

Более того, плагин для распаковки UPX предпринимает попытку восстановить исходный файл, даже если в сжатом файле отсутствует оригинальный PE заголовок. Обычно отсутствие заголовка у PE файла делает его полностью неработоспособным и не подлежащим восстановлению. Однако, используя PE Explorer, вы получаете неплохой шанс на восстановление и анализ таких файлов.

Менеджер плагинов

При выборе команды Plug-in Manager из меню Tools открыается окно Менеджера плагинов .

Менеджер плагинов отображает список плагинов, подключенных к PE Explorer, и позволяет устанавливать очередность их выполнения. Чем больше значение Priority, тем выше приоритет выполнения. Установив значение Priority равным нулю, вы отключаете плагин. Отключенные плагины помечены красным значком, включенные — зелёным.

Менеджер плагинов

Пожалуйста, обратите внимание, что текущая версия PE Explorer пока не поддерживает выполнение цепочки плагинов. Это значит, что сейчас вызов следующего по списку плагина произойдёт только в том случае, если предыдущий плагин вернул FALSE после исполнения. После первого же успешного срабатывания любого плагина процесс обработки прекращается и файл передаётся в PE Explorer.

Написание собственных плагинов

Плагин для распаковки UPX предназначен для только работы с файлами, сжатыми UPX. Если вы хотите расширить функциональность PE Explorer и создать свой собственный плагин для обработки файла во время его открытия, воспользуйтесь предоставленным API для плагинов. Документацию по API можно найти в файле помощи, в разделе Plug-Ins.

Обзорный тур
назад | след.

Как распаковать UPX?

Скачать вот отсюда программу UPX
http://upx.sourceforge.net/
и ею распаковать.

Скачать саму программу и выполнить команду
upx -d filenamepacked.exe

Похожие вопросы

Ваш браузер устарел

Мы постоянно добавляем новый функционал в основной интерфейс проекта. К сожалению, старые браузеры не в состоянии качественно работать с современными программными продуктами. Для корректной работы используйте последние версии браузеров Chrome, Mozilla Firefox, Opera, Microsoft Edge или установите браузер Atom.

Распаковка UPX вручную

Для примера возьмем любой файл и запакуем его с помощью UPX. Скачиваем с сайта упаковщик и запаковываем.

Убедимся, что файл запакован. Сделать это можно несколькими способами.

1) С помощью программы Detect it easy!

Как мы видим, он показывает, что файл упакован UPX(3.94)

2) С помощью PEid

Здесь тоже видим UPX.

3) С помощью PEView. PEView дает информацию о PE Header, из который мы можем увидеть, что бинарь содержит секции UPX.

Еще один способ понять, что что-то не так с файлом, это разница между значениями SizeOfRawData (размер данных на диске) и VirtualSize (количество памяти, которое надо выделить для секции). Например, у секции UPX0, SizeOfRawData равен 0, что уже ненормально, а VirtualSize = 67000, что говорит нам о том, что в секции заполняется данными во время выполнения.

4) Если открыть файл в IDA, то получим следующее сообщение:

IDA сообщает нам, что она не смогла определить стандартные секции в файле (.text, .data, …)

5) Посмотрев таблицу импорта, с помощью Dependency walker, мы видим только функции LodaLibrary, GetProcAddress. Такой набор функций говорит о том, что таблица импорта восстанавливается во время выполнение. Вручную загружается каждая библиотека (LoadLibrary) и достаются адреса каждой функции (GetProcAddress)

Мы определили, что файл запакован, теперь попробуем распаковать его вручную, с помощью IDA. Чтобы распаковать файл, нам необходимо сделать 3 вещи: 1) Отдебажить до того момента, когда данные распакуются 2) Разрезолвить таблицу импорта 3) Поменять OEP (Original Entry Point) на изначальный

 Открываем файл в IDA поставив галочку на "Manual load" и убрав с "Create imports segment" (If checked, IDA will convert .idata section definitions to "extrn" directives and truncate it). 

Далее нас попросят указать Image Base (его можно посмотреть, с помощью PEView, в IMAGE_OPTIONAL_HEADER), загружаем все секции. Теперь наша задача найти, когда выполняется инструкция PUSHA/PUSHAD (Поместить в стек значения всех 32-битных регистров общего назначения ). Запускаем, ищем, ставим брейкпоинт на PUSHAD.

С этой инструкции начинается процесс распаковки UPX, поэтому все значения регистров сохраняются. Соответственно, после распаковки должна быть выполнена инструкция POPA, которая восстановит прежние значения. На нее мы и должны поставить брейкпоинт. Сделать это можно двумя способами. 1) Text search по слову POPA, ставим брейкпоинт, продолжаем выполнение до срабатывания.

2) Выполняем инструкцию PUSHA (то есть EIP стоит на строке после PUSHA). Переходим на адрес ESP, с помощью нажатия стрелочки напротив ESP в списке регистров.

Ставим Hardware on write брейкпоинт размером 4 байта. Как альтернатива, можно также поставить брейкпоинт на адрес ESP + 4. Не забудь убрать брейкпоинт, после его срабатывания. Смысл в том, что ты ставишь брейкпоинт на ESP до распаковки. Когда все распакуется, ESP вернется к прежнему значению и выполнится POPA и сработает брейкпоинт.

После срабатывания брейкпонта на POPA, где-то рядом, дальше мы должны увидеть TAIL JMP.

TAIL JMP — инструкция, которая перенаправляет выполнение на OEP. Характерной особеностью адреса, по которому совершается переход, является его отдаленность, от текущего адреса. Это происходит, потому что данные распаковываются в секции UPX1 и помещаются в UPX0. Понять, что распаковка происходит в секцию UPX0 можно было по его свойствам SizeOfRawData=0 и VirtualSize. Плагины для дебаггеров, которые определяют OEP полагаются на это свойство перехода и определяют, когда выполнение в одной секции переходит на выполнение в другой. Выполняем инструкцию jmp.

Всё, теперь мы находимся на OEP, а значит надо сделать дамп распакованной в памяти программы. Делаем это, с помощью Lord PE. Запускаем LordPE, находим процесс, делаем dump full.

Открываем дамп в PE Editor (LordPE) и прописываем OEP, он у нас равен 57703 (RVA). Это адрес мы видим, после перехода по Tail JMP. Сохраняем.

Открываем дамп в Rebuild PE (Lord PE), чтобы подправить выравнивания и т.д.

Запускаем дамп, открываем ImpRec, чтобы подправить таблицу импорта. В ImpRec выбираем процесс дампа, нажимаем “IAT AutoSearch”, “Fix Dump”. Всё, можно сравнить таблицу импорта оригинального файла и полученного.

Крепость эльфов. Как распаковать исполняемый файл Linux, накрытый UPX

Упа­ков­щики и крип­торы хорошо извес­тны любите­лям усложнить обратную раз­работ­ку кода. Для вин­ды таких инс­тру­мен­тов целый зоопарк, в Linux все куда слож­нее: сей­час про­верен­но работа­ет с эль­фами под раз­личные плат­формы лишь UPX. Его исполь­зуют вирусо­писа­тели для упа­ков­ки бо­тов, май­неров и SSH-бэк­доров, а потому заос­трим на нем вни­мание и мы.

info

Эта статья написа­на по мотивам док­лада с новогод­ней сход­ки, орга­низо­ван­ной сооб­щес­твом SPbCTF в декаб­ре 2020 года. За­пись сход­ки со все­ми док­ладами дос­тупна на канале SPbCTF в YouTube.

Зачем это все?

На стра­нич­ке одно­го хороше­го пакера мож­но про­честь, что основная цель его сущес­тво­вания — умень­шить раз­мер исполня­емо­го фай­ла с вытека­ющей отсю­да эко­номи­ей дис­кового прос­транс­тва и сетево­го тра­фика. Нап­ример, UPX поз­воля­ет сжать исполня­емый файл на 50–70%, и он оста­нет­ся пол­ностью самодос­таточ­ным, потому что код, выпол­няющий рас­паков­ку в память, добав­ляет­ся к получив­шемуся бинарю. Для это­го же упа­ков­ка исполь­зует­ся и в PyInstaller при сбор­ке кода на Python в незави­симые исполня­емые фай­лы PE или ELF (при этом он может работать и в тан­деме с UPX).

Од­нако, как ты догады­ваешь­ся, пакеры отлично под­ходят еще и для того, что­бы нем­ного под­портить жизнь реверс‑инже­неру. В этом клю­че родс­твен­ны им крип­торы. В мире Linux, одна­ко, это ско­рее про­екты, боль­ше похожие на proof-of-concept, либо же прос­то что‑то ста­рое и, пря­мо ска­жем, в живой при­роде поч­ти не встре­чающееся.

Из упа­ков­щиков для фай­лов ELF в нас­тоящее вре­мя наибо­лее популя­рен UPX (в час­тнос­ти, сре­ди вирусо­писа­телей), пос­коль­ку осталь­ные пакеры либо под­держи­вают пол­торы архи­тек­туры, либо уже очень дав­но не обновля­лись (оце­нить количес­тво канув­ших в Лету про­ектов мож­но, полис­тав дав­ний об­зор упа­ков­щиков для Linux/BSD от Кри­са Кас­пер­ски).

Принцип работы среднестатистического пакера

Кон­цепту­аль­но упа­ков­щик работа­ет так. Код и дан­ные прог­раммы сжи­мают­ся без потерь каким‑либо алго­рит­мом (с исполь­зовани­ем lzma, zlib или чего‑либо еще), добав­ляет­ся код, выпол­няющий рас­паков­ку того, что получи­лось, затем добав­ляют­ся собс­твен­ные заголов­ки, и вуаля — у нас сжа­тый бинарь. Схе­матич­но про­цесс упа­ков­ки пред­став­лен ниже.

Упаковка исполняемого файла

При запус­ке такого фай­ла нач­нет выпол­нять­ся заг­рузчик, отве­чающий за рас­паков­ку сжа­того кода и дан­ных в память, пос­ле чего он переда­ет управле­ние в ори­гиналь­ную точ­ку вхо­да. Гру­бо говоря, получа­ется саморас­паковы­вающий­ся архив. Детали реали­зации в раз­ных пакерах могут раз­личать­ся — нап­ример, PyInstaller при соз­дании exe-фай­ла помеща­ет упа­кован­ные дан­ные в овер­лей, а заг­рузчик находит­ся перед упа­кован­ными дан­ными, а не пос­ле, как на схе­ме. Более изощ­ренные упа­ков­щики (ско­рее боль­ше напоми­нающие крип­торы), могут еще боль­ше усложнять этот про­цесс, но в целом это не меня­ет сути.

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

The Ultimate Packer for eXecutables

Этот про­ект праз­дну­ет в нынеш­нем году 25-летие. Его исходни­ки дос­тупны на Гит­хабе, он написан на плю­сах с при­месью ассем­бле­ра, поэто­му раз­бирать­ся в коде доволь­но‑таки весело. UPX под­держи­вает мно­жес­тво типов фай­лов и архи­тек­тур — не зря он такой популяр­ный. Более того, PyInstaller име­ет опцию —upx-dir , поз­воля­ющую при соз­дании архи­ва упа­ковать его при помощи UPX, тем самым умень­шая раз­мер резуль­тиру­юще­го фай­ла.

Как про­исхо­дит упа­ков­ка прог­раммы в UPX? Вна­чале опре­деля­ется ее фор­мат — PE, ELF, образ ядра Linux или что‑либо еще (го­ворят, в UPX мож­но паковать даже sh-скрип­ты!). Пос­ле это­го нуж­но опре­делить архи­тек­туру, под которую ском­пилиро­ван файл. Это свя­зано с тем, что заг­рузчик, который называ­ется в коде UPX stub loader («заг­лушка», стаб), плат­формен­но зависим. Его код написан на язы­ке ассем­бле­ра, потому что при сжа­тии раз­работ­чики ста­рают­ся эко­номить бук­валь­но каж­дый байт и добить­ся мак­сималь­ной ком­прес­сии. В свя­зи с этим быва­ет и так, что сам заг­рузчик тоже час­тично упа­кован. Так что UPX под­держи­вает те архи­тек­туры, под которые у него есть реали­зация ста­ба. Оце­нить спи­сок архи­тек­тур и типов фай­лов мож­но, взгля­нув на со­дер­жимое дирек­тории src/stub в сор­цах UPX.

Итак, если архи­тек­тура упа­ковы­ваемо­го фай­ла под­держи­вает­ся UPX, то для него фор­миру­ется заг­рузчик, сам файл сжи­мает­ся, и в целом наш сжа­тый бинарь готов. Для воз­можнос­ти ста­тичес­кой рас­паков­ки, которая выпол­няет­ся коман­дой upx -d , UPX добав­ляет в файл собс­твен­ные заголов­ки.

Заголовки UPX

До­бав­ляют­ся четыре заголов­ка, три из которых мож­но уви­деть в начале исполня­емо­го фай­ла:

  • loader info ( l_info ) содер­жит кон­троль­ную сум­му, магичес­кие сиг­натуры «UPX!», раз­мер и некото­рые парамет­ры заг­рузчи­ка;
  • packed program info ( p_info ). В этом заголов­ке находят­ся раз­меры неупа­кован­ного бло­ка p_blocksize и неупа­кован­ной (исходной) прог­раммы p_filesize , которые, как пра­вило, рав­ны;
  • block info ( b_info ) пред­варя­ет каж­дый сжа­тый блок и содер­жит информа­цию о раз­мерах до и пос­ле сжа­тия, алго­рит­ме (методе), уров­не сжа­тия бло­ка и дру­гих парамет­рах. На рисун­ке ниже ты можешь видеть по сме­щению 0x110 сиг­натуру ELF: это и есть начало упа­кован­ного фай­ла. Заголовки в начале
  • packheader добав­ляет­ся в кон­це фай­ла, обыч­но занимая нем­ного боль­ше 0x24 байт в зависи­мос­ти от вырав­нивания. Его выделя­ют две сиг­натуры UPX! , вто­рая из которых выров­нена по четырех­бай­товой гра­нице. В packheader записы­вает­ся информа­ция, необ­ходимая самому UPX, что­бы ста­тичес­ки рас­паковать бинарь, не при­бегая к коду заг­рузчи­ка. В нее вхо­дят, в час­тнос­ти, уже наз­ванные дан­ные — раз­мер рас­пакован­ного фай­ла и некото­рые парамет­ры сжа­тия. В резуль­тате это­го получа­ется некото­рая избы­точ­ность. Как видим, обве­ден­ное зна­чение сов­пада­ет с хра­нящи­мися в p_info раз­мерами неупа­кован­ных бло­ка и фай­ла. Это может нем­ного помочь нам в даль­нейшем при рас­смот­рении спо­собов защиты от ста­тичес­кой рас­паков­ки. Заголовок в конце файла

Ес­ли тебе хочет­ся луч­ше понять про­цесс ста­тичес­кой рас­паков­ки UPX, то нарав­не с чте­нием сор­цов ты можешь вос­поль­зовать­ся дебаж­ным фла­гом. Тог­да ты уви­дишь, что на осно­ве име­ющих­ся в бинаре заголов­ков упа­ков­щик выбира­ет фун­кцию, которой будет рас­паковы­вать файл. Здесь наб­люда­ется то же огра­ниче­ние, что и для stub loader: для каких фор­матов и аппа­рат­ных плат­форм они сущес­тву­ют, те и под­держи­вают­ся. Спи­сок весь­ма вну­шите­лен.

UPX перебирает все возможные функции упаковки перед тем, как сдаться

Распаковываем себя

Что же про­исхо­дит, ког­да бинарь рас­паковы­вает­ся не коман­дой upx -d , а сво­им собс­твен­ным кодом? В этом слу­чае за про­исхо­дящее отве­чает заг­рузчик. Рас­паковы­вать он может либо сра­зу в память, либо с исполь­зовани­ем вре­мен­ных фай­лов с пос­леду­ющим их запус­ком — это будет зависеть от кон­крет­ной реали­зации.

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

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

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

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

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