某微信小程序参数加密算法分析

渗透技巧 1年前 (2023) admin
790 0 0

0x00 前言

事件背景

某银行微信小程序测试渗透项目中,流量抓包发现请求和响应包均被加密,渗透测试无法实施,因此开启了加密算法破解之旅。该加密流程的极具典型性,a) 加密算法涉及RSA非对称加密、AES对称加密。b) AES Key IV绑定session,需拿wx.login生成的code置换。c)wx.login code,需要应用Frida hook 微信客户端关键函数。d) 微信小程序参数加密,仅允许微信登录场景非常常见。 

涉及到技术栈

  • • 加密算法基础知识:RSA加密,AES加密

  • • 微信小程序逆向

  • • 微信小程序登录认证流程

  • • Android APK frida hook

0x01 微信小程序逆向

请求响应包的数据均被加密,想要解密数据需要反编译微信小程序wxapkg,只能从代码层面梳理加密算法原理。流程如下: 

  1. 1. 在微信客户端找到待分析wxapkg文件

  2. 2. 使用PC微信小程序一键解密工具解密wxapkg文件。

  3. 3. 使用wxappUnpacker脚本进行分包。./bingo.sh testpkg/.wxapkg -s=../master-xxx

  4. 4. 利用微信开发者工具查看调试明文代码。

0x02 加密认证流程分析

拿到代码后开始静态代码分析来定位加密函数,全局搜索字符串,如:encrypt,decrypt,jiami,jiemi,AES,DES,RSA,AESKey或根据url,请求参数:login等定位加解密业务逻辑,有时候在浏览器console可能会产生调试日志等。
这次分析中采用AESKey搜索,找到如下代码:

function l(e) {
  console.log("arguments:",arguments)
  console.log("AES encrypt 参数:",a.globalData.aesKey_key, a.globalData.aesKey_iv)
  ......
  }

根据该代码,可确定加密算法为AES,加密参数存储在全局变量中a.globalData中,全局搜索对a.globalData.aesKey_keya.globalData.aesKey_iv赋值操作的代码,字符串全局搜索定位到如下代码:

function g() {
    return new Promise(function(s, r) {
        o.wxLogin()().then(function(e) {
          console.log("wxLogin 函数结果:" ,e)
            a.globalData.appMyself_key = n.generateKeys();
            var o = {
                code: e.code,
                publicKey: a.globalData.appMyself_key[0]
            };
            return console.log(o, "login-params"), c(t.login, o);
        }).then(function(t) {
            console.log(t, "登陆成功");
            var o = e.addpasjiemi.jiemi(t.data.content.aesKey, a.globalData.appMyself_key[1]);
            a.globalData.addpasjiemiAA = o, a.globalData.getSession = t.data.content.sessionId, 
            a.globalData.openId = t.data.content.id, a.globalData.aesKey_key = o.substring(016), 
            a.globalData.aesKey_iv = o.substring(16), s(t);
        }).catch(function(e) {
            console.log(e, "登陆失败"), r(e);
        });
    });
}

分析代码,梳理出调用流程:aesKey_iv 和 aesKey_key -> o 字符串 -> 函数e.addpasjiemi.jiemi(t.data.content.aesKey, a.globalData.appMyself_key[1])-> 因此需确定 t值和appMyself_keyappMyself_key根据 n.generateKeys()函数生成; t来源于c(t.login, o),跟进 c(t.login, o),其中o.code参数来源于微信登录接口wx.login返回的响应值。function c(a, t)代码如下:

function c(a, t) {
    var o = i(t);
    console.log(t, "--http-params--login--加密前");
    var n = e.addpasjiemi.addPass(JSON.stringify(o), "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFyD4xpy6JJG4bFGt4PdF7eDT4p9pKbDyz7zvyG7RgTKhNVm+mgmG4iuX04GLuBscin9g33LWm3586DimRkMXdMEIAA7lbfh7ADybG+rClhJmztWqIcJFDwCMUX8vaRg4uG5C+Vn6Pp7NeywDN/aDFxS9A/b83eZh2TeNDe/ywWQIDAQAB")
    , s = l(wx.request);
    return console.log(n, "data_mesage--login--加密后")
    , s({
        url: a,
        data: n,
        method"POST",
        header: {
            "content-type""application/json"
        }
    });
}

函数c(a, t)t参数进行加密签名处理,根据分析可知道,aesKey_iv 和 aesKey_key间接从l(wx.request)的响应中获得。因此最核心的是拦截到wx.login的响应值code
加密流程如下图所示:

某微信小程序参数加密算法分析

0x03 Frida hook wx.login认证流程

