6

你的密钥被我看见了 ,逆向获取密钥

 2 years ago
source link: https://blog.csdn.net/HBohan/article/details/123431855
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

遇到过很多次数据加密的情况。之前都是看到别人如何前端调试,然后逆向获取密钥解密流量,这一次,给大家实战一下。

一、逆向式

我们的目标是某信小程序。

首先还是来看看这个小程序的请求流量。当正常人一眼望去,丝毫理不清传递的是什么,我们基本就可以断定,其对流量进行了加密处理。

然后我们再看看返回请求——依然一头雾水:

经过上面两张图,可以判断这个小程序存在流量加密的情况。至于是全局的流量加密,还是部分流量加密,这个需要经过分析之后才能判断。

如果只是部分流量加密,那么还可以测一测有没有漏网之鱼,如果是全局流量加密的话,就必须对小程序进行逆向获取源代码,再进行分析了。

对某信小程序的逆向采用某神仙模拟器加一个6.X版的某信。因为高版本的安卓和某信不再信任系统的证书,这会造成无法抓包的情况,所以使用安卓5加6.X版本的某信。

再参考网上的文章,从模拟器中脱到了小程序的wxapkg文件。这个文件在我的环境中位于:

/data/data/com.tencent.mm/MicroMsg/7e3e7c**********706/appbrand/pkg

因为小程序比较多,不知道哪一个才是目标文件。通过adb把这几个wxapkg文件全部下载下来,然后就是从wxapkg文件中提取源代码,这里使用wxappUnpacker一键提取:

获取到的目标小程序的源代码文件结构如下,之后便是进入分析阶段了。

二、分析式

【点击查看】
1、网络安全学习路线
2、电子书籍(白帽子)
3、安全大厂内部视频
4、100份src文档
5、常见安全面试题
6、ctf大赛经典题目解析
7、全套工具包
8、应急响应笔记

进入代码审计环节,来分析前端的代码算法。

上面的小程序经过逆向,获取到的源代码结构如下:

因为之前没有分析过某信小程序,所以这里首先学习了一下小程序的一些基本知识。重点有两个,第一个是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请求的方法,并对外暴露接口:

在第108行中,有一段代码:

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参数和密文,点击解密之后返回明文,将明文修改之后点击加密,返回密文。

返回包的解密:

好了,这个小程序的流量加密分析到这就全部结束了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK