分析綜合實戰(zhàn):ISCC、NJCTF 與強網杯三道真題逆向全解析)
文檔網絡安全教程【免費下載鏈接】ctf-wikiCome and join us, we need you!項目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki點擊查看免費下載導讀本篇文章基于 ctf-wiki 倉庫 docs/zh-tw/docs/android/basic_reverse/static/complex-example.md 展開系統講解 Android 靜態(tài)分析中的綜合題目這類題目往往同時涉及 Java 層與 Nativeso層代碼需要通過反編譯、JNI 逆向、加密算法識別與腳本還原等手段聯合求解。讀完本文你將掌握 jadx 反編譯定位核心邏輯、IDA 分析 JNI 函數、識別 base64 / RC4 / AES 等常見算法以及編寫 Python 腳本還原明文flag的完整實戰(zhàn)流程并理解其對應的倉庫上下文Android 逆向基本介紹、Java 層靜態(tài)分析示例、原生層靜態(tài)分析示例。綜合題為何綜合在 Android 逆向基本介紹 中分析對象被劃分為兩類Java 層代碼與原生層Native代碼。單一題目的逆向往往只落在其中一層而綜合題目complex-example則刻意將邏輯分布在兩層甚至多段加密流程中Java 層負責 UI 交互、字符串預處理、調用 Native 接口Native 層so負責核心校驗或加解密密文可能先經 base64 等編碼再進入 XOR、RC4、AES 等密碼學變換。因此綜合題的求解天然是一條反編譯 → 定位關鍵函數 → 識別算法 → 寫腳本還原的流水線。而 Android 關鍵代碼定位 中提到的字符串定位法利用報錯信息、Toast 文案、log 定位函數與敏感 API 定位法在這一類題目中同樣適用——下文三道題正是這套方法論的完整演練。2017 ISCC Crackonebase64 編碼 JNI 字符變換反編譯定位主邏輯利用 jadx 對 apk 進行反編譯可以得到程序的基本邏輯如下對用戶輸入的內容進行base64 編碼然后在指定長度位置處插入\r\n這個操作對最終校驗沒有實際影響屬于干擾項之后程序將編碼后的內容傳遞給 so 中的check函數進行校驗。分析 so 中的 check 函數check是一個典型的 JNI 函數第一個參數a1是JNIEnv *它通過GetByteArrayRegion把 Java 層傳入的 byte 數組base64 編碼結果拷貝到 C 堆內存中再執(zhí)行一段字符級變換最后與硬編碼字符串比較。反編譯得到的核心邏輯如下env a1; len plen; str pstr; v7 malloc(plen); ((*env)-GetByteArrayRegion)(env, str, 0, len, v7); v8 malloc(len 1); memset(v8, 0, len 1); memcpy(v8, v7, len); v9 0; for ( i 0; ; i ) { --v9; if ( i len / 2 ) break; v11 v8[i] - 5; v8[i] v8[len v9]; v8[len v9] v11; } v8[len] 0; v12 strcmp(v8, 0HWYl1SE5UQWFfN?IPEo.UcshU); free(v8); free(v7); return v12 0;這段代碼的變換規(guī)則需要逐行拆解v9初始為 0循環(huán)體開頭執(zhí)行--v9因此循環(huán)進行到第i輪時v9 -(i1)v8[len v9]等價于v8[len - i - 1]即從字符串末尾向前取第i個字符變換核心是v8[i]前半段字符先自減 5然后與對稱位置的末尾字符v8[len-i-1]互換循環(huán)只在i len / 2時進行說明只處理字符串的前半部分與對稱位置的字符完成交換后即止最終用strcmp與硬編碼密文0HWYl1SE5UQWFfN?IPEo.UcshU比較v12 0視為通過嚴格說該返回值并不嚴謹但題目按相等設計。也就是說加密過程 base64(輸入) 的前半段逐字符減 5 并與對稱位置交換逆向時只需將密文對稱換回、再對前半段逐字符加 5最后 base64 解碼即可。Python 還原腳本根據上述規(guī)則很容易寫出對應的恢復代碼原文檔給出的是 Python 2 版本import base64 def solve(): ans 0HWYl1SE5UQWFfN?IPEo.UcshU length len(ans) flag [0] * length beg 0 end length while beg length / 2: end - 1 flag[beg] chr(ord(ans[end]) 5) flag[end] ans[beg] beg 1 flag .join(flag) print base64.b64decode(flag) if __name__ __main__: solve()腳本思路與 C 代碼完全對稱beg從頭遞增、end從尾遞減把密文對稱位置的字符換回同時把前半段密文逐字符5復原對應加密時的-5。若使用 Python 3只需將最后一行改為print(base64.b64decode(flag))并把除法與索引處理保持一致即可。運行結果如下? 2017ISCC python exp.py flag{ISCCJAVANDKYXX}從實戰(zhàn)角度看這道題的核心教訓在于so 層出現malloc/memcpy/strcmp 硬編碼字符串的模式幾乎必然是預處理后與密文比較的校驗邏輯逆向者的任務就是把字符級變換規(guī)則逐行翻譯成等價的還原代碼。2017 NJCTF easycrackJava 層異或 RC4 加密鏈程序基本邏輯通過簡單逆向可以發(fā)現程序的基本邏輯如下監(jiān)控界面文本框如果文本框內容改變則調用 nativeparseText函數parseText的主要功能如下首先調用 Java 層的函數messageMe獲取一個字符串mestr。這個函數的邏輯基本是依次將 packagename 最后一個.后面的字符串的每一個字符與 51 進行異或將結果拼接起來然后以mestr長度為周期將兩者進行異或核心邏輯為str[i j] mestr[j] ^ iinput[i j];即以mestr作為周期密鑰對輸入逐字節(jié)異或繼而下面以I_am_the_key為密鑰使用RC4加密對該部分進行加密然后將結果與最后的compare比較。識別 RC4 的依據在 Native 層如何確認這是 RC4原文檔給出了兩條非常實用的指紋依據在init函數中有256這個關鍵字而且基本就是 RC4 密鑰的初始化過程RC4 的 KSA 階段正是以 256 字節(jié)的 S 盒為核心crypt函數顯然就是一個 RC4 加密函數明顯就是 RC4 的加密邏輯PRGA 階段輸出密鑰流并與明文異或。這一按特征常數與結構識別算法的手法與 原生層靜態(tài)分析示例 中通過JNI_OnLoad與RegisterNatives表定位函數名的思路一脈相承先依據 256、S 盒交換等特征判斷算法族再驗證調用關系。解密腳本還原腳本需要反向走完整條鏈路RC4 解密 → 周期 XOR 解密 → messageMe 密鑰生成如下from Crypto.Cipher import ARC4 def messageme(): name easycrack init 51 ans for c in name: init ord(c) ^ init ans chr(init) return ans def decrypt(cipher,key): plain for i in range(0,len(cipher),len(key)): tmp cipher[i:ilen(key)] plain .join(chr(ord(tmp[i])^ord(key[i])) for i in range(len(tmp))) return plain def main(): rc4 ARC4.new(I_am_the_key) cipher C8E4EF0E4DCCA683088134F8635E970EEAD9E277F314869F7EF5198A2AA4 cipher .join(chr(int(cipher[i:i2], 16)) for i in range(0, len(cipher), 2)) middleplain rc4.decrypt(cipher) mestr messageme() print decrypt(middleplain,mestr) if __name__ __main__: main()腳本要點說明messageme()用包名尾段easycrack逐字符與 51初值異或模擬 Java 層的密鑰生成邏輯decrypt()按len(key)為周期切塊后逐字節(jié)異或對應 Native 層的周期異或密文C8E4...先按兩位十六進制轉成字節(jié)流再交給ARC4解密ARC4即 PyCrypto 對 RC4 的封裝對應加密方向為rc4.encrypt。運行結果如下? 2017NJCTF-easycrack python exp.py It_s_a_easyCrack_for_beginners ? 2017NJCTF-easycrack這道題的核心價值在于展示了一條Java 層生成密鑰 Native 層完成加密的跨層密鑰協商模式單看 Java 層無法得到完整校驗邏輯單看 Native 層又缺少mestr的生成規(guī)則必須兩層結合才能寫出正確的還原腳本。2018 強網杯 picture lock基于 APK 簽名的 AES 圖片加密程序概覽簡單分析之后發(fā)現這是一個圖片加密程序Java 層為 Native 層傳入image/下的第一個文件名、希望加密后的圖片文件名以及對應 apk 的簽名的 md5。加密的密鑰并非硬編碼而是從 APK 自身簽名指紋動態(tài)派生——這既防止了直接修改 apk 后仍能解密也要求逆向者必須先拿到原始簽名。識別 AES 與還原加密流程由于程序明顯是一個加密程序可以使用 IDA 的findcrypto 插件進行識別。結果發(fā)現了S 盒而且基本上符合AES的加密流程因此可以基本確定程序的主體是 AES 加密。經過細致分析native 層程序的基本流程如下將傳入的簽名的 md5 字符串分為兩半生成兩組密鑰每次讀入md5sig[i%32]大小的內容根據讀入的大小決定使用哪一組密鑰奇數使用第二組密鑰偶數使用第一組密鑰如果讀入的大小不夠 16 的話就將后面填充為不夠的大小例如大小為 12 時填充 4 個0x4此時修改后的內容必然夠 16 個字節(jié)對前 16 個字節(jié)進行AES 加密對于后面的字節(jié)將其與md5sig[i%32]依次進行異或??梢钥吹矫芪牡拿總€分塊長度都由簽名 md5 的對應字符決定分塊前半段16 字節(jié)走 AES、后半段走 XOR屬于典型的分段混合加密結構。這里的md5sig[i%32]實際是取 md5 十六進制字符串32 個字符的第i%32個字符的 ASCII 碼來充當長度與異或掩碼。獲取簽名 MD5既然知道加密算法那就很容易逆了。首先可以獲取簽名的 md5使用 JDK 自帶的keytool命令? picturelock keytool -list -printcert -jarfile picturelock.apk 簽名者 #1: 簽名: 所有者: CNa, OUb, Oc, Ld, STe, Cff 發(fā)布者: CNa, OUb, Oc, Ld, STe, Cff 序列號: 5f4e6be1 有效期為 Fri Sep 09 14:32:36 CST 2016 至 Tue Sep 03 14:32:36 CST 2041 證書指紋: MD5: F8:C4:90:56:E4:CC:F9:A1:1E:09:0E:AF:47:1F:41:8D SHA1: 48:E7:04:5E:E6:0D:9D:8A:25:7C:52:75:E3:65:06:09:A5:CC:A1:3E SHA256: BA:12:C1:3F:D6:0E:0D:EF:17:AE:3A:EE:4E:6A:81:67:82:D0:36:7F:F0:2E:37:CC:AD:5D:6E:86:87:0C:8E:38 簽名算法名稱: SHA256withRSA 主體公共密鑰算法: 2048 位 RSA 密鑰 版本: 3 擴展: #1: ObjectId: 2.5.29.14 Criticalityfalse SubjectKeyIdentifier [ KeyIdentifier [ 0000: 71 A3 2A FB D3 F4 A9 A9 2A 74 3F 29 8E 67 8A EA q.*.....*t?).g.. 0010: 3B DD 30 E3 ;.0. ] ]keytool -printcert輸出中的證書指紋給出了完整的MD5、SHA1、SHA256值其中 MD5 指紋即為程序所依賴的簽名哈希。接下來把帶冒號的 MD5 指紋轉成小寫十六進制字符串作為后續(xù)解密腳本的sig? picturelock md5valueF8:C4:90:56:E4:CC:F9:A1:1E:09:0E:AF:47:1F:41:8D ? picturelock echo $md5value | sed s/://g | tr [:upper:] [:lower:] f8c49056e4ccf9a11e090eaf471f418d這里sed s/://g用于去除冒號tr [:upper:] [:lower:]用于統一轉小寫——最終得到 32 個字符的簽名 md5 字符串與 Native 層md5sig[i%32]的索引規(guī)則完全對應。直接使用 AES 庫解密已知算法與密鑰后可以直接使用已有的 AES 庫進行解密#!/usr/bin/env python import itertools sig f8c49056e4ccf9a11e090eaf471f418d from Crypto.Cipher import AES def decode_sig(payload): ans for i in range(len(payload)): ans chr(ord(payload[i]) ^ ord(sig[(16i)%32])) return ans def dec_aes(): data open(flag.jpg.lock, rb).read() jpg_data f open(flag.jpg, wb) idx 0 i 0 cipher1 AES.new(sig[:0x10]) cipher2 AES.new(sig[0x10:]) while idx len(data): read_len ord(sig[i % 32]) payload data[idx:idxread_len] #print([] Read %d bytes % read_len) print([] Totally %d / %d bytes, sig index : %d % (idx, len(data), i)) if read_len % 2 0: f.write(cipher1.decrypt(payload[:0x10])) else: f.write(cipher2.decrypt(payload[:0x10])) f.write(decode_sig(payload[16:])) f.flush() idx read_len i 1 print([] Decoding done ...) f.close() dec_aes()腳本與加密流程逐一對應sig[:0x10]與sig[0x10:]分別是 md5 的前后半段即加密時派生的兩組 AES 密鑰對應 AES-128每次從密文文件讀取read_len ord(sig[i % 32])個字節(jié)與 Native 層每次讀入md5sig[i%32]大小的內容一致依據read_len % 2的奇偶選擇cipher1/cipher2解密前 16 字節(jié)payload[:0x10]剩余字節(jié)payload[16:]用sig[(16i)%32]逐字節(jié)異或還原對應加密時的掩碼異或每塊解密后寫入flag.jpg直到密文讀完。運行腳本后即可得到圖片解密結果flag 就包含在解密出的圖片中。這道題的核心價值在于展示了findcrypto 插件識別 AES 依據簽名指紋動態(tài)派生密鑰的綜合逆向場景即使不知道密鑰明文只要拿到原始 APK 簽名并理解分塊規(guī)則還原就是翻譯代碼的過程。綜合方法論從三道題看 Android 靜態(tài)分析實戰(zhàn)將三道題串起來可以提煉出一套可復用的綜合題求解流程反編譯定位入口用 jadx 反編譯 apk先找主 Activity 與關鍵監(jiān)聽函數如 Java 層靜態(tài)分析示例 中按報錯字符串Wrong Password、NOK_LICENCE_MSG反查代碼的做法識別 Native 層校驗so 層若通過JNI_OnLoadRegisterNatives動態(tài)注冊函數先讀注冊表定位真實函數名參考 原生層靜態(tài)分析示例 中off_400C的解析再用 findcrypto 等插件識別 S 盒、256 常數等算法指紋還原算法鏈路按編碼 → 異或 → RC4/AES的順序逐層逆向把 C/匯編級變換翻譯成 Python 腳本注意運行時干擾項Crackone 的\r\n插入、so 中修改seed的_init_my這類障眼法需要在交叉引用數據時特別留意驗證并輸出腳本運行得到 flag 后可結合 Android 動態(tài)調試 中介紹的 DDMS、IDA 動態(tài)調試等手段交叉驗證結論。綜合題的本質是多層校驗的編排而靜態(tài)分析的取勝之道在于用特征與常量識別算法、用交叉引用梳理數據流、用腳本精確還原每一層變換。掌握這三道真題后你便具備了應對同類 Android 逆向綜合題目的完整能力。贊分享文檔網絡安全教程【免費下載鏈接】ctf-wikiCome and join us, we need you!項目地址https://gitcode.com/gh_mirrors/ct/ctf-wiki點擊查看免費下載相關推薦ctf-wiki 內核態(tài) ROP 提權實戰(zhàn)狀態(tài)保存、swapgs/iretq 返回用戶態(tài)與強網杯 2018 core 全解析ctf wiki 內核態(tài) ROP 提權實戰(zhàn)狀態(tài)保存、swapgs/iretq 返回用戶態(tài)與強網杯 2018 core 全解析 本文是 ctf wiki 內核文檔網絡安全教程ctf-wiki Android 逆向指南Smali 語法與 Dalvik 字節(jié)碼指令全解ctf wiki Android 逆向指南Smali 語法與 Dalvik 字節(jié)碼指令全解 Smali 是 DalvikART字節(jié)碼的助記語法也是 An文檔網絡安全教程ctf-wiki Windows 逆向:花指令的編寫原理、IDA 修復方法與 2017 看雪 CTF 例題動態(tài)破解實戰(zhàn)ctf wiki Windows 逆向:花指令的編寫原理、IDA 修復方法與 2017 看雪 CTF 例題動態(tài)破解實戰(zhàn) 花指令 junk code 是 Wind文檔網絡安全教程創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考