iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
Security

走進資安現場: JavaScript資安逆向工程超實戰系列 第 19

Day 19 Webpack 編譯過的程式碼是如何運作的?解析打包後的結構

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250918/20169775cTtkGXENne.jpg

本系列文章所討論的 JavaScript 資安與逆向工程技術,旨在分享知識、探討防禦之道,並促進技術交流。
所有內容僅供學術研究與學習,請勿用於任何非法或不道德的行為。
讀者應對自己的行為負完全責任。尊重法律與道德規範是所有技術人員應共同遵守的準則。

本文同步發佈:https://nicklabs.cc/webpack-bundled-code-how-it-works

在前端資安逆向工程中遇到 Webpack 打包編譯過的程式碼是非常常見的,所以理解 Webpack 的內部機制,對於資安逆向工程來說,從打包編譯過的程式碼找到關鍵邏輯是非常之重要的。

Webpack 是什麼?

原由

Webpack 是前端模組打包工具,在 Webpack 出現之前可能會使用 多個標籤引入 JavaScript 檔案。

這會導致全域變數污染、載入順序問題以及請求過多等眾多問題。

Webpack 作為一個模組打包工具將這些分散的 JavaScript 模組打包成一個或多個檔案。

核心概念

Webpack 的核心概念是把專案中所有的資源(JavaScript、CSS、圖片、字體等)都視為模組,透過分析依賴關係,把它們打包成一個或多個「bundle 檔案」,方便在瀏覽器中載入與使用。

分析Webpack打包編譯後的程式

這是一個簡單的範例

(() => {
    var n = {
            123: (module, exports, t) => {
                const Dog = t(999);
                const d = new Dog();
                d.eat();
            },
            153: (module, exports, t) => {
                class Person{
                    constructor(n){
                        this.name = n;
                    }
                    sayHello(){
                        console.log(`Hello, ${this.name}!`);
                    }
                }
                module.exports = new Person("Nick")
            },
            999: (module, exports, t) => {
                class Dog {
                    eat() {
                        console.log(`The dog is eating food`);
                    }
                }
                module.exports = Dog;
            }
        },
        r = {};

    function t(u) {
        var e = r[u];
        if (void 0 !== e)
            return e.exports;
        var i = r[u] = { exports: {} };
        n[u].call(i.exports, i, i.exports, t);
        return i.exports;
    }

    t.g = function() {
        if ("object" == typeof globalThis)
            return globalThis;
        try {
            return this || new Function("return this")()
        } catch (n) {
            if ("object" == typeof window)
                return window
        }
    }(),
        t.o = (n, r) => Object.prototype.hasOwnProperty.call(n, r),
        t(123)
})();

立即執行函式

整包程式的本體使用立即執行函式包裝起來,起到一個封閉的作用域執行程式,也避免全域污染。

模組定義

這裡的 n 物件就像是 Webpack 打包後的模組表。

key 是模組 ID(通常是壓縮過或編號的數字)。

value 是一個函式,代表模組的程式碼。

var n = {
    123: (module, exports, t) => {
        const Dog = t(999);
        const d = new Dog();
        d.eat();
    },
    153: (module, exports, t) => {
        class Person{
            constructor(n){
                this.name = n;
            }
            sayHello(){
                console.log(`Hello, ${this.name}!`);
            }
        }
        module.exports = new Person("Nick")
    },
    999: (module, exports, t) => {
        class Dog {
            eat() {
                console.log(`The dog is eating food`);
            }
        }
        module.exports = Dog;
    }
}

模組快取

r = {};

這是快取物件,避免同一個模組重複執行。

模組載入器 (t)

function t(u) {
    var e = r[u];
    if(void 0 !== e)
        return e.exports;
    var i = r[u] = { exports: {} };
    n[u].call(i.exports, i, i.exports, t);
    return i.exports
}
  • 先檢查快取 r[u] 裡有沒有資料,如果有就是有載入過。
  • 沒有的話,建立一個新的模組物件 { exports: {} }。
  • 執行對應的模組函式 n[u],並傳入 (模組本身, exports 物件, 載入器函式)。
  • 回傳 exports。

輔助工具

t.g = function() {
    if("object" == typeof globalThis)
        return globalThis;
    try{
        return this || new Function("return this")()
    }catch(n){
        if("object" == typeof window)
            return window
    }
}(),
t.o = (n, r) => Object.prototype.hasOwnProperty.call(n, r),
  • t.g:取得全域物件(不管是 globalThis, window, global 都能取得)。
  • t.o:檢查物件是否有某個屬性(封裝 Object.prototype.hasOwnProperty)。

啟動程式

t(123)

外拋載入器

我們已經知道t函式是載入器,n是所有的模組,那我們可以將t外拋給window或是global這時我們可以隨心所欲的調用所有的模組。

https://ithelp.ithome.com.tw/upload/images/20250918/20169775gN7vj2FFBb.jpg

實際的執行結果如下

https://ithelp.ithome.com.tw/upload/images/20250918/20169775zhvgVgX3PQ.jpg

圖片中「1」為原先t(123)的執行結果。

圖片中「2」為外部調用t(999)的執行結果。

這時可以方便的調用所有模組對於逆向分析來說有極大的幫助。


上一篇
Day 18 什麼是「魔改算法」?以MD5為例深度剖析
下一篇
Day 20 逆向實戰 - 解析MD5簽名機制流程 (簡單)
系列文
走進資安現場: JavaScript資安逆向工程超實戰23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言