almost 9 years ago
題目是一個 apk。
直接上 apk-tool,馬上就報錯了:
Exception in thread "main" brut.androlib.AndrolibException: brut.directory.DirectoryException: java.util.zip.ZipException: invalid CEN header (encrypted entry)
Zip 檔有加密?!
稍微找了一下,可以發現目錄結構下有些檔案,是 apk 檔共通的檔案,所以只要從其他沒加密的 apk 把對應檔案拿出來,就可以有 known plaintext attack。
但是要做到這個 attack,需要用一樣的方法壓縮找到的 plaintext,所以就來看看他是怎麼壓縮的吧:
$ unzip -v AFERE.zip
Archive: AFERE.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
396 Defl:N 207 48% 2014-08-22 23:20 2f94166b res/anim/abc_fade_in.xml
...
$ unzip -v abc_fade_in.zip
Archive: abc_fade_in.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
396 Defl:N 219 45% 2014-08-15 15:45 2f94166b abc_fade_in.xml
奇怪,明明原始檔案大小一樣,壓縮方式一樣,連 CRC 都一樣,為什麼壓起來就是差了 12 byte...
仔細一想,ZIP 檔壓縮時如果有加密,會在檔案前面多 12 byte 的 header,所以這個檔案看起來會少 12 byte 其實是因為他根本沒加密?!
查了一下 ZIP 檔格式,指定檔案有沒有加密的是在 General purpose bit flag 的第一個 bit,手動把 APK 中相對應的 bit 改成 0 就解的開了...
(實際上我們需要的只有 classes.dex,所以只改這個檔案就夠了。)
後面就是簡單的 apk 反編譯了,jd-gui 解出來的有點錯誤,還是看 jad 解出來的比較好。
後半是個簡單的 crypto,就看懂 code 後把流程想辦法反過來就對了。
require 'openssl'
target = 'OKBvTrSKXPK3cObqoS21IW7Dg0eZ2RTYm3UrdPaVTdY*'.each_byte.to_a
a = 'S4wp902KOV7QRogXdIUCMW1/ktz8sa5c3xePGfENuDTvBFqAmrbnLlHZYyhJij6+'.each_byte.to_a
bytes = []
(0...11).each do |i|
v0, v1, v2, v3 = target[4*i...4*i+4].map{|x| a.index x}
bytes << ((v0 << 2) | (v1 >> 4))
bytes << (((v1 & 0x0f) << 4) | (v2 >> 2))
bytes << (((v2 & 0x03) << 6) | v3) if v3
end
orig = []
(0...11).each do |i|
b0, b1, b2 = bytes[3*i...3*i+3]
b2 ||= 0
orig << ((b0 >> 2) & 0x3f)
orig << (0x3f & ((b0 << 4) | ((b1 & 0xFF) >> 4)))
orig << (0x3f & ((b1 << 2) | ((b2 & 0xFF) >> 6)))
orig << (b2 & 0x3f)
end
cipher = OpenSSL::Cipher::Cipher.new('des-ecb')
cipher.decrypt
cipher.key = 'Mem3d4Da'
puts cipher.update(bytes.map(&:chr).join).inspect
Flag: ISG{f4kE3ncRyP71On!50ld}