设备指纹技术深度解析与绕过策略

设备指纹技术深度解析与绕过策略

📚 前置知识

本配方涉及以下核心技术,建议先阅读相关章节:

设备指纹 (Device Fingerprinting) 是指通过采集设备的软硬件特征,生成一个能够唯一标识该设备的、具有高熵值和稳定性的 ID 的过程。在当今的互联网服务中,它已成为反欺诈、反机器人、用户行为追踪和安全风控的基石技术。

绕过设备指纹并非简单地修改一两个参数,而是要创造一个完整的、逻辑自洽的、可信的虚拟设备"画像"。本指南将系统性地拆解主流的指纹采集维度,并探讨与之对应的核心绕过技术。


设备指纹的工作原理

指纹生成算法

设备指纹的生成并非简单地将所有采集到的信息拼接在一起,而是通过复杂的算法处理,确保生成的指纹具有唯一性、稳定性和不可逆性。

基本流程

对采集到的原始数据进行预处理:

  • 格式统一: 将不同格式的数据转换为标准格式(如MAC地址统一为小写、去除分隔符)
  • 缺失值处理: 对无法获取的字段使用默认值或特殊标记
  • 权重分配: 根据稳定性和唯一性给不同维度分配权重

特征组合 - 将处理后的数据按照预定规则组合:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 概念代码
fingerprint_input = {
    'hardware': {
        'android_id': 'abc123',
        'imei': '867530900000000',
        'mac': '00:11:22:33:44:55'
    },
    'software': {
        'model': 'Pixel 6',
        'sdk': 33,
        'fingerprint': 'google/raven/raven:...'
    },
    'environment': {
        'screen': '1080x2400',
        'dpi': 420,
        'timezone': 'Asia/Shanghai'
    }
}

import hashlib
import json

def generate_fingerprint(data):
    # 数据转为JSON字符串(确保顺序一致)
    json_str = json.dumps(data, sort_keys=True)
    # 计算SHA256
    fingerprint = hashlib.sha256(json_str.encode()).hexdigest()
    return fingerprint
算法输出长度特点适用场景
MD5128位速度快,但安全性低低安全要求场景
SHA-256256位安全性高,计算稍慢金融、高安全场景
MurmurHash可变速度极快,适合非加密大规模数据处理
xxHash可变性能优异实时计算场景

高级技术

1. 模糊Hash (Fuzzy Hashing)

允许设备指纹在细微变化时仍能匹配。使用 SimHash、MinHash 等算法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def simhash(features, hash_bits=64):
    """
    将特征向量转换为 SimHash 值
    相似特征会产生相似的Hash值
    """
    v = [0] * hash_bits

    for feature, weight in features.items():
        h = hash(feature)
        for i in range(hash_bits):
            if h & (1 << i):
                v[i] += weight
            else:
                v[i] -= weight

    fingerprint = 0
    for i in range(hash_bits):
        if v[i] >= 0:
            fingerprint |= (1 << i)

    return fingerprint

2. 分层指纹

  • 一级指纹(硬件指纹): 基于IMEI、Android ID等硬件ID
  • 二级指纹(系统指纹): 基于系统版本、设备型号等
  • 三级指纹(环境指纹): 基于网络、行为等临时特征
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def generate_tiered_fingerprint(data):
    # 一级指纹:硬件ID
    tier1 = hashlib.sha256(
        f"{data['imei']}|{data['android_id']}".encode()
    ).hexdigest()

    # 二级指纹:系统特征
    tier2 = hashlib.sha256(
        f"{tier1}|{data['model']}|{data['sdk']}".encode()
    ).hexdigest()

    # 三级指纹:完整特征
    tier3 = hashlib.sha256(
        json.dumps(data, sort_keys=True).encode()
    ).hexdigest()

    return {
        'strong': tier1,
        'medium': tier2,
        'weak': tier3
    }

3. 机器学习特征提取

  • 使用 PCA(主成分分析)提取关键特征
  • 使用聚类算法识别异常设备
  • 使用深度学习模型生成设备嵌入向量(Embedding)

熵值与稳定性

好的设备指纹需要在唯一性(高熵值)稳定性之间找到平衡。

熵值计算

熵值衡量一个特征的信息量和区分能力:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import math
from collections import Counter

