作者:保佑想-回丽水的阿卉 | 来源:互联网 | 2024-10-10 07:15
偶然有需求了解别人的小程序实现方法,网上相关资料很多,顺便了解了一下,做个总结,没啥技术含量,分享出来。要求安装Nodejs一台root后的安卓手机或者装有可以打开微信小程序的安卓
偶然有需求了解别人的小程序实现方法,网上相关资料很多,顺便了解了一下,做个总结,没啥技术含量,分享出来。
要求
- 安装Nodejs
- 一台root后的安卓手机或者装有可以打开微信小程序的安卓模拟器
- 一个敢于折腾的耐心
看起来很简单的样子
准备
安装反编译工具
【推荐】方法一:你可以通过git clone将它存在本地
git clone https://github.com/qwerty472123/wxappUnpacker.git
将工具放在需要的目录内(例如wxappUnpacker
)。
方法二:也可以直接下载这个工具包,点击下载,并解压出来。
接着在该项目内执行:
npm install esprima css-tree cssbeautify vm2 uglify-es js-beautify escodegen
安装完项目依赖后开始进行最复杂的操作,提取小程序包。
提取微信小程序文件包
此时你有两个选择:通过安卓虚拟机获取,用你已经root的安卓机操作。
安卓虚拟机
- 如果你是Windows,这就好说了。
【推荐】选择夜神模拟器下载并安装。
【似乎不太好用】我已经实践过了,这里有破解版的模拟器:Genymotion v2.12.2破解版。但是你要注册一个账号来添加虚拟设备,进行安装。安装完成后就可以启动了。
【失败】网易的Mumu也是安卓模拟器,但是经过实践,居然不支持微信小程序。
- 如果你是MacOS
上面提到的Genymotion
也是支持MacOS的,不过还是很麻烦。
Mumu似乎不错,结果上面提到了,MacOS下也是打不开微信小程序的。
结论:请自行尝试Genymotion
模拟,或者找其他我还没发现的模拟器。
已Root安卓手机
你用有一台牛逼闪闪的安卓手机,但是大部分手机不允许root的,或者说root也是非常复杂的,所以如果你不懂得如何root,请考虑使用安卓虚拟机!
如果你优秀的root过了,这里又有两个方案:
- 【风险极高】粗暴的下载一个root explorer破解版,并授权root权限!
- 【推荐】从谷歌商店或者可靠的应用市场下载
Root Explorer
,土豪请付款购买,好像不到6美元
,我这里尝试了一下ES文件浏览器
也可以,所以接下来下载它并安装好。
看到这里,我当你已经拥有了一台可以登录微信、安装了文件管理工具、并给它授予最高权限的安卓手机了!
提取文件
此时,文件就拿到了。
反编译
进入工具目录wxappUnpacker
,建一个文件夹,比如pkg
,将刚才拿到的文件放在这里。
假设,我要尝试反编译这个文件_46541548_7.wxapkg
,执行命令:
node wuWxapkg.js ./pkg/_46541548_7.wxapkg
顺利的话会生成一个同名的目录。打开这个目录就能看到了。
异常
程序出问题,工具出问题,代码有BUG,再常见不过了。以下几个异常,你也许也发生过,可能不明白,我把我遇到的异常理解分享一下:
未安装成功工具依赖的模块
Error: Cannot find module 'uglify-es'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
at Function.Module._load (internal/modules/cjs/loader.js:507:25)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object. (/Users/whidy/webs/wxappUnpacker/wuJs.js:3:16)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
那就是你没装好依赖,再执行一次npm run uglify-es
。
未识别的包
...
Saving files...
Unpack done.
/Users/whidy/webs/wxappUnpacker/wuWxapkg.js:104
}else throw Error("This package is unrecognizable.\nMay be this package is a subPackage which should be unpacked with -s=.\nOtherwise, please decrypted every type of file by hand.")
^
Error: This package is unrecognizable.
May be this package is a subPackage which should be unpacked with -s=.
Otherwise, please decrypted every type of file by hand.
at Array.packDone (/Users/whidy/webs/wxappUnpacker/wuWxapkg.js:104:14)
at CntEvent.decount (/Users/whidy/webs/wxappUnpacker/wuLib.js:17:43)
at ioLimit.runWithCb.err (/Users/whidy/webs/wxappUnpacker/wuLib.js:73:11)
at agent (/Users/whidy/webs/wxappUnpacker/wuLib.js:54:14)
at FSReqWrap.oncomplete (fs.js:141:20)
好像挺顺利,东西也出来了,可是最后还是报错了,推断是包内有包,子包解压失败。有关更多可以阅读:https://github.com/qwerty4721…
未定义的$gwx
Saving files...
Unpack done.
/Users/whidy/webs/wxappUnpacker/wuWxapkg.js:104
}else throw Error("This package is unrecognizable.\nMay be this package is a subPackage which should be unpacked with -s=.\nOtherwise, please decrypted every type of file by hand.")
^
Error: This package is unrecognizable.
May be this package is a subPackage which should be unpacked with -s=.
Otherwise, please decrypted every type of file by hand.
at Array.packDone (/Users/whidy/webs/wxappUnpacker/wuWxapkg.js:104:14)
at CntEvent.decount (/Users/whidy/webs/wxappUnpacker/wuLib.js:17:43)
at ioLimit.runWithCb.err (/Users/whidy/webs/wxappUnpacker/wuLib.js:73:11)
at agent (/Users/whidy/webs/wxappUnpacker/wuLib.js:54:14)
at FSReqWrap.oncomplete (fs.js:141:20)
这个就要修改一下工具源码了,打开wuWxss.js
文件,修改内容如下:
// 原始
function runVM(name,code){
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]();
}
}
改成新的:
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]();
}
}
再重新跑一次,Bingo!万事大吉。
总结
总的来说,这个操作还是比较容易的,最大的难点就是想办法提出文件了。工具别人写好了,有问题,Issue上面的解决方案很多,很快就能解决。
想要实现更多,也可以参考工具的说明文档通过不同的命令操作。
当然,小程序缓存到本地是迫不得已的,为了提高加载速度嘛。这个东西,微信官方大概已经知道了,我想可能也会封堵吧。这个微信官方或许也只是单纯打包了一下,所以就比较容易破解,如果他加壳,加密的话,或许以后就难了。
这也让我想起很多年前,我也搞过类似的事情,大约8年前玩安卓手机的时候,解锁Bootload,开启Root来自个性化手机几乎满天都是,大把一键root,一键解锁工具,因此那时候安卓手机安全性很低,小白用户不懂,一不小心就中毒群发小广告。
那时候也流行Wifi万能钥匙,流量很贵的啦,我经常蹭了网,再去系统目录找到那个存放wifi的配置文件来查看别人家的Wifi密码。然后再用这个密码尝试admin/密码,看看路由啥的,不过我没搞过破坏的。
好了,大家如果还有不明白的,可以留言,我有空再分析一下这个工具的实现方式,也顺便尝试一下其他小程序(SWAN,头条,支付宝等),是否也是类似的,等有了结论再来一篇了~