UPXによるパックとアンパックとか

バイナリやリバースエンジニアリングの入門書には
必ずといっていいほど取り上げられているパッカーUPXに関しての
使い方やアンパックの方法なんかをまとめてみます。

1.参考リンク

2.概要(wikipediaより引用)

※より詳しい内容はwikipediaを参照してください

UPX (ultimate packer for executables)は様々なOSのファイル形式に対応した
FLOSSの実行ファイル圧縮ソフトウェアである。

  • 圧縮にはUCLと呼ばれるデータ圧縮アルゴリズムを用いてる
  • UCLは解凍用のコードがわずか数百バイトで実装できるようなシンプルな設計となっている。UCLは解凍のための追加のメモリ割り当てを要求しない。このことはUPXで圧縮された実行ファイルが余計なメモリを要求しないことを意味し、明確な優位点となっている。
  • UPX(2.90 beta以上)では多くのプラットフォームでLZMAが利用可能になっている。

サポートされているフォーマット

  • ARM/PE
  • Atari/tos
  • *BSD/i386
  • djgpp2/COFF
  • dos/com
  • dos/exe
  • dos/sys
  • Linux/i386 a.out
  • i386、x86-64、ARM、PowerPC上のLinux/ELF
  • i386、x86-64、ARM上のLinux/kernel
  • Mach-O/ppc32、Mach-O/i386 (Google Goを用いて生成されたものを除く)
  • rtm32/PE
  • tmt/adam
  • PlayStation1/exe
  • Watcom/le
  • Win32/PE (.NET Frameworkを用いて作られたファイルを除く)

プレステの実行ファイルもかよ!!!

※補足リンク

3.実行ファイルをパックしてみる

UPX(1) Linux man pageより引用

Compress:
This is the default operation, eg. upx yourfile.exe will
compress the file specified on the command line.

簡単ですね

upxコマンド(winならupx.exe)の引数に圧縮したいファイルパスを指定して実行するだけ

サンプルコードはこちら。めっちゃ単純。

<

pre>

include <stdio.h>

int main(int argc, char *argv[]){

}

これを普通にコンパイルして、ファイルサイズを見てみます。

compile_before_pack

約48KBです。
ollydbgでアセンブリコードも見てみます。(実行ファイル全体じゃなくて、
ソースコードに対応する箇所だけ)

ソースコードにそのまんま対応しているのがわかると思います。

IDAで実行ファイルを解析してみた図がこちら。

before_pack_ida

こちらもパッと見でちゃんとソースコードが対応しているのがわかります。
問題なさそうなので、こちらをパックしてみます。

pack_exe

ファイルサイズが48kBから約29kBまで圧縮されました。わお。

まずはollydbgで見てみます、が。
さっきのような関数呼び出しや、文字列が見当たらない・・・・。

IDAで見てみると、パック前とくらべて半端じゃなく複雑になったことが
わかると思います。

packed_exe

UPXはupx.exe自体でアンパックもサポートしている上に、アルゴリズムも
単純で手動アンパックも比較的容易ですが、アセンブリコードやバイナリだけを
見れば、圧縮・そして難読化されていることが確認できると思います。

4.実行ファイルをアンパックしてみる

UPX(1) Linux man pageより引用

Decompress:
All UPX supported file formats can be unpacked using the -d switch, eg.
upx -d yourfile.exe will uncompress the file you’ve just compressed.

こちらも簡単。-dオプションをつけて、UPXでパックされてるファイルの
パスを渡すだけ。

unpacke_exe

ファイルサイズが元通りになってますね。
スクリーンショット撮り忘れちゃいましたが、バイナリもIDAやollydbgで
ちゃんと読めるようになってます。

5.upx.exeなしで手動アンパックしてみる

手順としては以下の通りです。詳細を書こうとおもったんだけど
参考にしてた本、何冊かに載ってた通りにしても再現できなかったので、ざっくり手順だけ

  1. パックされた実行ファイルをollydbgにアタッチする
  2. PUSHAD命令に対応するPOPAD命令を見つけてそこにブレークポイント仕掛ける
  3. POPAD命令でブレークしたら、そこからステップ実行を進めて、CALL命令見つける。
  4. CALL命令で移動した先で、プログラムを一時停止
  5. ollydump(Method2:Search DLL & API name string in dumped file)でダンプ

これだけ。4のCALL命令は僕の環境だといくつかあって、CALL命令のジャンプ先で
ollydumpすれば、どれかしら正解で普通に実行できます。

ちゃーんと読めば、ピンポイントでダンプできると思うんですが、環境によって違うので
うまく書けない・・・。

説明できることがあれば、改めてまとめたいと思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です