魔改编译-永久解决selenium痕迹(二)

😀 继续上篇,完善我们的selenium痕迹魔改,以对抗selenium的检测。

📝 主旨内容

检测点

正向开发的检测点

image.png

还有一个是

Notification.permission

自动化的时候通知权限是关闭的。不会开启。当然这个可能你需要在远程链接selenium服务的时候才会看到。

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Selenium WebDriver 检测</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
            overflow-x: hidden;
        }

        .container {
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(20px);
            border-radius: 24px;
            padding: 40px;
            max-width: 800px;
            width: 100%;
            box-shadow: 
                0 32px 64px rgba(0, 0, 0, 0.1),
                0 0 0 1px rgba(255, 255, 255, 0.2);
            position: relative;
            overflow: hidden;
        }

        .container::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 4px;
            background: linear-gradient(90deg, #667eea, #764ba2, #f093fb);
            border-radius: 24px 24px 0 0;
        }

        .header {
            text-align: center;
            margin-bottom: 40px;
        }

        .title {
            font-size: 3em;
            font-weight: 700;
            background: linear-gradient(135deg, #667eea, #764ba2);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            margin-bottom: 12px;
            letter-spacing: -0.02em;
        }

        .subtitle {
            color: #64748b;
            font-size: 1.2em;
            font-weight: 400;
        }

        .detection-grid {
            display: grid;
            gap: 24px;
            margin-bottom: 32px;
        }

        .detection-card {
            background: linear-gradient(145deg, #ffffff, #f8fafc);
            border: 1px solid rgba(226, 232, 240, 0.8);
            border-radius: 16px;
            padding: 24px;
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            position: relative;
            overflow: hidden;
        }

        .detection-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: linear-gradient(135deg, rgba(102, 126, 234, 0.05), rgba(240, 147, 251, 0.05));
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .detection-card:hover {
            transform: translateY(-4px);
            box-shadow: 
                0 20px 25px -5px rgba(0, 0, 0, 0.1),
                0 10px 10px -5px rgba(0, 0, 0, 0.04);
            border-color: rgba(102, 126, 234, 0.3);
        }

        .detection-card:hover::before {
            opacity: 1;
        }

        .card-header {
            display: flex;
            align-items: center;
            margin-bottom: 16px;
            position: relative;
            z-index: 1;
        }

        .card-icon {
            width: 48px;
            height: 48px;
            border-radius: 12px;
            background: linear-gradient(135deg, #667eea, #764ba2);
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 24px;
            margin-right: 16px;
            box-shadow: 0 8px 16px rgba(102, 126, 234, 0.3);
        }

        .card-title {
            font-size: 1.4em;
            font-weight: 600;
            color: #1e293b;
        }

        .card-description {
            color: #64748b;
            font-size: 1em;
            line-height: 1.6;
            margin-bottom: 20px;
            position: relative;
            z-index: 1;
        }

        .test-button {
            background: linear-gradient(135deg, #667eea, #764ba2);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 12px;
            cursor: pointer;
            font-size: 16px;
            font-weight: 600;
            transition: all 0.3s ease;
            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
            position: relative;
            z-index: 1;
        }

        .test-button:hover {
            transform: translateY(-2px);
            box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
        }

        .test-button:active {
            transform: translateY(0);
        }

        .result-container {
            margin-top: 16px;
            position: relative;
            z-index: 1;
        }

        .result {
            background: linear-gradient(135deg, #d1fae5, #a7f3d0);
            border: 1px solid #34d399;
            color: #065f46;
            padding: 16px;
            border-radius: 12px;
            font-weight: 500;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .warning {
            background: linear-gradient(135deg, #fef3c7, #fde68a);
            border: 1px solid #f59e0b;
            color: #92400e;
            padding: 16px;
            border-radius: 12px;
            font-weight: 500;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .run-all-button {
            background: linear-gradient(135deg, #8b5cf6, #a855f7);
            color: white;
            border: none;
            padding: 16px 32px;
            border-radius: 16px;
            cursor: pointer;
            font-size: 18px;
            font-weight: 700;
            width: 100%;
            transition: all 0.3s ease;
            box-shadow: 0 8px 20px rgba(139, 92, 246, 0.3);
            margin-bottom: 24px;
        }

        .run-all-button:hover {
            transform: translateY(-2px);
            box-shadow: 0 12px 28px rgba(139, 92, 246, 0.4);
        }

        .overall-result {
            background: linear-gradient(135deg, #1e293b, #334155);
            color: white;
            padding: 24px;
            border-radius: 16px;
            text-align: center;
            font-size: 1.2em;
            font-weight: 600;
            box-shadow: 0 8px 20px rgba(30, 41, 59, 0.3);
            display: none;
        }

        .overall-result.show {
            display: block;
            animation: slideUp 0.5s ease-out;
        }

        @keyframes slideUp {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .status-indicator {
            display: inline-block;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            margin-right: 8px;
        }

        .status-safe {
            background: #10b981;
            box-shadow: 0 0 8px rgba(16, 185, 129, 0.5);
        }

        .status-warning {
            background: #f59e0b;
            box-shadow: 0 0 8px rgba(245, 158, 11, 0.5);
        }

        .code-snippet {
            background: #1e293b;
            color: #e2e8f0;
            padding: 16px;
            border-radius: 8px;
            font-family: 'JetBrains Mono', 'Fira Code', monospace;
            font-size: 14px;
            margin: 12px 0;
            overflow-x: auto;
            border-left: 4px solid #667eea;
        }

        @media (max-width: 768px) {
            .container {
                padding: 24px;
                margin: 10px;
            }
            
            .title {
                font-size: 2.2em;
            }
            
            .detection-card {
                padding: 20px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1 class="title">🔍 WebDriver 检测器</h1>
            <p class="subtitle">高精度自动化浏览器识别系统</p>
        </div>
        
        <div class="detection-grid">
            <div class="detection-card">
                <div class="card-header">
                    <div class="card-icon">🤖</div>
                    <div class="card-title">Navigator WebDriver 检测</div>
                </div>
                <div class="card-description">
                    检测 <code>navigator.webdriver</code> 属性,这是最直接的 WebDriver 标识符。正常浏览器此值为 undefined,自动化浏览器会被设置为 true。
                </div>
                <div class="code-snippet">if (navigator.webdriver === true) {
    // 检测到自动化浏览器
    return true;
}</div>
                <button class="test-button" onclick="testWebdriver()">🔍 开始检测</button>
                <div class="result-container" id="webdriver-result"></div>
            </div>

            <div class="detection-card">
                <div class="card-header">
                    <div class="card-icon">🔔</div>
                    <div class="card-title">通知权限检测</div>
                </div>
                <div class="card-description">
                    检测浏览器通知权限状态。自动化浏览器的通知权限通常被默认拒绝,而正常用户浏览器会显示为默认状态或已授权。
                </div>
                <div class="code-snippet">if (Notification.permission === 'denied') {
    // 可能是自动化浏览器
    return true;
}</div>
                <button class="test-button" onclick="testNotification()">🔍 开始检测</button>
                <div class="result-container" id="notification-result"></div>
            </div>
        </div>

        <button class="run-all-button" onclick="runAllTests()">
            🚀 运行完整检测
        </button>
        
        <div id="overall-result" class="overall-result"></div>
    </div>

    <script>
        function testWebdriver() {
            const isWebDriver = navigator.webdriver === true;
            const resultElement = document.getElementById('webdriver-result');
            
            resultElement.innerHTML = `
                <div class="${isWebDriver ? 'warning' : 'result'}">
                    <span class="status-indicator ${isWebDriver ? 'status-warning' : 'status-safe'}"></span>
                    <strong>检测结果:</strong> ${isWebDriver ? '⚠️ 检测到 WebDriver 标识' : '✅ 未检测到自动化标识'}
                    <br><small>navigator.webdriver = ${navigator.webdriver}</small>
                </div>
            `;
            
            return isWebDriver;
        }

        function testNotification() {
            const permission = Notification.permission;
            const isDenied = permission === 'denied';
            const resultElement = document.getElementById('notification-result');
            
            let statusText = '';
            let isWarning = false;
            
            switch (permission) {
                case 'denied':
                    statusText = '⚠️ 通知权限被拒绝(可疑)';
                    isWarning = true;
                    break;
                case 'granted':
                    statusText = '✅ 通知权限已授权(正常)';
                    break;
                case 'default':
                    statusText = '✅ 通知权限为默认状态(正常)';
                    break;
                default:
                    statusText = '❓ 未知权限状态';
                    break;
            }
            
            resultElement.innerHTML = `
                <div class="${isWarning ? 'warning' : 'result'}">
                    <span class="status-indicator ${isWarning ? 'status-warning' : 'status-safe'}"></span>
                    <strong>检测结果:</strong> ${statusText}
                    <br><small>Notification.permission = "${permission}"</small>
                </div>
            `;
            
            return isDenied;
        }

        function runAllTests() {
            // 添加动画效果
            const button = document.querySelector('.run-all-button');
            button.style.transform = 'scale(0.95)';
            
            setTimeout(() => {
                button.style.transform = '';
                
                const webdriverResult = testWebdriver();
                
                setTimeout(() => {
                    const notificationResult = testNotification();
                    
                    setTimeout(() => {
                        showOverallResult(webdriverResult, notificationResult);
                    }, 300);
                }, 300);
            }, 100);
        }

        function showOverallResult(webdriverDetected, notificationDetected) {
            const detectionCount = (webdriverDetected ? 1 : 0) + (notificationDetected ? 1 : 0);
            const totalTests = 2;
            
            let resultText = '';
            let confidenceLevel = '';
            let riskLevel = '';
            
            if (detectionCount === 0) {
                resultText = '✅ 可能是真实用户浏览器';
                confidenceLevel = '可信度很高';
                riskLevel = 'background: linear-gradient(135deg, #10b981, #059669);';
            } else if (detectionCount === 1) {
                resultText = '⚠️ 存在自动化特征';
                confidenceLevel = '中等风险';
                riskLevel = 'background: linear-gradient(135deg, #f59e0b, #d97706);';
            } else {
                resultText = '🚨 高度疑似自动化浏览器';
                confidenceLevel = '高风险';
                riskLevel = 'background: linear-gradient(135deg, #ef4444, #dc2626);';
            }
            
            const percentage = Math.round((detectionCount / totalTests) * 100);
            
            const resultElement = document.getElementById('overall-result');
            resultElement.style.cssText = riskLevel;
            resultElement.innerHTML = `
                <div style="font-size: 1.5em; margin-bottom: 16px;">${resultText}</div>
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
                    <span>检测项目:</span>
                    <span><strong>${detectionCount}/${totalTests}</strong> 项异常</span>
                </div>
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
                    <span>风险等级:</span>
                    <span><strong>${confidenceLevel}</strong></span>
                </div>
                <div style="display: flex; justify-content: space-between; align-items: center;">
                    <span>自动化概率:</span>
                    <span><strong>${percentage}%</strong></span>
                </div>
            `;
            
            resultElement.classList.add('show');
        }

        // 页面加载完成后自动运行一次检测
        window.addEventListener('load', () => {
            setTimeout(() => {
                runAllTests();
            }, 1000);
        });
    </script>
</body>
</html>

解决办法

魔改浏览器

1、解决问题1

找到这个路径:src\third_party\blink\renderer\core\framenavigator.cc

image.png

注释掉上面的。默认让他返回false

2、修改通知权限

找到路径:src\third_party\blink\renderer\modules\notificationsnotification.cc

把如下地方改成kDefault,可能版本不同有点不一样。这里如果自己改需要注意。

image.png

🤗 总结归纳

本文主要是魔改两个地方navigator检测和通知数据检测。之前看到有的小伙伴说这种不是可以用一些其他工具替代。其实这个是业务问题。有一些业务会有批量远程驱动的需求这个时候有一些特征是很难抹除的。这个时候就可以派上用场了。还有就是可以定位一些ja3、ja4指纹。

精品文章

相关推荐
豆苗学前端8 分钟前
JavaScript原型对象、构造函数、继承与类详解
前端·javascript·后端
飞翔的佩奇10 分钟前
【完整源码+数据集+部署教程】【运动的&足球】足球比赛分析系统源码&数据集全套:改进yolo11-RFAConv
前端·python·yolo·计算机视觉·数据集·yolo11·足球比赛分析系统
智启七月27 分钟前
Dexbotic 开源深度解析:重构具身智能 VLA 研发的技术基石与实现路径
人工智能·python
参宿742 分钟前
图解Vue3 响应式,手动实现核心原理
前端·javascript·vue.js
2301_801252221 小时前
前端框架Vue(Vue 的挂载点与 data 数据对象)
java·前端·javascript·vue.js·前端框架
beyond阿亮1 小时前
nacos支持MCP Server注册与发现
java·python·ai·nacos·mcp
非凡ghost1 小时前
EaseUS Fixo(易我视频照片修复)
前端·javascript·后端
非凡ghost1 小时前
Avast Cleanup安卓版(手机清理优化)
前端·javascript·后端
感哥1 小时前
Python 装饰器
python
非凡ghost1 小时前
Atlantis Word Processor(文字处理软件)
前端·javascript·后端