Esempio n. 1
0
static void r_binfmt_macho64_load_segment(r_binfmt_s *bin, r_binfmt_macho64_segment_s *s) {
    r_binfmt_segment_s *seg;
    u64 vaddr, filesz, fileoff;
    u32 flags, initprot;

    seg = r_binfmt_segment_new();

    R_BINFMT_GET_INT(vaddr, s->vm_addr, bin->endian);
    R_BINFMT_GET_INT(filesz, s->file_size, bin->endian);
    R_BINFMT_GET_INT(fileoff, s->file_off, bin->endian);
    R_BINFMT_GET_INT(initprot, s->init_prot, bin->endian);

    flags = 0;
    if(initprot & R_BINFMT_MACHO_PROT_R)
        flags |= R_BINFMT_SEGMENT_FLAG_PROT_R;
    if(initprot & R_BINFMT_MACHO_PROT_W)
        flags |= R_BINFMT_SEGMENT_FLAG_PROT_W;
    if(initprot & R_BINFMT_MACHO_PROT_X)
        flags |= R_BINFMT_SEGMENT_FLAG_PROT_X;

    seg->addr = vaddr;
    seg->length = filesz;
    seg->start = bin->mapped + fileoff;
    seg->flags = flags;

    r_utils_list_push(&bin->segments, seg);
}
Esempio n. 2
0
void r_binfmt_elf32_load_symtab(r_binfmt_s *bin, r_binfmt_elf32_s *elf) {
  Elf32_Word i, sh_type, sh_size;
  Elf32_Off sh_offset;

  R_BINFMT_ASSERT(elf->ehdr != NULL);
  R_BINFMT_ASSERT(elf->shdr != NULL);


  for(i = 0; i < elf->shdr_entries; i++) {
    R_BINFMT_GET_INT(sh_type, elf->shdr[i].sh_type, bin->endian);

    if(sh_type == SHT_SYMTAB) {
      R_BINFMT_GET_INT(sh_size, elf->shdr[i].sh_size, bin->endian);

      R_BINFMT_ASSERT((sh_size % sizeof(Elf32_Sym)) == 0);

      R_BINFMT_GET_INT(sh_offset, elf->shdr[i].sh_offset, bin->endian);

      R_BINFMT_ASSERT(r_utils_add32(NULL, sh_offset, sh_size) &&
                      sh_offset + sh_size <= bin->mapped_size);

      elf->symtab = (Elf32_Sym*)(bin->mapped + sh_offset);
      elf->symtab_entries = sh_size / sizeof(Elf32_Sym);
      break;
    }
  }
}
Esempio n. 3
0
/* Fill bin->sections structure */
static void r_binfmt_elf64_load_sections(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  r_binfmt_section_s *section;
  Elf64_Word sh_name, sh_size, i;
  Elf64_Off strndx_off;
  Elf64_Addr sh_addr;
  Elf64_Half e_shstrndx;

  R_BINFMT_ASSERT(elf->ehdr != NULL);
  R_BINFMT_ASSERT(elf->shdr != NULL);

  R_BINFMT_GET_INT(e_shstrndx, elf->ehdr->e_shstrndx, bin->endian);
  R_BINFMT_ASSERT(e_shstrndx < elf->shdr_entries);

  R_BINFMT_GET_INT(strndx_off, elf->shdr[e_shstrndx].sh_offset, bin->endian);

  for(i = 0; i < elf->shdr_entries; i++) {
    R_BINFMT_GET_INT(sh_addr, elf->shdr[i].sh_addr, bin->endian);
    R_BINFMT_GET_INT(sh_size, elf->shdr[i].sh_size, bin->endian);
    R_BINFMT_GET_INT(sh_name, elf->shdr[i].sh_name, bin->endian);

    R_BINFMT_ASSERT(r_utils_add64(NULL, strndx_off, sh_name) &&
                    strndx_off + sh_name <= bin->mapped_size);

    section = r_binfmt_section_new();
    section->addr = sh_addr;
    section->size = sh_size;
    section->name = r_binfmt_elf64_get_name(bin, elf, e_shstrndx, sh_name);

    r_utils_linklist_push(&bin->sections, section);
  }
}
Esempio n. 4
0
void r_binfmt_elf64_load_dyntab(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  Elf64_Word i, sh_type, sh_size;
  Elf64_Off sh_offset;

  R_BINFMT_ASSERT(elf->ehdr != NULL);
  R_BINFMT_ASSERT(elf->shdr != NULL);

  for(i = 0; i < elf->shdr_entries; i++) {
    R_BINFMT_GET_INT(sh_type, elf->shdr[i].sh_type, bin->endian);

    if(sh_type == SHT_DYNAMIC) {
      R_BINFMT_GET_INT(sh_size, elf->shdr[i].sh_size, bin->endian);

      R_BINFMT_ASSERT((sh_size % sizeof(Elf64_Dyn)) == 0);

      R_BINFMT_GET_INT(sh_offset, elf->shdr[i].sh_offset, bin->endian);

      R_BINFMT_ASSERT(r_utils_add64(NULL, sh_offset, sh_size) &&
                      sh_offset + sh_size <= bin->mapped_size);

      elf->dyntab = (Elf64_Dyn*)(bin->mapped + sh_offset);
      elf->dyntab_entries = sh_size / sizeof(Elf64_Dyn);
      break;
    }
  }
}
Esempio n. 5
0
Elf64_Phdr* r_binfmt_elf64_get_segment(r_binfmt_s *bin, r_binfmt_elf64_s *elf, Elf64_Word type, Elf64_Word flags) {
  Elf64_Word i, p_type, p_flags;

  R_BINFMT_ASSERT_RET(NULL, elf->ehdr != NULL);
  R_BINFMT_ASSERT_RET(NULL, elf->phdr != NULL);

  for(i = 0; i < elf->phdr_entries; i++) {
    R_BINFMT_GET_INT(p_type, elf->phdr[i].p_type, bin->endian);
    R_BINFMT_GET_INT(p_flags, elf->phdr[i].p_flags, bin->endian);
    if(p_type == type && p_flags & flags)
      return &elf->phdr[i];
  }
  return NULL;
}
Esempio n. 6
0
static const char* r_binfmt_elf64_get_name(r_binfmt_s *bin, r_binfmt_elf64_s *elf, Elf64_Half section_id, Elf64_Word name) {
  Elf64_Off sh_offset;
  Elf64_Word sh_size;

  R_BINFMT_GET_INT(sh_offset, elf->shdr[section_id].sh_offset, bin->endian);
  R_BINFMT_GET_INT(sh_size, elf->shdr[section_id].sh_size, bin->endian);

  R_BINFMT_ASSERT_RET("", r_utils_add64(NULL, sh_offset, sh_size) &&
                      sh_offset + sh_size <= bin->mapped_size);

  R_BINFMT_ASSERT_RET("", name < sh_size);

  return (const char*)(bin->mapped + sh_offset + name);
}
Esempio n. 7
0
void r_binfmt_elf64_load_shdr(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  Elf64_Off e_shoff;
  Elf64_Half e_shnum;

  R_BINFMT_ASSERT(elf->ehdr != NULL);

  R_BINFMT_GET_INT(e_shoff, elf->ehdr->e_shoff, bin->endian);
  R_BINFMT_ASSERT(e_shoff < bin->mapped_size);

  R_BINFMT_GET_INT(e_shnum, elf->ehdr->e_shnum, bin->endian);

  R_BINFMT_ASSERT(r_utils_add64(NULL, e_shnum*sizeof(Elf64_Shdr), e_shoff) &&
                  e_shnum*sizeof(Elf64_Shdr) + e_shoff <= bin->mapped_size);

  elf->shdr = (Elf64_Shdr*)(bin->mapped + e_shoff);
  elf->shdr_entries = e_shnum;
}
Esempio n. 8
0
/* Get entry point */
static addr_t r_binfmt_elf64_getentry(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  Elf64_Addr e_entry;

  R_BINFMT_ASSERT_RET(0, elf->ehdr != NULL);

  R_BINFMT_GET_INT(e_entry, elf->ehdr->e_entry, bin->endian);
  return e_entry;
}
Esempio n. 9
0
/* Check evil or malformed files */
static int r_binfmt_macho64_check(r_binfmt_s *bin) {
    r_binfmt_macho64_header_s *hdr;
    r_binfmt_macho_cmd_s *cmd;
    u32 tmp, i, cmd_num, cmd_size, off, type;

    /* Already checked in r_binfmt_machoXX_is(),
       but if the check is removed in the future, the
       r_binfmt_machoXX_check() function must handle this case */
    if(bin->mapped_size < sizeof(*hdr))
        return 0;

    hdr = (r_binfmt_macho64_header_s*)(bin->mapped);

    R_BINFMT_GET_INT(cmd_num, hdr->h_cmd_num, bin->endian);

    /* Check each command */
    off = 0;
    for(i = 0; i < cmd_num; i++) {

        /* Check if off+sizeof(*hdr)+sizeof(*cmd) isn't greater than
           bin->mapped_size */
        if(!r_utils_add32(&tmp, sizeof(*hdr)+sizeof(*cmd), off))
            return 0;
        if(bin->mapped_size < tmp)
            return 0;

        cmd = (r_binfmt_macho_cmd_s*)(bin->mapped + off + sizeof(*hdr));

        /* Now check command */
        R_BINFMT_GET_INT(type, cmd->type, bin->endian);
        if(type == R_BINFMT_MACHO_CMD_TYPE_SEGMENT64) {
            if(!r_binfmt_macho64_check_segment(bin, (r_binfmt_macho64_segment_s*)cmd))
                return 0;
        }

        R_BINFMT_GET_INT(cmd_size, cmd->size, bin->endian);
        if(!cmd_size)
            return 0;
        if(!r_utils_add32(&off, off, cmd_size))
            return 0;
    }

    return 1;
}
Esempio n. 10
0
static void r_binfmt_macho32_load_segments(r_binfmt_s *bin) {
  r_binfmt_macho32_header_s *hdr;
  r_binfmt_macho_cmd_s *cmd;
  u32 i, cmd_num, type, off;

  hdr = (r_binfmt_macho32_header_s*)(bin->mapped);
  R_BINFMT_GET_INT(cmd_num, hdr->h_cmd_num, bin->endian);


  off = 0;
  for(i = 0; i < cmd_num; i++) {
    cmd = (r_binfmt_macho_cmd_s*)(bin->mapped + sizeof(r_binfmt_macho32_header_s) + off);
    R_BINFMT_GET_INT(type, cmd->type, bin->endian);
    if(type == R_BINFMT_MACHO_CMD_TYPE_SEGMENT) {
      r_binfmt_macho32_load_segment(bin, (r_binfmt_macho32_segment_s*)cmd);
    }

    off += r_binfmt_get_int32((byte_t*)&cmd->size, bin->endian);
  }
}
Esempio n. 11
0
static r_binfmt_arch_e r_binfmt_macho64_getarch(r_binfmt_s *bin) {
    r_binfmt_macho64_header_s *hdr;
    u32 cpu;

    hdr = (r_binfmt_macho64_header_s*)(bin->mapped);
    R_BINFMT_GET_INT(cpu, hdr->h_cpu, bin->endian);

    if(cpu == R_BINFMT_MACHO_CPU_X86_64)
        return R_BINFMT_ARCH_X86_64;

    return R_BINFMT_ARCH_UNDEF;
}
Esempio n. 12
0
static r_binfmt_pie_e r_binfmt_elf64_check_pie(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  Elf64_Half e_type;

  R_BINFMT_ASSERT_RET(R_BINFMT_PIE_UNKNOWN, elf->ehdr != NULL);

  R_BINFMT_GET_INT(e_type, elf->ehdr->e_type, bin->endian);

  if(e_type != ET_DYN)
    return R_BINFMT_PIE_DISABLED;

  return R_BINFMT_PIE_ENABLED;
}
Esempio n. 13
0
/* Check the fields of the machoXX segment */
static int r_binfmt_macho64_check_segment(r_binfmt_s *bin, r_binfmt_macho64_segment_s *seg) {
    u64 filesz, fileoff;
    u64 off;

    off = ((byte_t*)seg) - bin->mapped;

    if(!r_utils_add64(NULL, off, sizeof(*seg)))
        return 0;

    if(bin->mapped_size < off + sizeof(*seg))
        return 0;

    R_BINFMT_GET_INT(filesz, seg->file_size, bin->endian);
    R_BINFMT_GET_INT(fileoff, seg->file_off, bin->endian);

    if(!r_utils_add64(&off, fileoff, filesz))
        return 0;

    if(bin->mapped_size < off)
        return 0;

    return 1;
}
Esempio n. 14
0
static void r_binfmt_elf64_load_syms_dyntab(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  r_binfmt_sym_s *sym;
  Elf64_Half sh_link, st_name;
  Elf64_Off link_off;
  Elf64_Word i, sh_type;

  R_BINFMT_ASSERT(elf->ehdr != NULL);
  R_BINFMT_ASSERT(elf->shdr != NULL);
  R_BINFMT_ASSERT(elf->dynsym != NULL);

  sh_link = 0xFFFF;
  for(i = 0; i < elf->shdr_entries; i++) {
    R_BINFMT_GET_INT(sh_type, elf->shdr[i].sh_type, bin->endian);

    if(sh_type == SHT_DYNSYM) {
      R_BINFMT_GET_INT(sh_link, elf->shdr[i].sh_link, bin->endian);
      R_BINFMT_ASSERT(sh_link < elf->shdr_entries);
      break;
    }
  }

  if(sh_link == 0xFFFF)
    return;

  for(i = 0; i < elf->dynsym_entries; i++) {
    R_BINFMT_GET_INT(st_name, elf->dynsym[i].st_name, bin->endian);
    R_BINFMT_GET_INT(link_off, elf->shdr[sh_link].sh_offset, bin->endian);

    R_BINFMT_ASSERT(r_utils_add64(NULL, link_off, st_name) &&
                    link_off + st_name <= bin->mapped_size);

    sym = r_binfmt_sym_new();
    sym->name = r_binfmt_elf64_get_name(bin, elf, sh_link, st_name);
    sym->addr = elf->dynsym[i].st_value;
    r_utils_arraylist_push(&bin->syms, sym);
  }
}
Esempio n. 15
0
static r_binfmt_rpath_e r_binfmt_elf64_check_runpath(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  Elf64_Word i;
  Elf64_Sword d_tag;

  R_BINFMT_ASSERT_RET(R_BINFMT_RUNPATH_UNKNOWN, elf->dyntab != NULL);

  for(i = 0; i < elf->dyntab_entries; i++) {
    R_BINFMT_GET_INT(d_tag, elf->dyntab[i].d_tag, bin->endian);

    if(d_tag == DT_RUNPATH)
      return R_BINFMT_RUNPATH_ENABLED;
  }

  return R_BINFMT_RUNPATH_DISABLED;
}
Esempio n. 16
0
static r_binfmt_relro_e r_binfmt_elf64_check_relro(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  Elf64_Word i;
  Elf64_Sword d_tag;

  R_BINFMT_ASSERT_RET(R_BINFMT_RELRO_UNKNOWN, elf->ehdr != NULL);
  R_BINFMT_ASSERT_RET(R_BINFMT_RELRO_UNKNOWN, elf->phdr != NULL);
  R_BINFMT_ASSERT_RET(R_BINFMT_RELRO_UNKNOWN, elf->dyntab != NULL);

  if(r_binfmt_elf64_get_segment(bin, elf, PT_GNU_RELRO, ~0) == NULL) {
    return R_BINFMT_RELRO_DISABLED;
  }

  for(i = 0; i < elf->dyntab_entries; i++) {
    R_BINFMT_GET_INT(d_tag, elf->dyntab[i].d_tag, bin->endian);

    if(d_tag == DT_BIND_NOW)
      return R_BINFMT_RELRO_FULL;
  }

  return R_BINFMT_RELRO_PARTIAL;
}
Esempio n. 17
0
/* Fill bin->segments structure */
static void r_binfmt_elf64_load_segments(r_binfmt_s *bin, r_binfmt_elf64_s *elf) {
  r_binfmt_segment_s *seg;
  Elf64_Word i, p_type, p_flags, p_filesz;
  Elf64_Off p_offset;
  Elf64_Addr p_vaddr;
  Elf64_Half e_phnum;

  R_BINFMT_ASSERT(elf->ehdr != NULL);
  R_BINFMT_ASSERT(elf->phdr != NULL);

  R_BINFMT_GET_INT(e_phnum, elf->ehdr->e_phnum, bin->endian);

  for(i = 0; i < e_phnum; i++) {
    R_BINFMT_GET_INT(p_type, elf->phdr[i].p_type, bin->endian);
    R_BINFMT_GET_INT(p_flags, elf->phdr[i].p_flags, bin->endian);
    R_BINFMT_GET_INT(p_vaddr, elf->phdr[i].p_vaddr, bin->endian);
    R_BINFMT_GET_INT(p_offset, elf->phdr[i].p_offset, bin->endian);
    R_BINFMT_GET_INT(p_filesz, elf->phdr[i].p_filesz, bin->endian);

    R_BINFMT_ASSERT(r_utils_add64(NULL, p_offset, p_filesz) &&
                    p_offset + p_filesz <= bin->mapped_size);

    if(p_type == PT_LOAD) {
      seg = r_binfmt_segment_new();

      seg->flags = 0;
      if(p_flags & PF_X)
        seg->flags |= R_BINFMT_SEGMENT_FLAG_PROT_X;
      if(p_flags & PF_R)
        seg->flags |= R_BINFMT_SEGMENT_FLAG_PROT_R;
      if(p_flags & PF_W)
        seg->flags |= R_BINFMT_SEGMENT_FLAG_PROT_W;

      seg->addr = p_vaddr;
      seg->length = p_filesz;
      seg->start = bin->mapped + p_offset;

      r_utils_linklist_push(&bin->segments, seg);
    }
  }
}