static int has_dt_debug(Elf *elf, GElf_Ehdr *ehdr) { int i; for (i = 0; i < ehdr->e_phnum; i++) { GElf_Phdr phdr; GElf_Shdr shdr; Elf_Scn *scn; Elf_Data *data; unsigned int j; if (gelf_getphdr(elf, i, &phdr) == NULL) continue; if (phdr.p_type != PT_DYNAMIC) continue; scn = gelf_offscn(elf, phdr.p_offset); if (gelf_getshdr(scn, &shdr) == NULL) continue; if (shdr.sh_type != SHT_DYNAMIC) continue; if ((data = elf_getdata(scn, NULL)) == NULL) continue; for (j = 0; j < shdr.sh_size / gelf_fsize(elf, ELF_T_DYN, 1, EV_CURRENT); j++) { GElf_Dyn dyn; if (gelf_getdyn(data, j, &dyn)) { if (dyn.d_tag == DT_DEBUG) return 1; } } } return 0; }
// Extract the strings associated with the provided `DynamicTag` // from the DYNAMIC section of the ELF binary. Try<std::vector<std::string>> GetDynamicStrings(DynamicTag tag) const { if (sections.count(SectionType::DYNAMIC) == 0) { return Error("No DYNAMIC sections found in ELF"); } if (sections.count(SectionType::DYNAMIC) != 1) { return Error("Multiple DYNAMIC sections found in ELF"); } Elf_Scn* dynamic_section = sections.at(SectionType::DYNAMIC)[0]; // Walk through the entries in the dynamic section and look for // entries with the provided tag. These entries contain offsets to // strings in the dynamic section's string table. Consequently, we // also have to look for an entry containing a pointer to the // dynamic section's string table so we can resolve the strings // associated with the provided tag later on. Elf_Data* dynamic_data = elf_getdata(dynamic_section, NULL); if (dynamic_data == NULL) { return Error("elf_getdata() failed: " + stringify(elf_errmsg(-1))); } Option<uintptr_t> strtab_pointer = None(); std::vector<uintptr_t> strtab_offsets; for (size_t i = 0; i < dynamic_data->d_size / sizeof(GElf_Dyn); i++) { GElf_Dyn entry; if (gelf_getdyn(dynamic_data, i, &entry) == NULL) { return Error("gelf_getdyn() failed: " + stringify(elf_errmsg(-1))); } if ((DynamicTag)entry.d_tag == DynamicTag::STRTAB) { strtab_pointer = entry.d_un.d_ptr; } if ((DynamicTag)entry.d_tag == tag) { strtab_offsets.push_back(entry.d_un.d_ptr); } } if (strtab_offsets.empty()) { return std::vector<std::string>(); } if (strtab_pointer.isNone()) { return Error("Failed to find string table"); } // Get a reference to the actual string table so we can index into it. Elf_Scn* string_table_section = gelf_offscn(elf, strtab_pointer.get()); if (string_table_section == NULL) { return Error("gelf_offscn() failed: " + stringify(elf_errmsg(-1))); } size_t strtab_index = elf_ndxscn(string_table_section); if (strtab_index == SHN_UNDEF) { return Error("elf_ndxscn() failed: " + stringify(elf_errmsg(-1))); } // Find the strings in the string table from their offsets and return them. std::vector<std::string> strings; foreach (uintptr_t offset, strtab_offsets) { char* string = elf_strptr(elf, strtab_index, offset); if (string == NULL) { return Error("elf_strptr() failed: " + stringify(elf_errmsg(-1))); } strings.push_back(string); }
int hook_pltgot(char *exename, unsigned long offset) { int fd; int ret = -1; Elf *elf; GElf_Ehdr ehdr; Elf_Scn *sec; GElf_Shdr shdr; Elf_Data *data; size_t shstr_idx; size_t i; bool found = false; pr_dbg2("opening executable image: %s\n", exename); fd = open(exename, O_RDONLY); if (fd < 0) return -1; elf_version(EV_CURRENT); elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); if (gelf_getehdr(elf, &ehdr) == NULL) goto elf_error; if (elf_getshdrstrndx(elf, &shstr_idx) < 0) goto elf_error; for (i = 0; i < ehdr.e_phnum; i++) { GElf_Phdr phdr; if (gelf_getphdr(elf, i, &phdr) == NULL) goto elf_error; if (phdr.p_type == PT_LOAD && !found) { offset -= phdr.p_vaddr; found = true; } if (phdr.p_type != PT_DYNAMIC) continue; sec = gelf_offscn(elf, phdr.p_offset); if (!sec || gelf_getshdr(sec, &shdr) == NULL) continue; data = elf_getdata(sec, NULL); if (data == NULL) goto elf_error; if (find_got(data, shdr.sh_size / shdr.sh_entsize, offset) < 0) goto elf_error; } ret = 0; out: elf_end(elf); close(fd); return ret; elf_error: pr_dbg("%s\n", elf_errmsg(elf_errno())); goto out; }