示例#1
0
enum translation_state action_fail(struct translate *ts) {
  PRINT_DEBUG_FUNCTION_START("action_fail(*ts=%p)", ts);
  PRINT_DEBUG("unhandled opcode encountered in TU at %p: %s", ts->cur_instr,
              MEMDUMP(ts->cur_instr, ts->next_instr - ts->cur_instr));
  PRINT_DEBUG("giving up!!!");
  PRINT_DEBUG_FUNCTION_END("-> FAIL");

#ifdef DEBUG
  llprintf("\n\n\t\tERROR: unhandled opcode encountered in TU at %p: %s\n\n",
              ts->cur_instr, MEMDUMP(ts->cur_instr,
              ts->next_instr - ts->cur_instr));
  llprintf("\nERROR: unhandled opcode encountered in TU at %p\nBtOX will "
           "exit now!\n", ts->cur_instr);
#endif

#if defined(SLEEP_ON_FAIL)
  llprintf("Something bad happened (action_fail). Attach a debugger!\n");
  while (1);
#endif
  fbt_suicide(255);
  return CLOSE;
}
示例#2
0
/**
 * callback function used to scan the loaded libraries.
 * This function is used as callback in dl_iterate_phdr(3) to scan the sections
 * of a loaded library. The first object in the list (position 0) is always the
 * executable, the second one the vdso ("linux-gate.so"). The third object is
 * the secuBT library (libfastbt.so), because it is loaded with LD_PRELOAD.
 * The sections of the objects are added to the red-black-tree structure along
 * with information on whether they contain executable code.
 * For more info on dl_iterate_phdr, refer to its man page.
 * @param info the object info structure provided by dl_iterate_phdr
 * @param size the size of the info structure
 * @param data is used to store the position in the list of libraries
 */
static int fbt_memprotect_callback(struct dl_phdr_info *info, size_t size, void *data)
{
  int libnum = *((int*) data);

  // look for the base address in the library list
  int i = 0;
  for (i = 0; i < lib_list_size; i++) {
    if (library_list[i].base_addr ==  (void*) info->dlpi_addr) {
      // the entry for this object already exists in the library list
      (*((int*)data))++;
      return 0;
    }
  }

  if (lib_list_size >= lib_list_capacity) {
    fbt_lib_list_resize();
  }

  const char *name = info->dlpi_name;

  /*
   * The first entry of dl_iterate_phdr's table of objects is always the
   * executable itself, the second the vdso. They don't have dlpi_addr as
   * base address and have to be caught in order not to be processed again.
   * After these two come the shared objects.
   */
  if (0 == libnum) {
    if (lib_list_size > 0) {
      // executable has to be already be in the library list
      (*((int*)data))++;
      return 0;
    }
    name = "/proc/self/exe";
  } else if (1 == libnum) {
    if (lib_list_size > 1) {
      // vdso has to be already be in the library list
      (*((int*)data))++;
      return 0;
    }
    // ugly hack to get correct address of vdso
    void *vdso_addr = (void*) (info->dlpi_addr + info->dlpi_phdr[0].p_vaddr);

    // add vdso to library table
    library_list[lib_list_size].base_addr = vdso_addr;
    library_list[lib_list_size].length = PAGESIZE;
    library_list[lib_list_size].name = (char *) malloc(5 * sizeof(char));
    fbt_strcpy(library_list[lib_list_size].name, "vdso");
    lib_list_size++;


    // add vdso entry to sections tree
    struct mem_info *info = malloc(sizeof(*info));
    info->node.addr_begin = vdso_addr;
    info->node.addr_end = vdso_addr + PAGESIZE;
    info->sec_name = library_list[lib_list_size - 1].name;
    info->lib_index = lib_list_size - 1;
    info->flags = INFO_RFLAG | INFO_XFLAG;
    sections_root = rb_insert(sections_root, (struct rb_node*) info);

    (*((int*)data))++;
    return 0;
  }
  if (0 == fbt_strcmp(name, "")) {
    (*((int*)data))++;
    return 0;
  }

  // entry in library list
  library_list[lib_list_size].base_addr = (void*) info->dlpi_addr;
  library_list[lib_list_size].length = 0;
  library_list[lib_list_size].name = malloc(fbt_strnlen(name,0) + 1);
  fbt_strcpy(library_list[lib_list_size].name, name);
  lib_list_size++;

  /*
   * we map library file again to memory, because when it is loaded for execution, the
   * section header table and the section containing the section name strings are not
   * mapped to memory.
   */
  // open the file -> file descriptor
  int fd;
  fbt_open(name, O_RDONLY, 0x0, fd);
  if (-1 == fd) {
    fbt_suicide_str("fbt_iterate_sections: could not open executable or library file (memprotect_callback: fbt_mem_protection.c)\n");
    (*((int*)data))++;
    return -1;
  }

  // find out file size
  int filesize;
  fbt_lseek(fd, 0, SEEK_END, filesize);
  if (-1 == filesize) {
    fbt_suicide_str("fbt_iterate_sections: fstat failure, cannot find out file size (memprotect_callback: fbt_mem_protection.c)\n");
    return -1;
  }

  void *libmap;
  fbt_mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0, libmap);
  if ((void*) -1 == libmap) {
    fbt_suicide_str("fbt_iterate-sections: failed to map library to memory (memprotect_callback: fbt_mem_protection.c)\n");
    //fbt_close(fd);
    //(*((int*)data))++;
    return -1;
  }

  Elf32_Ehdr *header = (Elf32_Ehdr*) libmap;

  fbt_sym *dyn_symtab = NULL;
  char *dyn_strtab = NULL;
  void *dyn_hashtab = NULL;

  if (0 != header->e_shnum) {
    Elf32_Shdr *section_header = (Elf32_Shdr*) (libmap + header->e_shoff);

    int i = 0;
    for (i = 0; i < header->e_shnum; i++) {
      // only consider sections loaded into memory on execution
      if ((section_header[i].sh_size < 1)
          || ((section_header[i].sh_flags & SHF_ALLOC) == 0)) {
        continue;
      }

      // fill in node information
      struct mem_info *meminfo = (struct mem_info*) malloc(sizeof(*meminfo));
      meminfo->node.addr_begin = (void*) (info->dlpi_addr
                                          + section_header[i].sh_addr);
      meminfo->node.addr_end = meminfo->node.addr_begin
                               + section_header[i].sh_size;

      // calculate start address of the executable
      if ((0 == libnum) && (0 == library_list[0].base_addr)) {
        library_list[0].base_addr = (void*) ((long) (meminfo->node.addr_begin)
                                             & ~(PAGESIZE - 1));
      }

      // section name
      if (SHN_UNDEF != header->e_shstrndx) {
        const char *name_entry = (const char*) (libmap
                                                + section_header[header->e_shstrndx].sh_offset
                                                + section_header[i].sh_name);
        char *section_name = (char*) malloc(fbt_strnlen(name_entry,0) + 1);
        fbt_strcpy(section_name, name_entry);
        meminfo->sec_name = section_name;
      } else {
        const char* no_sec_names = "no section name string table";
        char *section_name = (char*) malloc(fbt_strnlen(no_sec_names,0) + 1);
        fbt_strcpy(section_name, no_sec_names);
        meminfo->sec_name = section_name;
      }
      // update size in memory
      int length = meminfo->node.addr_end
                   - library_list[lib_list_size - 1].base_addr;
      if (length > library_list[lib_list_size - 1].length) {
        library_list[lib_list_size - 1].length = length;
      }

      // flags
      meminfo->flags = INFO_RFLAG;
      if (section_header[i].sh_flags & SHF_WRITE) {
        meminfo->flags |= INFO_WFLAG;
      }
      if (2 == libnum) {
        // memory in libfastbt.so
        meminfo->flags |= INFO_BTFLAG;
      }
      if (section_header[i].sh_flags & SHF_EXECINSTR) {
        // only mark as executable if we memory not part of libfastbt.so
        meminfo->flags |= INFO_XFLAG;
      }
      meminfo->lib_index = lib_list_size - 1;

      sections_root = rb_insert(sections_root, (struct rb_node*) meminfo);

      // code for symbol checking
      if (SHT_DYNSYM == section_header[i].sh_type) {
        // we have found the dynamic linking symbol table
        dyn_symtab = (Elf32_Sym*) (info->dlpi_addr
                                   + section_header[i].sh_addr);
        if (2 == libnum) {
          // handling libfastbt.so, need to know # of symbols
          fbt_dyn_nsyms = section_header[i].sh_size / sizeof(fbt_sym);
        }
      }
      if (!fbt_strcmp(".dynstr", meminfo->sec_name)) {
        // string table for dynamic linking symbols
        dyn_strtab = (char*) (info->dlpi_addr
                              + section_header[i].sh_addr);
      }
      if (!fbt_strcmp(".gnu.hash", meminfo->sec_name)) {
        // hash table for dynamic linking symbols (gnu format)
        dyn_hashtab = (void*) (info->dlpi_addr
                               + section_header[i].sh_addr);
      }
    }
  }
