aboutsummaryrefslogblamecommitdiff
path: root/frida_mode/src/lib/lib.c
blob: 48d2ea2ac2ac9685e8e347317e57417aee2e1a8b (plain) (tree)
1
2
3
4
5
6
7
8
9






                       
 
                          
 
                  
                   
 

                                           


                            


                                                   


                            



                                 

























                                                                 

                                             




                                                               




                                                                              


                                         






                                  












                                                  




                                                    
 

                                                                  
 



                                                  


                                 







                                             


                                                                           


                                                                  

                                                                             

                                                                     













                                                          
                                                             


                               
                                                                        
 
                        

                                                                   
                                                                       








                                      



                       



                                                            

                                                       





                                     
                                                    





                                  
                                                     



                    

      
#ifndef __APPLE__
  #include <elf.h>
  #include <fcntl.h>
  #include <limits.h>
  #include <stdio.h>
  #include <sys/mman.h>
  #include <unistd.h>

  #include "frida-gumjs.h"

  #include "lib.h"
  #include "util.h"

  #if defined(__arm__) || defined(__i386__)
    #define ELFCLASS ELFCLASS32
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Phdr Elf_Phdr;
typedef Elf32_Shdr Elf_Shdr;
typedef Elf32_Addr Elf_Addr;
  #elif defined(__aarch64__) || defined(__x86_64__)
    #define ELFCLASS ELFCLASS64
typedef Elf64_Ehdr Elf_Ehdr;
typedef Elf64_Phdr Elf_Phdr;
typedef Elf64_Shdr Elf_Shdr;
typedef Elf64_Addr Elf_Addr;
  #else
    #error "Unsupported platform"
  #endif

typedef struct {

  gchar      name[PATH_MAX + 1];
  gchar      path[PATH_MAX + 1];
  GumAddress base_address;
  gsize      size;

} lib_details_t;

static guint64 text_base = 0;
static guint64 text_limit = 0;

static gboolean lib_find_exe(const GumModuleDetails *details,
                             gpointer                user_data) {

  lib_details_t *lib_details = (lib_details_t *)user_data;

  memcpy(lib_details->name, details->name, PATH_MAX);
  memcpy(lib_details->path, details->path, PATH_MAX);
  lib_details->base_address = details->range->base_address;
  lib_details->size = details->range->size;
  return FALSE;

}

static void lib_validate_hdr(Elf_Ehdr *hdr) {

  if (hdr->e_ident[0] != ELFMAG0) FFATAL("Invalid e_ident[0]");
  if (hdr->e_ident[1] != ELFMAG1) FFATAL("Invalid e_ident[1]");
  if (hdr->e_ident[2] != ELFMAG2) FFATAL("Invalid e_ident[2]");
  if (hdr->e_ident[3] != ELFMAG3) FFATAL("Invalid e_ident[3]");
  if (hdr->e_ident[4] != ELFCLASS) FFATAL("Invalid class");

}

static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {

  Elf_Phdr *phdr;
  gboolean  found_preferred_base = FALSE;
  Elf_Addr  preferred_base;
  Elf_Shdr *shdr;
  Elf_Shdr *shstrtab;
  char *    shstr;
  char *    section_name;
  Elf_Shdr *curr;
  char      text_name[] = ".text";

  phdr = (Elf_Phdr *)((char *)hdr + hdr->e_phoff);
  for (size_t i = 0; i < hdr->e_phnum; i++) {

    if (phdr[i].p_type == PT_LOAD) {

      preferred_base = phdr[i].p_vaddr;
      found_preferred_base = TRUE;
      break;

    }

  }

  if (!found_preferred_base) {

    FFATAL("Failed to find preferred load address");

  }

  FOKF("Image preferred load address 0x%016" G_GSIZE_MODIFIER "x",
       preferred_base);

  shdr = (Elf_Shdr *)((char *)hdr + hdr->e_shoff);
  shstrtab = &shdr[hdr->e_shstrndx];
  shstr = (char *)hdr + shstrtab->sh_offset;

  FOKF("shdr: %p", shdr);
  FOKF("shstrtab: %p", shstrtab);
  FOKF("shstr: %p", shstr);

  for (size_t i = 0; i < hdr->e_shnum; i++) {

    curr = &shdr[i];

    if (curr->sh_name == 0) continue;

    section_name = &shstr[curr->sh_name];
    FOKF("Section: %2" G_GSIZE_MODIFIER "u - base: 0x%016" G_GSIZE_MODIFIER
         "X size: 0x%016" G_GSIZE_MODIFIER "X %s",
         i, curr->sh_addr, curr->sh_size, section_name);
    if (memcmp(section_name, text_name, sizeof(text_name)) == 0 &&
        text_base == 0) {

      text_base = lib_details->base_address + curr->sh_addr - preferred_base;
      text_limit = text_base + curr->sh_size;
      FOKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base);
      FOKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit);

    }

  }

}

static void lib_get_text_section(lib_details_t *details) {

  int       fd = -1;
  off_t     len;
  Elf_Ehdr *hdr;

  fd = open(details->path, O_RDONLY);
  if (fd < 0) { FFATAL("Failed to open %s", details->path); }

  len = lseek(fd, 0, SEEK_END);

  if (len == (off_t)-1) { FFATAL("Failed to lseek %s", details->path); }

  FOKF("len: %ld", len);

  hdr = (Elf_Ehdr *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
  if (hdr == MAP_FAILED) { FFATAL("Failed to map %s", details->path); }

  lib_validate_hdr(hdr);
  lib_read_text_section(details, hdr);

  munmap(hdr, len);
  close(fd);

}

void lib_config(void) {

}

void lib_init(void) {

  lib_details_t lib_details;
  gum_process_enumerate_modules(lib_find_exe, &lib_details);
  FOKF("Executable: 0x%016" G_GINT64_MODIFIER "x - %s",
       lib_details.base_address, lib_details.path);
  lib_get_text_section(&lib_details);

}

guint64 lib_get_text_base(void) {

  if (text_base == 0) FFATAL("Lib not initialized");
  return text_base;

}

guint64 lib_get_text_limit(void) {

  if (text_limit == 0) FFATAL("Lib not initialized");
  return text_limit;

}

#endif