Skip to content

Commit

Permalink
Added a new ELF linking type for statically linked PIE binaries
Browse files Browse the repository at this point in the history
  • Loading branch information
elfmaster committed Mar 27, 2020
1 parent 85e949c commit 90d3f49
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 3 deletions.
4 changes: 2 additions & 2 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ all:
$(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) -O2 -g check_static_pie.c ../src/libelfmaster.a -o check_static_pie
$(CC) -O2 -g scount.c ../src/libelfmaster.a -o scount
$(CC) -O2 -g data_base.c ../src/libelfmaster.a -o data_base
$(CC) ../utils/stripx.c -o stripx
$(CC) -N -static -m32 -nostdlib nostdlib.c -o nostdlib32
$(CC) -N -static -nostdlib nostdlib.c -o nostdlib
Expand All @@ -36,4 +36,4 @@ all:
./stripx test_stripped
./stripx test32_stripped
clean:
rm elfparse ldd plt_dump plt_dump2 sections eh_frame test test2 test32bit_pie test_pie test_stripped test32bit stripx symbols checksec test32_stripped test_scop_binary elf_text nostdlib nostdlib32 test_scop test32_scop
rm elfparse ldd plt_dump plt_dump2 sections eh_frame test test2 test32bit_pie check_static_pie test_pie test_stripped test32bit stripx symbols checksec test32_stripped test_scop_binary elf_text nostdlib nostdlib32 test_scop test32_scop
34 changes: 34 additions & 0 deletions examples/check_static_pie.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Prints the dynamic symbol names with the corresponding PLT address
* Same as plt_dump2, but uses the plt iterator.
*/

#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;

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;
}
if (elf_linking_type(&obj) == ELF_LINKING_STATIC_PIE) {
printf("Executable is a PIE statically linked executable\n");
} else {
printf("Executable is not a static PIE linked executable\n");
}
return 0;
}
5 changes: 5 additions & 0 deletions include/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,9 @@ char * ldd_parse_line(struct elf_shared_object_iterator *);
*/
bool verify_so_is_toplevel(const char *, elfobj_t *);

/*
* See if a binaries linking is static PIE
*/
bool check_static_pie(elfobj_t *);

#endif // _LIBELFMASTER_INTERNAL_H_
1 change: 1 addition & 0 deletions include/libelfmaster.h
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@ elf_strtab(elfobj_t *obj)
typedef enum elf_linking_type {
ELF_LINKING_DYNAMIC,
ELF_LINKING_STATIC,
ELF_LINKING_STATIC_PIE,
ELF_LINKING_UNDEF /* Means its neither, such as an ET_REL or ET_CORE */
} elf_linking_type_t;

Expand Down
55 changes: 55 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,61 @@
static char *
ldso_strdup(struct elf_shared_object_iterator *, const char *);

bool
check_static_pie(struct elfobj *elfobj)
{
elf_segment_iterator_t p_iter;
struct elf_segment segment;
struct elf_section shdr;
elf_iterator_res_t ires;
bool has_dynamic_segment = false;
bool has_interp_segment = false;

/*
* A binary built with gcc -static-pie is not going to
* have a .plt section, even though it has many other
* characteristics of a dynamically linked object.
*/
if (elf_section_by_name(elfobj, ".plt", &shdr) == true)
return false;
/*
* A gcc -static-pie binary is of type ET_DYN since
* it is PIC code.
*/
if (elf_type(elfobj) != ET_DYN)
return false;

elf_segment_iterator_init(elfobj, &p_iter);
for (;;) {
ires = elf_segment_iterator_next(&p_iter, &segment);
if (ires == ELF_ITER_DONE)
break;
if (ires == ELF_ITER_ERROR)
return false;
if (segment.type == PT_INTERP)
has_interp_segment = true;
if (segment.type == PT_DYNAMIC)
has_dynamic_segment = true;
}
if (has_interp_segment == false && has_dynamic_segment == true) {
/*
* NO interpreter, but yes there is a dynamic segment--
* yet there is no .plt section, and this is of type ET_DYN
* so yes its a -static-pie executable.
*/
return true;
} else if (has_interp_segment == false & has_dynamic_segment == false) {
/*
* Pay attention to other static PIE types, including
* those that ElfMaster (me) published in June of 2019 on
* making statically linked executables PIE, in which case
* there is no dynamic segment.
*/
return true;
}
return false;
}

/*
* TODO Why is this defined in internal.c?
*/
Expand Down
3 changes: 2 additions & 1 deletion src/libelfmaster.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,8 @@ elf_linking_type(elfobj_t *obj)

if (obj->type != ET_EXEC && obj->type != ET_DYN)
return ELF_LINKING_UNDEF;

if (check_static_pie(obj) == true)
return ELF_LINKING_STATIC_PIE;
return (obj->flags & ELF_DYNAMIC_F) ? ELF_LINKING_DYNAMIC :
ELF_LINKING_STATIC;
}
Expand Down

0 comments on commit 90d3f49

Please sign in to comment.