[ksnctf] Jewel

ksnctfにチャレンジ 第15問目です。

※ksnctfは常駐型のCTFサイトです。 ※問題のページはコチラです。

Jewel

Androidアプリである apk ファイルが渡されます。 apkは zip アーカイブされているので

$ unzip Jewel.apk -d Jewel

展開できます。 この中の classes.dex が目的のファイルです。 コンパイルされているので dex2jar で jar に戻します。 dex2jarのセットが toolディレクトリにあるとして

$ tool/dex2jar-*/d2j-dex2jar.sh Jewel/classes.dex

これで classes-dex2jar.jar​ という名前で jar まで戻りました。 jar もまた unzip できます。

$ unzip ./classes-dex2jar.jar -d ./Class

これで Class/info/sweetduet/ksnctf/jewel/JewelActivity.java が閲覧可能になります。 内容をみると デバイスIDを取得して、そのIDを鍵にすることで AESで暗号化された Jewel/res/raw/jewel_c.png を復号し表示するという内容です。 FLAGもこの jewel_c.png を開けばわかるはずですが 肝心の デバイスID がわからない (=鍵がわからない) ので 画像を復号することができません。

ただし、15桁の値であるデバイスIDの上位8桁は 99999991 であり、デバイスIDをSHA256でhash化すると "356280a58d3c437a45268a0b226d8cccad7b5dd28f5d1b37abf1873cc426a8a5" ということが、デバイスID判定のコードから読み取れます。

よって下7桁分だけスクリプトで全通り検索して hash値が一致するものをみつければOKです。

必要なデバイスIDがわかったら KEY = "!(デバイスID)" IV = "kLwC29iMc4nRMuE5" を用いて AES-128-CBC にかけると もとの画像が復号できます。

画像によると、 pngに含まれるコメントデータにFLAGがあるらしいので

$ strings -n 21 jewel_c_dec.png
FLAG_????????????????

などを実行すればFLAGが取得できました。

以上の流れを 珍しくWrite up風に書くと↓こうなります。

#!/usr/bin/ruby

require 'digest/sha2'
require 'openssl'

target_id = "356280a58d3c437a45268a0b226d8cccad7b5dd28f5d1b37abf1873cc426a8a5"

#Step 1
puts "[+] Step1 "
for i in 0..9999999
    device_id = "99999991%07d"%i
    hashed_id = Digest::SHA256.hexdigest(device_id)
    if( hashed_id == target_id )
        puts " - device id = " + device_id
        break
    end
end

#Step2
puts "[+] Step2 "
puts " - Setup"
enc = File.open("jewel_c.png", "r")
dec = File.open("jewel_c_dec.png", "w")
cip = OpenSSL::Cipher::Cipher.new('AES-128-CBC')

cip.decrypt
cip.key = "!#{device_id}"
cip.iv  = "kLwC29iMc4nRMuE5"
puts " - key = !#{device_id}"
puts " - iv  = kLwC29iMc4nRMuE5"

puts " - Decrypt"
data = ""
data << cip.update(enc.read())
data << cip.final
dec.write(data)
puts " - done!"

#Step3
puts "[+] Step3 "
puts data[/FLAG_(.{16})/,0]