1. APK文件静态反编译 使用JEB2反编译及查看JAVA代码(该题不涉及native层,IDA ARM反汇编及调试有机会再讲),“EP”定位可通过manifest查看 onCreate函数可看到很直接的加密流程:MainActivity.encrypt接受屏幕输入和一串字符;判断其返回值是否等于“kNk3Qz+l/kLpGuKxf5iGE9cOoTmmn9Ac+UdF4b2CHqU=”: encrypt()函数传入的第二个参数“This is a AES-like encryption algorithm. However, we do some change. Therefore, you cannot directly use security class to decrypt the message. Our challenge is to find the plain text of this encrypt message with th fixed key.” 提示这是个变形的AES加密算法,可能是友善的也可能是误导,但后续我们可以此为依据进行验证加快解题速度。 1. 尝试运行 使用雷电安卓模拟器,随意输入“12345678”,验证其错误信息输出 “Incorrect Flag!”: 1. JEB2调试 Debugger->Start->Attach: 使用特定函数调用(如本例Base64.encodeToSTring)从JAVA定位到Smali代码,Ctrl+B下断点: 标准加密与APK调试验证对比: 1. 破解算法 APK算法首先对输入字串进行一个16分组,这里的变量名可通过快捷键n(类似IDA)重命名,帮助逆向理解: 对每16字符进行10轮变换 然后,做一个拼接(4是因为AES以4字节为一个单位): 最后对加密字串做base64输出。 对比关键的四个加密模块函数:字节代换substitute()、行移位shiftRows()、列混合mixCloumns()、轮密钥加addRoundKey()。 轮密钥加addRoundKey(): 轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作,与apk代码相符; 字节代换substitute(): 可发现APK代码中的有现成的逆S盒与标准逆S盒一致,暂时可推断也使用标准S盒: 行移位shiftRows(): 行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节,与APK代码一致: 列混合mixCloumns(): 首先四次变换的逻辑没有问题: 2,3,1,1 1,2,3,1 1,1,2,3 3,1,1,2 LightState.add()也没有问题: LightState.multiply2()发现异或值做了改变: 变形解密将“0x1b”改为“0x1d”配置好key及“kNk3Qz+l/kLpGuKxf5iGE9cOoTmmn9Ac+UdF4b2CHqU=”解密的16进制数组,解密得到flag为:
|