Javaはご存知の通り、javaファイルをclassファイルにコンパイルして実行する。
またはclassファイルを集めてアーカイブしたjarファイルなども使うが、Windowsのexeファイルのような実行ファイルとしてコンパイルすることは標準機能ではできない。
でも、Windowsではやはりアプリはexeファイルみたいなところがあるので、Javaをexe化するソフトウェアがある。
exe化することによる利点としては
+ ソフトウェアということがひと目で分かる。
+ 多くのClassファイルを一つにまとめることができる
というところがあるが
Classファイルが隠されてしまってどういう構成なのかわからないということにもなる。
というわけで、exe化したソフトウェアのソースを見てみたいということで
ちょっとexeからclassファイルを抽出してみよう。
僕はWindowsを持っていないので、知り合いが提供してくれたソフトウェアを使うことにする。
※Classファイルはバイナリだけれど、jadなどでデコンパイルすることは簡単に出来る。
バイナリエディタでexeファイルを見てみよう
exeファイルはもちろんバイナリだ。
例題に使うソフトウェアは、このexeだけでJavaで作ったプログラムを実行できる。
つまり、このexeファイルの中にclassが隠されているということだ。
Javaでclassファイルを一纏めにするのはjarという形式を使うが、これの実体は単なるzipだ。
このexeファイルのなかにおそらくjar化されたものが隠されていることだろう。
というわけでバイナリエディタで開いてみた。
バイナリは0と1で書かれているものだけれども、こんなふうに16進数で表示してくれる。
右側のペインはバイトをASCIIで表現してくれたものだ。
Launch4jという文字が見える。
これを使ってexe化したのだろう。
ZIPの部分を探す
すべてのファイルは0と1だけだけども、それを決まった形式でそれぞれのソフトウェアが読み込んでいる。
どういった形式かというのは規約で決まっている。
ZIPファイルの場合は中身のファイルエントリーごとに決まったヘッダのデータが挿入されている。
そして終端にも決まったデータが入っている。
最初のファイルエントリーのヘッダと、一番最後の終端レコードを探せばexe中のどこがzip形式のデータなのかわかる。
最初に現れるだろうローカルファイルヘッダの最初は、 0x504B0304 だ。
これをASCIIで表現すれば、PK\003\004 だ。
なぜPKなのかということだが、ZIPを開発した人がフィル・カッツなのでそのイニシャルということなんだろう。
彼は優れたプログラマだったが、アルコール依存症により2000年に他界している。
閑話休題、そのファイルヘッダを探した画像がこちら。
0x6600バイトから始まっているらしい。
同じように終わりも探してみよう。
終端レコードの始まりは 0x504B0506 だ。
終端レコードはこのPKがはじまってから数ビットには様々なデータが書かれるらしく、このexeの最後までzipであると思って問題ないだろう。
つまり、0x6600バイトから最後までがzip形式で抜き出せそうだ。
※オフセットが0x6600と書かれているが、アドレスと同じ意味だ。
1バイトは8bit 16進数2桁分が1バイト その1バイトごとにこのオフセットは一つ増える。
バイナリデータを抜き出す
ではこのexeから指定した場所から一部を抜き出さなければならない。
そういう時にはLinuxにはddコマンドがある。
ddコマンドはバイナリデータをそのままコピーしたりするときに使うけれども、どこからコピーするかという詳しい操作が可能になる。
単刀直入に僕が実行したコマンドをまず紹介する。
dd if=./JavaApp.exe of=./jtmp3.zip ibs=1 skip=26112
ifというのはコピー元、ofは出力先。逆にするとコピー元にするはずだったものを上書きしてしまうので本当に注意して欲しい。
ibsはコピー元から何バイトずつコピーしていくかを表している。
skipは先頭から何ブロック無視してコピーするかという意味で、ブロックはibsで指定した数値が1ブロックになる。
1バイトを指定したので、26112バイト無視することになる。
26112バイトがいきなり出てきたが、0x6600を10進数化した数字だ。
26112バイトから最後までをコピーして別ファイルにする。
それを解凍してみよう
バッチリ解凍できた。
META-INFなどが見えるので、jarファイルということがわかる。