def calculate_entropy(values):
    """
    计算一个特征的香农熵
    熵值越高,说明该特征区分能力越强
    """
    total = len(values)
    counter = Counter(values)

    entropy = 0
    for count in counter.values():
        p = count / total
        entropy -= p * math.log2(p)

    return entropy

# 示例
android_ids = ['id1', 'id2', 'id3', ...]  # 采集的数据
entropy = calculate_entropy(android_ids)
print(f"Android ID 熵值: {entropy} bits")
特征熵值唯一性稳定性
Android ID60+ bits中(恢复出厂会变)
MAC 地址48 bits中(越来越难获取)
设备型号8-10 bits
屏幕分辨率6-8 bits
传感器列表15-20 bits

稳定性评估

稳定性指的是设备在不同时间点、不同环境下生成的指纹一致性:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def stability_score(fingerprints):
    """
    评估同一设备在不同时间生成的指纹稳定性
    fingerprints: 同一设备多次生成的指纹列表
    """
    if len(fingerprints) < 2:
        return 1.0

    # 计算指纹之间相似度
    base = fingerprints[0]
    similarities = []

    for fp in fingerprints[1:]:
        # Hamming 距离
        diff = sum(c1 != c2 for c1, c2 in zip(base, fp))
        similarity = 1 - (diff / len(base))
        similarities.append(similarity)

    return sum(similarities) / len(similarities)

def quality_score(entropy, stability, coverage):
    """
    计算指纹方案质量分数
    entropy: 熵值 (0-100)
    stability: 稳定性 (0-1)
    coverage: 设备覆盖率 (0-1)
    """
    # 加权计算
    score = (
        entropy * 0.4 +           # 唯一性权重 40%
        stability * 50 * 0.4 +    # 稳定性权重 40%
        coverage * 100 * 0.2      # 覆盖率权重 20%
    )
    return score

指纹更新策略

1. 主动更新触发条件

  • 设备硬件变更(换SIM卡、重置设备)
  • App版本升级(指纹算法更新)
  • 定期刷新(如每30天)

2. 被动更新触发条件

  • 检测到指纹冲突(多个设备具有相同指纹)
  • 检测到异常行为(疑似改机)
  • 服务端要求强制更新

更新策略实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class FingerprintManager:
    def should_update(self, old_fp, new_data):
        """
        检查是否需要更新指纹
        """
        # 计算新指纹
        new_fp = self.generate_fingerprint(new_data)

        # 1. 关键字段变更
        critical_changed = self._check_critical_fields(old_fp, new_data)
        if critical_changed:
            return True, "Critical field changed"

        # 2. 相似度过低
        similarity = self._calculate_similarity(old_fp, new_fp)
        if similarity < 0.7:
            return True, "Low similarity"

        # 3. 时间过期
        if self._is_expired(old_fp):
            return True, "Expired"

        return False, "No update needed"

    def update_fingerprint(self, device_id, new_fp, reason):
        """
        更新指纹时保留历史记录
        """
        history = {
            'device_id': device_id,
            'old_fingerprint': self.current_fp,
            'new_fingerprint': new_fp,
            'update_reason': reason,
            'timestamp': time.time()
        }
        self._save_history(history)
        self.current_fp = new_fp

主流设备指纹采集维度

硬件层标识符

这些是传统的、权限较高的设备 ID。

标识符获取方式 (Java API)特点
Android IDSettings.Secure.getString(resolver, "android_id")Android 8.0 以上,对每个 App 和用户都不同。恢复出厂设置会改变。
IMEI/MEIDTelephonyManager.getImei()手机的唯一身份码。需要 READ_PHONE_STATE 权限,且越来越难获取。
IMSITelephonyManager.getSubscriberId()SIM 卡的唯一身份码。同样需要高权限。
MAC 地址WifiInfo.getMacAddress()Android 6.0 以后,App 获取到的通常是一个固定的假值 02:00:00:00:00:00

系统与软件特征

这是指纹库的主体,信息量大,获取成本低。

Build 属性: 通过 android.os.Build 类或直接读取 /system/build.prop 文件获取。

  • Build.MODEL: 设备型号 (e.g., “Pixel 6”)
  • Build.BRAND: 品牌 (e.g., “Google”)
  • Build.MANUFACTURER: 制造商 (e.g., “Google”)
  • Build.VERSION.SDK_INT: SDK 版本号 (e.g., 33)
  • Build.FINGERPRINT: 系统构建指纹,信息量巨大。

系统设置:

  • 屏幕分辨率、DPI (DisplayMetrics)
  • 系统语言、时区、默认字体列表。

软件环境:

  • 已安装应用列表 (PackageManager.getInstalledPackages)
  • 特定 App (如输入法) 的版本

硬件特性指纹

利用硬件的细微物理差异来创建指纹。

  • 传感器数据: 读取加速度计、陀螺仪等传感器的校准数据或在特定操作下的读数。不同批次的传感器存在物理差异。
  • CPU/GPU 信息:
    • 读取 /proc/cpuinfo 获取 CPU 型号、核心数、特性等。
    • 通过 OpenGL/WebGL API 查询 GPU 供应商、渲染器信息,甚至可以执行一个标准渲染任务,将渲染结果的 Hash 作为指纹。
  • 摄像头参数: CameraCharacteristics 中包含的详细参数。

通过 SVC (系统调用) 获取信息

这是一种高级的反 Hook 技术,常见于加固方案中。其核心思想是绕过所有上层 API 和 libc 函数,通过 SVC 指令直接发起系统调用 (syscall) 来获取信息或执行操作。

原理: SVC 是 ARM 处理器的一条指令,它会触发一个软件中断,使 CPU 从用户态(User Mode)切换到管理态(Supervisor Mode),从而执行内核代码。这是所有系统调用的基础。加固厂商在 SO 文件中直接嵌入 SVC 指令,可以不经过 libc.so 中的 read, open, ioctl 等函数,直接调用内核中对应的功能。

应用场景:

  • 绕过 API Hook: 这是其最主要的目的。由于 Frida、Xposed 等框架主要 Hook 的是 App 进程空间中的函数(Java API 或 Native API),SVC 指令直接与内核交互,使得这些上层 Hook 完全失效。
  • 读取敏感文件: 直接使用 open/read 的系统调用号来读取 /proc/self/maps, /proc/cpuinfo 等文件,以检测环境或收集指纹。
  • 执行反调试: 使用 ptrace 的系统调用号来执行反调试检查。

分析与识别:

  • 静态分析: 在 IDA 等反汇编工具中,直接搜索 SVC 指令。如果一个 SO 文件中含有大量 SVC 指令,且其上下文逻辑复杂,则极有可能使用了该技术。
  • 动态分析: Hook 系统调用需要更底层的工具。Frida 的 Stalker 可以用来跟踪指令级的执行流程,从而捕捉到 SVC 的调用。

网络环境指纹

  • IP 地址: 最基础的维度,结合地理位置库可以判断用户位置。
  • 网络信息: 运营商名称 (TelephonyManager.getNetworkOperatorName)、Wi-Fi BSSID/SSID。
  • TLS/JA3 指纹: 在建立 TLS 连接时,客户端 Client Hello 包的特征可以构成一个稳定的指纹,用于识别特定的网络库和版本。

行为特征指纹

行为特征是一种动态指纹,基于用户的操作模式和设备使用习惯。

采集维度

1. 触摸行为

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
view.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // 采集触摸压力
        float pressure = event.getPressure();
        // 采集触摸面积
        float size = event.getSize();
        // 采集触摸坐标和时间戳
        long timestamp = event.getEventTime();
        float x = event.getX();
        float y = event.getY();

        // 构建触摸特征向量
        TouchFeature feature = new TouchFeature(pressure, size, timestamp, x, y);
        return false;
    }
});

2. 传感器行为

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

sensorManager.registerListener(new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];

        // 分析持握姿态、步态特征等
        analyzeMotionPattern(x, y, z);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);

3. 应用使用模式

  • App 启动时间分布
  • 常用 App 列表及使用频率
  • 前后台切换模式
  • 应用安装/卸载习惯

4. 网络行为

  • 访问时间模式(工作日 vs 周末,白天 vs 晚上)
  • 请求频率和间隔
  • 网络切换习惯(WiFi ↔ 4G/5G)
  • 常用地理位置

