当你在对某个APP进行安全测试时,如果发现网络传输的数据包被加密了,该怎么办?你肯定希望找到它的加解密算法,从而窥探明文数据。对于不同类型的APP,其加密算法的藏身之处也有所不同。
如果面对的是原生APP(使用Java/Kotlin或Objective-C/Swift开发),那么加解密逻辑很可能位于应用的Java层(或OC层),或是更底层的so库(Native层)中。而如果这是一个H5 APP(即混合应用,前端页面由HTML5技术构建),那么秘密大概率就藏在JavaScript代码里。
如何找到这些关键的JS代码?通常有两种情况:一种是JS文件被打包在APK的资源目录(assets或res)中;另一种则是APP在首次运行时,通过网络动态加载JS文件。如果你确认目标是个H5 APP,却在抓包时没看到JS文件的请求,不妨试试清空APP缓存后再重新运行,往往就能抓到这些关键的资源加载请求。
本次演示的目标,就是一个运行时动态加载JS的H5 APP。
0x01 初步探测与目标锁定
首先,抓取APP的登录请求。我们能看到传输的数据(如Authorization头或请求体)已经被处理成一串“天书”,如下图所示,这是典型的加密特征。

当APP第一次启动时,通过抓包工具(如Burp Suite)可以看到它加载了大量的.js、.css等资源文件,这正是典型的H5应用特征。

接下来的核心问题就是:如何在浩如烟海的JS代码中找到加解密算法的位置?如果代码没有被严重混淆,你可以尝试直接搜索一些关键词,例如 encrypt, decrypt, AES, DES, CBC, padding 等。也可以留意数据包中出现的特定字符串,比如请求头里的 Authorization: Basic,或者请求接口路径 /app/appLogin。
当然,更通用的方法是定位到登录功能的前端代码,然后通过调试工具一步步跟踪执行流程,最终顺藤摸瓜找到执行加密操作的函数。
0x02 动态调试环境搭建
要进行高效的JS代码动态调试,你需要准备好以下工具:
确保WebViewDebugHook插件已安装并激活。然后,用USB线将手机连接到电脑,并将手机的USB连接模式从“仅充电”改为“传输文件(MTP)”,这是开启ADB调试的必要步骤。

在电脑的Chrome浏览器地址栏输入:chrome://inspect/#devices。如果一切配置正常,你将在“Remote Target”列表中看到目标APP的名称和其内部的WebView。

点击对应WebView下方的 inspect 按钮,一个新的开发者工具窗口将弹出,并附加到目标APP的页面。
0x03 代码分析与断点调试
成功附加后,你首先会看到APP的登录界面。在开发者工具的“Sources”面板中,你可以浏览该页面加载的所有前端资源文件,包括关键的JS文件。

通过搜索关键词 encrypt 或观察代码结构,我们很快定位到了疑似负责加密的JS文件。例如,下图展示的代码中清晰地出现了 CryptoJS.AES.encrypt 等字样,这几乎是明牌告诉我们加密算法是AES。

进一步查看,甚至可以找到格式化后的、更清晰的加密函数定义,其中明确指出了加密模式为CBC,填充方式为PKCS7。

锁定关键函数后,在疑似执行加密的代码行左侧点击,设置一个断点(快捷键 Ctrl+B 或直接鼠标点击行号)。这个前端逆向的常规操作,能让我们在数据流经时按下暂停键。

设置好断点后,回到APP界面执行登录操作。如果我们的判断正确,那么代码执行到断点处时就会自动暂停。

此时,调试器已暂停。我们可以在“Scope”或“Watch”窗口中查看当前函数的局部变量、参数值。最关键的是,我们能直接看到用于加密的密钥(Key)、初始化向量(IV) 以及待加密的原始数据。下图示例中,这些信息被清晰地展示出来。

0x04 验证与解密
至此,我们已经成功“捕获”了加密算法的所有要素:算法(AES)、模式(CBC)、填充(PKCS7)、密钥和IV。接下来就是验证时刻。
使用获取到的参数,我们可以编写一个简单的解密脚本(例如使用Python的cryptography库或在线工具),对抓包数据中加密的部分(如Authorization头中Basic后面的字符串,或请求体内容)进行解密。

如上图所示,当解密后的结果与预期相符(例如显示出明文的用户名密码)时,就证明整个分析过程是正确且成功的。从此,这个APP的加密通信在你面前就变成了“透明”的。
希望这篇关于H5 APP数据包加密分析的实战教程能对你有所启发。安全研究离不开对细节的把握和耐心的调试,如果你想探讨更多关于JavaScript逆向或移动安全的话题,欢迎来我们云栈社区交流分享。