javascript/**
 * 统一检测当前页面是否运行在自动化/爬虫/测试环境
 * 返回:非空字符串即表示检测到可疑特征,字符串内容即为命中详情
 */
function detectAutomationEnvironment() {
    // 1. 可疑的全局对象名
    const SUSPICIOUS_WINDOW_PROPS = [
        '_phantom', '__nightmare', '_selenium', 'callPhantom', 'callSelenium',
        '_Selenium_IDE_Recorder', '__fxdriver_unwrapped', 'fxdriver_id', 'webdriver',
        'domAutomation', 'Buffer', 'emit', 'spawn', 'fmget_targets'
    ];
    // 2. 可疑的 document 属性(旧版 webdriver/selenium 遗留)
    const SUSPICIOUS_DOC_PROPS = [
        '__webdriver_evaluate', '__selenium_evaluate', '__webdriver_script_function',
        '__webdriver_script_func', '__webdriver_script_fn', '__fxdriver_evaluate',
        '__driver_unwrapped', '__webdriver_unwrapped', '__driver_evaluate',
        '__selenium_unwrapped', '__fxdriver_unwrapped'
    ];
    // 3. 正则:UA 包含 Headless/Phantom
    const UA_RE = /Headless|Phantom/i;
    // 4. 正则:Navigator 属性名里包含 dive(某些旧检测库)
    const NAV_PROP_RE = /dive/i;
    let evidence = '';   // 收集所有命中的线索
    /* ---------- 1. 检测全局对象 ---------- */
    SUSPICIOUS_WINDOW_PROPS.forEach(prop => {
        if (window[prop] !== undefined) evidence += `window.${prop};`;
    });
    // Cypress 比较特殊,单独判断
    if ('Cypress' in window) evidence += 'window.Cypress;';
    /* ---------- 2. 检测 document 上的遗留属性 ---------- */
    SUSPICIOUS_DOC_PROPS.forEach(prop => {
        if (document[prop] !== undefined) evidence += `document.${prop};`;
    });
    // 检测形如 $cdc_... 的旧版缓存对象
    Object.getOwnPropertyNames(document).forEach(prop => {
        if (/\$[a-z]dc_/.test(prop) && document[prop] && document[prop].cache_) {
            evidence += `document.${prop}.cache_;`;
        }
    });
    /* ---------- 3. 检测 html 标签上的属性 ---------- */
    const htmlAttrs = ['selenium', 'webdriver', 'driver'];
    htmlAttrs.forEach(attr => {
        if (document.documentElement.hasAttribute(attr)) {
            evidence += `htmlElement.hasAttribute(${attr});`;
        }
    });
    /* ---------- 4. 检测 navigator.webdriver 标志 ---------- */
    if (navigator.webdriver !== undefined) {
        evidence += `navigator.webdriver=${navigator.webdriver.toString().slice(0, 50)};`;
    }
    /* ---------- 5. 检测 UA 中的 Headless/Phantom ---------- */
    if (UA_RE.test(navigator.userAgent)) {
        evidence += 'ua contains Headless|Phantom;';
    }
    /* ---------- 6. 检测 navigator 属性名里是否含 dive ---------- */
    try {
        let proto = navigator;
        while (proto) {
            Object.getOwnPropertyNames(proto).forEach(prop => {
                if (NAV_PROP_RE.test(prop)) evidence += `navigator key:${prop};`;
            });
            proto = Object.getPrototypeOf(proto);
        }
    } catch (_) {
        // 忽略异常
    }
    /* ---------- 7. 检测 Sequentum(少见) ---------- */
    if (window.external && window.external.toString) {
        const extStr = window.external.toString();
        if (extStr.includes('Sequentum')) {
            evidence += `window.external.toString()=${extStr.slice(0, 50)};`;
        }
    }
    return evidence;
}
验证码按用户交互复杂度可分为两大类:
需要用户完成特定验证任务,包括:
bashwinrm delete winrm/config/listener?Address=*+Transport=HTTP winrm delete winrm/config/listener?Address=*+Transport=HTTPS
bash winrm create winrm/config/listener?Address=*+Transport=HTTP @{Port="8050"}
 winrm create winrm/config/listener?Address=*+Transport=HTTPS @{Port="8051"}
Xhopee的协议里有很多值得逆向的内容,这一篇文章我们主要讲解cookie中的ds的生成
我们可以看到,这是一个32位的字符串,首先想到会不会是一个md5算法呢?我们可以全局搜索md5的特征值