行为指纹生成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class BehaviorFingerprint:
    def __init__(self):
        self.touch_features = []
        self.sensor_features = []
        self.app_usage = {}
        self.network_pattern = {}

    def extract_touch_signature(self, touch_events):
        """从触摸事件提取用户签名"""
        pressures = [e.pressure for e in touch_events]
        velocities = self._calculate_velocities(touch_events)

        signature = {
            'avg_pressure': np.mean(pressures),
            'std_pressure': np.std(pressures),
            'avg_velocity': np.mean(velocities),
            'touch_rhythm': self._analyze_rhythm(touch_events)
        }
        return signature

    def generate_behavior_fingerprint(self):
        """生成综合行为指纹"""
        touch_sig = self.extract_touch_signature(self.touch_features)
        motion_sig = self.extract_motion_signature(self.sensor_features)
        usage_sig = self.extract_usage_signature(self.app_usage)

        # 组合为行为特征向量
        behavior_vector = {
            'touch': touch_sig,
            'motion': motion_sig,
            'usage': usage_sig,
            'network': self.network_pattern
        }

        return hashlib.sha256(
            json.dumps(behavior_vector, sort_keys=True).encode()
        ).hexdigest()

核心绕过技术与策略

Hook 技术 (Frida/Xposed)

核心思路: 识别 -> Hook -> 伪造

  1. 识别: 定位 App 获取关键指纹信息的代码位置(Java API 或 JNI 函数)。
  2. Hook: 使用 Frida 或 Xposed 拦截这些函数的调用。
  3. 伪造: 在函数返回前,用一套预设的、自洽的假数据替换真实返回值。

Frida 概念脚本 (伪造 Build.MODEL):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Java.perform(function () {
    var Build = Java.use("android.os.Build");
    Build.MODEL.value = "Pixel 4";  // 修改 MODEL 字段

    var String = Java.use("java.lang.String");
    var TelephonyManager = Java.use("android.telephony.TelephonyManager");
    TelephonyManager.getDeviceId.overload().implementation = function () {
        console.log("Hooked getDeviceId(). Returning a fake IMEI.");
        return String.$new("867530900000000");  // 返回伪造 IMEI
    };
});

深度设备修改 (“改机”)

需要 Root 权限,直接修改 /system/build.prop 等系统级文件,或通过内核模块修改系统调用的返回值。

  • 优点: 无法通过应用层的检测手段识破,因为 App 获取到的就是系统层返回的"真实"数据。
  • 缺点: 技术门槛高,工作量巨大。

环境虚拟化与容器技术

虚拟化和容器技术是规模化设备指纹绕过的核心基础设施,能够在单台物理机上运行数百个独立的 Android 实例。

Android 虚拟化技术栈

1. 基于 QEMU 的完整虚拟化

Android 官方模拟器(AVD)基于 QEMU 实现:

1
2
3
4
5
# 启动 AVD 模拟器
emulator -avd Pixel_6_API_33 \
    -no-snapshot \
    -wipe-data \
    -gpu swiftshader_indirect

主要问题

1
2
3
4
5
6
7
# 容易被检测的特征
getprop ro.hardware           # 返回 "goldfish" 或 "ranchu"
getprop ro.product.model      # 返回 "android SDK built for x86"
getprop ro.build.fingerprint  # 包含 "通用" 字样

# 缺失传感器
pm list features | grep sensor  # 大量传感器缺失

2. 基于容器的方案 (Docker/LXC)

容器技术提供更轻量的隔离:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Dockerfile for Android container
FROM ubuntu:20.04

# 安装 Android 环境
RUN apt-get update && apt-get install -y \
    openjdk-11-jdk \
    android-sdk \
    adb \
    fastboot

# 配置 Android 环境
ENV ANDROID_HOME=/opt/android-sdk
ENV PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools

# 运行 ADB 服务
CMD ["adb", "-a", "nodaemon", "server"]

3. 专业容器方案:Redroid

Redroid 是一个基于 Docker 的 Android 容器方案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 运行 Redroid 容器
docker run -d \
    --name redroid \
    --privileged \
    -v ~/data:/data \
    -p 5555:5555 \
    redroid/redroid:11.0.0-latest

# 连接到 Redroid
adb connect localhost:5555
adb shell

云手机技术详解

云手机架构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌─────────────────────────────────────────────────┐
│            用户接入层 (Access Layer)             │
│  - Web 控制台                                    │
│  - API 服务                                      │
│  - 自动化脚本                                    │
├─────────────────────────────────────────────────┤
│        云手机实例层 (Instance Layer)             │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐         │
│  │ 云手机1  │ │ 云手机2  │ │ 云手机N  │ ...     │
│  │ Android  │ │ Android  │ │ Android  │         │
│  └──────────┘ └──────────┘ └──────────┘         │
├─────────────────────────────────────────────────┤
│       虚拟化层 (Virtualization Layer)            │
│  - ARM 虚拟化 (KVM/QEMU)                         │
│  - GPU 虚拟化 (vGPU)                             │
│  - 网络虚拟化 (VPC)                              │
├─────────────────────────────────────────────────┤
│           硬件层 (Hardware Layer)                │
│  - ARM 服务器 (华为鲲鹏/飞腾)                    │
│  - 高性能存储 (NVMe SSD)                         │
│  - 专用 GPU (Mali/Adreno)                        │
└─────────────────────────────────────────────────┘

云手机平台对比

平台架构密度性能成本适用场景
华为云手机ARM 服务器+KVM企业级应用
红手指ARM 容器自动化、挂机
多多云手机x86+容器批量注册、养号
AWS Device Farm真机极高极高测试、兼容性验证

构建一致性的"设备画像"

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class DeviceFingerprintManager:
    def __init__(self, device_pool_db):
        self.db = device_pool_db
        self.used_fingerprints = set()

    def get_unused_fingerprint(self):
        """从设备池中获取未使用的指纹"""
        while True:
            fp = self.db.get_random_fingerprint()
            fp_hash = hashlib.md5(json.dumps(fp).encode()).hexdigest()

            if fp_hash not in self.used_fingerprints:
                self.used_fingerprints.add(fp_hash)
                return fp

    def apply_fingerprint(self, adb_device, fingerprint):
        """将指纹应用到设备"""
        # 修改系统属性
        for key, value in fingerprint['build_props'].items():
            adb_device.shell(f"setprop {key} {value}")

        # 安装预设 App
        for apk in fingerprint['apps']:
            adb_device.install(apk)

        # 设置位置
        adb_device.shell(f"settings put secure location_mode 3")
        adb_device.shell(
            f"am startservice -a com.example.fakelocation "
            f"--es lat {fingerprint['location']['lat']} "
            f"--es lng {fingerprint['location']['lng']}"
        )

    def rotate_fingerprint(self, adb_device, interval_hours=24):
        """定期轮换设备指纹"""
        while True:
            new_fp = self.get_unused_fingerprint()
            self.apply_fingerprint(adb_device, new_fp)

            # 记录使用历史
            self.db.log_usage(adb_device.serial, new_fp, timestamp=time.time())

            time.sleep(interval_hours * 3600)

商业化产品与服务

国内主流设备指纹服务商

1. 顶象科技 (DingXiang)

产品: 顶象设备指纹 (Device Fingerprint)

技术特点

  • 采集 200+ 设备特征维度
  • 支持 Android、iOS、Web、小程序
  • 99.9%+ 设备唯一性识别率
  • 设备指纹有效期 90 天+
  • 支持私有化部署

定价:按 API 调用次数计费,企业版约 0.005-0.01 元/次

2. 同盾科技 (Tongdun)

产品: 同盾设备指纹

技术特点

  • 结合 AI 和大数据分析
  • 设备行为画像
  • 实时风险决策
  • 覆盖金融、电商、O2O 等场景

API 示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests
import time

def tongdun_device_risk(device_id, event_type):
    """调用同盾设备风险评估 API"""
    url = "https://api.tongdun.cn/riskService"

    params = {
        "partner_code": "your_partner_code",
        "device_id": device_id,
        "event_type": event_type,  # 如: login, register, pay
        "timestamp": int(time.time() * 1000)
    }

    # 添加签名
    params["sign"] = generate_sign(params)

    response = requests.post(url, json=params)
    result = response.json()

    return {
        "risk_score": result["final_score"],     # 风险分数 0-100
        "risk_level": result["risk_level"],      # high/medium/low
        "device_labels": result["labels"]        # 设备标签
    }

