主机序列号的修改方法与原理
-
-
- [🔍 什么是主机序列号?](#🔍 什么是主机序列号?)
- [❓ 为什么要修改序列号?](#❓ 为什么要修改序列号?)
- 方法一:拦截read函数(用户空间修改)
- 方法二:内核驱动修改
- 方法三:VirtualBox虚拟机修改
- 方法对比表
- 结论
-
🔍 什么是主机序列号?
主机序列号是设备出厂时烧录的唯一硬件ID,如同设备的"DNA身份证"。它被存储在:
- BIOS/UEFI芯片(主板固件)
- 设备树文件 (Linux系统路径:
/proc/device-tree/serial-number
) - DMI信息表 (系统硬件数据库,路径:
/sys/class/dmi/id/
)
ℹ️ 通过终端命令
sudo dmidecode -s system-serial-number
可查看
❓ 为什么要修改序列号?
场景 | 说明 | 典型案例 |
---|---|---|
隐私保护 | 防止设备被远程追踪 | 公共WiFi环境下避免设备指纹识别 |
软件授权 | 绕过硬件绑定限制 | 试用期结束后重装专业软件 |
测试兼容性 | 模拟不同硬件环境 | 验证软件在不同设备型号的表现 |
安全研究 | 隐藏真实设备指纹 | 渗透测试中规避目标系统检测 |
⚠️ 法律提示:修改序列号可能违反用户协议,仅限合法用途(如隐私保护、授权测试)
方法一:拦截read函数(用户空间修改)
原理图解
尝试读取序列号 匹配目标路径 不匹配 应用程序 系统调用read 拦截器检测路径 返回自定义序列号 返回真实数据
技术核心 :通过 LD_PRELOAD
环境变量优先加载自定义库,劫持系统读取函数
⚖️ 优缺点
- ✅ 优点:无需重启、不修改硬件
- ❌ 局限 :
- 仅对动态链接程序有效
- 终端关闭后失效
dmidecode
等命令仍读取原始值
操作步骤详解
c
# 创建隔离的工作目录
rm serial_modifier_0 -rf
mkdir serial_modifier_0
cd serial_modifier_0
# 生成动态拦截库源码
cat > api_hook.c <<-'EOF'
#include <unistd.h>
#include <time.h>
#define __USE_GNU
#include <dlfcn.h>
#include <sys/syscall.h>
#include <signal.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <set>
#include <map>
#define WITH_PTHREADS
#ifdef WITH_PTHREADS
#include <pthread.h>
static pthread_mutex_t mutex;
# define LOCK (pthread_mutex_lock(&mutex));
# define UNLOCK (pthread_mutex_unlock(&mutex));
#else
# define LOCK ;
# define UNLOCK ;
#endif
// 添加文件操作拦截相关函数指针
typedef int (*open_ptr)(const char *, int, ...);
typedef ssize_t (*read_ptr)(int, void *, size_t);
typedef int (*close_ptr)(int);
static open_ptr real_open = NULL;
static open_ptr real_open64 = NULL;
static read_ptr real_read = NULL;
static close_ptr real_close = NULL;
// 目标文件路径和固定返回值
static const char *target_path = "/proc/device-tree/serial-number";
static const char *fixed_serial = "2538922146412";
static const size_t fixed_serial_len = 13; // 不包括结尾的空字符
// 定义要替换的序列号
static const char *src_serial="f2a15610d4af3adf";
static const size_t src_serial_len = 16; // 不包括结尾的空字符
// 用于跟踪目标文件的文件描述符和读取位置
static std::set<int> target_fds;
static std::map<int, size_t> read_positions;
static void init()
{
// 初始化文件操作函数指针
if(NULL==real_read)
{
real_read = (read_ptr)dlsym(RTLD_NEXT, "read");
}
}
// 拦截read函数
extern "C" ssize_t read(int fd, void *buf, size_t count)
{
LOCK
init();
ssize_t ret = real_read(fd, buf, count);
// 检测到目标序列号时进行替换
if((ret>=src_serial_len) && strcmp((char*)buf, src_serial) == 0 )
{
memcpy(buf, fixed_serial, fixed_serial_len);
UNLOCK
return fixed_serial_len; // 返回修改后的长度
}
UNLOCK
return ret;
}
EOF
# 编译共享库(关键步骤解释)
unset LD_PRELOAD
g++ -fPIC -shared -o libapi_hook.so api_hook.c -ldl
# -fPIC: 生成位置无关代码
# -shared: 创建共享库
# -ldl: 链接动态加载库
# 测试原始序列号
cat /proc/device-tree/serial-number
# 加载拦截库(核心步骤)
export LD_PRELOAD=/opt/libapi_hook.so
# 验证修改效果
cat /proc/device-tree/serial-number
# 恢复原始环境
unset LD_PRELOAD
方法二:内核驱动修改
原理图解
用户 内核 DMI内存 硬件 加载驱动模块 禁用写保护 允许修改 写入新序列号 数据更新成功 重启后失效 用户 内核 DMI内存 硬件
⚠️ 风险提示
- 操作不当可能导致系统崩溃
- 需关闭Secure Boot等安全机制
- 部分品牌机有硬件写保护
原理与适用场景
原理 :通过内核模块直接修改DMI内存区域,覆盖原始序列号
适用场景:
- 需绕过硬件级检测的场景
操作步骤详解
bash
# 创建驱动开发目录
rm serial_modifier_1 -rf
mkdir serial_modifier_1
cd serial_modifier_1
# 生成内核模块源码
cat > serial_modifier.c <<-'EOF'
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/dmi.h>
#include <linux/string.h>
#include <linux/io.h>
#include <asm/pgtable.h>
#define NEW_SERIAL "2538922146412" // 替换为您需要的新序列号
static char *original_serial_addr = NULL;
static char *saved_serial = NULL;
static unsigned long original_cr0;
// 使内存页可写
static void make_rw(unsigned long address)
{
unsigned int level;
pte_t *pte = lookup_address(address, &level);
if (pte) {
set_pte(pte, pte_mkwrite(*pte));
}
}
// 使内存页只读
static void make_ro(unsigned long address)
{
unsigned int level;
pte_t *pte = lookup_address(address, &level);
if (pte) {
set_pte(pte, pte_clear_flags(*pte, _PAGE_RW));
}
}
void rewrite(int key)
{
const char *dmi_serial = dmi_get_system_info(key);
if (!dmi_serial) {
printk(KERN_ERR "Failed to get DMI serial number\n");
return;
}
printk(KERN_INFO "Original DMI serial: %s\n", dmi_serial);
// 保存原始地址和值
char * original_serial_addr = (char *)dmi_serial;
// 禁用写保护
original_cr0 = read_cr0();
write_cr0(original_cr0 & ~X86_CR0_WP);
// 使目标内存可写
make_rw((unsigned long)original_serial_addr);
// 写入新序列号
strncpy(original_serial_addr, NEW_SERIAL, strlen(NEW_SERIAL));
original_serial_addr[strlen(NEW_SERIAL)] = '\0'; // 确保终止
// 恢复写保护
make_ro((unsigned long)original_serial_addr);
write_cr0(original_cr0);
printk(KERN_INFO "DMI serial changed to: %s\n", NEW_SERIAL);
}
static int __init serial_mod_init(void)
{
rewrite(DMI_PRODUCT_SERIAL);
rewrite(DMI_CHASSIS_SERIAL);
return 0;
}
static void __exit serial_mod_exit(void)
{
}
module_init(serial_mod_init);
module_exit(serial_mod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("DMI Serial Number Override");
EOF
# 创建Makefile
cat > Makefile <<-'EOF'
obj-m += serial_modifier.o
EXTRA_CFLAGS += -fno-pie
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
EOF
# 编译内核模块
make
# 查看原始DMI信息
cat /sys/class/dmi/id/chassis_serial
cat /sys/class/dmi/id/product_serial
# 加载内核模块(需要root权限)
insmod serial_modifier.ko
# 验证修改结果
cat /sys/class/dmi/id/chassis_serial
cat /sys/class/dmi/id/product_serial
方法三:VirtualBox虚拟机修改
适用场景
适合测试多设备兼容性,无需触碰物理硬件
原理与适用场景
原理 :通过虚拟机管理程序修改虚拟硬件信息
适用场景:
- 虚拟机环境中的序列号修改
- 快速切换不同硬件配置
- 无需内核操作的解决方案
操作步骤详解
powershell
# 删除现有序列号配置
.\VBoxManage.exe setextradata "ubuntu" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemSerial" --delete
# 设置新序列号
.\VBoxManage.exe setextradata "ubuntu" "VBoxInternal/Devices/pcbios/0/Config/DmiSystemSerial" "string:2538922146412"
# 验证配置
.\VBoxManage.exe getextradata "ubuntu" enumerate
参数说明
参数 | 说明 |
---|---|
setextradata |
修改虚拟机额外配置 |
pcbios/0/Config/ |
BIOS配置路径 |
DmiSystemSerial |
DMI系统序列号键名 |
string:2538922146412 |
新序列号值 |
方法对比表
特性 | 用户拦截 | 内核修改 | 虚拟机配置 |
---|---|---|---|
修改层级 | 用户层 | 内核层 | 虚拟化层 |
持久性 | 临时 | 重启失效 | 配置持久 |
难度 | ⭐☆☆☆☆ | ⭐⭐⭐⭐☆ | ⭐⭐☆☆☆ |
风险 | 低 | 高 | 零 |
生效范围 | 部分应用 | 全系统 | 单虚拟机 |
结论
- 临时测试 → 选择方法一(
LD_PRELOAD
) - 物理机永久修改 → 方法二(需专业技术)
- 虚拟机环境 → 方法三(最安全便捷)
- 检测工具差异 :
cat /proc/...
→ 方法一、二有效dmidecode
→ 仅方法三有效
道德提醒:技术应用需遵守法律法规,禁止用于软件盗版或欺诈行为