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

精品文章

相关推荐
liuyunshengsir2 分钟前
PyTorch 动态量化(Dynamic Quantization)
人工智能·pytorch·python
电子云与长程纠缠10 分钟前
UE5制作六边形包裹球体效果
开发语言·python·ue5
DFT计算杂谈19 分钟前
KPROJ编译教程
java·前端·python·算法·conda
念恒123061 小时前
Python(循环中断)
开发语言·python
tsfy20031 小时前
Python 处理中文文件名的3个坑(附 Flask 上传解决函数)
开发语言·python·flask·文件上传·中文编码
AI技术控1 小时前
KV Cache 缓存机制的原理和应用:从 Transformer 推理到大模型服务优化
人工智能·python·深度学习·缓存·自然语言处理·transformer
vx-程序开发2 小时前
基于机器学习的动漫可视化系统的设计与实现-计算机毕业设计源码08339
java·c++·spring boot·python·spring·django·php
熊猫_豆豆2 小时前
一个模拟四轴飞行器在随机气流扰动下悬停飞行的交互式3D仿真网页,包含飞行器建模与PID控制算法
javascript·3d·html·四轴无人机模拟飞行
爱睡懒觉的焦糖玛奇朵2 小时前
【从视频到数据集:焦糖玛奇朵的魔法工具Video To YOLO Dataset】
人工智能·python·学习·yolo·音视频
石榴树下的七彩鱼2 小时前
医疗票据 OCR 识别 API 多场景落地指南:医保结算 + 商保理赔 + 医疗信息化(附 Python/Java 完整示例)
java·python·ocr·石榴智能·医疗票据ocr·医保结算·ocrapi