node.js中PC端微信小程序包解密的处理思路

2022-04-15 0 893
目录
  • 小程序的源码在哪里
  • PC端小程序是怎么被加密的
  • 解密思路
    • 预处理
    • 加密后的头部部分
    • 加密后的尾部部分
  • 再漂亮点
    • commander
    • chalk
  • 源代码

    原来发布在掘金,搬过来好了。

    微信小程序在PC端是加密存储的,如果直接打开是看不到什么有用的信息的,需要经过解密才可以看到包内具体的内容。本文使用nodejs实现解密算法,主要涉及到crypto, commander, chalk三个包的使用。

    小程序的源码在哪里

    PC端打开过的小程序会被缓存到本地微信文件的默认保存位置,可以通过微信PC端=>更多=>设置查看:

    node.js中PC端微信小程序包解密的处理思路

    进入默认保存位置下的/WeChat Files/WeChat Files/Applet文件夹,可以看到该目录下有一系列前缀为wx的文件(文件名其实是小程序的appid),这些就是我们打开过的小程序啦:

    node.js中PC端微信小程序包解密的处理思路

    进入其中某个小程序的文件夹,我们可以看到一个名字为一串数字的文件夹。点进这个文件夹, 就可以看到一个__APP__.wxapkg文件,也就是小程序对应的代码啦:

    node.js中PC端微信小程序包解密的处理思路

    然而,当我们打开这个文件之后却发现是这样的:

    node.js中PC端微信小程序包解密的处理思路

    WTF 这能看出来个。很明显,这个文件是经过加密的,需要解密才能看到我们想看到的东西。

    PC端小程序是怎么被加密的

    这里参考了一位大佬用Go语言写的PC端wxapkg解密代码。整理一下的话,加密流程是这样的:

    node.js中PC端微信小程序包解密的处理思路

    首先将明文代码在第1024字节处一分为二,前半部分使用CBC模式的AES加密,后半部分则直接进行异或。最后,将加密后的两节拼接起来,并在最前边写入固定的字符串:”V1MMWX”。

    所以,我们打开__APP__.wxapkg文件看到的就是加密后的代码,如果想还原回去的话,需要从后往前逐步推回去。

    解密思路

    预处理

    我们使用node.js去写一个解码的程序。根据上边加密的流程,我们首先读取加密文件,把前6个字节的固定字符串去除。由于AES加密和异或前后数据的位数是相同的,我们可以据此获取到加密后的头部1024字节和加密后的尾部部分:

    const fs = require('fs').promises;
    ...
     
    const buf = await fs.readFile(pkgsrc); // 读取原始Buffer
    const bufHead = buf.slice(6, 1024 + 6);
    const bufTail = buf.slice(1024 + 6);

    加密后的头部部分

    为了得到这1024个字节的明文,我们需要知道AES加密的初始向量iv,以及一个32位的密钥。已知16字节的初始向量iv是字符串:“the iv: 16 bytes”,我们接下来需要计算出这个由pbkdf2算法导出的32位的密钥。

    pbkdf2(Password-Based Key Derivation Function)是一个用来生成密钥的函数,它使用一个伪随机函数,将原文密码和salt作为输入,通过不断的迭代得到密钥。在crypto库中,pbkdf2函数是这样的:

    const crypto = require('crypto');
    ...
     
    crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)

    其中参数分别是:原文密码、盐值、迭代次数、密钥长度、散列算法、回调函数。已知salt是”saltiest”,原文密码为微信小程序的id(也就是wx开头的那个文件夹名),迭代次数为1000,散列算法为sha1。因此,我们可以写出计算密钥的代码:

    crypto.pbkdf2(wxid, salt, 1000, 32, 'sha1', (err, dk) => {
        if (err) {
            // 错误
        }
        // dk即为计算得到的密钥
    })

    密钥和初始向量iv都有了之后,我们可以开始对密文进行解密了。AES加密算法是一种非对称加密算法,它的密钥分成公开的公钥和只有自己知道的私钥,任何人都可以使用公钥进行加密,但是只有持有私钥的人解密得到明文。

    小程序使用的加密算法是CBC(Cipher Block Chaining, 密码分组链接)模式的AES,也就是它在加密的时候,首先把明文进行分块,然后将每一块与前一块加密后的密文进行异或,再使用公钥进行加密,得到每一块的密文。对于第一块明文,由于它不存在前一块明文,因此它会与初始向量iv进行异或,再进行公钥加密。在实现的时候,我们只需要调用crypto提供的解密函数就可以啦。

    我们知道,AES算法根据密钥长度的不同有AES128, AES192和AES256。回顾上边,我们的密钥是32字节,也就是256位的,因此显然我们应该使用的是AES256。综上,我们可以写出来解密的代码:

    const decipher = crypto.createDecipheriv('aes-256-cbc', dk, iv);
    const originalHead = Buffer.alloc(1024, decipher.update(bufHead));

    其中originalHead就是我们要的前1024字节的明文啦。我们可以打印出来看看:

    node.js中PC端微信小程序包解密的处理思路

    嗯…… 有那么点意思了。

    加密后的尾部部分

    这一部分就很简单啦。由于异或运算是具有自反性的,因此只需要简单的判断一下小程序id的位数获得异或的xorKey,再把它与密文进行异或,就可以得到原文了:

    const xorKey = wxid.length < 2 ? 0x66 : wxid.charCodeAt(wxid.length - 2);
    const tail = [];
    for(let i = 0; i < bufTail.length; ++i){
        tail.push(xorKey ^ bufTail[i]);
    }
    const originalTail = Buffer.from(tail);

    将头部部分的明文与尾部部分的明文进行拼接,再以二进制形式写入文件,就可以得到最终的明文啦。

    再漂亮点

    根据上边的描述,我们可以把我们整个的解密过程封装成一个黑盒子:

    node.js中PC端微信小程序包解密的处理思路

    commander

    我们可以使用commander库让程序直接从命令行读取小程序的id和密文包。commander是一个nodejs命令行界面的解决方案,可以很方便的定义自己的cli命令。比如说对于下面这一串代码:

    const program = require('commander');
    ...
    program
        .command('decry <wxid> <src> [dst]')
        .description('解码PC端微信小程序包')
        .action((wxid, src, dst) => {
            wxmd(wxid, src, dst);
        })
     
    program.version('1.0.0')
        .usage("decry <wxid> <src> [dst]")
        .parse(process.argv);

    我定义了一个”decry <wxid> <src> [dst]”的命令,其中尖括号代表必选参数,方括号代表可选参数。description内是关于这个命令的描述文本,action则是执行这段命令。在控制台使用node执行代码之后,可以看到如下界面:

    node.js中PC端微信小程序包解密的处理思路

    于是我们就可以根据提示,输入参数进行解密啦。commander.js的中文文档在这里。

    chalk

    为了让我们的控制台多一抹颜色,我们可以使用chalk.js来美化输出。chalk的基本用法也比较简单:

    const chalk = require('chalk');
    ...
     
    console.log(chalk.green('绿了'))

    这样我们就可以在黑白的控制台上填上一抹绿色,替大熊猫实现梦想:

    node.js中PC端微信小程序包解密的处理思路

    除此之外,我们还可以使用es6的字符串标签模板更方便的使用chalk。具体的参考chalk官方文档吧。

    源代码

    代码发布到github和gitee啦,可以给大家参考一下下~

    github点这里, gitee点这里

    到此这篇关于node.js中PC端微信小程序包解密的文章就介绍到这了,更多相关nodejs微信小程序解密内容请搜索NICE源码以前的文章或继续浏览下面的相关文章希望大家以后多多支持NICE源码!

    免责声明:
    1、本网站所有发布的源码、软件和资料均为收集各大资源网站整理而来;仅限用于学习和研究目的,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 不得使用于非法商业用途,不得违反国家法律。否则后果自负!

    2、本站信息来自网络,版权争议与本站无关。一切关于该资源商业行为与www.niceym.com无关。
    如果您喜欢该程序,请支持正版源码、软件,购买注册,得到更好的正版服务。
    如有侵犯你版权的,请邮件与我们联系处理(邮箱:skknet@qq.com),本站将立即改正。

    NICE源码网 JavaScript node.js中PC端微信小程序包解密的处理思路 https://www.niceym.com/21355.html