#ifdef SECU_NX_PROG
  // only executed on first run of this function
  if (0 == libnum) {
    /*
     * Set the memory of the program non-executable. We cannot do the same
     * to the libraries, as we need some of them ourselves.
     */
    /* TODO: protect libs as well and compile bt statically */
    int ret;
    fbt_mprotect(library_list[0].base_addr, library_list[0].length,
                 PROT_READ | PROT_WRITE, ret);
  }
#endif
#ifdef SECU_DETECT_SYMBOL_COLLISIONS
  if ((NULL != dyn_symtab) && (NULL != dyn_strtab) && (NULL != dyn_hashtab)) {
    if (0 == libnum) {
      /*
       * we can not check the symbols of the executable now because
       * libfastbt.so has not been processed yet.
       */
      exe_dyn_symtab = dyn_symtab;
      exe_dyn_strtab = dyn_strtab;
      exe_dyn_hashtab = dyn_hashtab;
    } else if (2 == libnum) {
      fbt_dyn_symtab = dyn_symtab;
      fbt_dyn_strtab = dyn_strtab;

      // ok, now we can check the symbols of the executable
      if (!fbt_check_sym_collision(exe_dyn_symtab, exe_dyn_strtab,
                                   exe_dyn_hashtab)) {
        // symbol collision detected
        fbt_suicide_str("Symbol collision in the executable (memprotect_callback: fbt_mem_protection.c)\n");
      }
    } else if (libnum > 2) {
      // check symbols of library
      if (!fbt_check_sym_collision(dyn_symtab, dyn_strtab, dyn_hashtab)) {
        llprintf("Symbol collision in %s\n", name);
        ffflush();
        fbt_suicide();
      }
    }
  } else {
    // one of the tables was not found!
    llprintf("Fatal: One of the tables for symbol checking was not found!\n"
             "symtab: %p, strtab: %p, hashtab: %p\n", dyn_symtab,
             dyn_strtab, dyn_hashtab);
    ffflush();
    fbt_suicide();
  }
#endif
  (void)dyn_hashtab;
  (void)dyn_strtab;
  (void)dyn_symtab;

  int ret;
  fbt_munmap(libmap, filesize, ret);
  fbt_close(fd, ret);
  (*((int*)data))++;
  return 0;
}