小米商城 3.6亿下载量, 阅读榜第10. 比较有意思的是它使用了 Retrofit用于接口的开发 (Retrofit 是 Square 公司开发的一个 类型安全 的 HTTP 客户端库,专为 Android 和 Java 设计。它本质上是 对 OkHttp 的高级封装,通过 接口注解 将 HTTP API 转换为可调用的 Java/Kotlin 接口,极大简化了网络请求的代码。)
原文链接: https://www.yuque.com/again-719bb/pfhi8f/oee7ugfig95w4kw5
分析这个接口, 主要原因是加密字段比较多
输入手机号后, 会向/v2/passport/phone/status接口查询状态
收集接口关键信息
发现可能是A + AndroidID的拼接 builder.a("X-Device", "A:" + k.this.sAndroidId.get());
我们知道每个app的AndroidID都是不一样的, 所以尝试运行app后使用fridahook获取一下
控制台打印, 那基本上就做实了 x-device: A:62a16f76968f9b5f就是一个简单的拼接
看起来像这个, 跟网络有关, 包括下面的 intercept也是调用同样的方法
getMuid是被我rename过了, 之前叫m
在函数名上按 F, 复制到脚本中
可以确定就是这个m方法获取的
继续分析它是怎么设置的, 查询引用 发现在init阶段初始化了这个类, 但是没有任何地方 set
分析k类, 发现是个内部类, jadx有bug 无法正常跳转 (会显示空白)
我们看一下 encryptUtil.g方法, 发现其实是个md5, 那和我们一开始分析的32位对应上了
尝试Hook一下, 发现Hook不到, 那这就奇怪了(.... 补充:spawn启动 第一时间没Hook到, 重新保存后就正常了)
Hook下内部类$K, 发现onInit调用了 并且成功返回了值. 但是encryptUtil.g这个md5没反应 你这不扯犊子呢?
OK虽然没成功Hook到md5(可能是bug 或者 被劫持了), 但是可以确定密文是一致的, 而明文是从Client.f38029x.get()获取. 我的思路是 在 onInit的时候再调用一次 get 看看明文数据
x是个静态方法, 我们直接调用即可, 需要注意的是 有另一个方法叫x, 所以需要在x前面加下划线
发现结果是个0, 需要验证一下, 那可以确定muid在未登录状态下 md5(0) , 暂时固定
特征: 与base64相似
看起来不像base64, 因为常规base64没下划线
直接搜索/v2/passport/phone/status看看有没有组装流程
只搜索到一个关键信息, 而且还是一个接口?
这些注解看上去有点子说法的, 把整个 interface 丢给GPT
GPT说这个是用于 Retrofit的一个RESTFul接口注册, 用于动态生成
那么@Encryption这个注解就很可疑了! 跳过去发现就是一个空的接口, 而且有点怪异 使用的是 @interface
那就找一下相关的引用吧. 发现只有一个地方使用, 其他都是声明.
这啥玩意. 遇事不决可问AI, AI不语就砸键盘 :)AI说这是一个 运行时注解处理器 (implements IAnnotationProcessor)其作用是把注解转换成内部参数 Map @Encryption => _internal_encryption=1
那就搜一下_internal_encryption看看有没有具体实现喽
最终定位implements okhttp3.Interceptor
可以看到(String) eVar.d(request, "_internal_encryption");貌似是取值 (可能就是上面put的值)!TextUtils.isEmpty(str) || this.aesEncryptionALl这个应该就是判断了使用frida Hook一下验证是否正确
可以看到 e.d result第一次进入是1
那现在基本可以确定加密逻辑在l(request);中, 我们来分析一下 l获取 Request.Method 然后调用不同的逻辑分支. 如果是get调用h, 否则调用j
那我们是这个POST, 所以直接看j就好了. 让AI帮我们格式化一下
那我们content-type => application/x-www-form-urlencoded(FormBody) 走 g方法
g方法就是获取http body 中的value进行处理后赋值回去, 然后重新生成一个新的RequestBody
再来看一下f方法
发现q.aes就是aes加密
使用Hook的方式获取aes的初始数据. data/key都是byte数组 需要转换一下
打印结果, 我们发现key是非固定值每次重新启动就动态生成, 而data也被拼接了 +86 的国际区号data/key/padding都有了 IV初始化向量就是static块中的明文0102030405060708我们来验证一下
因为重启了app, 需要重新发包phone参数验证
而 eVar.h则是flag为11的base64
问一下ai Base64.encode flag. 11 那不就是 8 + 2 + 1
参数收集
33位, 有点像 前缀的A + 个32位的时间格式?
找了一圈, 发现这个RequestInterceptor 最可疑
找下strB的生成
回复或点赞可查看完整内容
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-290056.htm
[原创][萌新学逆向]某漫画Status接口分析 (Java层)
366 浏览
4 回复
taiqiangl
有frida检测呀
感谢分享,受教了。
谢谢