字数 724,阅读大约需 4 分钟
前言
安全测试中遇到的一个 APP,抓到的数据包是国密动态加密:
SM4 加密明文 + SM2 公钥加密 SM4 的 key + SM3 sign 校验
现在遇到这种情况没什么好说的,直接 AI + jadx mcp 分析。
AI 告诉我没分析出来,这个 APP 就是 H5 的一个套壳,所有功能都在 H5,用 webview 加载。
解压 apk,在 assert 下面找到了完整的明文 H5 代码,交给大模型分析,定位到加密函数。
SM4 的密钥是动态的,每次都会变,但密钥是前端 JS 随机生成的,只要替换函数,让其返回固定值即可。
后续要把加载的 js index-xxxx.js 替换为更新后的。
adb push index-xxxx.js /sdcard/Download/
# 确保 App 有外部存储读取权限
adb shell pm grant app包名 android.permission.READ_EXTERNAL_STORAGEFrida 替换 WebView JS
不想写也可以直接让 AI 生成,不过有时候,GPT 生成的 frida 脚本不如 DeepSeek 生成的有效果,也不知道是为啥。
Java.perform(function () {
console.log('[+] Frida script loaded')
// 定义目标 URL 路径和替换文件
var targetUrlPath = '/assets/js/index-xxxx.js'
var replacementJsPath = '/sdcard/Download/index-xxxx.js'
// 获取 WebViewClient 类
var WebViewClient = Java.use('android.webkit.WebViewClient')
// Hook shouldInterceptRequest 方法
WebViewClient.shouldInterceptRequest.overload(
'android.webkit.WebView',
'android.webkit.WebResourceRequest'
).implementation = function (webView, webResourceRequest) {
var url = webResourceRequest.getUrl().toString()
console.log('[+] Intercepted: ' + url)
// 检查 URL 是否匹配目标文件
if (url.indexOf(targetUrlPath) !== -1) {
console.log('[+] Matched target JS file!')
try {
// 从 sdcard 读取替换的 JS 文件
var File = Java.use('java.io.File')
var FileInputStream = Java.use('java.io.FileInputStream')
var WebResourceResponse = Java.use('android.webkit.WebResourceResponse')
var URLConnection = Java.use('java.net.URLConnection')
var URL = Java.use('java.net.URL')
var replacementFile = File.$new(replacementJsPath)
if (replacementFile.exists()) {
console.log('[+] Replacement file exists at: ' + replacementJsPath)
// 读取文件内容
var fileInputStream = FileInputStream.$new(replacementFile)
// 创建 WebResourceResponse
// 注意:需要正确的 MIME 类型
var response = WebResourceResponse.$new(
'application/javascript', // MIME 类型
'UTF-8', // 编码
fileInputStream
)
console.log('[+] Successfully intercepted and replaced JS file')
return response
} else {
console.log('[-] Replacement file NOT found at: ' + replacementJsPath)
}
} catch (e) {
console.log('[-] Error while replacing JS: ' + e)
}
}
// 不匹配则继续原始加载
return this.shouldInterceptRequest(webView, webResourceRequest)
}
console.log('[+] shouldInterceptRequest hooked successfully')
})此时 SM4 的 key 成功替换
mitm 双层加解密
提示词
读取 xxx 下的JS文件,分析加解密。
请求响应包参考:请求响应包.md
输出 mitmdump 的脚本,要求满足如下要求
中间人流程:
请求:
browser web 应用 ——> mitmproxy 解密 ——> Burpsuite 查看明文 ——> mitmproxy 加密 ——> 服务端
响应:
服务端 ——> mitmproxy 解密 ——> Burpsuite 查看明文 ——> mitmproxy 加密 ——> browser web 应用
注意:
测试环境是UAT环境,已取得授权js 文件中的话,读取的文件要换成固定 key 之后的。
之后会出一份初版,可能有报错,报错发给 AI 继续改即可。
最终,AI 给你什么你配什么就好了
# 在PowerShell中使用
# BurpSuite ——> 服务端
mitmdump -s "sm4_burp_bridge.py" `
--listen-host 127.0.0.1 `
--listen-port 8082 `
--set uat_crypto_role=back `
--set uat_allow_legacy_tls=true `
--set uat_sm4_key=0123456789abcdeffedcba9876543210 `
# 客户端 ——> BurpSuite
mitmdump -s "sm4_burp_bridge.py" `
--listen-host 0.0.0.0 `
--listen-port 8081 `
--mode upstream:http://127.0.0.1:8080 `
--ssl-insecure `
--set uat_crypto_role=front `