吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2778|回复: 26
上一主题 下一主题
收起左侧

[Web逆向] 某招聘网站的反调试与反反调试策略

  [复制链接]
跳转到指定楼层
楼主
桐姥爷 发表于 2026-3-9 02:49 回帖奖励
本帖最后由 桐姥爷 于 2026-3-9 02:51 编辑

某招聘网站的反调试分析与绕过总结

1. 网站反调试技术

分析文件:app.80fffb17.js

1.1 入口:abFn -> noDebug

// app.80fffb17.js:49815
(0, g.abFn)();
// app.80fffb17.js:52425-52431
e.abFn = function() {
  var t, e = null === (t = window.iGeekRoot) || void 0 === t || null === (t = t.aBService) || void 0 === t || null === (t = t.abData) || void 0 === t || null === (t = t.nd_result_13912_number_1) || void 0 === t ? void 0 : t.result;
  try {
    e !== "Q,M,&L,b".split(",").join("") && (0, r.noDebug)({
      env: "prod",
      appName: "zhipin_geek_spa_web"
    }, o.ndObj.cb)
  } catch (t) { console.log(t) }
}

含义:业务入口触发 abFn,再根据条件进入 noDebug

1.2 快捷键拦截(F12 / Ctrl+Shift+I/J / Ctrl+U/S)

// app.80fffb17.js:52696-52705
function rt(t) {
  const e = $[g(P)] ? (t, e) => t.metaKey && t.altKey && (73 === e || 74 === e) : (t, e) => t.ctrlKey && t.shiftKey && (73 === e || 74 === e),
        n = $[g(P)] ? (t, e) => t.metaKey && t.altKey && 85 === e || t.metaKey && 83 === e : (t, e) => t.ctrlKey && (83 === e || 85 === e);
  t.addEventListener(g("`;^<[S:5c45I"), r => {
    const o = (r = r || t.event).keyCode || r.which;
    if (123 === o || e(r, o) || n(r, o)) return function(t, e) {
      return (e = e || t.event).returnValue = !1, e.preventDefault(), !1
    }(t, r)
  }, !0)
}

含义:阻止常见打开开发者工具和查看源码的快捷键。

1.3 隐藏 iframe 取“干净原生 API”

// app.80fffb17.js:52670-52687
function J(t) {
  var e;
  try {
    W || (W = document.createElement("iframe"), W.style.display = "none", document.body.appendChild(W));
    if (Array.isArray(t)) return t.map(t => {
      var e;
      return null === (e = W.contentWindow) || void 0 === e ? void 0 : e[t]
    });
    return null === (e = W.contentWindow) || void 0 === e ? void 0 : e[t]
  } catch (e) {
    return Array.isArray(t) ? t.map(t => window[t]) : window[t]
  }
}

含义:通过 iframe.contentWindow 获取未被主窗口 hook 的原生方法,绕过简单补丁。

1.4 DevTools 检测轮询与触发链

// app.80fffb17.js:53067-53070
(() => {
  if (!t) {
    for (const t of Bt) t.type, t.XCID();
    et()
  }
}, 500)
// app.80fffb17.js:52973-52980
XCID() {
  var t, e;
  const n = g(a), r = g("[d^;oS:pcSVI"), o = g("`QW]`S:5"), i = g(s), u = g("wvWc0Mpcd^][Q{jX:rbu>;");
  (!0 === (null === (e = null === (t = window[n]) || void 0 === t ? void 0 : t[r]) || void 0 === e ? void 0 : e[o]) || window[i] && window.document.querySelector(u)) && this[g(c)]()
}
// app.80fffb17.js:52944-52946
}[g(c)]() {
  this.seact(), _t(xt), ht(), this.type
}

含义:每 500ms 执行检测器;命中 DevTools 条件后调用 onDevToolOpen,最终执行 ht()

1.5 触发后的破坏动作(核心)

// app.80fffb17.js:52873-52905
try {
  window[g("c:Jwc1l")] = null, window[g("c:Jwcu>;")](g(""), g("q:WwcSr;"))
} catch (t) { window.console.log(t) }
try {
  window[g("X;pbIn;")]()
} catch (t) { window.console.log(t) }
try {
  window[g("`dvswS:vX5I")][g("Xvdc`9>;")]()
} catch (t) { window.console.log(t) }
dt(() => {
  try { document[g(d)][g("`^R|[^ZeoaND")] = g("") } catch (t) { window.console.log(t) }
  try { window.location[g("`SBw[u>;")] = g("") } catch (t) { window.console.log(t) }
  !function() {
    const t = document.createElement("style"),
          e = [g("`Sr}cG>;"), g(d), g("XQJ~")],
          n = ["filter: blur(20px) !important", "display: none !important", "visibility: hidden !important", "opacity: 0 !important"],
          r = Math.floor(Math.random() * n.length);
    e.forEach(e => { t.textContent = `${e} { ${n[r]} }` }), document[g(ut)].appendChild(t)
  }()
}, 100)

含义:打开空页、关闭/后退、清空 body、改 location.href、注入隐藏样式,组合拳让页面不可用。

1.6 反篡改失败后的惩罚(内存炸弹)

// app.80fffb17.js:52817-52830
function lt(t) {
  let e = { success: !0, methods: {} };
  try {
    t.forEach(t => {
      let n = J(t);
      if (t.includes(".")) {
        const [e, r] = t.split(".");
        n = window[e][r]
      }
      n && /\[native code\]/.test(n.toString()) ? e.methods[t] = !0 : (e.success = !1, e.methods[t] = !1)
    })
  } catch (t) {}
  return e
}
// app.80fffb17.js:52707-52735
function ot() {
  try {
    const t = [], e = () => {
      for (let e = 0; e < 1e3; e++) {
        const n = {};
        for (let t = 0; t < 1e3; t++) n[`key_${e}_${t}`] = "x".repeat(1e3);
        t.push(n)
      }
      const e = [];
      for (let t = 0; t < 100; t++) e.push(new Array(1e4).fill("JBwd{b5S=[d^pg@M9`^rw0{3vd:cd{+bdWpX^g/[QBk1"));
      t.push(...e)
    };
    e();
    const r = window.setInterval(() => {
      try {
        const e = [];
        for (let t = 0; t < 1e3; t++) e.push(new Array(1e4).fill("x"));
        t.push(...e)
      } catch (t) { window.clearInterval(r) }
    }, 10)
  } catch (t) {}
}

含义:检测到“方法被改”后,触发内存/CPU 压制。

1.7 调用链

  1. abFn 执行(49815)  
  2. 条件触发 noDebug52428)  
  3. 检测轮询 for (const t of Bt) t.XCID()53069)  
  4. 检测命中 -> onDevToolOpen52944-52946)  
  5. onDevToolOpenht()52945)  
  6. ht() 执行跳转/清空/样式破坏(52873-52905)  

2. 通过 Hook 定位到关键代码

这一段是定位思路。

2.1 第一步:先抓“谁在跳转”

先在 document-start 注入最小 trap,只拦截并打印这些高价值 sink:

  • window.open
  • location.assign/replace/reload
  • location.href setter
  • history.back/go/forward

核心思路是:不先猜业务代码,而是先抓最终破坏动作调用者。

2.2 第二步:从运行时栈反推到 bundle 位置

最早抓到的关键日志形态是:

[REDIRECT-TRAP] open()
from: https://www.zhipin.com/web/geek/jobs
to:
stack:
  at ht (app.80fffb17.js:54:43498)
  at Et.onDevToolOpen (app.80fffb17.js:54:44611)
  at Et.XCID (app.80fffb17.js:54:48576)

这个栈直接给出了关键链路:

  • XCID(检测器)
  • onDevToolOpen(触发点)
  • ht(执行破坏动作)

于是再回到本地快照 app.80fffb17.js 按这些符号/模式定位,最终落到:

  • ht()app.80fffb17.js:52838 附近
  • onDevToolOpen[g(c)]()):app.80fffb17.js:52944-52946
  • XCID()app.80fffb17.js:5297353069 附近轮询调用

2.3 第三步:确认“它会绕过主窗口 hook”

在定位阶段发现 J(t) 会创建隐藏 iframe,并从 contentWindow 取原生方法:

// app.80fffb17.js:52670-52687
W || (W = document.createElement("iframe"), W.style.display = "none", document.body.appendChild(W));
return W.contentWindow[t];

