案例一:Java层存在硬编码密钥
反编译apk,在包com.xxx.xxxx.utils中泄露加密key,同时可知加密方式为AES/ECB/PKCS5Padding
对登录请求数据包中,使用加密key进行解密
也可以使用Wallbreaker 查看类以及对象属性(若app存在双进程守护需先解决双进程守护)
objection -g com.xxxx.xxx explore -P ~/.objection/plugins
搜索类,根据给的 pattern 对所有类名进行匹配,列出匹配到的所有类名
plugin wallbreaker classsearch <pattern>
ClassDump,输出类的结构,获取密钥
plugin wallbreaker classdump <classname> [--fullname]
案例二:Java层不存在硬编码密钥
通过关键词找到关键方法com.xxx.e.b.d,可以看到该方法没有中没有硬编码的key值,当前知道加密方式为DES,同时没有特殊指定的话默认为ECB模式,方法d传入字节bArr,最终指定秘钥为bArr2,而该方法的作用只是截取bArr的前8个字节(des加密秘钥固为8个字节),因此只需知道传入的bArr即可获取秘钥
使用objection hook打印d方法调用和返回值
android hooking watch class_method com.xxxx.e.b.d --dump-args --dump-backtraces --dump-return
转换为字符即可获取密钥
也可以编写frida hook脚本,执行脚本即可查看加解密信息
function hook() { Java.perform(function () { var b=Java.use("com.xxx.xxx"); b.b.overload("java.lang.String").implementation= function(a){ console.log(a); var ret=this.b(a) console.log(ret); return a; } }); } setImmediate(hook);
执行查看结果
frida -U xxx.xxx.xxx.xxx -l test.js
使用spawn的模式启动Frida的一个好处是可以带着HOOK脚本重启应用程序,避免错过hook点
frida -U -f com.xxxx.xxx -l test.js --no-pause
案例三:HMACSHA签名存在硬编码密钥
抓包发现数据包存在签名,正常请求如下
修改数据包内容再次请求提示签名不正确
对其脱壳后找到签名算法代码
使用objection hook打印c方法调用和返回值
android hooking watch class_method com.xxx.x.x.c --dump-args --dump-backtraces --dump-return
可以知道明文格式:请求方法+&+URI+body,和签名后的结果
Java 将参数构造好后传给native函数com.xxxx.x.x.c,带了native关键字的说明java的作用范围达不到了,会去调用底层C语言的库。在最终执行的时候,通过JNI(调用本地方法接口)加载本地方法库中的方法。com.xxxxx.x.x.c的实现位于libhw-s.so 中,因此使用ida逆向libhw-s.so,搜索相关签名算法的关键字符,找到密钥
案例四:app使用动态密钥
测试某APP发现请求包和返回包内容均进行了加密
使用密码自吐脚本发现每次加密的密钥都会改变,但是iv固定
对APP进行脱壳并分析代码,由于iv是固定的,尝试直接搜索iv找到加密的地方,跟踪m6560CL
发现加密处理在so层中
hook decrypt方法发现该方法只加解密了手机号并非完整的数据包内容,看来并非是这里
hook genRandomKey方法发现返回值就是AES对应的密钥
输出AES对应的密钥
使用密钥和iv对数据进行解密发现解密失败,复制出请求包内容发现该内容为三段字符
其中第二段才是需要的json请求包内容
编写frida脚本固定密钥,使用固定后的密钥和iv即可更方便的对数据进行操作
function main() { Java.perform(function(){ var AESCoder = Java.use("com.xxx.xxxx.xxxx.xxxx.CryptoUtil"); AESCoder["genRandomKey"].implementation = function (){ let ret = this.genRandomKey(); var abb="uo2etSg6XNlq4nEv"; return abb; } }); } setImmediate(main)
经测试发现只需第二段加密字段即可正常执行且返回包内容为明文数据
案例五:加密在Native层实现
登录时看到数据包请求包被加密
脱壳后查看代码,通过登录接口跟进一下loginRequestTask方法
从该方法中可知baseBean3.getData()用于获取加密的返回包数据,使用AesUtil.decrypt对数据进行了解密并返回解密内容
跟进AesUtil类
发现该方法的实现在so层中
在so文件中通过关键词找到相应密钥和iv
解密成功
还没有评论,来说两句吧...