Skip to content

Instantly share code, notes, and snippets.

@pablogsal
Created December 5, 2022 16:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pablogsal/9fc8d4df2fe6d6267eb92dd97e6ea1f1 to your computer and use it in GitHub Desktop.
Save pablogsal/9fc8d4df2fe6d6267eb92dd97e6ea1f1 to your computer and use it in GitHub Desktop.
#include <elf.h>
#include <fcntl.h>
#include <link.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <elf.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// Translates the given address into an offset within the specified core file.
// Returns the offset on success, or -1 if the address is not contained in any
// segment.
long translate_address(int fd, Elf64_Ehdr *ehdr, unsigned long addr) {
// Find the segment containing the address.
Elf64_Phdr phdr;
lseek(fd, ehdr->e_phoff, SEEK_SET);
while (read(fd, &phdr, sizeof(phdr)) == sizeof(phdr)) {
if (phdr.p_type == PT_LOAD && addr >= phdr.p_vaddr &&
addr < phdr.p_vaddr + phdr.p_memsz) {
// Found the segment containing the address.
return addr - phdr.p_vaddr + phdr.p_offset;
}
}
return -1;
}
void print_dt_debug(struct r_debug *dt_debug) {
printf("DT_DEBUG entry:\n");
printf(" d_tag: %llu\n", (unsigned long long)dt_debug->r_map);
}
int main(int argc, char *argv[]) {
// Open the core file.
int fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("failed to open core file");
return 1;
}
// Read the ELF header from the core file.
Elf64_Ehdr ehdr;
ssize_t n = read(fd, &ehdr, sizeof(ehdr));
if (n < 0) {
perror("failed to read ELF header");
return 1;
}
// Check if the core file is in ELF format.
if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3) {
fprintf(stderr, "not an ELF file\n");
return 1;
}
unsigned long addr;
// Find the NOTE section containing the auxiliary vector.
Elf64_Phdr phdr;
lseek(fd, ehdr.e_phoff, SEEK_SET);
while (read(fd, &phdr, sizeof(phdr)) == sizeof(phdr)) {
if (phdr.p_type == PT_NOTE) {
// Found the NOTE section. Read its contents.
char *buf = malloc(phdr.p_filesz);
if (!buf) {
perror("failed to allocate buffer for NOTE section");
return 1;
}
lseek(fd, phdr.p_offset, SEEK_SET);
if (read(fd, buf, phdr.p_filesz) != phdr.p_filesz) {
perror("failed to read NOTE section");
return 1;
}
// Iterate over the notes in the NOTE section.
Elf64_Nhdr *nhdr = (Elf64_Nhdr *)buf;
char *name = buf + sizeof(Elf64_Nhdr);
char *desc = buf + sizeof(Elf64_Nhdr) + ((nhdr->n_namesz + 3) & ~3);
while ((char *)nhdr < buf + phdr.p_filesz) {
// Check if this is the auxiliary vector note.
if (nhdr->n_type == NT_AUXV && !strcmp(name, "CORE")) {
// Found the auxiliary vector note. Print the AT_PHDR entry.
Elf64_auxv_t *auxv = (Elf64_auxv_t *)desc;
while ((char *)auxv < desc + nhdr->n_descsz) {
if (auxv->a_type == AT_PHDR) {
// Found the AT_PHDR entry. Print its value.
printf("AT_PHDR: 0x%lx\n", auxv->a_un.a_val);
addr = auxv->a_un.a_val;
break;
}
auxv++;
}
}
// Advance to the next note.
nhdr = (Elf64_Nhdr *)(desc + ((nhdr->n_descsz + 3) & ~3));
name = (char *)nhdr + sizeof(Elf64_Nhdr);
desc = name + ((nhdr->n_namesz + 3) & ~3);
}
}
}
Elf64_Phdr phdr2;
long offset = translate_address(fd, &ehdr, addr);
lseek(fd, offset, SEEK_SET);
while (read(fd, &phdr2, sizeof(phdr2)) == sizeof(phdr2)) {
if (phdr2.p_type == PT_DYNAMIC) {
// Found the dynamic segment.
break;
}
}
if (phdr2.p_type != PT_DYNAMIC) {
fprintf(stderr, "no dynamic segment found\n");
return 1;
}
// Translate the address of the dynamic segment into an offset within the ELF
// file.
offset = translate_address(fd, &ehdr, phdr2.p_vaddr);
lseek(fd, offset, SEEK_SET);
Elf64_Dyn dt_debug;
while (read(fd, &dt_debug, sizeof(Elf64_Dyn)) == sizeof(Elf64_Dyn)) {
if (dt_debug.d_tag == DT_DEBUG) {
offset = translate_address(fd, &ehdr, dt_debug.d_un.d_ptr);
lseek(fd, offset, SEEK_SET);
struct r_debug debug;
read(fd, &debug, sizeof(debug));
void* the_lmap_addr = debug.r_map;
while (the_lmap_addr != NULL) {
offset = translate_address(fd, &ehdr, the_lmap_addr);
lseek(fd, offset, SEEK_SET);
struct link_map lmap;
read(fd, &lmap, sizeof(lmap));
offset = translate_address(fd, &ehdr, lmap.l_name);
lseek(fd, offset, SEEK_SET);
char buff[100] = {0};
int i = 0;
while(1) {
read(fd, (buff+i), 1);
if(buff[i] == 0) break;
i++;
}
printf("The thing is: %s\n", buff);
the_lmap_addr = lmap.l_next;
}
break;
}
}
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment