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

📄 unexelf.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
2           0x60874     0x80a9874   0           0x80        0           7           0            */#include <sys/types.h>#include <stdio.h>#include <sys/stat.h>#include <memory.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <elf.h>#include <sys/mman.h>#ifndef emacs#define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1)#elseextern void fatal(char *, ...);#endif/* Get the address of a particular section or program header entry, * accounting for the size of the entries. */#define OLD_SECTION_H(n) \     (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))#define NEW_SECTION_H(n) \     (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))#define OLD_PROGRAM_H(n) \     (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))#define NEW_PROGRAM_H(n) \     (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))typedef unsigned char byte;/* **************************************************************** * unexec * * driving logic. * * In ELF, this works by replacing the old .bss section with a new * .data section, and inserting an empty .bss immediately afterwards. * */voidunexec (new_name, old_name, data_start, bss_start, entry_address)     char *new_name, *old_name;     unsigned data_start, bss_start, entry_address;{  extern unsigned int bss_end;  int new_file, old_file, new_file_size;  /* Pointers to the base of the image of the two files. */  caddr_t old_base, new_base;  /* Pointers to the file, program and section headers for the old and new   * files.   */  Elf32_Ehdr *old_file_h, *new_file_h;  Elf32_Phdr *old_program_h, *new_program_h;  Elf32_Shdr *old_section_h, *new_section_h;  /* Point to the section name table in the old file */  char *old_section_names;  Elf32_Addr old_bss_addr, new_bss_addr;  Elf32_Word old_bss_size, new_data2_size;  Elf32_Off  new_data2_offset;  Elf32_Addr new_data2_addr;  int n, old_bss_index, old_data_index, new_data2_index;  struct stat stat_buf;  /* Open the old file & map it into the address space. */  old_file = open (old_name, O_RDONLY);  if (old_file < 0)    fatal ("Can't open %s for reading: errno %d\n", old_name, errno);  if (fstat (old_file, &stat_buf) == -1)    fatal ("Can't fstat(%s): errno %d\n", old_name, errno);  old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);  if (old_base == (caddr_t) -1)    fatal ("Can't mmap(%s): errno %d\n", old_name, errno);#ifdef DEBUG  fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size,	   old_base);#endif  /* Get pointers to headers & section names */  old_file_h = (Elf32_Ehdr *) old_base;  old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);  old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);  old_section_names = (char *) old_base    + OLD_SECTION_H(old_file_h->e_shstrndx).sh_offset;  /* Find the old .bss section.  Figure out parameters of the new   * data2 and bss sections.   */  for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)    {#ifdef DEBUG      fprintf (stderr, "Looking for .bss - found %s\n",	       old_section_names + OLD_SECTION_H(old_bss_index).sh_name);#endif      if (!strcmp (old_section_names + OLD_SECTION_H(old_bss_index).sh_name,		   ".bss"))	break;    }  if (old_bss_index == old_file_h->e_shnum)    fatal ("Can't find .bss in %s.\n", old_name, 0);  old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;  old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;#if defined(emacs) || !defined(DEBUG)  bss_end = (unsigned int) sbrk (0);  new_bss_addr = (Elf32_Addr) bss_end;#else  new_bss_addr = old_bss_addr + old_bss_size + 0x1234;#endif  new_data2_addr = old_bss_addr;  new_data2_size = new_bss_addr - old_bss_addr;  new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;#ifdef DEBUG  fprintf (stderr, "old_bss_index %d\n", old_bss_index);  fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);  fprintf (stderr, "old_bss_size %x\n", old_bss_size);  fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);  fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);  fprintf (stderr, "new_data2_size %x\n", new_data2_size);  fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);#endif  if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)    fatal (".bss shrank when undumping???\n", 0, 0);  /* Set the output file to the right size and mmap(2) it.  Set   * pointers to various interesting objects.  stat_buf still has   * old_file data.   */  new_file = open (new_name, O_RDWR | O_CREAT, 0666);  if (new_file < 0)    fatal ("Can't creat(%s): errno %d\n", new_name, errno);  new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;  if (ftruncate (new_file, new_file_size))    fatal ("Can't ftruncate(%s): errno %d\n", new_name, errno);  new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,		   new_file, 0);  if (new_base == (caddr_t) -1)    fatal ("Can't mmap(%s): errno %d\n", new_name, errno);  new_file_h = (Elf32_Ehdr *) new_base;  new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);  new_section_h = (Elf32_Shdr *)    ((byte *) new_base + old_file_h->e_shoff + new_data2_size);  /* Make our new file, program and section headers as copies of the   * originals.   */  memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);  memcpy (new_program_h, old_program_h,	  old_file_h->e_phnum * old_file_h->e_phentsize);  memcpy (new_section_h, old_section_h,	  old_file_h->e_shnum * old_file_h->e_shentsize);  /* Fix up file header.  We'll add one section.  Section header is   * further away now.   */  new_file_h->e_shoff += new_data2_size;  new_file_h->e_shnum += 1;#ifdef DEBUG  fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);  fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);  fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);  fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);#endif  /* Fix up a new program header.  Extend the writable data segment so   * that the bss area is covered too. Find that segment by looking   * for a segment that ends just before the .bss area.  Make sure   * that no segments are above the new .data2.  Put a loop at the end   * to adjust the offset and address of any segment that is above   * data2, just in case we decide to allow this later.   */  for (n = new_file_h->e_phnum - 1; n >= 0; n--)    {      if (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz > old_bss_addr)	fatal ("Program segment above .bss in %s\n", old_name, 0);      if (NEW_PROGRAM_H(n).p_type == PT_LOAD	  && (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz	      == old_bss_addr))	break;    }  if (n < 0)    fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);  NEW_PROGRAM_H(n).p_filesz += new_data2_size;  NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz;#if 0 /* Maybe allow section after data2 - does this ever happen? */  for (n = new_file_h->e_phnum - 1; n >= 0; n--)    {      if (NEW_PROGRAM_H(n).p_vaddr	  && NEW_PROGRAM_H(n).p_vaddr >= new_data2_addr)	NEW_PROGRAM_H(n).p_vaddr += new_data2_size - old_bss_size;      if (NEW_PROGRAM_H(n).p_offset >= new_data2_offset)	NEW_PROGRAM_H(n).p_offset += new_data2_size;    }#endif  /* Fix up section headers based on new .data2 section.  Any section   * whose offset or virtual address is after the new .data2 section   * gets its value adjusted.  .bss size becomes zero and new address   * is set.  data2 section header gets added by copying the existing   * .data header and modifying the offset, address and size.   */  for (n = 1; n < new_file_h->e_shnum; n++)    {      if (NEW_SECTION_H(n).sh_offset >= new_data2_offset)	NEW_SECTION_H(n).sh_offset += new_data2_size;      if (NEW_SECTION_H(n).sh_addr	  && NEW_SECTION_H(n).sh_addr >= new_data2_addr)	NEW_SECTION_H(n).sh_addr += new_data2_size - old_bss_size;    }  new_data2_index = old_file_h->e_shnum;  for (old_data_index = 1; old_data_index < old_file_h->e_shnum;       old_data_index++)    if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,		 ".data"))      break;  if (old_data_index == old_file_h->e_shnum)    fatal ("Can't find .data in %s.\n", old_name, 0);  memcpy (&NEW_SECTION_H(new_data2_index), &OLD_SECTION_H(old_data_index),	  new_file_h->e_shentsize);  NEW_SECTION_H(new_data2_index).sh_addr = new_data2_addr;  NEW_SECTION_H(new_data2_index).sh_offset = new_data2_offset;  NEW_SECTION_H(new_data2_index).sh_size = new_data2_size;  NEW_SECTION_H(old_bss_index).sh_size = 0;  NEW_SECTION_H(old_bss_index).sh_addr = new_data2_addr + new_data2_size;  /* Write out the sections. .data and .data1 (and data2, called   * ".data" in the strings table) get copied from the current process   * instead of the old file.   */  for (n = new_file_h->e_shnum - 1; n; n--)    {      caddr_t src;      if (NEW_SECTION_H(n).sh_type == SHT_NULL	  || NEW_SECTION_H(n).sh_type == SHT_NOBITS)	continue;      if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data")	  || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),		      ".data1"))	src = (caddr_t) NEW_SECTION_H(n).sh_addr;      else	src = old_base + OLD_SECTION_H(n).sh_offset;      memcpy (NEW_SECTION_H(n).sh_offset + new_base, src,	      NEW_SECTION_H(n).sh_size);    }  /* Close the files and make the new file executable */  if (close (old_file))    fatal ("Can't close(%s): errno %d\n", old_name, errno);  if (close (new_file))    fatal ("Can't close(%s): errno %d\n", new_name, errno);  if (stat (new_name, &stat_buf) == -1)    fatal ("Can't stat(%s): errno %d\n", new_name, errno);  n = umask (777);  umask (n);  stat_buf.st_mode |= 0111 & ~n;  if (chmod (new_name, stat_buf.st_mode) == -1)    fatal ("Can't chmod(%s): errno %d\n", new_name, errno);}

⌨️ 快捷键说明

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