这解释了为什么“只 hook 主窗口 API”一开始拦不全。

2.4 第四步:定位时使用的关键 Hook 代码(精简版)

// 关键:统一记录 from/to/stack
function trap(action, target) {
  const stack = new Error('[REDIRECT-TRAP] stack').stack;
  console.groupCollapsed(`[REDIRECT-TRAP] ${action}`);
  console.log('from:', location.href);
  console.log('to:', target);
  console.log(stack);
  console.groupEnd();
}

// 关键:先抓 window.open
const rawOpen = window.open;
window.open = function (...args) {
  trap('open()', args[0]);
  return rawOpen.apply(this, args);
};

// 关键:抓 location.href setter
const proto = Object.getPrototypeOf(window.location);
const hrefDesc = Object.getOwnPropertyDescriptor(proto, 'href');
Object.defineProperty(proto, 'href', {
  configurable: true,
  get: hrefDesc.get,
  set(url) {
    trap('location.href =', url);
    return hrefDesc.set.call(this, url);
  }
});

这套“先抓 sink -> 看 stack -> 回 bundle 对位”的方法,能在混淆代码里快速找到真正生效的反调试逻辑,而不是在大包里盲猜。


3. 绕过策略

实现文件:hook.js(Tampermonkey,@run-at document-start

3.1 总体策略

  • 不改站点 bundle,走运行时 hook。  
  • 主目标是阻断“破坏动作”(跳转、清空 DOM、样式遮蔽、惩罚定时器)。  
  • 避免误伤正常业务定时器,最后收敛为“高置信规则”。

3.2 跳转/刷新/窗口动作统一拦截

// hook.js:205-229(节选)
patchMethod(win.Location.prototype, 'assign', (args) => args[0], { lock: true, tag: prefix });
patchMethod(win.Location.prototype, 'replace', (args) => args[0], { lock: true, tag: prefix });
patchMethod(win.Location.prototype, 'reload', () => '[reload]', { lock: true, tag: prefix });

patchWindowLocationSetter(win, prefix); // window.location= / document.location=

patchMethod(win, 'open', (args) => args[0], { lock: true, tag: prefix });
patchMethod(win, 'stop', () => '[stop]', { lock: true, tag: prefix });
patchMethod(win, 'close', () => '[close]', { lock: true, tag: prefix });

含义:直接封堵 ht() 里的主要跳转/关闭路径。

3.3 DOM 破坏防护

// hook.js:295-311(节选)
if (this === document.body && stackMatched(stack)) {
  console.warn('[REDIRECT-TRAP] blocked body.innerHTML overwrite');
  return;
}
return innerHTMLDesc.set.call(this, value);
// hook.js:327-335(节选)
const suspiciousStyle = /blur\(20px\)|display:\s*none|visibility:\s*hidden|opacity:\s*0/i.test(css);
if (suspiciousStyle && stackMatched(stack)) {
  console.warn('[REDIRECT-TRAP] blocked suspicious STYLE append');
  return node;
}

含义:阻断“清空 body + 注入隐藏样式”。

3.4 解决“隐藏 iframe 绕过 hook”

// hook.js:255-260(节选)
function patchIframeNode(node, reason) {
  if (!node || node.tagName !== 'IFRAME') return;
  const install = () => {
    if (node.contentWindow) installWindowGuards(node.contentWindow, `iframe(${reason})`);
  };
  install();
}
// hook.js:336-354(节选)
const result = rawAppendChild.call(this, node);
patchIframeNode(node, 'appendChild');
...
const result = rawInsertBefore.call(this, newNode, referenceNode);
patchIframeNode(newNode, 'insertBefore');

含义:页面新增 iframe 时,把同样防护注入到 iframe.contentWindow,补上绕过口。

3.5 定时器策略:从“全拦截”收敛到“高置信拦截”

// hook.js:25-26
const STACK_FLAG = /onDevToolOpen|XCID|noDebug|(?:^|\W)abFn(?:\W|$)|(?:^|\W)ot(?:\W|$)/i;
const CALLBACK_FLAG = /new Array\(1e4\)\.fill\(['"]x['"]\)|['"]x['"]\.repeat\(1e4\)|nested_/i;
// hook.js:173-178
function shouldBlockTimer(callback) {
  if (!CONFIG.blockSuspiciousTimers) return false;
  const timerStack = getStack('[REDIRECT-TRAP] timer stack');
  if (stackMatched(timerStack)) return true;
  return callbackMatched(callback);
}

含义:只拦截反调试/内存炸弹定时器,不再误伤 Vue/路由/埋点的正常定时器。

3.6 当前状态

  • 打开 DevTools 后不再被强制刷新或重定向。  
  • 页面能正常加载和操作。  
  • 如后续站点升级 hash 或策略,按同样方法重新抓栈和收敛规则即可。

免费评分

参与人数 24威望 +1 吾爱币 +41 热心值 +24 收起 理由
hwh425 + 1 热心回复!
qsj521521 + 1 + 1 谢谢@Thanks!
testcopy + 1 + 1 我很赞同!
lucky61 + 1 + 1 用心讨论,共获提升!
allspark + 1 + 1 用心讨论,共获提升!
Carinx + 1 + 1 谢谢@Thanks!
BrutusScipio + 1 + 1 用心讨论,共获提升!
liuxuming3303 + 1 + 1 谢谢@Thanks!
涛之雨 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
aihetianshui + 1 + 1 我很赞同!
Miracle-紫狼 + 1 + 1 谢谢@Thanks!
ytfh1131 + 1 + 1 谢谢@Thanks!
chengdragon + 1 + 1 感谢分享,不明觉厉
weidechan + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
唐小样儿 + 1 + 1 我很赞同!
wahahehe + 1 + 1 我很赞同!
夸克逃逸 + 2 + 1 不明觉厉
cyz98 + 1 谢谢@Thanks!
Bizhi-1024 + 1 谢谢@Thanks!
elan + 1 + 1 用心讨论,共获提升!
gun008 + 1 + 1 用心讨论,共获提升!
buluo533 + 1 + 1 用心讨论,共获提升!
xuhao4577062311 + 1 + 1 我很赞同!
laozhang4201 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
wudalang123 发表于 2026-4-23 18:47
grade1984 发表于 2026-3-12 17:28
请教一下:

中的这个 hook.js 的完整文件可以提供吗?

[JavaScript] 纯文本查看 复制代码
// ==UserScript==
// [url=home.php?mod=space&uid=170990]@name[/url]         招聘网站反调试绕过
// [url=home.php?mod=space&uid=467642]@namespace[/url]    http://tampermonkey.net/
// [url=home.php?mod=space&uid=1248337]@version[/url]      1.0
// @description  干翻 DevTools 反调试
// [url=home.php?mod=space&uid=686208]@AuThor[/url]       你爹
// [url=home.php?mod=space&uid=195849]@match[/url]        https://www.zhipin.com/*
// @run-at       document-start
// [url=home.php?mod=space&uid=609072]@grant[/url]        unsafeWindow
// ==/UserScript==

(function() {
    'use strict';

    const win = unsafeWindow;
    const CONFIG = {
        blockRedirects: true,
        blockDomWipe: true,
        blockStylesPoison: true,
        blockSuspiciousTimers: true,
        patchIframes: true
    };

    // 栈特征匹配反调试调用链
    const STACK_FLAG = /onDevToolOpen|XCID|noDebug|(?:^|\W)abFn(?:\W|$)|(?:^|\W)ot(?:\W|$)/i;
    const CALLBACK_FLAG = /new Array\(1e4\)\.fill\(['"]x['"]\)|['"]x['"]\.repeat\(1e4\)|nested_/i;

    function getStack() {
        try { throw new Error(); } catch(e) { return e.stack || ''; }
    }

    function stackMatched(stack) {
        return STACK_FLAG.test(stack);
    }

    function callbackMatched(cb) {
        if (typeof cb === 'string') return CALLBACK_FLAG.test(cb);
        if (typeof cb === 'function') {
            try { return CALLBACK_FLAG.test(cb.toString()); } catch(e) { return false; }
        }
        return false;
    }

    function shouldBlockTimer(callback) {
        if (!CONFIG.blockSuspiciousTimers) return false;
        const stack = getStack();
        if (stackMatched(stack)) return true;
        return callbackMatched(callback);
    }

    // 通用方法劫持
    function patchMethod(obj, methodName, getTargetArg, opts = {}) {
        const original = obj[methodName];
        if (!original) return;
        obj[methodName] = function(...args) {
            if (opts.lock) {
                const stack = getStack();
                if (stackMatched(stack)) {
                    console.warn(`[HOOK] blocked ${methodName}`, args);
                    if (methodName === 'reload') return;
                    if (methodName === 'open') return null;
                    if (methodName === 'close') return;
                    if (methodName === 'stop') return;
                    // assign/replace 默认无返回值
                    return;
                }
            }
            return original.apply(this, args);
        };
    }

    function patchWindowLocationSetter(winObj, prefix) {
        const proto = Object.getPrototypeOf(winObj.location);
        const desc = Object.getOwnPropertyDescriptor(proto, 'href');
        if (desc && desc.set) {
            const originalSetter = desc.set;
            Object.defineProperty(proto, 'href', {
                configurable: true,
                get: desc.get,
                set: function(url) {
                    const stack = getStack();
                    if (CONFIG.blockRedirects && stackMatched(stack)) {
                        console.warn('[HOOK] blocked location.href =', url);
                        return;
                    }
                    return originalSetter.call(this, url);
                }
            });
        }
    }

    // body.innerHTML 防护
    function patchBodyInnerHTML() {
        const body = win.document.body;
        if (!body) return;
        const desc = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');
        if (desc && desc.set) {
            const originalSetter = desc.set;
            Object.defineProperty(body, 'innerHTML', {
                configurable: true,
                get: desc.get,
                set: function(value) {
                    const stack = getStack();
                    if (CONFIG.blockDomWipe && this === body && stackMatched(stack)) {
                        console.warn('[HOOK] blocked body.innerHTML overwrite');
                        return;
                    }
                    return originalSetter.call(this, value);
                }
            });
        }
    }

    // style 注入拦截
    function patchStyleAppend() {
        const rawAppendChild = win.document.head.appendChild;
        win.document.head.appendChild = function(node) {
            if (CONFIG.blockStylesPoison && node.tagName === 'STYLE') {
                const css = node.textContent || '';
                const suspicious = /blur\(20px\)|display:\s*none|visibility:\s*hidden|opacity:\s*0/i.test(css);
                if (suspicious) {
                    const stack = getStack();
                    if (stackMatched(stack)) {
                        console.warn('[HOOK] blocked suspicious STYLE append');
                        return node;
                    }
                }
            }
            return rawAppendChild.call(this, node);
        };
    }

    // iframe 递归注入防护
    function installWindowGuards(targetWin, tag) {
        if (!targetWin || targetWin._hooked) return;
        targetWin._hooked = true;
        // 劫持 iframe 内的 location 等
        try {
            patchMethod(targetWin.Location.prototype, 'assign', null, { lock: true });
            patchMethod(targetWin.Location.prototype, 'replace', null, { lock: true });
            patchMethod(targetWin.Location.prototype, 'reload', null, { lock: true });
            patchWindowLocationSetter(targetWin, tag);
            patchMethod(targetWin, 'open', null, { lock: true });
            patchMethod(targetWin, 'stop', null, { lock: true });
            patchMethod(targetWin, 'close', null, { lock: true });
        } catch(e) {}
    }

    function patchIframeNode(node) {
        if (!node || node.tagName !== 'IFRAME') return;
        const install = () => {
            if (node.contentWindow) installWindowGuards(node.contentWindow, 'iframe');
        };
        install();
        // 监听 load 事件确保 contentWindow 可用
        node.addEventListener('load', install);
    }

    function hookIframeCreation() {
        const rawAppendChild = win.document.body.appendChild;
        win.document.body.appendChild = function(node) {
            const result = rawAppendChild.call(this, node);
            if (CONFIG.patchIframes) patchIframeNode(node);
            return result;
        };
        const rawInsertBefore = win.document.body.insertBefore;
        win.document.body.insertBefore = function(newNode, refNode) {
            const result = rawInsertBefore.call(this, newNode, refNode);
            if (CONFIG.patchIframes) patchIframeNode(newNode);
            return result;
        };
    }

    // 定时器拦截
    function hookTimers() {
        const rawSetInterval = win.setInterval;
        win.setInterval = function(callback, delay, ...args) {
            if (shouldBlockTimer(callback)) {
                console.warn('[HOOK] blocked setInterval', callback);
                return 0;
            }
            return rawSetInterval.call(this, callback, delay, ...args);
        };
        const rawSetTimeout = win.setTimeout;
        win.setTimeout = function(callback, delay, ...args) {
            if (shouldBlockTimer(callback)) {
                console.warn('[HOOK] blocked setTimeout', callback);
                return 0;
            }
            return rawSetTimeout.call(this, callback, delay, ...args);
        };
    }

    // 主入口
    function init() {
        console.log('[HOOK] 反调试绕过脚本已加载');
        patchMethod(win.Location.prototype, 'assign', null, { lock: true });
        patchMethod(win.Location.prototype, 'replace', null, { lock: true });
        patchMethod(win.Location.prototype, 'reload', null, { lock: true });
        patchWindowLocationSetter(win, 'main');
        patchMethod(win, 'open', null, { lock: true });
        patchMethod(win, 'stop', null, { lock: true });
        patchMethod(win, 'close', null, { lock: true });
        patchBodyInnerHTML();
        patchStyleAppend();
        hookIframeCreation();
        hookTimers();
    }

    if (win.document.readyState === 'loading') {
        win.document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();


保存为 .user.js,油猴直接装。别他妈问为什么没用,自己看控制台有没有 [HOOK] 日志。没用说明网站改特征了,自己调正则。
推荐
wudalang123 发表于 2026-4-23 18:45
testcopy 发表于 2026-3-21 20:13
反调试在小网站见多了,还第一次遇到大网站干这么小气的事情
原来还有从 iframe 取原生方法反 hook 这种招 ...

  • DevTools检测:别他妈猜了,就那几招
    • 时间差:Date 被置空后抛错?说明检测代码依赖 Date.now() 或 performance 来算 debugger 执行耗时。你置空 Date 等于把数学函数删了,代码直接崩——这不算绕过,这叫炸
    • 真正检:窗口大小差(outerHeight - innerHeight)、toString 扒 [native code]、console.profile、window.devtools 遗留特征、debugger 加定时器卡死。
    • 不触发检测?做梦呢。源码里 setInterval 每500ms 跑 XCID(),你除非把整个检测轮询的定时器清了或者改条件,否则检测肯定跑。你置空 setInterval 只是让它不执行,但检测逻辑本身没消失。绕过检测的唯一正解:Hook 掉检测函数里那些判断条件(比如伪造窗口宽高、让 toString 返回原生码)。
  • iframe那招怎么发现:因为你他妈傻到只Hook主窗口
    • 你往 window.open 扔个栈打印,发现跳到 J(t) 里面生成一个隐藏 iframe,再从 contentWindow 取方法。你断点进去一看——W.contentWindow.fetch 是干净的,主窗口的被你Hook了。
    • 怎么发现的?抓跳转栈时看到 J 函数,点进去看源码,发现 createElement('iframe')。或者你用 MutationObserver 监控 DOM,看到突然多个隐藏 iframe,进去查 contentWindow 就露馅了。
    • 这招不新鲜,专门搞你这种只会改 window 的崽种。
大网站干小气事是因为用户多,不能像小站那样直接崩你浏览器。你运气好碰上个半吊子检测,真要上全量组合拳(Web Worker 跑检测 + 内存炸弹 + 跨域 iframe),你连栈都看不到。
沙发
或者8 发表于 2026-3-9 08:22
3#
xjcyxyx 发表于 2026-3-9 08:37
厉害了,先看下代码研究下
4#
vdycmx 发表于 2026-3-9 09:10
看起来很厉害的样子
5#
loikee 发表于 2026-3-9 15:46
这么厉害
6#
blueluckycard 发表于 2026-3-9 18:29
学习一下。感谢了
7#
AuroraVerses 发表于 2026-3-10 07:01
不是很明白
8#
zdian 发表于 2026-3-10 09:40
学习了!
9#
qe13323 发表于 2026-3-10 16:06
看起来很厉害的样子
10#
lbb2ch 发表于 2026-3-10 16:43
厉害,学习到了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-4-24 07:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表