最近在工作的过程中,遇到了几次数据加密的情况。之前都是看大佬们如何前端调试,然后逆向获取密钥解密流量,这一次遇到了,便好好实战一下,抄起我的“乱杀三式”。首先还是来看看这个小程序的请求流量。当正常人一眼望去,丝毫理不清传递的是什么,我们基本就可以断定,其对流量进行了加密处理。经过上面两张图,可以判断这个小程序存在流量加密的情况。至于是全局的流量加密,还是部分流量加密,这个需要经过分析之后才能判断。如果只是部分流量加密,那么还可以测一测有没有漏网之鱼,如果是全局流量加密的话,就必须对小程序进行逆向获取源代码,再进行分析了。对微信小程序的逆向采用某神仙模拟器加一个6.X版的微信。因为高版本的安卓和微信不再信任系统的证书,这会造成无法抓包的情况,所以使用安卓5加6.X版本的微信。再参考网上的文章,从模拟器中脱到了小程序的wxapkg文件。这个文件在我的环境中位于:/data/data/com.tencent.mm/MicroMsg/7e3e7c**********706/appbrand/pkg
因为小程序比较多,不知道哪一个才是目标文件。通过adb把这几个wxapkg文件全部下载下来,然后就是从wxapkg文件中提取源代码,这里使用wxappUnpacker一键提取:获取到的目标小程序的源代码文件结构如下,之后便是进入分析阶段了。因为之前没有分析过微信小程序,所以这里首先学习了一下小程序的一些基本知识。重点有两个,第一个是app.js,这个文件是整个项目的入口文件,通过App()方法来注册一个小程序,并确定了整个程序的生命周期。第二个便是module.exports,微信小程序的模块化,个人理解就是对外暴露的方法,可以供其他方法调用这个模块,类似于public方法。了解完上面这两个点,再回到项目的源代码本身,通过浏览整个文件结构,发现对于加密的方法定义都位于/utils文件下。其中需要关注的是encrypt.js文件,里面定义了关于流量的加解密方法。直接上代码。从上面的代码中看到encrypt.js通过module.exports对外暴露了encrypt和decrypt两个方法。这两个应该就是用于对流量进行加密和解密的方法了。先来分析encrypt函数:Encrypt函数传递两个参数e和n,然后将参数n通过r函数处理之后赋值给s,其中r函数内容如下。为了安全里面的字符串,截取长度均已经修改,与原程序不同:r函数将传递的参数截取一段然后与字符串进行拼接,然后使用SHA256函数签名,再截取中间一部分,将字母转换成大写之后返回。再回到encrypt函数,变量i存储的AES加密解密的密钥,此处使用硬编码的方式写在代码当中。然后变量u存储格式化之后的s变量,变量c存储格式化之后的参数e。先了解一下AES的加密。对于AES有不同的模式,本程序中使用了CBC的模式,这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。在使用CBC模式进行加解密过程中,需要定义一个初始向量。初始向量用于随机数据加密,达到的效果是对相同的明文,传递相同的密钥。不同的初始向量可以产生不同的密文。再回到代码本身。可以看到encrypt函数调用了AES模块的encrypt方法进行加密,传递的参数,依次为c明文,i密钥,然后变量u表示初始向量,采用CBC模式进行加密。Encrypt函数分析完了,再看decrypt函数,上代码:Decrypt函数还是传递两个参数e,s然后通过formatString函数将参数e处理一下,其中formString函数具体内容如下,对e参数进行去除换行空格的处理:变量i还是存储r函数处理后的参数s,变量u存储的还是格式化的密钥,变量c存储格式化后的变量i,最后调用AES模块的decrypt函数进行解密,结果存储在变量o当中。进行解密的参数传递,e密文,u密钥,c初始化向量,采用CBC模式解密。这里加密和解密的初始化向量都是由r函数进行处理的。在上面分析中,加密解密传递的都是两个参数,然后其中一个参数是用于生成初始向量的。因为在上面的过程中,这个参数不是固定的,所以需要分析这个参数的来源,这样才能完整的对整个数据进行解密。再回到项目本身,在app.js中引入了一个request.js文件,在这个文件当中封装了http请求的方法,并对外暴露接口:r=(0,n.encrypt)(JSON.stringify(r),d)
这段代码应该就是调用加密函数对请求数据进行了加密。这里传递了两个参数,其中d参数就是加密过程中用于生成iv向量的参数,而在第103行最后可以看到,d参数的来源是函数getRandomUuid。接下来看看这个函数的内容:这个函数的作用只是生成一个随机的字符串然后返回。但是在上一张图的第105行代码将这个d赋值给了i.uuid,在我们最开始看请求数据包的时候,在http请求的请求体中就存在一个uuid的字段:所以可以确认,这个uuid的字段就是用于生成iv向量的参数。然后继续跟进我们的代码,在进行流量加密之后,会调用一个c函数,然后再return。所以我们需要看一下这个c函数的具体内容,因为解密的过程应该在这个c函数当中:在第61行的位置发送一个http请求,如果请求成功进入回调函数,对数据进行解密,这个解密可以看到传递的参数c.uuid就是请求包中的uuid字段。整个小程序的分析到这里基本就结束了,接下来只需要根据上面的密钥、iv向量生成、算法等等写一个解密的脚本就可以了。为了高(tou)效(lan)作(mo)业(yu),使用之前搞开发写的PHP版AES解密脚本改了改,最后的效果如下:输入uuid参数和密文,点击解密之后返回明文,将明文修改之后点击加密,返回密文。
文章来源: http://mp.weixin.qq.com/s?__biz=MzAwMzYxNzc1OA==&mid=2247498975&idx=1&sn=cba9b2b7dcd5f96f0f7519a1bdf7705f&chksm=9b3ada6eac4d5378c3a477db13e4204753c5e99ce8603010414bd808c716485458f95ef0a11b#rd
如有侵权请联系:admin#unsafe.sh