3. 数美科技 (ISHUMEI)

技术特点

  • 专注于内容安全和业务安全
  • 设备指纹+行为分析
  • 实时黑产设备库
  • 支持多场景风控

应用场景

  • 羊毛党识别
  • 虚假注册拦截
  • 刷单检测
  • 恶意爬虫识别

4. 网易易盾 (NetEase YiDun)

产品: 易盾设备指纹

技术特点

  • 网易内部风控技术外化
  • 游戏、社交场景优化
  • 设备唯一性识别
  • 设备环境检测(Root、模拟器、Hook 框架)

SDK 集成示例(Android):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// 初始化
NECaptcha.getInstance()
    .init(context, "your_business_id", new NECaptchaListener() {
        @Override
        public void onReady() {
            // 获取设备指纹
            String deviceId = NEDeviceRisk.getDeviceId();
        }
    });

// 获取设备风险信息
NEDeviceRisk.check(context, new NEDeviceRiskCallback() {
    @Override
    public void onResult(NEDeviceRiskResult result) {
        int riskLevel = result.getRiskLevel();  // 0-4 级风险
        boolean isEmulator = result.isEmulator();
        boolean isRooted = result.isRoot();
        boolean isHooked = result.isHook();
    }
});

国际知名产品

1. FingerprintJS

类型: 开源 + 商业版

特点

  • 主要用于 Web 浏览器指纹
  • 开源版本基础功能免费
  • Pro 版提供 99.5% 准确率

使用示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import FingerprintJS from "@fingerprintjs/fingerprintjs";

// 初始化 agent
const fpPromise = FingerprintJS.load();

// 获取访客标识
fpPromise
    .then((fp) => fp.get())
    .then((result) => {
        // 访客标识
        const visitorId = result.visitorId;
        console.log(visitorId);

        // 所有组件(浏览器特征)
        console.log(result.components);
    });

2. DeviceAtlas

特点

  • 包含数万种设备型号
  • 主要用于移动广告和分析
  • 支持云端 API 和本地部署

开源工具与框架

设备指纹采集框架

1. FingerprintJS

2. android-device-names

  • 支持 12000+ 设备型号
  • 可以根据 Build.MODEL 获取市场化设备名称
1
2
3
4
5
6
7
8
9
DeviceName.with(context).request(new DeviceName.Callback() {
    @Override
    public void onFinished(DeviceName.DeviceInfo info, Exception error) {
        String manufacturer = info.manufacturer;  // "Samsung"
        String marketName = info.marketName;      // "Galaxy S21"
        String model = info.model;                // "SM-G991B"
        String codename = info.codename;          // "o1s"
    }
});

反指纹工具

1. Magisk 模块

1
2
3
4
5
6
# 修改设备指纹
props ro.build.fingerprint "google/raven/raven:12/..."
props ro.product.model "Pixel 6"

# 应用修改
props ro.build.product "raven"

2. Xposed 模块

XPrivacyLua

3. Frida 脚本库

常用的设备信息 Hook 脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Java.perform(function() {
    // 拦截 Build 类所有字段
    var Build = Java.use("android.os.Build");
    Build.BRAND.value = "google";
    Build.MODEL.value = "Pixel 6";
    Build.DEVICE.value = "raven";
    Build.PRODUCT.value = "raven";
    Build.MANUFACTURER.value = "Google";

    // Hook Settings.Secure
    var Settings = Java.use("android.provider.Settings$Secure");
    Settings.getString.overload(
        "android.content.ContentResolver",
        "java.lang.String"
    ).implementation = function(resolver, name) {
        if (name == "android_id") {
            return "fake_android_id_12345678";
        }
        return this.getString(resolver, name);
    };

    // Hook TelephonyManager
    var TelephonyManager = Java.use("android.telephony.TelephonyManager");
    TelephonyManager.getDeviceId.overload().implementation = function() {
        return "fake_imei_123456789012345";
    };
});

对抗与挑战

Hook 框架检测

  • 检查 /proc/self/maps 中是否加载了 frida-agent.soXposedBridge.jar
  • 检测 Frida 的默认端口 27042
  • 通过 try-catch 执行一个会因 Xposed 修改而改变行为的函数,判断是否抛出异常

服务端交叉验证

