アーキテクチャをスマートに。

株式会社ネオジニア代表。ITアーキテクトとしてのお仕事や考えていることなどをたまに綴っています。(記事の内容は個人の見解に基づくものであり、所属組織を代表するものではありません)

世界初!Pure Java で DLL - 解説編(2)

さて続きです。

コード中で、実行してデバッガで追いかけてみないとわからない部分は、

long addr = 0x65f5520;
...
  jni.write(b ^ (byte)(addr/**//=32) & 037);  // b ^ (byte)(addr>>=5) & 0x1f

のあたりではないかと思います。


ビット演算の部分の解説

"Hello fooL !\n" を1バイトずつ取り出してXORしているのですが、この演算を詳細に追いかけてみましょう。
0x65f5520 は 16進数なのですが、これを2進数で表記すると、

0000 0110 0101 1111 0101 0101 0010 0000

です。Googleで確認
これを、>>=5 して 0x1f で AND をとるので、5ビットずつ使うわけです。
5ビットずつに分けて表記すると、

00 00011 00101 11110 10101 01001 00000

となります。これを右から使っていきますが、一番右は使われません。
すなわち、

00 00011 00101 11110 10101 01001 00000
   5回目 4回目 3回目 2回目 初回  使われない

となります。

一方、"Hello fooL !\n" を1バイトずつ取り出している方を見てみましょう。
実際にXOR演算されるのは5文字だけなので、"Hello" の部分だけ着目します。
まず ASCIIコード表 を見て1文字ずつ2進数にしてみます。

H : 0x48 = 01001000
e : 0x65 = 01100101
l : 0x6c = 01101100
l : 0x6c = 01101100
o : 0x6f = 01101111

ですね。

では、1文字ずつ順番に XOR してみましょう。XORはビットが異なるときに1、同じ時に0になる演算ですね。→wikipedia:排他的論理和
※ビット演算は、筆算形式で書くとわかりやすいですね。

初回	(H)  01001000  XOR  01001
      01001000
  XOR    01001
  ------------
   =  01000001   = 0x41

演算結果は 01000001、16進数で書くと 0x41 です。
続けて、2〜5回目の演算も調べてみましょう。

2回目	(e)  01100101  XOR  10101
      01100101
  XOR    10101
  ------------
   =  01110000   = 0x70
3回目	(l)  01101100  XOR  11110
      01101100
  XOR    11110
  ------------
   =  01110010   = 0x72
4回目	(l)  01101100  XOR  00101
      01101100
  XOR    00101
  ------------
   =  01101001   = 0x69
5回目	(o)  01101111  XOR  00011
      01101111
  XOR    00011
  ------------
   =  01101100   = 0x6c

これ以降は、addr の値が 0 になってしまうので、XORの効果はありません。

では、演算結果をASCIIコード表で逆引きし、文字を割り当ててみましょう。

0x41 : A
0x70 : p
0x72 : r
0x69 : i
0x6c : l

これで "Hello" → "April" の変換ができました。

実はこれは一種の暗号とも考えることができます。
0x65f5520 が暗号鍵になっており、この鍵がないと元の文字列が取り出せないわけです。


以上で解説は終わりです。

作品の評価

今回のネタを作品として評価した場合、どういう観点で評価したらいいかな、と考えていました。

おそらく、多く人はコードを見ただけでは何をしているのか明解でないので、実行してみないとわからない、という印象を受けたのではないでしょうか。
それが一番の狙いで、「よくわからないけど、何か難しいことやってDLL化するのかな」と思わせられたとしたら、今回のネタは大成功です。

まぁそれもそのはず、故意に難読化したり、リフレクションやシステムプロパティを駆使して実行時の状態を動的に取得するようなコードになっていますから。

逆に、「よくわからないけど、何かを System.out に出力してるだけだな」と感づかれてしまった場合は、大失敗です。

または、実際に実行してみた人が "Hello DLL !" と出力されることを期待したかどうかが評価の分かれ目になるかもしれません。

あなたはどう感じましたか?

所感

エイプリルフールネタは今回が初挑戦でした。
こういうのはセンスが求められるので、難しいですね。

今回のネタは、実は3月初旬からネタを仕込んでいろいろ考えていたのですが、自分なりに、「ITエンジニアが楽しめるエイプリルフールネタってなんだろうな」って考えたとき、

  • トリッキーなプログラミングテクニックを使って
  • センセーショナルな話題で
  • わかる人にだけわかるマニアックコンテンツとして
  • 一見バカらしいけど真面目に文章化する
  • ネタばらしの時は、キッチリわかりやすく解説をする(自己満足で終わらない)

って感じかな〜、という答えを出しました。

4月1日の公開直前になって、過去のエイプリルフールネタサイトやらを見なおしていると、あまりにも自分のセンスのなさを再認識し、公開をやめようかとためらいました。。。

それでも、失敗を恐れずに自分の作品を発信すべきと思ったので、公開に至りました。


今回の記事を、ここまで読んでくださった方に感謝。
この記事によって、何か新しい発見につながれば嬉しいです。