I'm trying to use libelf to edit some things in ELF binaries, but so far I'm unable to even write the binary out without corrupting it. This sample:
#include <libelf.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
#include <gelf.h>
int main() {
elf_version(EV_CURRENT);
int fd = open("elftest", O_RDWR, 0);
assert(fd >= 0);
Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL);
assert(elf != NULL);
assert(elf_kind(elf) == ELF_K_ELF);
assert(elf_update(elf, ELF_C_WRITE) != -1);
elf_end(elf);
close(fd);
}
which should just read in elftest and write it back out unchanged instead converts a working C hello world into a program that segfaults immediately (according to gdb, even before main is called).
The first discrepancy I noticed with readelf -h was that it moved the start of section headers back somewhat, and also reports that
readelf: Warning: the .dynamic section is not contained within the dynamic segment
What is causing libelf to alter the executable even when nothing is actually changed?
which should just read in elftest and write it back out unchanged instead converts a working C hello world into a program that segfaults immediately
This sure looks like a bug in libelf.
Adding this line immediately after elf_open() fixes your program:
Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL);
elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT); // add this
but I don't think it should be necessary.
P.S. I know this is just an example, but putting functional parts of your program inside assert() is a really bad idea. Doing this:
assert(elf_update(elf, ELF_C_WRITE) != -1);
will make you sorry sooner or later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With