Android逆向——定位到某书 Sign 算法(上)

简介: Android逆向——定位到某书 Sign 算法

一、浅谈Okhttp拦截器

添加一个自定义拦截器很简单,只需要实现 Okhttp 的 Interceptor 接口,重写其中的intercept 方法,最后在 OkHttpClient.Builder 链式代码中注册和添加这个拦截器,为什么要称作“自定义“拦截器呢?因为 Okhttp 核心实现就是基于其内部五大拦截器,我们下文再说。

需要注意的是,Retrofit 是基于 Okhttp 的封装,所以当我们谈论“Retrofit的拦截器”,其实就是OKhttp的拦截器。

先看一下上一节,我们用 Okhttp 实现网络请求的 demo


640.jpg


对照着看一下 Okhttp 发送请求的执行流程

640.jpg


我们分析大红框里的内容,这张图有些繁琐,也可以转化640.jpg成下图。



还是直接上图,就像流水线工厂一样,一个一无所有的 Request,依照顺序依次经过五大拦截器的前置拦截,最后拿到response后,再倒序经过五大拦截器的后置拦截。

我们引用@yuashuai 所举的例子,他表述的既生动又贴切。

老张有很多干面条,但是他想吃汤面,可是自己又不会做,但是碰巧村里大郎会做,于是老张拿一包干面条让大郎做成了汤面。但是老张发现他做面不好吃,盐都没放,连个青菜叶子都没有。

这时候老张正好碰到隔壁老王,老王说了这东西我也会做,比他做的好吃多了。于是老张又拿着一包干面条给了老王,老王说老张你等着,我马上回家给你做,做好了就给你送过去。但是老王回家并没有做,而是去家里拿了一包盐,然后去找隔壁老李了,原来老王并不会做面,但是他知道隔壁老李会做,而且做得比较好吃。于是他把干面条和盐都交给了老李。老李对老王说你回去等着吧,做好了马上给你送过去。可是老李同样不会做,但是他知道村里的大郎会做,这时老李首先回厨房拿了两个生菜叶子,然后带着老王给的干面条和盐去找大郎了,对大郎说,生菜叶子,盐,面条都给你了,你快给我做一碗面。大郎对老李说好嘞,3分钟就好了,3分钟后,老李拿着做好了的放了盐和生菜叶子的一碗面回去了。本来打算直接给老王,但是一想,自己放了两个生菜叶子,不吃点这个面吃不是有点亏,于是老李偷偷了吃了几根面。然后老李去找老王说你的面做好了并把面交给了老王。老王一看这面只有两个青菜叶子,营养是不是不够呀!于是老王又买了半斤熟牛肉,切切放了进去。然后老王去找老张说你的面做好了,还说道这么大一碗你也吃不完吧,让小张也吃点。最后老张吃着老王送来的红烧牛肉面感动的肉牛满面。

这里的干面条就可以看做一个最原始的 request,到老王哪里被加了点盐,到老李哪里被加了生菜叶子,于是大郎才能把这个request做成放了盐和生菜叶子的response,这个response回到老李哪里又被啃了几口,到老王哪里又被放了点牛肉。于是最后回到老张里收到的response就是被扣了几口并且加了牛肉的response。这样整个链条是不是就清楚了!

@Wanghao 画了一张非常全面的图。

在第三讲的末尾我们讨论过 BridgeInterceptor 拦截器,它会对我们我们配置的 request请求补充头信息,比如请求类型、UA,如果你自己不加ua,Bridge 拦截器就会添加“okhttp/版本号”这样的ua。

640.jpg


这是 BridgeIntercetpor 的源码

640.jpg


我们也可以自定义拦截器,分为应用级别拦截器和网络级别拦截器,在 @Wanghao 的图上我们可以看到它们分别作用的时机。

1.应用级别拦截器:只会调用一次,获取到最终的 response 结果

2.网络级别拦截器:可以感知到网络的请求的重定向,以及重试会被执行多次

这两种拦截器在注册方式各不同,分别调用 addInterceptor()以及 addNetworkInterceptor 方法进行注册,但实现拦截器的步骤没有不同,所以我们不做过多笔墨。


640.jpg


640.jpg


二、分析一个简单的拦截器

我们随便找一个拦截器 demo 分析一下,我们需要熟悉拦截器的具体操作,找到它代码流程上的一些特征,然后根据这些特征在Jadx中搜索反编译后的 Java 代码,去寻找某书实现添加sign等等11个参数的拦截器。

除此之外还有个思路,上文说到,自定义的拦截器分为 Application 拦截器和 Network 拦截器,但不管哪一种,都需要在 OkHttpClient.Builder 链式代码中通过 addInterceptor/addNetworkInterceptor 方法添加和注册后才能生效,那我们可以全局搜索 addInterceptor 以及 addNetworkInterceptor,然后得到拦截器的线索,这样应该也是可以的。我们先看看当前的这个思路。

640.jpg


我们可以看到三个明显的特征:

一: 是实现Interceptor接口 “public class xxx(自定义的拦截器名) implements Interceptor {”

二: 是重写intercept方法“public (可能有修饰符) Response intercept(Chain Chain)……”

三: 是添加字段时调用的 “.addQueryParameter” 方法(这儿我们加了个“.”,可以缩小检索范围),如果是添加Header 头信息,则会调用 ”.header“ 这个方法

如果 App 没有对 Okhttp 类进行混淆,那我们就可以根据这三个特征找到  Retrofit 的拦截器实现。

我们这儿再多说两句,看图中第九行,Request originalRequest = chain.request(); 这个demo作者为什么要将这个Request命名为 originalRequest(original:原先的,原始的)呢?

再回想一下拦截器的工作原理。想象一下一个流水线,request 是材料,response 是产品,从头到尾经历了许多次加工(拦截器)。每个拦截器先通过 chain.request() 得到这个 reqeust,经过一系列操作后的 request,再放回 chain.proceed 方法,最后return 回去,request 经过了一次洗礼,等待它的是不断的新的洗礼。

640.png

chain.proceed 这个方法名非常精准和有神,Okhttp采用了设计模式中的责任链模式,感兴趣的可以看一下这篇关于责任链的文章https://www.cnblogs.com/aeolian/p/8888958.html

因此,对于每一个拦截器来说,取到的request就是原始和过去的,命名就可能会用”old“、”original“,返回到reqeust就可能用”final“、”new“修饰,解释到这儿,我想大家对拦截器应该有了一个具象的了解了。

上面我们找到了三个特征,那么接下来我们通过 Jadx 的全局搜索功能,开始寻找某书 Retrofit的拦截器,进而找到 sign 等参数的实现。如果你的电脑内存只有 8G,那么接下来的这一步操作对你十分有用,除此之外,它对我们搜索关键代码点也有奇效。

反编译一个App,你会看到成千上万的类和方法,我们可以简单将这些类和方法分成“具体业务逻辑的代码”和“App架构和工具的代码”,前者的类名一般是包名.xxx,比如某书App包名为 com.xingin.xhs,它的业务代码就是 com.xingin.xxxx;而第二类往往五花八门,比如 Android本身的一些方法类 “android.xx”,腾讯的sdk“com.tencent.xxx”,微博的登录接入sdk“com.weibo.xxx”。

我们想要定位到的内容/加解密逻辑等等,基本都在前者的类里,而后者既缭乱人眼,烦人心神,又占用内存,Jadx给我们提供了屏蔽这些类的方法,屏蔽后Jadx将不再反编译这些类,你也无法再跳转到该方法里,或者在全局检索时看到这些类中扰人的代码。

方法很简单,只需要在类列表中选中某个类,右键 exclude 即可屏蔽这个类。

640.jpg


相关文章
|
6月前
|
算法 Android开发
Android签名算法的原理
Android签名算法的原理
68 0
|
2月前
|
Java 测试技术 Android开发
Android性能测试——发现和定位内存泄露和卡顿
本文详细介绍了Android应用性能测试中的内存泄漏与卡顿问题及其解决方案。首先,文章描述了使用MAT工具定位内存泄漏的具体步骤,并通过实例展示了如何分析Histogram图表和Dominator Tree。接着,针对卡顿问题,文章探讨了其产生原因,并提供了多种测试方法,包括GPU呈现模式分析、FPS Meter软件测试、绘制圆点计数法及Android Studio自带的GPU监控功能。最后,文章给出了排查卡顿问题的四个方向,帮助开发者优化应用性能。
166 4
Android性能测试——发现和定位内存泄露和卡顿
|
3月前
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点讲解了如何使用 Kotlin 实现 AES-256 的加密和解密,并提供了详细的代码示例。通过生成密钥、加密和解密数据等步骤,展示了如何在 Kotlin 项目中实现数据的安全加密。
119 1
|
3月前
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点展示了如何使用 Kotlin 实现 AES-256 的加密和解密,提供了详细的代码示例。
74 2
|
4月前
|
机器学习/深度学习 搜索推荐 算法
利用机器学习算法增强IAA广告定位和预测:实现个性化广告投放以最大化收益
【7月更文第30天】在当今高度竞争的移动应用市场中,应用内广告(IAA)是许多开发者获取收入的重要途径之一。然而,传统的广告推送方式往往忽略了用户的个体差异性,导致广告效果不佳。通过运用机器学习技术,我们可以更准确地理解用户偏好,从而实现个性化的广告推送。
292 0
|
5月前
|
存储 算法 Java
Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。
【6月更文挑战第21天】Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。简单哈希表实现未涵盖冲突解决和删除操作。
57 1
|
5月前
|
算法 Java API
记录我第一次在Android开发图像处理算法的经历
记录我第一次在Android开发图像处理算法的经历
35 1
|
6月前
|
自然语言处理 算法 搜索推荐
Android文字匹配度算法
【5月更文挑战第15天】
|
6月前
|
算法 前端开发 Android开发
Android文字基线Baseline算法的使用讲解,Android开发面试题
Android文字基线Baseline算法的使用讲解,Android开发面试题
Android文字基线Baseline算法的使用讲解,Android开发面试题
|
6月前
|
机器学习/深度学习 算法 网络架构
基于yolov2深度学习网络的单人口罩佩戴检测和人脸定位算法matlab仿真
摘要:该内容展示了一个基于YOLOv2的单人口罩佩戴检测和人脸定位算法的应用。使用MATLAB2022A,YOLOv2通过Darknet-19网络和锚框技术检测图像中的口罩佩戴情况。核心代码段展示了如何处理图像,检测人脸并标注口罩区域。程序会实时显示检测结果,等待一段时间以优化显示流畅性。