Skip to content

Commit

Permalink
Added in initial draft of access write (modification) functions for s…
Browse files Browse the repository at this point in the history
…ections, segments, and symbols, added several basic accessor functions and elf_symbol_count, elf_section_count, elf_segment_count, elf_dynsym_count
  • Loading branch information
elfmaster committed Jan 31, 2019
1 parent c6bf3f5 commit db830d9
Show file tree
Hide file tree
Showing 11 changed files with 792 additions and 16 deletions.
79 changes: 79 additions & 0 deletions ELF_STRUCTURE_MODIFICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# General notes

```
It is often times desirable to modify certain ELF structures, however it breaks the
convention of using the API when directly accessing the ELF structures from the
elfobj_t struct which is meant to be an opaque type. There are now accessor write
functions for modifying symbol table entries, segment entries, and section header
entries. In the future we will add the ability to modify other areas as well such
as notes, dynamic segment, etc.
Do not confuse these accessors with the soon to be merged instrumentation API functions
that @ulexec is adding into the code base, however these accessor write functions are
used by that code on the back-end.
Please see examples/modify_*.c and read the comments as well for caveats. This will show
you how to modify a given structure. Often times structures will be modified by index,
and within the body of an iterator function. Every iterator has an index value; make sure
to use index - 1, when modifying an object. For example:
/*
* Demonstrates how to modify symbol entries in .symtab
* where we modify each entries st_value member.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <sys/types.h>
#include <search.h>
#include <sys/time.h>
#include <string.h>
#include "../include/libelfmaster.h"
int main(int argc, char **argv)
{
elfobj_t obj;
elf_error_t error;
elf_dynsym_iterator_t ds_iter;
elf_symtab_iterator_t sm_iter;
struct elf_symbol symbol;
if (argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj,
ELF_LOAD_F_STRICT|ELF_LOAD_F_MODIFY, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
elf_symtab_iterator_init(&obj, &sm_iter);
while (elf_symtab_iterator_next(&sm_iter, &symbol) == ELF_ITER_OK) {
struct elf_symbol sym;
printf("%s: %#lx-%#lx\n",symbol.name, symbol.value,
symbol.value + symbol.size);
memcpy(&sym, &symbol, sizeof(struct elf_symbol));
sym.value = 0xdeadbeef;
if (elf_symtab_modify(&obj, sm_iter.index - 1, &sym, &error) == false) {
printf("Failed to modify elf symbol table: %s\n", elf_error_msg(&error));
}
}
/*
* NOTE: commit cannot be called inside of the symtab iterator,
* this will be fixed in the future.
*/
elf_symtab_commit(&obj);
elf_symtab_iterator_init(&obj, &sm_iter);
printf("After .symtab modification\n");
while (elf_symtab_iterator_next(&sm_iter, &symbol) == ELF_ITER_OK) {
struct elf_symbol sym;
printf("%s: %#lx-%#lx\n",symbol.name, symbol.value,
symbol.value + symbol.size);
}
elf_close_object(&obj);
}
4 changes: 4 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ all:
$(CC) -m32 -fPIC -pie -Wl,-z,separate-code test.c -o test32_scop
$(CC) -g objdump_libelfmaster.c ../src/libelfmaster.a -o objdump_elfmaster -lcapstone
$(CC) -Wl,-z,separate-code,-z,relro,-z,now test.c -o test_scop
$(CC) -O2 -g modify_symbol.c ../src/libelfmaster.a -o modify_symbol
$(CC) -O2 -g modify_dynsym.c ../src/libelfmaster.a -o modify_dynsym
$(CC) -O2 -g modify_segment.c ../src/libelfmaster.a -o modify_segment
$(CC) -O2 -g modify_section.c ../src/libelfmaster.a -o modify_section
$(CC) ../utils/stripx.c -o stripx
$(CC) -N -static -m32 -nostdlib nostdlib.c -o nostdlib32
$(CC) -N -static -nostdlib nostdlib.c -o nostdlib
Expand Down
39 changes: 39 additions & 0 deletions examples/elf_text.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <sys/types.h>
#include <search.h>
#include <sys/time.h>
#include "../include/libelfmaster.h"

int main(int argc, char **argv)
{
elfobj_t obj;
elf_error_t error;
struct elf_symbol symbol;

if (argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj,
ELF_LOAD_F_SMART|ELF_LOAD_F_FORENSICS, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
if (elf_flags(&obj, ELF_SCOP_F) == true) {
printf("SCOP binary\n");
}
ssize_t ret = elf_scop_text_filesz(&obj);
printf("ret: %zu\n", ret);
if (ret > 0) {
printf("Total text segment size: %lu bytes\n", ret);
}
printf("elf_executable_text_base: %lx offset: %lx\n", elf_executable_text_base(&obj),
elf_executable_text_offset(&obj));
elf_close_object(&obj);
}
62 changes: 62 additions & 0 deletions examples/modify_dynsym.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Demonstrates how to modify every dynamic symbol table
* entry, where we modify the st_value's.
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <sys/types.h>
#include <search.h>
#include <sys/time.h>
#include <string.h>
#include "../include/libelfmaster.h"

int main(int argc, char **argv)
{
elfobj_t obj;
elf_error_t error;
elf_dynsym_iterator_t ds_iter;
struct elf_symbol symbol;

if (argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj,
ELF_LOAD_F_STRICT|ELF_LOAD_F_MODIFY, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
elf_dynsym_iterator_init(&obj, &ds_iter);
while (elf_dynsym_iterator_next(&ds_iter, &symbol) == ELF_ITER_OK) {
struct elf_symbol sym;

printf("%s: %#lx-%#lx\n",symbol.name, symbol.value,
symbol.value + symbol.size);
memcpy(&sym, &symbol, sizeof(struct elf_symbol));
sym.value = 0xdeadbeef;
/*
* NOTE use iter.index - 1, otherwise it will not hit sym[0] and will
* eventually go out of bounds.
*/
if (elf_dynsym_modify(&obj, ds_iter.index - 1, &sym, &error) == false) {
printf("Failed to modify elf symbol table: %s\n", elf_error_msg(&error));
}
}
/*
* commit cannot be called inside of the dynsym iterator
*/
elf_dynsym_commit(&obj);
elf_dynsym_iterator_init(&obj, &ds_iter);
printf("After .dynsym modification\n");
while (elf_dynsym_iterator_next(&ds_iter, &symbol) == ELF_ITER_OK) {
struct elf_symbol sym;

printf("%s: %#lx-%#lx\n",symbol.name, symbol.value,
symbol.value + symbol.size);
}

elf_close_object(&obj);
}
57 changes: 57 additions & 0 deletions examples/modify_section.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Demonstrates how we modify the sh_addr of the .text section
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <sys/types.h>
#include <search.h>
#include <sys/time.h>
#include <string.h>
#include "../include/libelfmaster.h"

int main(int argc, char **argv)
{
elfobj_t obj;
elf_error_t error;
elf_section_iterator_t iter;
struct elf_section section;

if (argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj,
ELF_LOAD_F_STRICT|ELF_LOAD_F_MODIFY, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
elf_section_iterator_init(&obj, &iter);
while (elf_section_iterator_next(&iter, &section) == ELF_ITER_OK) {
struct elf_section s;

if (strcmp(section.name, ".text") == 0) {
memcpy(&s, &section, sizeof(s));
s.address = 0xdeadbeef;
elf_section_modify(&obj, iter.index - 1, &s, &error);
}
}
/*
* Technically you can call this within the elf_section_iterator_next body,
* whereas with elf_symtab/dynsym_modify you cannot. But it makes sense to
* call it after you have made all of your changes because it is fairly
* expensive.
*/
elf_section_commit(&obj);
elf_section_by_name(&obj, ".text", &section);
printf("text section modified to sh_addr of: %#lx\n", section.address);
/*
* Unlike elf_section/elf_symtab/elf_dynsym modify, with elf_segment
* modify we do not need to call a commit function because we don't
* keep any internal abstract representations of the segments.
* so we can just close the object and be done.
*/
elf_close_object(&obj);
}
48 changes: 48 additions & 0 deletions examples/modify_segment.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Demonstrates how we modify the p_vaddr of the first LOAD segment.
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <sys/types.h>
#include <search.h>
#include <sys/time.h>
#include <string.h>
#include "../include/libelfmaster.h"

int main(int argc, char **argv)
{
elfobj_t obj;
elf_error_t error;
elf_segment_iterator_t iter;
struct elf_segment segment;

if (argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj,
ELF_LOAD_F_STRICT|ELF_LOAD_F_MODIFY, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
elf_segment_iterator_init(&obj, &iter);
while (elf_segment_iterator_next(&iter, &segment) == ELF_ITER_OK) {
if (segment.offset == 0) {
struct elf_segment s;

memcpy(&s, &segment, sizeof(segment));
s.vaddr = 0xdeadbeef;
elf_segment_modify(&obj, iter.index - 1, &s, &error);
}
}
/*
* Unlike elf_section/elf_symtab/elf_dynsym modify, with elf_segment
* modify we do not need to call a commit function because we don't
* keep any internal abstract representations of the segments.
* so we can just close the object and be done.
*/
elf_close_object(&obj);
}
62 changes: 62 additions & 0 deletions examples/modify_symbol.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Demonstrates how to modify symbol entries in .symtab
* where we modify each entries st_value member.
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <sys/types.h>
#include <search.h>
#include <sys/time.h>
#include <string.h>
#include "../include/libelfmaster.h"

int main(int argc, char **argv)
{
elfobj_t obj;
elf_error_t error;
elf_dynsym_iterator_t ds_iter;
elf_symtab_iterator_t sm_iter;
struct elf_symbol symbol;

if (argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj,
ELF_LOAD_F_STRICT|ELF_LOAD_F_MODIFY, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
elf_symtab_iterator_init(&obj, &sm_iter);
while (elf_symtab_iterator_next(&sm_iter, &symbol) == ELF_ITER_OK) {
struct elf_symbol sym;

printf("%s: %#lx-%#lx\n",symbol.name, symbol.value,
symbol.value + symbol.size);
memcpy(&sym, &symbol, sizeof(struct elf_symbol));
sym.value = 0xdeadbeef;
if (elf_symtab_modify(&obj, sm_iter.index - 1, &sym, &error) == false) {
printf("Failed to modify elf symbol table: %s\n", elf_error_msg(&error));
}
}
/*
* NOTE: commit cannot be called inside of the symtab iterator,
* this will be fixed in the future, however it will incurr overhead
* to call after each symbol modification, but it may at times be
* desirable in some edge cases.
*/
elf_symtab_commit(&obj);
elf_symtab_iterator_init(&obj, &sm_iter);
printf("After .symtab modification\n");
while (elf_symtab_iterator_next(&sm_iter, &symbol) == ELF_ITER_OK) {
struct elf_symbol sym;

printf("%s: %#lx-%#lx\n",symbol.name, symbol.value,
symbol.value + symbol.size);
}

elf_close_object(&obj);
}
Loading

0 comments on commit db830d9

Please sign in to comment.