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

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

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

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

小程序的源码在哪里

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

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

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

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

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

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

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

首先将明文代码在第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字节的明文啦。我们可以打印出来看看:

嗯…… 有那么点意思了。

加密后的尾部部分

这一部分就很简单啦。由于异或运算是具有自反性的,因此只需要简单的判断一下小程序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);

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

再漂亮点

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

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执行代码之后,可以看到如下界面:

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

chalk

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

const chalk = require('chalk');
...

console.log(chalk.green('绿了'))

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

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

源代码

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

github点这里, gitee点这里

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

(0)

相关推荐

  • 微信小程序 获取手机号 JavaScript解密示例代码详解

    当我们在开发微信小程序中,有一个常用的功能,就是获取用户的手机号,然后一键登入小程序,那么手机号如何获取呢?请认真看完本文,保证可以获取到用户的手机号. 刚开始开发微信小程序的时候,想着实现手机验证码登入,后来查阅资料得知,发给用户的短信是要自己付费的.后来想想,微信获取用户的手机号一样可以保证手机号码的真实性,因为手机号既然可以绑定微信,那么肯定是被严格核验过的,然后就开始了获取手机号之旅,网上教程有很多,但不知什么原因,都是会少一些内容,有的只有前端代码,没有后端:有的后端代码是PHP,不是

  • 微信小程序登录数据解密及状态维持实例详解

    本文实例讲述了微信小程序登录数据解密及状态维持.分享给大家供大家参考,具体如下: 学习过小程序的朋友应该知道,在小程序中是不支持cookie的,借助小程序中的缓存我们也可以存储一些信息,但是对于一些比较重要的信息,我们需要通过登录状态维持来保存,同时,为了安全起见,用户的敏感信息,也是需要加密在网络上传输的. 前台,service.封装了http请求,同时封装了getSession(通过code获取服务器生成的session).getUserInfo(获取用户信息).getDecryptionD

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

    目录 小程序的源码在哪里 PC端小程序是怎么被加密的 解密思路 预处理 加密后的头部部分 加密后的尾部部分 再漂亮点 commander chalk 源代码 原来发布在掘金,搬过来好了. 微信小程序在PC端是加密存储的,如果直接打开是看不到什么有用的信息的,需要经过解密才可以看到包内具体的内容.本文使用nodejs实现解密算法,主要涉及到crypto, commander, chalk三个包的使用. 小程序的源码在哪里 PC端打开过的小程序会被缓存到本地微信文件的默认保存位置,可以通过微信PC端

  • JS中promise化微信小程序api

    promise化的原因 微信小程序的api用的是对象参数回调模式,很容易造成回调地狱,代码难以阅读,判断,修改 和调试. 微信小程序api示例 // 获取用户信息 wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) { // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 wx.getUserInfo({ success: res => { // 可以将 res 发送给后台解码

  • 微信小程序dom操作的替代思路实例分析

    本文实例讲述了微信小程序dom操作的替代思路.分享给大家供大家参考,具体如下: 微信小程序无法操作dom,这意味着之前js中的各种习惯方法必须换一种思路实现 在尝试了几类情况后,发现部分情况下可以用{{}}变量绑定来实现效果. 比如: 一.实现view的显示和隐藏 在js中的data设置变量 bottomHidden1:"block": 然后在wxml中的view中设置<view class="bottom1" style="display:{{bo

  • 微信小程序后台解密用户数据实例详解

     微信小程序后台解密用户数据实例详解 微信小程序API文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html openId : 用户在当前小程序的唯一标识 因为最近根据API调用https://api.weixin.qq.com/sns/jscode2session所以需要配置以下服务,但是官方是不赞成这种做法的, 而且最近把在服务器配置的方法给关闭了.也就是说要获取用户openid,地区等信息只能在后台获取. 一下是官方的

  • java实现微信小程序加密数据解密算法

    一.概述 微信推出了小程序,很多公司的客户端应用不仅具有了APP.H5.还接入了小程序开发.但是,小程序中竟然没有提供Java版本的加密数据解密算法.这着实让广大的Java开发人员蛋疼. 微信小程序提供的加密数据解密算法链接 我们下载的算法示例如下: 木有Java!! 木有Java!! 木有Java!! 那么如何解决这个问题,我们一起来实现Java版本的微信小程序加密数据解密算法. 二.实现Java版本的微信小程序加密数据解密算法 1.创建项目 这里,我们创建一个Maven工程,具体创建步骤略.

  • 微信小程序向Java后台传输参数的方法实现

    首先,微信小程序我使用的是微信web开发者工具 想要向后台传输数据,需要在js中写 在微信小程序的官方文档中可以看到一个api叫wx.request它的作用是用来发送https请求的 在js代码中,我们先使用wx.request这个api,它需要我们去写url,这个url其实就是Java代码部署在服务器上运行后的地址,这里我们没有真实服务器,我们使用tomcat去运行后端代码,将这个url复制给微信小程序的url中 我的Java代码在运行时出现一个问题,就是找不到我这个类,一直报404错误,一个

  • node.js微信小程序配置消息推送的实现

    在开发微信小程序时,有一个消息推送,它的解释是这样的. 消息推送具体的内容是下面的这个网址   https://developers.weixin.qq.com/miniprogram/dev/framework/server-ability/message-push.html,他介绍的也还可以,就是我这里换成了node代码. 消息推送 启用并设置消息推送配置后,用户发给小程序的消息以及开发者需要的事件推送,都将被微信转发至该服务器地址中. 在微信小程序的首页开发里面,开发设置中,微信的官网中,

  • 微信小程序使用第三方库Underscore.js步骤详解

    前言 Underscore.js是一个很精干的库,压缩后只有4KB.Underscore 提供了100多个函数,包括常用的:map.filter.invoke - 当然还有更多专业的辅助函数,如:函数绑定.JavaScript 模板功能.创建快速索引.强类型相等测试等等.弥补了标准库的不足,大大方便了JavaScript的编程. 微信小程序无法直接使用require( 'underscore.js' )进行调用. 微信小程序模块化机制 微信小程序运行环境支持CommoJS模块化,通过module

  • JS绘制微信小程序画布时钟

    微信小程序官方组件也提供了画布功能,下面分享一下如何创建微信小程序画布时钟. 总体思路是对pages中的一个小程序页面构建画布时钟逻辑程序,通过app.json公共设置来配置入口. 首先来看一下构建这样一个小程序所需要的目录结构 从目录结构就可以看出来这个程序是简单的单层页面,画布渲染在pages下面的index页面上. 其中对程序有实际驱动作用的代码分别在index.js,index.wxml,index.wxss和app.json这几个文件中 Index.js文件里面存放着程序的逻辑层数据,

  • 微信小程序中多个页面传参通信的学习与实践

    前言 微信小程序越来越火,不少公司都在将原生代码转为微信小程序代码.在开发过程中,由于微信小程序wx.navigateBack方法并不支持返回传参,导致一些页面,尤其是从列表页面跳入详情页,用户在详情页改变了状态,返回后无论是否刷新页面,体验都不是很好.在android中,我们一般采用setresult方法来返回参数,或者直接使用rxjava框架或者eventbus框架来解决此类问题. 业务分析 此类需求大概意思是:A页面进入B页面,B页面返回并传值给A. 探索之路 刚开始我想采用一个比较偷懒的

随机推荐