世界初!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日の公開直前になって、過去のエイプリルフールネタサイトやらを見なおしていると、あまりにも自分のセンスのなさを再認識し、公開をやめようかとためらいました。。。
それでも、失敗を恐れずに自分の作品を発信すべきと思ったので、公開に至りました。
今回の記事を、ここまで読んでくださった方に感謝。
この記事によって、何か新しい発見につながれば嬉しいです。