这是设备指纹技术最强大的地方。后端服务会将客户端上传的几百个维度的指纹数据进行交叉比对。一个 IMEI 显示是三星设备,但 Build.FINGERPRINT 却属于小米,这种矛盾会立刻导致该设备被标记为高风险。

交叉验证规则示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class FingerprintValidator:
    def __init__(self):
        self.device_database = self.load_device_db()
        self.inconsistency_rules = self.load_rules()

    def validate_fingerprint(self, fingerprint):
        """验证设备指纹一致性"""
        issues = []

        # 规则1:品牌与型号匹配
        if not self.check_brand_model_match(
            fingerprint['brand'],
            fingerprint['model']
        ):
            issues.append({
                'type': 'brand_model_mismatch',
                'severity': 'high',
                'message': f"Brand {fingerprint['brand']} does not match model {fingerprint['model']}"
            })

        # 规则2:屏幕分辨率与型号匹配
        expected_resolution = self.device_database.get_resolution(fingerprint['model'])
        if fingerprint['screen_resolution'] != expected_resolution:
            issues.append({
                'type': 'resolution_mismatch',
                'severity': 'medium',
                'message': f"Unexpected resolution for {fingerprint['model']}"
            })

        # 规则3:传感器列表完整性
        expected_sensors = self.device_database.get_sensors(fingerprint['model'])
        if len(fingerprint['sensors']) < len(expected_sensors) * 0.8:
            issues.append({
                'type': 'sensor_missing',
                'severity': 'high',
                'message': 'Too few sensors for this device model'
            })

        return {
            'is_valid': len(issues) == 0,
            'risk_score': self.calculate_risk_score(issues),
            'issues': issues
        }

机器学习检测

使用标注数据训练模型,识别真实设备 vs 伪造设备:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.neural_network import MLPClassifier
import numpy as np

class DeviceAuthenticityClassifier:
    def __init__(self):
        self.models = {
            'random_forest': RandomForestClassifier(n_estimators=200, max_depth=15),
            'gradient_boosting': GradientBoostingClassifier(n_estimators=100),
            'neural_network': MLPClassifier(hidden_layer_sizes=(128, 64, 32))
        }
        self.feature_extractor = FeatureExtractor()

    def train(self, X_train, y_train):
        """
        训练分类器
        X_train: 设备指纹特征
        y_train: 标签 (0=伪造, 1=真实)
        """
        for name, model in self.models.items():
            print(f"Training {name}...")
            model.fit(X_train, y_train)

    def predict(self, fingerprint):
        """预测设备真实性"""
        features = self.feature_extractor.extract(fingerprint)

        # 集成投票
        votes = []
        probabilities = []

        for name, model in self.models.items():
            pred = model.predict([features])[0]
            prob = model.predict_proba([features])[0]
            votes.append(pred)
            probabilities.append(prob[1])  # 真实设备概率

        # 加权平均
        avg_probability = np.mean(probabilities)

        return {
            'is_genuine': avg_probability > 0.5,
            'confidence': avg_probability,
            'votes': dict(zip(self.models.keys(), votes))
        }

实战案例分析

💡 思路一句话: 抓包 + hook 双管齐下 — 抓包看请求中携带了哪些设备信息字段,hook 系统 API (Build, TelephonyManager, Settings.Secure) 确认数据来源,然后逐一伪造。

案例 1:某电商平台设备指纹分析

💡 思路一句话: mitmproxy 拦截请求 → 找到 device_id/fingerprint 参数 → jadx 搜索参数名定位采集代码 → Frida hook 篡改采集结果实现设备伪装。

背景:某大型电商平台面临大量刷单、虚假评论和薅羊毛行为,需要通过设备指纹识别恶意用户。

技术方案

