首先我们登陆抓个包,可以发现有一个sign签名认证,在app与服务端接口安全的问题上,sign是一个很好的办法来保证安全性。
服务端会根据客户端的加密方式,得到一个sign(签名),和客户端传过来的参数做对比一样就继续下面的数据调用,错误就直接结束程序,所以中间改了数据包的话,服务端是直接给你数据包结束掉的。
Sign原理:用户登录后向服务器提供用户认证信息(如账户和密码),服务器认证完后给客户端返回一个Token令牌,用户再次获取信息时,带上此令牌,如果令牌正确,则返回数据。
那么我们反编译该APP,通过搜索字符串、查找相关函数,最终定位到sign数据包的相关代码段,分析它是如何处理传参并生成最终的sign值。
跟进第一个i0.a, 静态我们可以看出,它是将传进的参数进行了MD5的一次加密,
我们在它传参进来明文处下断点,再将加密返回后下个断
开始调试,获取明文
单步调试到返回密文
返回的密文确实是经过MD5加密一次,但是和篇头抓包的sign差了最后八位,
之前分析是进了两次方法,我们继续跟进
跟进之前的sign可以看见,数据以参数形式传入了getEncryptDeviceId方法
跳转到该方法的定义处,可以发现getEncryptDeviceId方法是由native标识符修饰的JNI层函数
JNI函数具体定义在哪一个so文件中,可以通过查看相关的loadLibrary操作
打开libcryp.so文件,通过其导出表找到getEncryptDeviceId方法的实现。
(对于命名规范的android JNI层函数,都是以"Java_包名_类名_方法名"的格式来命名的,若要分析的目标方法没有按照命名规范,就要涉及到android中的JNI_OnLoad以及JNI函数的动态注册机制了,这里不过多解释。)
跟进到该方法,可以静态分析到它的算法,如下
这里我将该伪C代码翻译为JS代码后,成功得到后八位
至此我们的分析出来的sign就是 18c93acf307b0ba142df393b9722b0d112351f2d
与篇头抓包的sign相同,至此已经清楚的分析出了该sign加密的流程方式