文章总结: 这篇文章详细记录了对安卓APP验证码加密机制的逆向分析过程。作者通过静态分析和动态分析发现验证码使用了AES加密,但初始分析因忽略多态和密钥处理而失败。最终通过仔细代码审查发现密钥经过SHA-256处理,偏移量直接使用。作者还探讨了Fridahook和算法助手Pro等工具的使用限制,并展示了如何使用AI工具Cursor辅助分析加密逻辑,成功定位到加密函数和参数。文章强调了在逆向工程中细心观察和多角度分析的重要性,以及AI在安全研究中的应用潜力。 综合评分: 85 文章分类: 移动安全,逆向分析,渗透测试,AI安全,实战经验
安卓黑盒背后的密钥:验证码加密解析与 AI 破局实录
原创
blue澜
逐影安全
2025年11月3日 09:53 北京
黑盒背后的密钥:验证码加密解析与 AI 破局实录
文章首发奇安信攻防社区:https://forum.butian.net/share/4613
| | | — | | 本公众号技术文章仅供参考! 文章仅用于学习交流,请勿利用文章中的技术对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。 |
#
0x01 条条大路”不”通罗马
测试APP的时候发现验证码是4位的,立即就想APP是否存在防爆破机制,如果没有的话4位验证码很容易就爆破出来了
抓包看看,一看人麻了,多么熟悉的Nonce,sign等参数,想着肯定又存在Sign校验了,又得扣加密逻辑好烦
但是不知怎么的可能是懒,胡乱改了改参数和请求头的一些值,发现后端并没有校验,感情你在这跟我玩虚张声势呢
不过虽然sign校验是不存在,但是参数的加密,肉眼可见肯定是存在的,不过再开始逆向扣算法之前,为了防止做无用功,所以直接将这个包重发了100次,观察响应体并没有出现速率限制、验证码重置相关的信息,看来很可能不存在防止爆破限制,还有的搞
于是直接将APP拿去脱壳(脱壳这里先不讲,后续想着专门写一篇详细讲讲,目前网上也有非常多优秀文章大家可以学习学习),直接拖进jadx,全局搜索接口关键字定位到了,看到它有两个参数,第一个是map,第二个就是一个不知道干嘛用的参数,上图抓包里面也可以看到那个值是空的, 所以这里可以知道其余的值phone、captcha、action都放在了第一个参数map里面
按X查看函数被谁调用,下图可以清晰的看到参数全部放到了map里面,其中验证码的值是将str2利用AESutil类里面的m49295b函数处理后放里的,所以这里基本上定位到了加密函数,接着点进m49295b
嗯呢挺好挺容易,这么快在上面就看到了key和偏移
不是这两个值完全不一样啊,怎么回事,难不成不是,这个期间我又回看了很多代码,然后尝试了很多次发现还是一直对不上,浪费了很长时间,栓Q了
差点忘了,我还有神器呢,干嘛新新苦苦手动逆向呢,直接打开算法助手,勾选对应APP,然后将加密打开
重新触发一下对应的功能点,我输入的验证码是6666,搜一下,搜出来很多,但是很明显都不是啊?什么情况这是
没办法了,用frida hook一下吧,我hook的是下面这个函数,然后直接利用jadx的功能一键将frida代码拷贝了过来
放到frida的hook框架代码里面
function hookTest1(){
//放到了这里
}
function main(){
Java.perform(function(){
hookTest1();
});}
setImmediate(main);
发现hook到了, 但是参数因为是个枚举类型,所以具体的值不可以见,但是这里其实可以很明确,确实传参就是我们看到的那两个
为了进一步证明,于是我这时尝试hook这个mo50430b这个函数,还是直接右键复制为frida片段
重新触发发现hook不到,人麻了,不是哥们服了啊
0x02 发现问题
这个时候就很无语了,说实话这个东西本来以为很简单,轻车熟路了,没想到浪费了这么久,于是想着细心点,这回细看看,当我仔细看了下面这代码时候茅塞顿开
AESUtil里面调用的加密的函数,我跟进去发现到了AbsAesAlgorithm不过这个时候发现它是个抽象函数,没有函数体
那么也就说真正代码执行不在这里,我们回过来继续看,这里是f65543a调用的加密函数,而这个对象哪来的呢,看上面发现一个明显的多态定义,这里真正new的是一个AesV2Util,而那个抽象函数所在的Absxxx是它的父类而已,所以我们真正要找的是AesV2Util
代码如下,上面部分大概就是检查缓存判断是否已经创建过加密对象,如果没创建过那就走到L23创建一个新的加密对象
那么具体看这个加密对象怎么创建的,这里三个参数r0、r5、r6、分别是1和key和iv,定位到了这里,不能发现key和iv这里都不是直接用的,而是分别都被函数调用了
那我们首先看key是什么情况,对应的是m50433e,代码如下,原来如此这个key并不是直接用的,而是用SHA-256后的值,怪不得算不出来
那再看一下iv怎么处理的也就是m50432d,大概就是这个样子,可以看到最后其实就是将iv变成了字节数组然后作为IV,说人话就是直接用了
既然如此验证一下,对上了,完美!
0x03 问题攻破和复盘
既然如此那么就来复盘一下为什么一开始浪费了那么久说白了就是因为没细看,然后忽略了多态的声明,以及KEY在使用前的处理
既然如此那么回过头来再解决一下为什么算法助手Pro和frida都出问题了没成功呢
我又重新触发了一下验证码我输入的是1234但是没有hook到,不过因为手机号也做了加密,而且用的一个算法,搜手机号却搜到了,如下图key和iv也是非常准确的,也算是一个平替方案吧
然后就是frida,我回过头又仔细看了眼frida函数,注意由于我是在函数调用那块直接用jadx右键复制的frida代码,由于存在多态,它hook的是父类这个抽象函数,而不是子类重写的具体的函数,所以能hook到东西才怪,而且就算hook到了,这里key还是没处理之前所以也是不准确的,所以这里要改一下
所以我最后决定直接hook这个javax.crypto.spec.SecretKeySpec的构造函数,因为它的参数第一个是字节型数组就是我们想要的处理后的key,如果hook别的值参数或返回值都是一些对象,非常不方便,
hook脚本如下
function hookTest1(){
var SecretKeySpec = Java.use("javax.crypto.spec.SecretKeySpec");
SecretKeySpec.$init.overload("[B", "java.lang.String").implementation = function(keyBytes, algorithm) {
// 把 byte[] 转成 hex
var hex = '';
for (var i = 0; i < keyBytes.length; i++) {
var b = keyBytes[i] & 0xFF;
hex += (b < 16 ? '0' : '') + b.toString(16);
}
console.log("[*] SecretKeySpec key:", hex, "algorithm:", algorithm);
return this.$init(keyBytes, algorithm);
};
}
function main(){
Java.perform(function(){
hookTest1();
});}
setImmediate(main);
然后就可以了,不过由于app内部加密不止这一个,所以结果很多,干扰也是非常多的
0x04 AI加持,秒出结果
对于这种复杂的事情,我非常希望能通过AI解决,所以我之前写过一篇《破译之眼:AI重构前端渗透对抗新范式》,大概就是利用Gemini2.5的支持100w上下文的特性,直接让其分析所有js,那么这次我仍然希望通过AI解决,对于研发而言,现在出现了非常多优秀的完全的AI编程IDE,如:Cursor、Trae、CodeBuddy等等
所以我打算尝试一下,而按照我的习惯自然选择了Cursor(大模型用的还是Gemini2.5),首先利用jadx导出
用cursor打开,然后给出提示词
当前这个文件夹下面有很多文件这是根据一个app反编译过来的里面有大量的代码,现在有个请求/auth/v1/phone_auth,你要找到这个请求并且根据链路分析,它的参数存在加密,找到加密函数以及key和iv
它执行了一会确实定位到了,而且分析了代码,但是犯了个错误还是没有发现SHA-256那步
所以我这里提示一下
没有这么简单,它的秘钥确实是xxxx,不过经过了变形
(因为我们这里是带着答案用的AI,所以上面的提示词正常情况下我们是不知道有变形的,不过我们大可以猜测,那么真正利用AI进行加密逻辑挖掘的时候,提示次完全可以变成下面这种形式)
应该没有这么简单,我查到了这里,对应的秘钥和偏移我也尝试了,但是得出来的结果并不准确,你再仔细看看,看看是否存在那些遗漏的步骤,这个KEY和IV是否就是最终的,在使用之前是否经过某些变形之类的
也是非常牛的分析到了,过程非常快
最后让其输出一下变形后的值
0x05 后续
然后就这样了呗( ̄▽ ̄)/
查看原文:《安卓黑盒背后的密钥:验证码加密解析与 AI 破局实录》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论