魔改编译-永久解决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指纹。

精品文章

相关推荐
Danceful_YJ11 分钟前
4.权重衰减(weight decay)
python·深度学习·机器学习
我命由我1234530 分钟前
前端开发问题:SyntaxError: “undefined“ is not valid JSON
开发语言·前端·javascript·vue.js·json·ecmascript·js
Jokerator32 分钟前
深入解析JavaScript获取元素宽度的多种方式
javascript·css
海天胜景35 分钟前
vue3 当前页面方法暴露
前端·javascript·vue.js
GISer_Jing43 分钟前
前端面试常考题目详解
前端·javascript
Zonda要好好学习1 小时前
Python入门Day5
python
中微子2 小时前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
电商数据girl2 小时前
有哪些常用的自动化工具可以帮助处理电商API接口返回的异常数据?【知识分享】
大数据·分布式·爬虫·python·系统架构
CoooLuckly2 小时前
numpy数据分析知识总结
python·numpy
天天向上10242 小时前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js