「逆コンパイル」の編集履歴(バックアップ)一覧はこちら

逆コンパイル」(2015/05/24 (日) 04:42:06) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

<h1>逆コンパイル</h1> <h2>バージョン: industrialcraft-2-2.2.720-experimental</h2> <h3>概要</h3> <table border="1" cellpadding="1" cellspacing="1" style="width:400px;float:right;"><tbody><tr><td style="text-align:center;"><br /><br /><br />  </td> </tr><tr><td style="text-align:center;"> </td> </tr></tbody></table><p><span style="line-height:20.7999992370605px;">逆コンパイルとは、ソースコードからバイナリや別の中間コードに変換するコンパイルという操作の逆で、バイナリや中間コードからソースコードを生成する操作である。</span></p> <p><span style="line-height:20.7999992370605px;">一般的に逆コンパイルは非常に難しい操作だが、Javaでは割と簡単にできる。その簡単さはすさまじく、MinecraftのMODが大規模化したのもこれのせいであろう。</span></p> <p style="clear:right;"> </p> <h3>アセンブリ</h3> <p><span style="line-height:20.7999992370605px;">Javaはコンパイル時に実行可能形式のバイナリではなく、</span><span style="line-height:20.7999992370605px;color:rgb(255,140,0);">クラスファイルという実行するにはもう一回ちょっとコンパイルしないといけないバイナリ</span><span style="line-height:20.7999992370605px;">を出力している。EclipseにASMのプラグインを入れて使ってみると、クラスファイルの中に存在するJavaのアセンブリコードを見たり、クラスファイルを出力(Dump)するJavaソースコードを生成したりできる。<span style="color:#A9A9A9;">ただし、Javaのメソッドは65535バイトの壁があるようで、馬鹿でかいクラスをDumpさせようとするとそのままでは実行できない。でも別のメソッドを作って大まかに分けてやるとできる。</span></span></p> <p>うまく使うと<span style="color:#FF8C00;">jarしか持っていないJavaライブラリ(身近な例でいうとMOD)</span>を持っていたらその中身をインタプリタ言語の如く改造やデバッグしたりできる。</p> <p> 更に、CoreModというMinecraftForgeの機能を使うとMod内のコードでこのJavaアセンブリをいじれるようになり、どうしてもAPIだけではいじれないものの挙動すら変更ができる(例えばTileEntityCropのプライベートメソッド内のバグ)。Forgeの鍛冶力は変態である。</p> <h3>逆コンパイラ</h3> <p>筆者はそんなに逆コンパイラに詳しくは無いが、とりあえず<a href="http://jd.benow.ca/" style="line-height:20.7999992370605px;">Java Decompiler</a><span style="line-height:20.7999992370605px;">とPleiades Eclipse 4.4 Lunaにくっついてくる逆コンパイラ(JD-EclipseとJad)で一応満足の行く逆コンパイルが出来ているのでこれを使っている。</span></p> <h4>逆コンパイルコードの不正確さ</h4> <p style="line-height:20.7999992370605px;"><a href="http://www54.atwiki.jp/mi_ic2/pages/108.html">種分析機</a>の記事にある通り、逆コンパイラごとに性能が異なるようである。この記事だけ見るとPleiades Eclipseにくっついてくる奴が出す内容を信じるのが良さそうであるが、なんか<strong>完璧な逆コンパイラなんて無い</strong>気もする。</p> <p style="line-height:20.7999992370605px;">ちなみに<span style="line-height:20.7999992370605px;">交配と雑草について発生してい(る|た)switchに起因する謎挙動は、実際にゲーム内で確認したしEclipseのクラスビューワで見ても正しくバグっているコードが出てくるので間違いない。</span></p> <h3>MinecraftのMODにおける逆コンパイル</h3> <p>Minecraftのソースコードは公表されていない(はずな)ので、MOD作りでは、Forge(MCP)が<span style="color:#FF8C00;">MinecraftのJavaアセンブリを逆コンパイルして出てきたJavaコード</span>をソースコードにして改造パッチを当てたものを親プログラムに利用している。<strong>この時点で逆コンパイルが出てきている</strong>。</p> <p> 同様に、ソースコードが公開されていないMODでも逆コンパイルすればソースが見えてくるのである(ソースが公開されているのに逆コンパイルをしていたらたぶん無駄足になると思う(公式ソースコードが本当にソースコードである保証は無いが))。</p> <p> Javaでプログラムを書く以上、配布ファイルからソースが解読されることは普通であると考えなければならない。それゆえ、どうしてもソースを守りたければ難読化などの手段によってハッカーを萎えさせるという対策が必要となる(Minecraftも元は難読化されているが)。</p> <h3>IndustrialCraft2 Experimentalにおける逆コンパイル</h3> <p>IC2Expではソースコードをまだ見つけていないので、逆コンパイルの手順を踏む必要がありそうである(<span style="line-height:20.7999992370605px;">下記のリストによると無さそう</span>)(実はあるよ!って場合は募集中)。</p> <ul style="line-height:20.7999992370605px;"><li><a href="https://github.com/agaricusb/ForgeMod/wiki/List-of-Open-Source-Forge-Mods">List of Open Source Forge Mods</a>(https://github.com/agaricusb/ForgeMod/wiki/List-of-Open-Source-Forge-Mods)/2015年4月20日</li> <li><a href="http://www.minecraftforge.net/wiki/List_of_Open_Source_Forge_Mods">List of Open Source Forge Mods</a>(http://www.minecraftforge.net/wiki/List_of_Open_Source_Forge_Mods)/<span style="line-height:20.7999992370605px;">2015年</span><span style="line-height:20.7999992370605px;">4月</span><span style="line-height:20.7999992370605px;">20日</span></li> </ul><p>ただしdev版が公開されている(dev版とは、デベロップ中でのコンパイルやデバッグ実行は<span style="color:#FF8C00;">全ての難読化が取り払われることを目指し手の加えられたMinecraft</span>を使うので、その状態のMinecraftに入れられるjarのこと)ので、それを見ると逆コンパイルするだけで開発者の手元のソースに近いコードが取り出せる。</p> <h3>ソースコードの抽出方法</h3> <ul style="line-height:20.7999992370605px;"><li>IC2Expの<a href="http://ic2api.player.to:8080/job/IC2_experimental/">Jenkins</a>から目的のバージョンのdev版のJarをダウンロードする</li> <li><a href="http://jd.benow.ca/">Java Decompiler</a>でヘルプメニューからソースセーブの行番号・メタデータの出力をOFFにする</li> <li>Java DecompilerでダウンロードしたIC2ExpのJarを開き、zipに保存する</li> <li>Zipファイルを展開し、適当なフォルダに設置する</li> <li>なんかのツールを使うなどしてうまい具合に差分抽出する(<a href="http://mercurial.selenic.com/">Mercurial</a>)</li> </ul><p><a href="http://www54.atwiki.jp/mi_ic2/pages/104.html" style="line-height:20.7999992370605px;">MODの更新履歴</a><span style="line-height:20.7999992370605px;">も公式に発表されたものではなく、逆コンパイルしたコードをMercurialに突っ込んで差分抽出したものを評価し掲載している。</span></p> <h3><span style="line-height:20.7999992370605px;">FernFlower</span></h3> <p> ForgeはどうやってMinecraftを逆コンパイルしているのかとForgeGradleのJarを逆コンパイルして覗いてみると、ForgeはMinecraftの逆コンパイルに<a href="https://github.com/fesh0r/fernflower" style="line-height:1.6em;">FernFlower</a>なるものを使っていた。</p> <p>とりあえずソースをダウンロードしてコンパイルして圧縮して実行してみると、</p> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"> <span style="color:#808080;">java -cp fernflower.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler</span><span style="color:#FF0000;">industrialcraft-2-2.2.720-experimental-dev.jar</span><span style="color:#0000FF;">out</span></div> <p>outにそれらしいjavaファイルが大量に含まれるjarが出現した。</p> <p><span style="line-height:1.6em;">あのForgeが使ってるんだし一番尤もらしく見える・・・</span></p> <h4>バッチファイル化</h4> <p>以下のフォルダ構成にする。</p> <ul><li>どこかのディレクトリ <ul><li>fernflower.bat (下記参照)</li> <li>fernflower.jar (コンパイルしたもの。単にzipして拡張子をjarにしただけでMANIFEST未設定でも可)</li> <li>decompile (空フォルダ) <ul><li>カラッポ</li> </ul></li> </ul></li> </ul><p><span style="line-height:1.6em;">fernflower.batの内容↓</span></p> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"> <p>java -cp "%~dp0fernflower.jar" org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler %1 "%~dp0decompile"</p> <p>move "%~dp0decompile\%~nx1" "%~dpn1-src.zip"</p> <p>mkdir "%~dpn1-src"<br /> set cd=%CD%<br /> cd "%~dpn1-src"<br /> jar xvf "%~dpn1-src.zip"<br /> cd %cd%</p> <p>pause</p> </div> <p>これで、<span style="line-height:20.7999992370605px;"><span style="color:#FF8C00;">fernflower.batにjarファイルをD&amp;D</span>で喰わせたjarファイルと同じディレクトリに-src.jarと-srcが生成される。レジストリをいじってjarの右クリックコマンドに追加するとD&amp;Dすらいらなくなる</span></p> <p> </p>
<h1>逆コンパイル</h1> <h2>バージョン: industrialcraft-2-2.2.720-experimental</h2> <h3>概要</h3> <table border="1" cellpadding="1" cellspacing="1" style="width:400px;float:right;"><tbody><tr><td style="text-align:center;"><br /><br /><br />  </td> </tr><tr><td style="text-align:center;"> </td> </tr></tbody></table><p><span style="line-height:20.7999992370605px;">逆コンパイルとは、ソースコードからバイナリや別の中間コードに変換するコンパイルという操作の逆で、バイナリや中間コードからソースコードを生成する操作である。</span></p> <p><span style="line-height:20.7999992370605px;">一般的に逆コンパイルは非常に難しい操作だが、Javaでは割と簡単にできる。その簡単さはすさまじく、MinecraftのMODが大規模化したのもこれのせいであろう。</span></p> <p style="clear:right;"> </p> <h3>アセンブリ</h3> <p><span style="line-height:20.7999992370605px;">Javaはコンパイル時に実行可能形式のバイナリではなく、</span><span style="line-height:20.7999992370605px;color:rgb(255,140,0);">クラスファイルという実行するにはもう一回ちょっとコンパイルしないといけないバイナリ</span><span style="line-height:20.7999992370605px;">を出力している。EclipseにASMのプラグインを入れて使ってみると、クラスファイルの中に存在するJavaのアセンブリコードを見たり、クラスファイルを出力(Dump)するJavaソースコードを生成したりできる。<span style="color:#A9A9A9;">ただし、Javaのメソッドは65535バイトの壁があるようで、馬鹿でかいクラスをDumpさせようとするとそのままでは実行できない。でも別のメソッドを作って大まかに分けてやるとできる。</span></span></p> <p>うまく使うと<span style="color:#FF8C00;">jarしか持っていないJavaライブラリ(身近な例でいうとMOD)</span>を持っていたらその中身をインタプリタ言語の如く改造やデバッグしたりできる。</p> <p> 更に、CoreModというMinecraftForgeの機能を使うとMod内のコードでこのJavaアセンブリをいじれるようになり、どうしてもAPIだけではいじれないものの挙動すら変更ができる(例えばTileEntityCropのプライベートメソッド内のバグ)。Forgeの鍛冶力は変態である。</p> <h3>逆コンパイラ</h3> <p>筆者はそんなに逆コンパイラに詳しくは無いが、とりあえず<a href="http://jd.benow.ca/" style="line-height:20.7999992370605px;">Java Decompiler</a><span style="line-height:20.7999992370605px;">とPleiades Eclipse 4.4 Lunaにくっついてくる逆コンパイラ(JD-EclipseとJad)で一応満足の行く逆コンパイルが出来ているのでこれを使っている。</span></p> <h4>逆コンパイルコードの不正確さ</h4> <p style="line-height:20.7999992370605px;"><a href="http://www54.atwiki.jp/mi_ic2/pages/108.html">種分析機</a>の記事にある通り、逆コンパイラごとに性能が異なるようである。この記事だけ見るとPleiades Eclipseにくっついてくる奴が出す内容を信じるのが良さそうであるが、なんか<strong>完璧な逆コンパイラなんて無い</strong>気もする。</p> <p style="line-height:20.7999992370605px;">ちなみに<span style="line-height:20.7999992370605px;">交配と雑草について発生してい(る|た)switchに起因する謎挙動は、実際にゲーム内で確認したしEclipseのクラスビューワで見ても正しくバグっているコードが出てくるので間違いない。</span></p> <h3>MinecraftのMODにおける逆コンパイル</h3> <p>Minecraftのソースコードは公表されていない(はずな)ので、MOD作りでは、Forge(MCP)が<span style="color:#FF8C00;">MinecraftのJavaアセンブリを逆コンパイルして出てきたJavaコード</span>をソースコードにして改造パッチを当てたものを親プログラムに利用している。<strong>この時点で逆コンパイルが出てきている</strong>。</p> <p> 同様に、ソースコードが公開されていないMODでも逆コンパイルすればソースが見えてくるのである(ソースが公開されているのに逆コンパイルをしていたらたぶん無駄足になると思う(公式ソースコードが本当にソースコードである保証は無いが))。</p> <p> Javaでプログラムを書く以上、配布ファイルからソースが解読されることは普通であると考えなければならない。それゆえ、どうしてもソースを守りたければ難読化などの手段によってハッカーを萎えさせるという対策が必要となる(Minecraftも元は難読化されているが)。</p> <h3>IndustrialCraft2 Experimentalにおける逆コンパイル</h3> <p>IC2Expではソースコードをまだ見つけていないので、逆コンパイルの手順を踏む必要がありそうである(<span style="line-height:20.7999992370605px;">下記のリストによると無さそう</span>)(実はあるよ!って場合は募集中)。</p> <ul style="line-height:20.7999992370605px;"><li><a href="https://github.com/agaricusb/ForgeMod/wiki/List-of-Open-Source-Forge-Mods">List of Open Source Forge Mods</a>(https://github.com/agaricusb/ForgeMod/wiki/List-of-Open-Source-Forge-Mods)/2015年4月20日</li> <li><a href="http://www.minecraftforge.net/wiki/List_of_Open_Source_Forge_Mods">List of Open Source Forge Mods</a>(http://www.minecraftforge.net/wiki/List_of_Open_Source_Forge_Mods)/<span style="line-height:20.7999992370605px;">2015年</span><span style="line-height:20.7999992370605px;">4月</span><span style="line-height:20.7999992370605px;">20日</span></li> </ul><p>ただしdev版が公開されている(dev版とは、デベロップ中でのコンパイルやデバッグ実行は<span style="color:#FF8C00;">全ての難読化が取り払われることを目指し手の加えられたMinecraft</span>を使うので、その状態のMinecraftに入れられるjarのこと)ので、それを見ると逆コンパイルするだけで開発者の手元のソースに近いコードが取り出せる。</p> <h3>ソースコードの抽出方法</h3> <ul style="line-height:20.7999992370605px;"><li>IC2Expの<a href="http://ic2api.player.to:8080/job/IC2_experimental/">Jenkins</a>から目的のバージョンのdev版のJarをダウンロードする</li> <li><a href="http://jd.benow.ca/">Java Decompiler</a>でヘルプメニューからソースセーブの行番号・メタデータの出力をOFFにする</li> <li>Java DecompilerでダウンロードしたIC2ExpのJarを開き、zipに保存する</li> <li>Zipファイルを展開し、適当なフォルダに設置する</li> <li>なんかのツールを使うなどしてうまい具合に差分抽出する(<a href="http://mercurial.selenic.com/">Mercurial</a>)</li> </ul><p><a href="http://www54.atwiki.jp/mi_ic2/pages/104.html" style="line-height:20.7999992370605px;">MODの更新履歴</a><span style="line-height:20.7999992370605px;">も公式に発表されたものではなく、逆コンパイルしたコードをMercurialに突っ込んで差分抽出したものを評価し掲載している。</span></p> <h3><span style="line-height:20.7999992370605px;">FernFlower</span></h3> <p> ForgeはどうやってMinecraftを逆コンパイルしているのかとForgeGradleのJarを逆コンパイルして覗いてみると、ForgeはMinecraftの逆コンパイルに<a href="https://github.com/fesh0r/fernflower" style="line-height:1.6em;">FernFlower</a>なるものを使っていた。</p> <p>とりあえずソースをダウンロードしてコンパイルして圧縮して実行してみると、</p> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;"> <span style="color:#808080;">java -cp fernflower.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler</span><span style="color:#FF0000;">industrialcraft-2-2.2.720-experimental-dev.jar</span><span style="color:#0000FF;">out</span></div> <p>outにそれらしいjavaファイルが大量に含まれるjarが出現した。</p> <p><span style="line-height:1.6em;">あのForgeが使ってるんだし一番尤もらしく見える・・・</span></p> <h4>バッチファイル化</h4> <p>以下のフォルダ構成にする。</p> <ul><li>どこかのディレクトリ <ul><li>fernflower.bat (下記参照)</li> <li>fernflower.jar (コンパイルしたもの。単にzipして拡張子をjarにしただけでMANIFEST未設定でも可)</li> <li>decompile (空フォルダ) <ul><li>カラッポ</li> </ul></li> </ul></li> </ul><p><span style="line-height:1.6em;">fernflower.batの内容↓</span></p> <div style="background:#eee;border:1px solid #ccc;padding:5px 10px;">java -cp "%~dp0fernflower.jar" org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler %1 "%~dp0decompile"<br /><br /> move "%~dp0decompile\%~nx1" "%~dpn1-src.zip"<br /><br /> mkdir "%~dpn1-src"<br /> set cd=%CD%<br /> cd "%~dpn1-src"<br /> jar xvf "%~dpn1-src.zip"<br /> cd %cd%<br /><br /> pause</div> <p>これで、<span style="line-height:20.7999992370605px;"><span style="color:#FF8C00;">fernflower.batにjarファイルをD&amp;D</span>で喰わせたjarファイルと同じディレクトリに-src.jarと-srcが生成される。レジストリをいじってjarの右クリックコマンドに追加するとD&amp;Dすらいらなくなる</span></p> <p> </p>

表示オプション

横に並べて表示:
変化行の前後のみ表示: