网友真实露脸自拍10p,成人国产精品秘?久久久按摩,国产精品久久久久久无码不卡,成人免费区一区二区三区

小程序模板網

微信小程序“反編譯”實戰(二):源碼還原(下篇)

發布時間:2018-05-16 15:56 所屬欄目:小程序開發教程

page-freme.html

在小程序中使用 WXML 文件描述頁面的結構, WXSS 文件描述頁面的樣式。工程中有一個 app.wxss 文件用于定義一些全局的樣式,會自動被 import 到各個頁面中;另外每個頁面也都分別包含 page.wxml 和 page.wxss 用于描述其頁面的結構和樣式;同時,我們也會自定義一些公共的 xxxCommon.wxss 樣式文件和公共的 xxxTemplate.wxml 模板文件供一些頁面復用,一般在各自頁面的 page.wxss 和 page.wxml 中去 import 。

當“編譯”小程序后,所有的 .wxml 文件和 app.wxss 及公共 xxxCommon.wxss 樣式文件的將被整合到 page-freme.html 文件中,而每個頁面的 page.wxss 樣式文件,將分別單獨在各自的路徑下生成一個 page.html 文件。

page-freme.html 文件的內容結構如下:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'">
    <link rel="icon" href="data:image/ico;base64,aWNv">
    <script>
      // 一些全局變量的聲明
      var __pageFrameStartTime__ = Date.now();
      var __webviewId__;
      var __wxAppCode__ = {};
      var __WXML_GLOBAL__ = {
        entrys: {},
        defines: {},
        modules: {},
        ops: [],
        wxs_nf_init: undefined,
        total_ops: 0
      };
      
      // 小程序編譯基礎庫版本
      /*v0.6vv_20180125_fbi*/
      window.__wcc_version__ = 'v0.6vv_20180125_fbi';
      window.__wcc_version_info__ = {
        "customComponents": true,
        "fixZeroRpx": true,
        "propValueDeepCopy": false
      };
      
      var $gwxc
      var $gaic = {}
      $gwx = function(path, global) {
        // $gwx 方法定義(最核心)
      }
      
      var BASE_DEVICE_WIDTH = 750;
      var isIOS = navigator.userAgent.match("iPhone");
      var deviceWidth = window.screen.width || 375;
      var deviceDPR = window.devicePixelRatio || 2;
      function checkDeviceWidth() {
        // checkDeviceWidth 方法定義
      }
      checkDeviceWidth()
      
      var eps = 1e-4;
      function transformRPX(number, newDeviceWidth) {
        // transformRPX 方法定義
      }
      
      var setCssToHead = function(file, _xcInvalid) {
        // setCssToHead 方法定義
      }
      setCssToHead([])(); // 先清空 Head 中的 CSS
      setCssToHead([...]); // 設置 app.wxss 的內容到 Head 中,其中 ... 為小程序工程中 app.wxss 的內容
      var __pageFrameEndTime__ = Date.now()
          </script>
  </head>
  <body>
    <div></div>
  </body>
</html>

相比其他文件, page-freme.html 比較復雜,微信把 .wxml 和部分 .wxss 直接“編譯”并混淆成 JS 代碼放入上述文件中,然后通過調用這些 JS 代碼來構造 Virtual-Dom ,進而渲染頁面。

其中最核心的是 $gwx 和 setCssToHead 這兩個方法。

$gwx 用于通過 JS 代碼生成所有 .wxml 文件,其中每個 .wxml 文件的內容結構都在 $gwx方法中被定義好并混淆了,我們只要傳給它頁面的 .wxml 路徑參數,即可獲取到每個 .wxml 的內容,再簡單加工一下即可還原成“編譯”前的內容。

在 $gwx 中有一個 x 數組用于存儲當前小程序都有哪些 .wxml 文件,例如,“知識小集”小程序的 x 值如下:

var x = ['./pages/detail/detail.wxml', '/towxml/entry.wxml', './pages/index/index.wxml', './pages/search/search.wxml', './towxml/entry.wxml', '/towxml/renderTemplate.wxml', './towxml/renderTemplate.wxml'];

此時我們可以在 Chrome 中打開 page-freme.html 文件,然后在 Console 中輸入如下命令,即可得到 index.wxml 的內容(輸出一個 JS 對象,通過遍歷這個對象即可還原出 .wxml 的內容)

$gwx("./pages/index/index.wxml")

setCssToHead 方法用于根據幾段被拆分的樣式字符串數組生成 .wxss 代碼并設置到 HTML 的 Head 中,同時,它還將所有被 import 引用的 .wxss 文件(公共 xxxCommon.wxss 樣式文件)所對應的樣式數組內嵌在該方法中的 _C 變量中,并標記哪些文件引用了 _C 中數據。另外在 page-freme.html 文件的末尾,調用了該方法生成全局 app.wxss 的內容設置到 Head 中。

