/*
  Program: virusstart 
  Program by: lockdown (www.lockeddown.net)
  Date: March 13, 2002

One technique for inserting a virus into an ELF binary is to overwrite the start
address with an address that points to the payload.  This program checks to see
if the start address is equal to the .text segment address.  If they are not
equal it then sets the start address equal to the .text segment.  This does not remove the payload from the program but should prevent it from being executed
unless the virus has some back up way to access the payload.

To scan your box do:
find / -exec ./virusstart -s {} \;
This is very slow.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <elf.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FALSE 0
#define TRUE 1

void usage(char *);
void scan_file(char *,int);

int main(int argc, char **argv)
{
  int fix;
  struct stat statb;

  if(strcmp(argv[1],"-f") && strcmp(argv[1],"-s"))
  {
    usage(argv[0]);
    return 1;
  }

  if(argc!=3)
  {
    usage(argv[0]);
    return 1;
  }

  if(!strcmp(argv[1],"-f"))
    fix = TRUE;
  if(!strcmp(argv[1],"-s"))
    fix = FALSE;

  if(stat(argv[2],&statb)==-1)
  {
    perror("stat");
    return 1;
  }

  if(S_ISREG(statb.st_mode))
  {
    scan_file(argv[2],fix);
    return 0;
  }

  return 0;
}/* main */

void scan_file(char *name,int fix)
{
  int fd,i,j;
  Elf32_Ehdr ehdr;
  Elf32_Shdr *shdr,*sections;
  Elf32_Phdr *phdr;
  Elf32_Sym *sym;
  char version[4],*sdata,*pdata,*symdata,*string_table,*symb;

  if((fd=open(name,O_RDONLY))==-1)
  {
    perror("open");
    return;
  }

  if(read(fd,&ehdr,sizeof(ehdr))<0)
  {
    perror("read");
    return;
  }

  /*is it an ELF file?*/
  sprintf(version,"%c%c%c",ehdr.e_ident[EI_MAG1],ehdr.e_ident[EI_MAG2],
          ehdr.e_ident[EI_MAG3]);
  if(strcmp(version,"ELF"))
    exit(1);
  
  /*ELF and executable?*/
  if(ehdr.e_version !=EV_CURRENT && ehdr.e_type !=ET_EXEC)
    exit(1);

  /*get shdr*/
  lseek(fd,ehdr.e_shoff,SEEK_SET);
  sdata=(void *)malloc(sizeof(*shdr) *ehdr.e_shnum);
  if(read(fd,sdata,sizeof(*shdr) *ehdr.e_shnum)<0)
  {
    perror("read");
    exit(1);
  }
  shdr=(Elf32_Shdr *)sdata;
  sections= shdr +ehdr.e_shstrndx;
  lseek(fd,sections->sh_offset,SEEK_SET);
  string_table=malloc(sections->sh_size);
  if(read(fd,string_table,sections->sh_size)<0)
  {
    perror("read");
    exit(1);
  }
  close(fd);

  for(i=0;i<ehdr.e_shnum;i++,shdr++)
  {
    if(shdr !=NULL)
    {
      if(!strcmp(".text",(string_table + shdr->sh_name)))
      {
        if(ehdr.e_entry != shdr->sh_addr)
        {
          if(!fix)
            printf("%s: is infected\n",name);
          if(fix)
          {
            printf("%s: is infected, attempting to fix\n",name);
            if((fd=open(name,O_RDWR))==-1)
            {
              perror("open");
              return;
            }

            ehdr.e_entry = shdr->sh_addr;
            if(write(fd,&ehdr,sizeof(ehdr))<0)
            {
              perror("write");
              exit(1);
            }

            close(fd);
          }
        }
      }
    }
  }

  return;
}/*scan_file*/

void usage(char *name)
{
  printf("Usage: %s <option> <name>\n",name);
  printf("\tWhere name is the name of an ELF binary file to fix.\n");
  printf("\toption is -f for fix or -s to scan only\n");
  return;
}/* usage */

