微信小程序反编译总结

参考博客

https://www.cnblogs.com/yangda/p/12941806.html
https://blog.csdn.net/larasse/article/details/106264834
https://blog.csdn.net/qq_41297837/article/details/103962564

操作步骤

  1. 下载node.js
  2. 下载 wxappUnpacker https://github.com/ROBOT008/wxappUnpacker 或者自行在github上搜索wxappUnpacker选择下载 或者百度云链接 提取码:hao6
  3. 在cmd中切换到wxappUnpacker的目录下,输入以下命令安装依赖(百度云下载可以不执行这一步),会创建一个 node_modules 的文件夹:
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
  1. 下载安卓模拟器,登录微信并打开微信小程序
  2. 找到文件路径 /data/data/com.tencent.mm/MicroMsg/{User}/appbrand/pkg 其中{User} 为当前用户的用户名,类似于 2bc**************b65
  3. 文件后缀为.wxapkg就是微信小程序的’包’,发送这样的文件到电脑,如果发送不了就压缩一下。
  4. 解析主包命令执行命令 node wuWxapkg.js testpkg/master-xxx.wxapkg(主包)
    解析子包命令执行命令 node wuWxapkg.js testpkg/sub-1-xxx.wxapkg -s=../master-xxx
    注:-s参数可为相对路径或绝对路径相对路径的起点不是当前目录 而是子包解包后的目录,如果相对路径的文件夹不存在,就无法产生wxml和js文件到主包的目录
├── testpkg
│   ├── sub-1-xxx.wxapkg #被解析子包
│   └── sub-1-xxx               #相对路径的起点
│       ├── app-service.js
│   ├── master-xxx.wxapkg #被解析主包
│   └── master-xxx             # ../master-xxx 就是这个目录
│       ├── app.json

在这里插入图片描述

一些说明

  1. 在找寻wxapkg包的时候,有一个大约10M的wxapkg的包反编译出来没有pages、lib等文件夹,并且这个包反编译会报This package is unrecognizable或者 not a directory, scandir 'D:\223\_1123949441_432\WAAutoService.js'错误,这个包有可能是微信小程序运行的一些核心包
  2. 分包和主包的文件名下划线后面的数字都是一样,主包的大小要比分包大
    在这里插入图片描述

遇到的问题

编译报magic number is not correct

【描述】我遇到这种情况是因为我直接用的是电脑版微信文件下的 .wxapkg文件
【解决】直接在安卓模拟器上登录微信,获取模拟器上的 .wxapkg文件

编译出来没有wxss文件 vd_version_info is not define

在这里插入图片描述【解决】只需要进wuWxss.js文件里修改一下方法就行,找到function runOnce() 方法,修改成以下代码:

function runOnce() {
		for (let name in runList) {
			var start = `var window = window || {}; var __pageFrameStartTime__ = Date.now(); var __webviewId__; var __wxAppCode__={}; var __mainPageFrameReady__ = function(){}; var __WXML_GLOBAL__={entrys:{},defines:{},modules:{},ops:[],wxs_nf_init:undefined,total_ops:0}; var __vd_version_info__=__vd_version_info__||{};
			$gwx=function(path,global){
				if(typeof global === 'undefined') global={};if(typeof __WXML_GLOBAL__ === 'undefined') {__WXML_GLOBAL__={};
			}__WXML_GLOBAL__.modules = __WXML_GLOBAL__.modules || {};
			}`;
		runVM(name, start + " \r\n" + runList[name]);
		}
	}

修改wxWxss文件的runVm函数 ,改为

function runVM(name, code) {
      let wxAppCode = {};
      let handle = {cssFile: name};
      let gg = new GwxCfg();
      let tsandbox = {
         $gwx: GwxCfg.prototype["$gwx"],
         __mainPageFrameReady__: GwxCfg.prototype["$gwx"],   //解决 $gwx is not defined
         __vd_version_info__: GwxCfg.prototype["$gwx"],  //解决 __vd_version_info__ is not defined
         __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]();
         }
      }
   }
【未解决】反编译wxss文件时报错 SyntaxError: Unexpected end of input在这里插入图片描述
.wxapkg不是微信小程序的包

【报错】This package is unrecognizable 或者 not a directory, scandir 'D:\223\_1123949441_432\WAAutoService.js'
【说明】当前反编译的包不是工程文件夹,里面都是微信的基础包,无需还原。
在这里插入图片描述在这里插入图片描述

【未解决】Illegal return statement

【问题说明】反编译其他的包可以,但是反编译这个包就报错了
【解决】我觉得可能是 wxappUnpacker 不支持反编译新开发的小程序;去gitub上查找最新的 wxappUnpacker,重新安装依赖,就可以避免这个问题。
在这里插入图片描述在解决了上面的问题后,js和wxml都可以反编译得到,但是wxss不能得到,同时出现下面这个错误;希望有大佬路过,可以解决这个问题,谢谢。
我猜想可能是因为这个小程序采用了分包才导致的这个问题,当我反编译其他没有采用分包的小程序的时候,就得到了所有的文件,包括wxss。
在这里插入图片描述在这里插入图片描述

