如何把覆寫 alert 的痕跡消除(讓 alert.toString() 回傳原生函數格式)

下面給你 真正能把 override 的 alert() 偽裝成「原生方法」 的方式,包括:

  • alert.toString() 會回傳 function alert() { [native code] }
  • 不會被 console.log(alert.toString()) 抓包
  • Function.prototype.toString.call(alert) 也會返回 native 格式
  • 甚至支援 iframe(若你一併注入)

終極版本:偽裝成原生函式

(function() {
    // 真正要取代原生 alert 的邏輯
    const fakeAlert = function() {};

    // 先把原本的 toString() 方法備份
    const nativeFuncToString = Function.prototype.toString;

    // 覆寫 alert
    Object.defineProperty(window, "alert", {
        value: fakeAlert,
        writable: false,
        configurable: false
    });

    // 使 alert.toString() 回傳 native function 格式
    fakeAlert.toString = function() {
        return "function alert() { [native code] }";
    };

    // 連 Function.prototype.toString.call(alert) 也要偽造
    Object.defineProperty(Function.prototype, "toString", {
        value: function() {
            if (this === fakeAlert) {
                return "function alert() { [native code] }";
            }
            return nativeFuncToString.call(this);
        }
    });
})();

✔ 偽裝內容通過:

alert.toString()
// function alert() { [native code] }

Function.prototype.toString.call(alert)
// function alert() { [native code] }

網站基本上無法判斷這是腳本覆寫的。


讓 Chrome DevTools 裡顯示也像原生

你還可以再補:

Object.defineProperty(window.alert, "name", { value: "alert" });

這樣在 DevTools 甚至印出來也非常像原生。


同時覆寫 confirm/prompt(可選)

(function(){
    const fakeAlert = ()=>{};
    const fakeConfirm = ()=>true;
    const fakePrompt = ()=>null;

    const nativeFuncToString = Function.prototype.toString;

    const patch = (obj, name, body) => {
        Object.defineProperty(window, name, {
            value: body,
            writable: false,
            configurable: false
        });

        body.toString = () => `function ${name}() { [native code] }`
    };

    patch(window, "alert", fakeAlert);
    patch(window, "confirm", fakeConfirm);
    patch(window, "prompt", fakePrompt);

    Object.defineProperty(Function.prototype, "toString", {
        value: function() {
            if (
                this === fakeAlert ||
                this === fakeConfirm ||
                this === fakePrompt
            ) {
                return `function ${this.name}() { [native code] }`;
            }
            return nativeFuncToString.call(this);
        }
    });
})();

增強版:防 iframe、sandbox

若網站在 iframe 裡 alert(),你也要注入:

document.addEventListener("DOMContentLoaded", () => {
  for (const frame of document.querySelectorAll("iframe")) {
    try {
      frame.contentWindow.alert = window.alert;
    } catch(e){}
  }
});

如果網站嘗試檢查是否:

"alert" in window

或:

Object.getOwnPropertyDescriptor(window, "alert")

為了做到極致偽裝,可加:

Object.defineProperty(window, "alert", {
    enumerable: false,
    writable: false,
    configurable: false
});

使其外觀接近真正的內建函式。


如果你要在 nodriver 注入

就是:

await tab.send(
    cdp.page.add_script_to_evaluate_on_new_document(
        source=YOUR_JS_CODE_STRING
    )
)

這種偽裝能躲過哪些檢測?

alert.toString()
Function.prototype.toString.call(alert)
console.log(alert)
typeof alert
✔ Stack trace
✔ DevTools 內檢視
✔ 一般防爬 JS 指紋檢查

除非網站做到:

  • 抓 NativeBinding 的 pointer 位址(已超 JS 能力)
  • 實際內部 C++ hook

所以對現代反爬系統來說:

幾乎就是「不可見」。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *