非手続き型言語の生成するコードとは
昨日の最後のプログラム、リソースをテキストでべた打ちしながら
これはまともなアプリケーションなら書き換えられんように
しなければならないなぁ、そんなもん簡単な暗号化でも施しといたらいいやん?
でもそれだと逆アセしたら簡単に解析されてしまうんじゃ…。
あれ、ちょっと待てよ。Haskellのコードって逆アセして普通に
処理が追えるようなものなのか?遅延評価だぞ、遅延評価。
というか、そもそも処理も記述しないしな。
もしかしたらお手軽に破られにくい軽量な暗号が実現するかも、
ということで、調べてみることにした。
module Main(main) where import System import System.IO import Data.Char import Data.Bits main = do [mode,infile] <- getArgs case mode of "-d" -> p infile ".dec" decr "-e" -> p infile ".enc" encr _ -> error "unknown option" where p infile ext f = do let outfile = takeWhile (/='.') infile ++ ext ih <- openBinaryFile infile ReadMode oh <- openBinaryFile outfile WriteMode dat <- hGetContents ih hPutStr oh $ f dat encr xs = map chr ps where ns = map ord xs ps = [(a `xor` b) `xor` 0x55 | (a,b) <- zip (0:ns) ns] decr xs = map chr $ n:f (n:ns) where (n:ns) = map ((xor 0x55) . ord) xs f [_] = [] f (x:y:rest) = d:f (d:rest) where d = x `xor` y
適当に暗号・複合プログラムをでっち上げた。
encrが符号化・decrが復号化である。
アルゴリズムは隣り合うバイト同士のxorをとって
それから55hをxorするだけの簡単なもの。
これをGHCを用いてアセンブリリストにコンパイルしてみた。
で、読んでみようと思ったのだが、案の定というか、
思った通りというか、全然読めない。
.text .align 2 .long _r1fH_srt+16 .long 131072 .long 851986 _s1ht_info: .text _s1ht_entry: /APP /NO_APP leal -20(%ebp), %eax cmpl 84(%ebx), %eax jb L45 addl $12, %edi cmpl 92(%ebx), %edi jbe L44 L45: movl $3, 108(%ebx) jmp *-8(%ebx) L44: leal -8(%ebp), %eax movl $_stg_upd_frame_info, (%eax) movl %esi, 4(%eax) movl $_s1hr_info, -8(%edi) movl $_GHCziBase_ord_closure, -12(%ebp) leal -8(%edi), %eax movl %eax, -16(%ebp) movl $_GHCziBase_zi_closure, %esi subl $20, %ebp jmp _stg_ap_pp_ret
適当な抜粋。全体では2000行ぐらいあるけど。
movl $_GHCziBase_ord_closure, -12(%ebp)
この辺にordを使ったかな、という痕跡が見て取れる。
がしかし、やっぱり全く読めない。
ソースのどことどこが対応しているのかさえ分からない。
しかも上のアセンブリソース、実際に実行ファイルから
逆アセンブラした場合はラベルが無いわけで、この程度も読み取れるかどうか。
結局今のところの感想としては
「解読無理っぽい」
そこで、今回は読者(居るんかいな?)への挑戦を残しておく。
符号・復号プログラムからアルゴリズムを推測して欲しい。
アルゴリズムが分かった方はコメントあたりでお知らせ願いたい。
プログラムは上のソースのencrとdecrを書き換えただけのもの。
アルゴリズムのレベルも大体上と同じぐらい。
正解者先着一名様には………何もありません。
私の考えの浅はかさが露呈するだけ…。