请选择app.json/project.config.json 的目录在这里插入图片描述

【解决】将项目下的 app-config.json 改名为 app.json

成功截图

在这里插入图片描述

手动获取相关的js代码

如果你想学习一下别人的代码逻辑,但是用上面的方法得不到js代码,可以试着手动来得到js代码,尤其是分包中的js代码。
对于主包,如果用上面的方法只能得到空文件,那么就可以试试下面这些单独的命令来得到 js,wxml,wxss等代码源码

- `node wuConfig.js <app-config.json...>` 将 app-config.json 中的内容拆分到各个文件对应的 .json 和 app.json , 并通过搜索 app-config.json 所在文件夹下的所有文件尝试将 iconData 还原为 iconPath 。
- `node wuJs.js <app-service.js...>` 将 app-service.js (或小游戏中的 game.js ) 拆分成一系列原先独立的 javascript 文件,并使用 Uglify-ES 美化,从而尽可能还原编译前的情况。如果是子包的app-service.js,则需要另外处理(和主包的app-service.js保持结构一致定义了__wxAppCode__,并没有`$gwx('init', global);`- `node wuWxml.js [-m] <files...>` 将编译/混合到 page-frame.html ( 或 app-wxss.js 或 page-frame.js ) 中的 wxml 和 wxs 文件还原为独立的、未编译的文件。如果加上`-m`指令,就会阻止`block`块自动省略,可能帮助解决一些相关过程的 bug 。
- `node wuWxss.js <dirs...>` 通过获取文件夹{{dirs}}下的 page-frame.html ( 或 app-wxss.js ) 和其他 html 文件的内容,还原出编译前 wxss 文件的内容。
- `node wuWxapkg.js [-o] [-d] [-s=<Main Dir>] <files...>` 将 wxapkg 文件解包,并将包中上述命令中所提的被编译/混合的文件自动地恢复原状。如果加上`-o`指令,表示仅解包,不做后续操作。如果加上`-d`指令,就会保留编译/混合后所生成的新文件,否则会自动删去这些文件。同时,前面命令中的指令也可直接加在这一命令上。而如果需要解压分包,请先解压主包,然后执行`node wuWxapkg.js [-d] -s=<Main Dir> <subPackages...>`,其中`Main Dir`为主包解压地址。除`-d``-s`外,这些指令两两共存的后果是未定义的(当然,是不会有危险的)。

微信小程序中js相关的代码都在 app-service.js中,在下面这段代码中,/bookingSuccess/bookingSuccess.js是js文件名【绿色的】,其中 define()括号中 "use strict";}); require("/bookingSuccess/bookingSuccess.js");之间的代码为 js文件的内容【红色的】。在 app-service.js文件中,你只需要关心类似于下面这段代码的其他代码,一般在最后。

__wxRoute = ‘/bookingSuccess/bookingSuccess’;__wxRouteBegin = true; wxAppCurrentFile = ‘/bookingSuccess/bookingSuccess.js’; define(" / b o o k i n g S u c c e s s / b o o k i n g S u c c e s s . j s \color{#228B22}{/bookingSuccess/bookingSuccess.js} /bookingSuccess/bookingSuccess.js", function(require, module, exports, window,document,frames,self,location,navigator,localStorage,history,Caches,screen,alert,confirm,prompt,XMLHttpRequest,WebSocket,Reporter,webkit,WeixinJSCore){ “use strict”; Page({data:{num:0,time:"",shopName:""},onLoad:function(n){this.setData({num:n.num,time:n.time,shopName:n.shopName}),wx.hideShareMenu()},myBooking:function(){wx.redirectTo({url:"/myYuyue/myYuyue"})},onReady:function(){},onShow:function(){},onHide:function(){},onUnload:function(){},onPullDownRefresh:function(){},onReachBottom:function(){},onShareAppMessage:function(){}});
});
require(" / b o o k i n g S u c c e s s / b o o k i n g S u c c e s s . j s \color{#228B22}{/bookingSuccess/bookingSuccess.js} /bookingSuccess/bookingSuccess.js");

提示:这里的js代码需要自己手动美化(有很多在线美化js的网站)
如下图,有三个js文件,绿框为文件名,红框为文件内容,黑框可以作为寻找标识。
在这里插入图片描述最后将 !0 批量替换成 false; !1批量替换成 true

手动获取wxss

参考 https://blog.csdn.net/weixin_35839384/article/details/113717707

wxss和wxml 的代码在 page-frame.js,例如想获取 /bookingSuccess/bookingSuccess.wxss的内容:

  • 将以下代码另存为html文件
  • 首先搜索 wxAppCode[’/bookingSuccess/bookingSuccess.wxss’] = setCssToHead,可以看到setCssToHead是一个函数
  • 将函数的第一个参数(数组)替换为以下html代码中setCssToHead的第一个参数
  • 最后运行html就可以得到wxss