因此,我們可以在每個調用 setCssToHead 方法的地方提取相應 .wxss 的內容并還原。

對于 page-freme.html 文件中 $gwx 和 setCssToHead 這兩個方法更詳細的分析,可以參考這篇 文章 。

此外, checkDeviceWidth 方法顧明思議,用于檢測屏幕的寬度,其檢測結果將用于 transformRPX 方法中將 rpx 單位轉換為 px 像素。

rpx 的全稱是 responsive pixel ,它是小程序自己定義的一個尺寸單位,可以根據當前設備屏幕寬度進行自適應。小程序中規定,所有的設備屏幕寬度都為 750rpx ,根據設備屏幕實際寬度的不同, 1rpx 所代表的實際像素值也不一樣。

*.html

上面提到,每個頁面的 page.wxss 樣式文件,“編譯”后將分別在各自的所在路徑下生成一個 page.html 文件,每個 page.html 的結構如下:

<style></style>
<page></page>
<script>
  var __setCssStartTime__ = Date.now();
  setCssToHead([...])() // 設置 search.wxss 的內容
  var __setCssEndTime__ = Date.now();
  document.dispatchEvent(new CustomEvent("generateFuncReady", {
    detail: {
      generateFunc: $gwx('./pages/search/search.wxml')
    }
  }))
</script>

在該文件中通過調用 setCssToHead 方法將 .wxss 樣式內容設置到 Head 中,所以同樣地,我們可以根據 setCssToHead 的調用參數提取每個頁面的 page.wxss 。

資源文件

小程序工程中的圖片、音頻等資源文件在“編譯”后將直接被拷貝到 .wxapkg 包中,其原始的路徑也保留不變,因此我們可以直接使用。

“反編譯”

在上一節,我們完成了 .wxapkg 包幾乎所有文件內容的簡要分析。現在我們介紹一下如何通過 node.js 腳本幫我們還原出小程序的源碼。

在這里需要再次感謝 wxappUnpacker 作者提供的還原工具,讓我們可以“站在巨人的肩膀上”輕松地去完成“反編譯”。它的使用如下:

  • node wuConfig.js <path/to/app-config.json> : 將 app-config.json 中的內容拆分成各個頁面所對應的 page.json 和 app.json ;

  • node wuJs.js <path/to/app-service.js> : 將 app-service.js 拆分成一系列原先獨立的 JS 文件,并使用 Uglify-ES 美化工具盡可能將代碼還原為“編譯”前的內容;

  • node wuWxml.js [-m] <path/to/page-frame.html> : 從 page-frame.html 中提取并還原各頁面的 .wxml 和 app.wxss 及公共 .wxss 樣式文件;

  • node wuWxss.js <path/to/unpack_dir> : 該命令參數為 .wxapkg 解包后目錄,它將分析并從各個 page.html 中提取還原各頁面的 page.wxss 樣式文件;

同時,作者還提供了 一鍵 解包并還原的腳本,你只需要提供一個小程序的 .wxapkg 文件,然后執行如下命令:

node wuWxapkg.js [-d] <path/to/.wxapkg>

此腳本就會自動將 .wxapkg 文件解包,并將包中相關的已被“編譯/混淆”的文件自動地恢復原狀(包括目錄結構)。

PS: 此工具依賴 uglify-es , vm2 , esprima , cssbeautify , css-tree 等 node.js 包,所以你可能需要 npm install xxx 安裝這些依賴包才能正確執行。

更詳細的用法及相關問題請查閱該開源項目的 GitHub repo。

最后,我們在 微信開發者工具 中新建一個空小程序工程,并將上述還原后的相關目錄文件導入工程,即可編譯運行起來,如下圖為“知識小集”小程序 .wxapkg 還原后的代碼工程:

以上,大功告成!

總結

本文詳細分析了 .wxapkg 解包后的各文件結構,并介紹了如何通過腳本“一鍵還原”得到任意小程序的源碼。

對于一些簡單的,且使用微信官方介紹的原生開發方式開發的小程序,用上述工具基本可以直接還原得到可運行的源碼,但是對于一些邏輯復雜,或者使用 WePY 、 Vue 等一些框架開發的小程序,還原后的源碼可能會有一些小問題,需要我們人肉去分析解決。

后續

本文對小程序源碼“編譯”后的各文件內容結構及用途的分析相對比較零散,而且沒有對各文件的依賴關系及加載邏輯進行研究,后續我們再寫一些文章講解微信客戶端是如何解析加載小程序 .wxapkg 包并運行起來。



易優小程序(企業版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://www.xiuhaier.com/wxmini/doc/course/24435.html 復制鏈接 如需定制請聯系易優客服咨詢:800182392 點擊咨詢
QQ在線咨詢
AI智能客服 ×