wx.login 的响应值code获取走过的坑 
思路1: 通过微信开发者工具运行代码,动态调试代码
加密请求参数,响应返回session_key无效。经查阅微信官方文档.
调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台帐号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台帐号)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。
在微信开发者工具动态调试用的appId是本人的测试账号,因此无权限生成小程序appID对应的code. 开发服务器无法根据该code向腾讯接口换取session_key, 故失败。
思路2: 歪门邪道
根据appid生成任意code,联系某论坛,要价6000 RMB,放弃。一方面钱的问题,另外这是个骗子,腾讯安全团队应该不会发现不出来这个简单的业务逻辑漏洞。
思路3: 自己动手处理wx.login
Frida主要用于Java层的hook,而小程序是由JS编写的,无法直接进行hook。安卓的WebView组件用于网页的解析和js执行,JSBridge可以支持js代码调用安卓的java代码,微信小程序特有的API则是由WxJsBridge提供的,因此以wx. 开头的API都能在这个框架中找到对应的Java代码,通过hook js api对应的Java代码可实现微信小程序的api hook
利用jadx-gui工具分析微信android端 APK文件, 测试发现 package com.tencent.mm.plugin.appbrand.jsapi.auth中的类JsApiLogin的子类LoginTaskwx.login 对应的Java代码。

某微信小程序参数加密算法分析

发现asn()函数实现了登录流程,然而该函数没有参数和返回值,hook没有意义。

  public final void asn() {
            AppMethodBeat.i(46053);
            final a aVar = new a() { // from class: com.tencent.mm.plugin.appbrand.jsapi.auth.JsApiLogin.LoginTask.3
                @Override // com.tencent.mm.plugin.appbrand.jsapi.auth.JsApiLogin.LoginTask.a
                public final void onSuccess(String str) {
                    AppMethodBeat.i(326809);
                    Log.i("MicroMsg.JsApiLogin""onSuccess !");
                    LoginTask.this.code = str;
                    LoginTask.this.rFe = "ok";
                    LoginTask.a(LoginTask.this);
                    AppMethodBeat.o(326809);
                }
                ....
            }
  }

onSuccess函数str参数虽然拿到了code,但是内部函数无法直接hookLoginTask.a(LoginTask.this) 这段引起了我的注意,该函数被调用前,LoginTask已经完成赋值操作,提取LoginTaskcode值即可。

static /* synthetic */ boolean a(LoginTask loginTask) {
            AppMethodBeat.i(46057);
            boolean cpA = loginTask.cpA();
            AppMethodBeat.o(46057);
            return cpA;
        }

hook的函数分析完毕,Frida javascript 测试代码较为简单,如下:

Java.perform(function(){
    var InnerClasses = Java.use("com.tencent.mm.plugin.appbrand.jsapi.auth.JsApiLogin$LoginTask");
    InnerClasses.a.overload('com.tencent.mm.plugin.appbrand.jsapi.auth.JsApiLogin$LoginTask').implementation = function (str){
        var result = this.a(str);
        console.log("Enter the LoginTask.a functions");
        console.log("The result is",str.code.value)
        return result;
    }
})

执行:frida -UF -l ./hookcode.js 小程序点击微信登录,code hook 成功。结果如下:

Script loaded successfully 
Enter the LoginTask.a functions
The result is 051p7A0w3NE9a03EcS0w3etsp13p7A0R

由于wx.login code 有效时间5分钟,调用一次即实现。this.a(str)验证函数要注释掉。导致的问题,微信小程序一直卡在登录中页面,不过没关系,我们已经拿到code, 自己实现代码换回AES_Key 和 AES_IV.

Java.perform(function(){
    var InnerClasses = Java.use("com.tencent.mm.plugin.appbrand.jsapi.auth.JsApiLogin$LoginTask");
    InnerClasses.a.overload('com.tencent.mm.plugin.appbrand.jsapi.auth.JsApiLogin$LoginTask').implementation = function (str){
        //var result = this.a(str);
        console.log("Enter the LoginTask.a functions");
        console.log("The result is",str.code.value)
        //return result;
    }
})

0x04 代码实现

剩下的调用Javascript代码,即可获取AES_Key和 AES_IV。加密算法破解成功。

某微信小程序参数加密算法分析

0x05 安全建议

传输参数加密在一定程度上增加了黑客攻击成本,同时会引入新的安全风险,例如,常规扫描器、WAF、DLP、NDR等安全产品能力失效。任何加密算法都可能存在被破解的风险,因此,为保障线上业务自身的安全性,Numen建议项目方在上线前开展渗透测试及代码审计服务。

某微信小程序参数加密算法分析

Numen 官网
https://numencyber.com/ 
GitHub
https://github.com/NumenCyber
Twitter
https://twitter.com/@numencyber
Medium
https://medium.com/@numencyberlabs
LinkedIn
https://www.linkedin.com/company/numencyber/

原文始发于微信公众号(Numen Cyber Labs):某微信小程序参数加密算法分析

版权声明:admin 发表于 2023年2月27日 下午3:02。
转载请注明:某微信小程序参数加密算法分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...