如何通过反编译获取小程序源码
Alplune 摸鱼ing
10.22日更新

微信PC端于 2.7.0 版本开始支持打开小程序,因此也可以直接在PC端打开小程序获取到pkg文件,pkg文件路径在微信默认保存位置下 WeChat Files\Applet\wx{…………}\中

但是直接拿去反编译会出现报错,原因是文件被加密了,需要先用解密工具解密,然后再反编译。

Error: Magic number is not correct!


背景

​ 最近在学习怎么写小程序,在写练习小demo时想到,小程序并没有开发者工具,如果想学习其他优秀的小程序怎么写,并没有很好的途径去看源代码。而且小程序代码放在微信的服务器上,也不方便获取,如果有办法获取小程序的源码就好啦


工具准备
  1. node.js运行环境:

    后面用于运行node脚本 。下载地址:https://nodejs.org/en/

  2. 反编译的脚本:

    源码链接 mirrors / xuedingmiaojun / wxappunpacker · GitCode

  3. 夜神模拟器(不唯一,用于获取pkg文件)

    下载地址:https://www.yeshen.com/cn/download/fullPackage


获取编译后的pkg文件

在模拟器中登录微信,随便打开目标小程序

打开文件管理器,找到/data/data/com.tencent.mm/MicroMsg 目录 ,然后找到一个很长的用户随机码,继续找到/appbrand/pkg/xxx,接下来会出现小程序A的wxapkg包

image-20221020120357991

长按复制时间排序最新的那个文件,后点开右边工具栏的文件助手

image-20221020120622664

点击打开安卓文件夹,把刚刚复制的文件粘贴到安卓文件夹中

image-20221020120830433

然后我们就可以在电脑相应的路径下得到该pkg文件了

安装脚本依赖并执行

1.安装依赖

到达脚本文件所在处,打开命令行依次执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
npm install

npm install esprima
    
npm install css-tree
    
npm install cssbeautify
    
npm install vm2
    
npm install uglify-es
    
npm install js-beautify

2.执行脚本命令

1
2
node  wuWxapkg.js C:\Users\pc-03\Nox_share\ImageShare\xxx.wxapkg
后面那个是pkg文件的地址,记得修改!

3.编译结果

  • 编译成功

    image-20221020121727393

  • 编译失败

    • Module build failed: Error: Cannot find module ‘escodegen’

      1
      npm i --save-dev escodegen
    • Error: Cannot find module ‘cheerio’

      1
      2
      3
      4
      5
      6
      7
      8
      9
      npm install uglify-es --save
      npm install esprima --save
      npm install css-tree --save
      npm install cssbeautify --save
      npm install vm2 --save
      npm install uglify-es --save
      npm install js-beautify --save
      npm install escodegen --save
      npm install cheerio --save
    • 未识别的包
      说明拿到的两个.wxapkg文件里,当前反编译的包不是工程文件夹,再去管理器看下,是不是还有另一个文件呢!这个.wxapkg里面都是微信的基础包,是无需还原的!!!

    • SyntaxError: Unexpected end of input 解决wxss文件缺失问题
      修改wxappUnpacker中wuWxss.js部分代码,具体如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      function runVM(name,code){

      let wxAppCode={},handle={cssFile:name};

      let gg = new GwxCfg();

      let tsandbox = {$gwx:GwxCfg.prototype["$gwx"],__mainPageFrameReady__:GwxCfg.prototype["$gwx"],__wxAppCode__:wxAppCode,setCssToHead:cssRebuild.bind(handle)};

      let vm = new VM({sandbox:tsandbox});

      vm.run(code);

      for(let name in wxAppCode)if(name.endsWith(".wxss")){

      handle.cssFile=path.resolve(frameName,"..",name);

      wxAppCode[name]();

      }

      /*

      let wxAppCode={},handle={cssFile:name};

      let vm=new VM({sandbox:Object.assign(new GwxCfg(),{__wxAppCode__:wxAppCode,setCssToHead:cssRebuild.bind(handle)})});

      vm.run(code);

      for(let name in wxAppCode)if(name.endsWith(".wxss")){

      handle.cssFile=path.resolve(frameName,"..",name);

      wxAppCode[name]();

      }*/

      }

修改后再次编译,成功后同目录下就出现了完整的同名的文件夹了~


总结

​ 前前后后花了大概一天时间完成了这个过程,小小开心一下。期间看网上很多教程都有不少纰漏,例如脚本源代码地址失效,获取文件方式繁琐且失败率高,脚本依赖安装不完整等等。所以决定记录下来,方便以后和大家一起学习交流~