Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ae5d3f0
prevent overrunning beyond the text segment in internal.c:original_ep
elfmaster Oct 3, 2018
b63a0d3
fixed bugs having to do with invalid symbol->st_name dereference
elfmaster Oct 4, 2018
84f399b
...
elfmaster Oct 9, 2018
1dd7b77
fixed elf_address_pointer and dw_read_location
elfmaster Oct 11, 2018
bf0053b
initial commit
Oct 12, 2018
dd30d14
implemented address to offset conversion helper functions
Oct 13, 2018
aa59757
implemented address to offset conversion helper functions
Oct 13, 2018
02db4ec
data segment injection implemented
Oct 13, 2018
8fd1a13
data segment injection implemented
Oct 13, 2018
2e0e6a8
data segment injection implemented
Oct 13, 2018
e428d3e
data segment injection implemented
Oct 13, 2018
21e30a1
data segment injection implemented
Oct 13, 2018
457060f
minor fixes
Oct 13, 2018
26b45bf
minor fixes
Oct 13, 2018
7b0eb3d
minor fixes
Oct 13, 2018
bcf6eed
minor fixes
Oct 13, 2018
2d3ec5a
implemented reverse_text_section infection
Dec 7, 2018
826ab11
minor fixes
Dec 7, 2018
2a1cc9a
minor fixes
Dec 7, 2018
23ac882
implemented interpending infection (appending at the end of code sect…
Dec 21, 2018
5f94ba7
implemented section offset re-alignment after infection
Dec 27, 2018
1de9f62
implemented section offset re-alignment after infection
Dec 27, 2018
4b5216a
implemented section offset re-alignment after infection
Dec 27, 2018
151a2f9
implemented section offset re-alignment after infection
Dec 27, 2018
c94acef
initial support for basic code injection
Jan 4, 2019
dfaf6cf
intiial code injection support (sync with master)
Jan 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# libelfmaster
## Update as of 11/17/18 -- I have a local branch with many new fixes that will be finished and committed by the end of December, been very busy.

## Secure ELF parsing library

Expand Down
7 changes: 7 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ Fix all parsing bugs in crashes. I have some more fixing and testing to go befor
the release tag of this alpha version, so this last commit is not a complete update to
the code base, but resolves quite a number of the existing issues.

## Handle SCOP (Secure code partitioning)

We must determine how functions such as elf_text_base are going to work
when there are multiple LOAD segments in SCOP linked binaries.

## Merge in Ignacios work for code injection

## 9/17/2018

Make sure that we take into account dynamic segments that exist in
Expand Down
38 changes: 21 additions & 17 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
CC=gcc
all:
gcc -O2 -g -fPIC -pie elfparse.c ../src/libelfmaster.a -o elfparse
gcc -O3 -g ldd.c ../src/libelfmaster.a -o ldd
gcc -O2 -g read_mem.c ../src/libelfmaster.a -o read_mem
gcc -O2 -g plt_dump.c ../src/libelfmaster.a -o plt_dump
gcc -O2 -g plt_dump2.c ../src/libelfmaster.a -o plt_dump2
gcc -O2 -g sections.c ../src/libelfmaster.a -o sections
gcc -O0 -ggdb symbols.c ../src/libelfmaster.a -o symbols
gcc -O2 -g eh_frame.c ../src/libelfmaster.a -o eh_frame
gcc -O2 -g checksec.c ../src/libelfmaster.a -o checksec
gcc -O2 -g -fPIC -pie test.c -o test_pie
gcc -O2 -no-pie test.c ../src/libelfmaster.a -o test
gcc -O2 -fPIC -pie test.c ../src/libelfmaster.a -o test2_pie
gcc -O2 -no-pie test.c ../src/libelfmaster.a -o test_stripped
gcc -O2 -no-pie -m32 test.c ../src/libelfmaster.a -o test32bit
gcc -O2 -fPIC -pie -m32 test.c ../src/libelfmaster.a -o test32bit_pie
gcc -no-pie -m32 test.c -o test32_stripped
gcc ../utils/stripx.c -o stripx
$(CC) -O0 -g -fPIC -pie elfparse.c ../src/libelfmaster.a -o elfparse
$(CC) -O0 -g ldd.c ../src/libelfmaster.a -o ldd
$(CC) -O2 -g read_mem.c ../src/libelfmaster.a -o read_mem
$(CC) -O2 -g plt_dump.c ../src/libelfmaster.a -o plt_dump
$(CC) -O2 -g plt_dump2.c ../src/libelfmaster.a -o plt_dump2
$(CC) -O2 -g sections.c ../src/libelfmaster.a -o sections
$(CC) -O0 -ggdb symbols.c ../src/libelfmaster.a -o symbols
$(CC) -O2 -g eh_frame.c ../src/libelfmaster.a -o eh_frame
$(CC) -O2 -g checksec.c ../src/libelfmaster.a -o checksec
$(CC) -O2 -g -fPIC -pie test.c -o test_pie
$(CC) -O2 -no-pie test.c ../src/libelfmaster.a -o test
$(CC) -O2 -fPIC -pie test.c ../src/libelfmaster.a -o test2_pie
$(CC) -O2 -no-pie test.c ../src/libelfmaster.a -o test_stripped
$(CC) -O2 -no-pie -m32 test.c ../src/libelfmaster.a -o test32bit
$(CC) -O2 -fPIC -pie -m32 test.c ../src/libelfmaster.a -o test32bit_pie
$(CC) -no-pie -m32 test.c -o test32_stripped
$(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) -fPIC -pie -Wl,-z,separate-code,-z,relro,-z,now test.c -o test_scop
$(CC) ../utils/stripx.c -o stripx
./stripx test_stripped
./stripx test32_stripped
clean:
Expand Down
5 changes: 4 additions & 1 deletion examples/checksec.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ int main(int argc, char **argv)
struct elf_symbol symbol;
elf_linking_type_t link_type;
bool dynamic = false, relro = false, strict_linking = false, executable_data = false,
pax = false, writable_text = false, executable_stack = false;
pax = false, writable_text = false, executable_stack = false, scop = false;
unsigned int pax_flags;
char pax_string[256] = {0};

Expand All @@ -48,6 +48,9 @@ int main(int argc, char **argv)
printf("%s\n", elf_error_msg(&error));
return -1;
}
if (elf_flags(&obj, ELF_SCOP_F) == true)
printf("SCOP (Secure code partitioning) is enabled\n");

