逆コンパイル

バージョン: industrialcraft-2-2.2.720-experimental

概要




 
 

逆コンパイルとは、ソースコードからバイナリや別の中間コードに変換するコンパイルという操作の逆で、バイナリや中間コードからソースコードを生成する操作である。

一般的に逆コンパイルは非常に難しい操作だが、Javaでは割と簡単にできる。その簡単さはすさまじく、MinecraftのMODが大規模化したのもこれのせいであろう。

 

アセンブリ

Javaはコンパイル時に実行可能形式のバイナリではなく、クラスファイルという実行するにはもう一回ちょっとコンパイルしないといけないバイナリを出力している。EclipseにASMのプラグインを入れて使ってみると、クラスファイルの中に存在するJavaのアセンブリコードを見たり、クラスファイルを出力(Dump)するJavaソースコードを生成したりできる。ただし、Javaのメソッドは65535バイトの壁があるようで、馬鹿でかいクラスをDumpさせようとするとそのままでは実行できない。でも別のメソッドを作って大まかに分けてやるとできる。

うまく使うとjarしか持っていないJavaライブラリ(身近な例でいうとMOD)を持っていたらその中身をインタプリタ言語の如く改造やデバッグしたりできる。

更に、CoreModというMinecraftForgeの機能を使うとMod内のコードでこのJavaアセンブリをいじれるようになり、どうしてもAPIだけではいじれないものの挙動すら変更ができる(例えばTileEntityCropのプライベートメソッド内のバグ)。Forgeの鍛冶力は変態である。

逆コンパイラ

筆者はそんなに逆コンパイラに詳しくは無いが、とりあえずJava DecompilerとPleiades Eclipse 4.4 Lunaにくっついてくる逆コンパイラ(JD-EclipseとJad)で一応満足の行く逆コンパイルが出来ているのでこれを使っている。

逆コンパイルコードの不正確さ

種分析機の記事にある通り、逆コンパイラごとに性能が異なるようである。この記事だけ見るとPleiades Eclipseにくっついてくる奴が出す内容を信じるのが良さそうであるが、なんか完璧な逆コンパイラなんて無い気もする。

ちなみに交配と雑草について発生してい(る|た)switchに起因する謎挙動は、実際にゲーム内で確認したしEclipseのクラスビューワで見ても正しくバグっているコードが出てくるので間違いない。

MinecraftのMODにおける逆コンパイル

Minecraftのソースコードは公表されていない(はずな)ので、MOD作りでは、Forge(MCP)がMinecraftのJavaアセンブリを逆コンパイルして出てきたJavaコードをソースコードにして改造パッチを当てたものを親プログラムに利用している。この時点で逆コンパイルが出てきている

同様に、ソースコードが公開されていないMODでも逆コンパイルすればソースが見えてくるのである(ソースが公開されているのに逆コンパイルをしていたらたぶん無駄足になると思う(公式ソースコードが本当にソースコードである保証は無いが))。

Javaでプログラムを書く以上、配布ファイルからソースが解読されることは普通であると考えなければならない。それゆえ、どうしてもソースを守りたければ難読化などの手段によってハッカーを萎えさせるという対策が必要となる(Minecraftも元は難読化されているが)。

IndustrialCraft2 Experimentalにおける逆コンパイル

IC2Expではソースコードをまだ見つけていないので、逆コンパイルの手順を踏む必要がありそうである(下記のリストによると無さそう)(実はあるよ!って場合は募集中)。

ただしdev版が公開されている(dev版とは、デベロップ中でのコンパイルやデバッグ実行は全ての難読化が取り払われることを目指し手の加えられたMinecraftを使うので、その状態のMinecraftに入れられるjarのこと)ので、それを見ると逆コンパイルするだけで開発者の手元のソースに近いコードが取り出せる。

ソースコードの抽出方法

  • IC2ExpのJenkinsから目的のバージョンのdev版のJarをダウンロードする
  • Java Decompilerでヘルプメニューからソースセーブの行番号・メタデータの出力をOFFにする
  • Java DecompilerでダウンロードしたIC2ExpのJarを開き、zipに保存する
  • Zipファイルを展開し、適当なフォルダに設置する
  • なんかのツールを使うなどしてうまい具合に差分抽出する(Mercurial

MODの更新履歴も公式に発表されたものではなく、逆コンパイルしたコードをMercurialに突っ込んで差分抽出したものを評価し掲載している。

FernFlower

ForgeはどうやってMinecraftを逆コンパイルしているのかとForgeGradleのJarを逆コンパイルして覗いてみると、ForgeはMinecraftの逆コンパイルにFernFlowerなるものを使っていた。

とりあえずソースをダウンロードしてコンパイルして圧縮して実行してみると、

java -cp fernflower.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompilerindustrialcraft-2-2.2.720-experimental-dev.jarout

outにそれらしいjavaファイルが大量に含まれるjarが出現した。

あのForgeが使ってるんだし一番尤もらしく見える・・・

バッチファイル化

以下のフォルダ構成にする。

  • どこかのディレクトリ
    • fernflower.bat (下記参照)
    • fernflower.jar (コンパイルしたもの。単にzipして拡張子をjarにしただけでMANIFEST未設定でも可)
    • decompile (空フォルダ)
      • カラッポ

fernflower.batの内容↓

java -cp "%~dp0fernflower.jar" org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler %1 "%~dp0decompile"

move "%~dp0decompile\%~nx1" "%~dpn1-src.zip"

mkdir "%~dpn1-src"
set cd=%CD%
cd "%~dpn1-src"
jar xvf "%~dpn1-src.zip"
cd %cd%

pause

これで、fernflower.batにjarファイルをD&Dで喰わせたjarファイルと同じディレクトリに-src.jarと-srcが生成される。レジストリをいじってjarの右クリックコマンドに追加するとD&Dすらいらなくなる

 

最終更新:2015年05月24日 04:42