微信小程序“反編譯”實(shí)戰(zhàn)(一):解包
本實(shí)戰(zhàn)教程將一步步告訴你如何“反編譯”獲得其它小程序的源代碼,包括“解包”和“源碼還原”兩篇,主要參考了看雪論壇、V2EX、GitHub 等網(wǎng)站上的帖子、教程、工具,在此不勝感激,參考鏈接詳見文章底部,以及加上了我自己的一些理解和總結(jié)。
我們知道,在微信開發(fā)者工具中開發(fā)完小程序后,我們點(diǎn)擊“上傳”按鈕,微信開發(fā)者工具會(huì)進(jìn)行“編譯”,對(duì) JS 代碼進(jìn)行壓縮混淆以及對(duì) wxml、wxss 和資源文件等進(jìn)行整合打包成一個(gè) .wxapkg 文件上傳給微信服務(wù)器。
所以要“反編譯”小程序,首先我們要獲取到小程序?qū)?yīng)的 .wxapkg 包。
之前在 V2EX 上有一篇文章介紹了如何通過某 URL 直接下載每個(gè)小程序的 .wxapkg,但很快被微信封了。
因此,我們只能從手機(jī)端入手,在手機(jī)上找到微信客戶端下載保存在本地的小程序包。
獲取小程序的 .wxapkg 文件
工具:一臺(tái)已越獄的 iPhone 手機(jī)或者已 Root 的 Android 手機(jī)
本文以 iPhone 4S, iOS 8.4.1 為例,微信版本 v6.6.6。
在已越獄的 iPhone 上打開 Cydia,搜索并安裝 iFile 或者 Filza 等文件瀏覽 App,打開 iFile 或者 Filza,跳轉(zhuǎn)到本地 App 安裝目錄:/var/mobile/Containers/Data/Application/,此時(shí),你可以看到當(dāng)前 iPhone 上已安裝的 App 列表,如下圖所示:

找到“微信”的目錄(我手機(jī)上對(duì)應(yīng)的是:297286CE-9055-400A-99FA-D2D7C0735DCF 文件夾),點(diǎn)擊進(jìn)入,即為微信在此 iPhone 上的“沙盒”(Sandbox),相信 iOS 開發(fā)者對(duì)此目錄已經(jīng)非常熟悉了,該目錄下主要有 Documents、Library 和 tmp 等文件夾,通常用于存放不同的數(shù)據(jù)和文件,這里不再贅述。我們在當(dāng)前微信“沙盒”目錄中搜索 wxapkg 關(guān)鍵字,即可找到當(dāng)前 iPhone 中微信已下載的小程序包,如下圖:

我們發(fā)現(xiàn)搜索到的 .wxapkg 文件名都是以數(shù)字命名的,如圖中的 2.wxapkg 和 25.wxapkg,它們的命名有什么規(guī)則呢?又放在哪呢?我們接著往下看。
經(jīng)過簡單分析我們發(fā)現(xiàn),微信下載的小程序包存放在以下目錄:
- /path/to/WeiChat SandBox/Library/WechatPrivate/{UserId}/WeApp/LocalCache/release/
其中,{UserId} 為當(dāng)前登錄的微信賬號(hào) Id 的 MD5 值(32 位字符串),例如我手機(jī)上小程序包存放的完整目錄為:
- /var/mobile/Containers/Data/Application/297286CE-9055-400A-99FA-D2D7C0735DCF/Library/WechatPrivate/c15d9cced65acecd30d2d6522df2f973/WeApp/LocalCache/release/
該目錄的內(nèi)容如下圖所示:

目錄中有一系列以 wx... 開頭的文件夾,這些 wx... 的 18 位字符串即為每個(gè)小程序?qū)?yīng)的 AppId,在每個(gè) wx... 文件夾中都放著當(dāng)前小程序?qū)?yīng)的 .wxapkg 包,它以數(shù)字命名,數(shù)字代表著當(dāng)前包為開發(fā)者第幾次發(fā)布的(它與開發(fā)者在發(fā)布小程序時(shí)指定的版本號(hào)是不同的),例如我們的“知識(shí)小集”小程序一共發(fā)布了兩個(gè)版本,所以 wx48...85db 文件中存放有 2.wxapkg 文件:

另外,我們發(fā)現(xiàn),在 iOS 上,微信也為每個(gè)小程序分配了一個(gè) Sandbox 文件夾用于管理小程序在本地存儲(chǔ)的數(shù)據(jù)和文件,如圖:

其路徑為:
- /path/to/WeiChat SandBox/Library/WechatPrivate/{UserId}/WeApp/Sandbox/wx...(小程序 AppId)
By The Way,Android 手機(jī)上小程序包的存放目錄為(需 Root 權(quán)限才能訪問):
- /data/data/com.tencent.mm/MicroMsg/{UserId}/appbrand/pkg/
拷貝 .wxapkg 文件到電腦上
通過上述分析,我們可以知道到小程序的壓縮包 .wxapkg 存放在哪,接下來我們需要將手機(jī)上的 .wxapkg 文件拷貝到電腦上。
在 iPhone 上打開 Cydia 搜索并安裝 OpenSSH 后,在 iPhone > 設(shè)置 > 無線局域網(wǎng)中查看你當(dāng)前手機(jī)連接的 WiFi,并記錄 IP 地址,例如我的為:192.168.1.17,然后在你的 Mac 電腦上打開終端(與 iPhone 連接同一 WiFi),就可以通過 SSH 登錄到你的手機(jī)上了(具體的細(xì)節(jié)詳見 Cydia 上 OpenSSH 下載頁面的使用說明):
- ssh root@192.168.1.17
接下來我們就可以通過 scp 命令從 iPhone 上拷貝文件到我們的電腦上了,例如,在我的 Mac 上的命令行里執(zhí)行(不需要 ssh 登錄到 iPhone 上,直接在 Mac 的終端上執(zhí)行):
- scp root@192.168.1.17:/var/mobile/Containers/Data/Application/297286CE-9055-400A-99FA-D2D7C0735DCF/Library/WechatPrivate/c15d9cced65acecd30d2d6522df2f973/WeApp/LocalCache/release/wx48...85db/2.wxapkg /Users/Zubin/Desktop/WeApp/
就可以把“知識(shí)小集”小程序的包 2.wxapkg 拷貝到我 Mac 桌面上的 WeApp 文件夾中了。
當(dāng)然,如果你的電腦有安裝 iTool 或者 PP助手 之類的工具,當(dāng)連接已越獄的 iPhone 好像可以直接訪問手機(jī)上的目錄和文件,可能就不用這么麻煩了(未驗(yàn)證)。
.wxapkg 解包
上述費(fèi)了很大周折我們終于拿到每個(gè)小程序的 .wxapkg 包,接下來我們可以對(duì)它進(jìn)行分析了。首先 .wxapkg 文件到底是什么呢?你可能會(huì)認(rèn)為它就是類似 Android 的 .apk 或者 iOS 的 .ipa 安裝包,本質(zhì)上是一個(gè) .zip 壓縮包?其實(shí)不是的!,它是一個(gè)二進(jìn)制文件,實(shí)際的文件結(jié)構(gòu)如下圖:

圖片取自文章 微信小程序源碼閱讀筆記,同時(shí)此文章的作者也提供了解包的腳本(各種語言的)放在了 GitHub 上:
我下載了 Python 2 的解包腳本,與 .wxapkg 文件放在一個(gè)目錄,然后在命令行里執(zhí)行如下命名即可得到解包后的文件:
- python unwxapkg.py 2.wxapkg
以“知識(shí)小集”小程序?yàn)槔?,解包后得到的文件目錄如?已經(jīng)基本與我開發(fā)“知識(shí)小集”小程序的工程目錄一致了):

每個(gè)小程序解包后的文件都大同小異,主要包含如下文件:
- app-service.js: 小程序工程中所有 JS 文件的匯總,已被混淆;
- app-config.json: 小程序工程 app.json 以及各個(gè)頁面的 JSON 配置文件匯總,可直接查看;
- page-frame.html: 所有頁面的 .wxml 和 app.wxss 樣式文件的匯總,可讀性差,需要還原;
- *.html: 包含每個(gè)頁面對(duì)應(yīng)的 .wxss 信息,可讀性較好;
- 資源文件: 各類圖片、音頻等資源文件
總結(jié)
本文主要介紹了如何獲取小程序的 .wxapkg 包文件,以及如何解包獲得小程序“編譯”混淆后的代碼和資源文件。在下一篇文章《微信小程序“反編譯”實(shí)戰(zhàn)(二):源碼還原》將介紹如何將 .wxapkg 包內(nèi)內(nèi)容還原為”編譯”前的內(nèi)容。