<br><br>结果:<br><br>
<script type="text/javascript">
var __wxAppCode__= __wxAppCode__ || {}; 
     var BASE_DEVICE_WIDTH = 750;
var isIOS=navigator.userAgent.match("iPhone");
var deviceWidth = window.screen.width || 375;
var deviceDPR = window.devicePixelRatio || 2;
var checkDeviceWidth = window.__checkDeviceWidth__ || function() {
var newDeviceWidth = window.screen.width || 375
var newDeviceDPR = window.devicePixelRatio || 2
var newDeviceHeight = window.screen.height || 375
if (window.screen.orientation && /^landscape/.test(window.screen.orientation.type || '')) newDeviceWidth = newDeviceHeight
if (newDeviceWidth !== deviceWidth || newDeviceDPR !== deviceDPR) {
deviceWidth = newDeviceWidth
deviceDPR = newDeviceDPR
}
}
checkDeviceWidth()
var eps = 1e-4;
var transformRPX = window.__transformRpx__ || function(number, newDeviceWidth) {
if ( number === 0 ) return 0;
number = number / BASE_DEVICE_WIDTH * ( newDeviceWidth || deviceWidth );
number = Math.floor(number + eps);
if (number === 0) {
if (deviceDPR === 1 || !isIOS) {
return 1;
} else {
return 0.5;
}
}
return number;
}
window.__rpxRecalculatingFuncs__ = window.__rpxRecalculatingFuncs__ || [];
var __COMMON_STYLESHEETS__ = __COMMON_STYLESHEETS__||{}

var setCssToHead = function(file, _xcInvalid, info) {
var Ca = {};
var css_id;
var info = info || {};
var _C = __COMMON_STYLESHEETS__
function makeup(file, opt) {
var _n = typeof(file) === "string";
if ( _n && Ca.hasOwnProperty(file)) return "";
if ( _n ) Ca[file] = 1;
var ex = _n ? _C[file] : file;
var res="";
for (var i = ex.length - 1; i >= 0; i--) {
var content = ex[i];
if (typeof(content) === "object")
{
var op = content[0];
if ( op == 0 )
res = transformRPX(content[1], opt.deviceWidth) + "px" + res;
else if ( op == 1)
res = opt.suffix + res;
else if ( op == 2 )
res = makeup(content[1], opt) + res;
}
else
res = content + res
}
return res;
}
var styleSheetManager = window.__styleSheetManager2__
var rewritor = function(suffix, opt, style){
opt = opt || {};
suffix = suffix || "";
opt.suffix = suffix;
if ( opt.allowIllegalSelector != undefined && _xcInvalid != undefined )
{
if ( opt.allowIllegalSelector )
console.warn( "For developer:" + _xcInvalid );
else
{
console.error( _xcInvalid );
}
}
Ca={};
css = makeup(file, opt);
if (styleSheetManager) {
var key = (info.path || Math.random()) + ':' + suffix
if (!style) {
styleSheetManager.addItem(key, info.path);
window.__rpxRecalculatingFuncs__.push(function(size){
opt.deviceWidth = size.width;
rewritor(suffix, opt, true);
});
}
styleSheetManager.setCss(key, css);
return;
}
if ( !style )
{
var head = document.head || document.getElementsByTagName('head')[0];
style = document.createElement('style');
style.type = 'text/css';
style.setAttribute( "wxss:path", info.path );
head.appendChild(style);
window.__rpxRecalculatingFuncs__.push(function(size){
opt.deviceWidth = size.width;
rewritor(suffix, opt, style);
});
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
if ( style.childNodes.length == 0 )
style.appendChild(document.createTextNode(css));
else
style.childNodes[0].nodeValue = css;
}
return css
}
return rewritor;
}
__wxAppCode__['pages'] = setCssToHead([".",[1],"container{background-color:#f7f7f7}\n.",[1],"gray{color:#dcdcdc!important}\n.",[1],"purple{color:#9f8bea!important}\n.",[1],"repair-state-panel,.",[1],"work-sheet-panel{display:-webkit-flex;display:flex;-webkit-flex-direction:column;flex-direction:column;margin-top:",[0,15],"}\n.",[1],"repair-state-title,.",[1],"work-sheet-title{color:#888;padding:",[0,5]," 0 ",[0,10]," ",[0,30],"}\n.",],undefined,{path:"./pages"});

document.write(__wxAppCode__['pages']("",{deviceWidth:375},document.body))
</script>

但是这个只能在iPhone 6上适配,需要改成rpx,方能适配其他的设备终端。rpx和px 的转换公式:
rpx = px * 2
px = rpx / 2
经过转换后,问题就完美解决

手动获取html信息

wxml 的代码也在 page-frame.js中,使用wxml.js只能得到wxml的整体架构,但是有很多值为Empty,这是因为解析__WXML_GLOBAL__.ops_cached.$gwx1_1数组失败,手动根据var m0=function(e,s,r,gg)函数的执行过程还原

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值