if ((link_type = elf_linking_type(&obj)) == ELF_LINKING_UNDEF) {
printf("Object: %s is not an executable or shared library\n", argv[0]);
exit(EXIT_SUCCESS);
Expand Down
95 changes: 95 additions & 0 deletions examples/code_injection.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <sys/types.h>
#include <search.h>
#include <sys/time.h>
#include <elf.h>
#include <link.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdbool.h>
#include <search.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include "../include/libelfmaster.h"
#include "../include/internal.h"

/*
* Opens a given file and checks if it contains an ELF magic. (More checks can be implemented).
*/
int main (int argc, char **argv)
{
elfobj_t obj1;
elfobj_t obj2;
elfobj_t objdest;
elf_error_t error;
uint64_t p_address;
uint64_t p_offset;
bool res;

// http://shell-storm.org/shellcode/files/shellcode-806.php
uint8_t stub[] = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48" \
"\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05";

if (argc != 3) {
printf("Usage: %s <host> <output binary>\n", argv[0]);
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj1, ELF_LOAD_F_STRICT, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
/*
* In case the binary payload is residing in disk, we can use these functions to load
* it, as if it was an ELF file or some binary blob.
*
if (elf_has_header(argv[2], &res, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
if (res) {
if (elf_open_object(argv[2], &obj2, ELF_LOAD_F_STRICT, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
} else {
if (elf_open_stub(argv[2], &obj2, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
}
* Otherwise stubs can be also operated as byte-arrays.
*/

if (elf_init_stub(&obj2, stub, sizeof(stub), &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
if (elf_create_object(argv[2], &objdest, &obj1, obj1.size + obj2.size,
ELF_LOAD_F_STRICT, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
if (elf_inject_code(&objdest, &obj2, &p_offset, ELF_INJECT_F_POSTPEND, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
if(internal_offset_to_address(&objdest, p_offset, &p_address, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
printf("Payload written at offset: 0x%lx, address: 0x%lx\n", p_offset, p_address);

if (elf_commit_object(&objdest, objdest.size, 0, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
return 0;
}
5 changes: 5 additions & 0 deletions examples/elfparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ int main(int argc, char **argv)
struct elf_shared_object_iterator so_iter;
struct timeval tv, tv2;
unsigned int count = 0;
bool scop = false;

if (elf_open_object(argv[1], &obj, ELF_LOAD_F_FORENSICS,
&error) == false) {
Expand Down Expand Up @@ -76,6 +77,10 @@ int main(int argc, char **argv)

elf_segment_iterator_init(&obj, &p_iter);
while (elf_segment_iterator_next(&p_iter, &segment) == ELF_ITER_OK) {
if (elf_flags(&obj, ELF_SCOP_F) == true && scop == false) {
printf("SCOP enabled\n");
scop = true;
}
printf("\nAddr: %#lx\n", segment.vaddr);
printf("Filesz: %#lx\n", segment.filesz);
printf("MemSz: %#lx\n", segment.memsz);
Expand Down
81 changes: 81 additions & 0 deletions examples/objdump_libelfmaster.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* NOTE Very quick prototype does not take section header sh_align
* into consideration so it sometimes shows the wrong instructions
* on section borders. Also without some tweaking capstone won't
* show sections that have non-code, so we only get several contiguous
* sections of code disassembled
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <inttypes.h>

#include "../include/libelfmaster.h"
#include <capstone/capstone.h>

int main(int argc, char **argv)
{
csh handle;
cs_insn *insn;
size_t count;
elfobj_t obj;
elf_error_t error;
struct elf_section section;
elf_section_iterator_t s_iter;
uint64_t base_vaddr, base_offset;
size_t len;
uint8_t *ptr;
int i;

if (argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj, ELF_LOAD_F_FORENSICS, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
elf_section_iterator_init(&obj, &s_iter);
while (elf_section_iterator_next(&s_iter, &section) == ELF_ITER_OK) {
if (strcmp(section.name, ".init") == 0) {
base_vaddr = section.address;
base_offset = section.offset;
break;
}
}
len = elf_text_filesz(&obj) + elf_data_filesz(&obj);
ptr = elf_offset_pointer(&obj, base_offset);
if (ptr == NULL) {
printf("Unable to get offset: %lx\n", base_offset);
return -1;
}
if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK)
return -1;

printf("Disassembling %lu bytes\n", len - base_offset);
count = cs_disasm(handle, ptr, len - base_offset, base_vaddr, base_offset, &insn);
if (count > 0) {
size_t j;
bool checked = false;
for (j = 0; j < count; j++) {
char *sname = ".unknown";
char *symname = "sub_unknown";
struct elf_symbol symbol;

if (elf_symbol_by_value(&obj, insn[j].address, &symbol) == true)
symname = symbol.name;

if (elf_section_by_address(&obj, insn[j].address, &section) == true)
sname = section.name;

printf("%s:%s:0x%"PRIx64":\t%s\t\t%s\n", section.name, symname,
insn[j].address, insn[j].mnemonic,
insn[j].op_str);
}
cs_free(insn, count);
} else
printf("ERROR: Failed to disassemble given code!\n");
cs_close(&handle);

return 0;
}
2 changes: 1 addition & 1 deletion examples/pltgot.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ int main(int argc, char **argv)
elfobj_t obj;
elf_error_t error;
elf_pltgot_iterator_t pltgot_iter;
struct elf_pltgot pltgot;
struct elf_pltgot_entry pltgot;

if (argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
Expand Down
2 changes: 1 addition & 1 deletion examples/symbols.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ int main(int argc, char **argv)
exit(EXIT_SUCCESS);
}
if (elf_open_object(argv[1], &obj,
ELF_LOAD_F_SMART|ELF_LOAD_F_FORENSICS, &error) == false) {
ELF_LOAD_F_STRICT, &error) == false) {
fprintf(stderr, "%s\n", elf_error_msg(&error));
return -1;
}
Expand Down
4 changes: 3 additions & 1 deletion include/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,9 @@ void free_arrays(elfobj_t *);

void free_misc(elfobj_t *);

bool insane_headers(elfobj_t *);
bool insane_section_headers(elfobj_t *);

bool insane_dynamic_segment(elfobj_t *);

bool reconstruct_elf_sections(elfobj_t *, elf_error_t *);

Expand Down
Loading