アセンブリで書かれたRC4は見た瞬間分かるか

先日、Japan Security Analyst Conference 2018に行ってきました。中津留さんの講演が終わってからの質疑応答で次のようなやり取りがありました。

Q: どうやって解析の効率化をしていますか?
A: pythonスクリプトを書いたり、あとは経験でRC4とかぱっと見で分かります

一方、twitterでは@ykameさんが次のような発言をされていました。

https://twitter.com/YuhoKameda/status/956340441917501441

ということで、改めてRC4を読んでみました。

RC4アルゴリズム復習

inaz2さんの素晴らしい記事が分かりやすいです。Pythonコードも記載されているので読めばなんとなく流れは分かるかと思います。
Pythonでストリーム暗号RC4を実装し、脆弱性の一端を垣間見る - ももいろテクノロジー
簡単なメモを残しておくと、KSA(Key-scheduling algorithm)とPRGA(Pseudo-random generation algorithm)の2つに処理が分かれています。

  1. KSAで鍵を元に256バイトのSという配列を初期化
  2. PRGAでSを更新しながら1バイトずつ出力

あとは出力されたバイト列と平文のXOR取るという流れです。

アセンブリで書かれたRC4

今回はマルウェアの検体ではなく、CODEBLUE CTFで出題されたIncident Responseを読んでいきます。(作問者はCharo-ITさん)
今回はRC4に関連する箇所のみ掲載します。まずはKSAから。

KSAの処理を追いかけてみます。

KSA
[0x00FA] aa_KSA_initializeSを初期化
         S[i] = i // iは0から255まで
[0x0112] aa_KSA_main_loopS[i]と交換するS[j]を決定
         j = (j + S[i] + key[i%len(key)])
[0x012D] 最後にS[i]S[j]を交換する(これを繰り返す)

続いてPRGAの処理

PRGA
[0x016A] i = (i+1)    % 256
[0x0181] j = (j+S[i]) % 256
[0x0184] S[i]S[j]を交換する
[0x019A] K = S[(S[i] + S[j]) % 256]を出力

RC4
[0x019F] PRGAから出力されたKdata[i]をXORで計算


RC4と特定するための特徴

ぱっと見でRC4だと特定するための特徴と思われるものをまとめてみます。

  • 256バイトのSという状態を持つ
  • 最初に鍵を元にKSAによってSの状態が初期化される(初回のみ呼ばれる)
  • Sの状態変化はswapで行われる
  • データの暗号化はPRGAから出力された1バイト値をXORによって暗号化する
  • KSAとPRGAの計算は似ている(けど鍵の計算がないので少し違う)
  • 暗号化と復号が同じ処理(送信と受信で同じ関数を使っている場合)

まとめ

たくさん読んで、たくさん経験する必要がある。
経験の浅さを痛感しました。間違っている箇所などあればご指摘いただけると嬉しいです。

最後に何もコメントを書いてないパターンも載せておきます。