1. 指纹采集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class EcommerceFingerprintCollector {
    public DeviceFingerprint collect(Context context) {
        DeviceFingerprint fp = new DeviceFingerprint();

        // 基本硬件信息
        fp.setAndroidId(getAndroidId(context));
        fp.setModel(Build.MODEL);
        fp.setBrand(Build.BRAND);

        // 网络信息
        fp.setIpAddress(getIPAddress());
        fp.setMacAddress(getMacAddress(context));

        // App 信息
        fp.setInstalledApps(getInstalledApps(context));

        // 行为特征
        fp.setTouchPressure(collectTouchPressure());
        fp.setTypingSpeed(collectTypingSpeed());

        // 环境检测
        fp.setIsRooted(checkRootStatus());
        fp.setIsEmulator(checkEmulatorStatus());
        fp.setIsHooked(checkHookStatus());

        return fp;
    }

    private boolean checkHookStatus() {
        // 检测 Frida
        if (checkFridaPort()) return true;
        if (checkFridaLibraries()) return true;

        // 检测 Xposed
        if (checkXposedEnvironment()) return true;

        return false;
    }
}

2. 风控决策

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class EcommerceRiskEngine:
    def __init__(self):
        self.fingerprint_db = FingerprintDatabase()
        self.ml_detector = DeviceAuthenticityClassifier()
        self.behavior_analyzer = BehaviorSequenceDetector()

    def check_order_risk(self, user_id, device_fp, order_info):
        """订单风险评估"""
        risk_factors = []
        risk_score = 0

        # 1. 设备指纹检查
        device_risk = self.check_device_fingerprint(device_fp)
        if device_risk['is_suspicious']:
            risk_factors.append(device_risk)
            risk_score += 30

        # 2. 设备关联分析
        related_devices = self.fingerprint_db.find_related_devices(device_fp)
        if len(related_devices) > 10:
            risk_factors.append({
                'type': 'device_cluster',
                'message': f'Device associated with {len(related_devices)} other devices'
            })
            risk_score += 25

        # 3. 用户行为分析
        user_behavior = self.fingerprint_db.get_user_behavior(user_id)
        if self.is_bot_behavior(user_behavior):
            risk_factors.append({'type': 'bot_behavior'})
            risk_score += 35

        # 决策
        if risk_score >= 60:
            action = 'reject'
        elif risk_score >= 40:
            action = 'manual_review'
        else:
            action = 'approve'

        return {
            'action': action,
            'risk_score': risk_score,
            'risk_factors': risk_factors
        }

案例 2:金融 App 风控绕过

💡 思路一句话: 金融 App 风控更严(硬件级检测+行为分析),需要组合方案:Magisk 隐藏 root + 设备信息全量伪造 + 操作行为模拟(随机延迟、滑动轨迹)。

背景:某金融 App 使用顶象设备指纹进行风控,攻击者尝试绕过进行批量注册和薅羊毛。

App 保护措施

  1. 集成顶象 SDK 采集设备指纹
  2. SO 层加固(360 加固)
  3. 检测 Root、模拟器、Hook 框架
  4. 网络请求签名验证

分析过程

Step 1: 设备指纹 SDK 定位

1
2
3
4
5
6
7
8
9
# 反编译 APK
apktool d app.apk

# 搜索设备指纹相关代码
grep -r "getDeviceId" .
grep -r "fingerprint" .

# 找到 SDK 包名
# com.dingxiang.sdk.fingerprint

Step 2: Frida Hook 分析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Java.perform(function() {
    // Hook 顶象 SDK
    var DXFingerprint = Java.use("com.dingxiang.sdk.fingerprint.DXFingerprint");

    DXFingerprint.getDeviceId.implementation = function() {
        console.log("[*] getDeviceId() called");

        // 返回伪造设备 ID
        var fakeDeviceId = "fake_dx_device_id_" + Math.random().toString(36).substring(7);
        console.log("[*] Returning fake device ID: " + fakeDeviceId);

        return fakeDeviceId;
    };

    // Hook 采集方法
    DXFingerprint.collect.implementation = function(context) {
        console.log("[*] collect() called");

        // 修改采集数据
        var result = this.collect(context);

        // 篡改指纹数据
        modifyFingerprintData(result);

        return result;
    };
});

教训

  1. 单纯的 Hook 不够:需要完整的环境伪装
  2. 设备一致性至关重要:所有参数必须逻辑自洽
  3. 行为模拟必不可少:纯技术绕过容易被行为分析识破
  4. 成本与收益平衡:高质量绕过需要较高成本

总结

成功的绕过,本质上是一场关于"伪造一个天衣无缝的设备画像"的持久战。


相关内容

如果这篇文章对你有帮助,请我喝杯咖啡吧~
+5 支付宝支付宝
+5 微信微信