Created
December 5, 2022 16:22
-
-
Save pablogsal/9fc8d4df2fe6d6267eb92dd97e6ea1f1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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