diff options
author | Anthony G. Basile <basile@opensource.dyc.edu> | 2011-05-05 15:46:23 -0400 |
---|---|---|
committer | Anthony G. Basile <basile@opensource.dyc.edu> | 2011-05-05 15:46:23 -0400 |
commit | 1fe9aab862a37ebb377333133560b7790324eb2b (patch) | |
tree | 508ba7a2364577dbd8533818245ab48bf426b588 /poc | |
parent | tests: renaming to be more specific (diff) | |
parent | Revamped tests, added poc (diff) | |
download | elfix-1fe9aab862a37ebb377333133560b7790324eb2b.tar.gz elfix-1fe9aab862a37ebb377333133560b7790324eb2b.tar.bz2 elfix-1fe9aab862a37ebb377333133560b7790324eb2b.zip |
poc/mangle-paxflags.c: remove EI_PAX and PT_PAX_FLAGS from an elf
Diffstat (limited to 'poc')
-rw-r--r-- | poc/Makefile.am | 26 | ||||
-rw-r--r-- | poc/bad-mmap.c | 33 | ||||
-rw-r--r-- | poc/mangle-paxflags.c | 181 |
3 files changed, 240 insertions, 0 deletions
diff --git a/poc/Makefile.am b/poc/Makefile.am new file mode 100644 index 0000000..e8c94d5 --- /dev/null +++ b/poc/Makefile.am @@ -0,0 +1,26 @@ +noinst_PROGRAMS = mangle-paxflags bad-mmap +mangle_paxflags_SOURCES = mangle-paxflags.c +mangle_paxflags_LDADD = -lelf +bad_mmap_SOURCES = bad-mmap.c + +check_SCRIPTS = poc.sh + +poc.sh: + @echo "================================================================================" + @echo + ./mangle-paxflags bad-mmap + ./bad-mmap + @echo + @echo "========================================" + @echo + ./mangle-paxflags -p bad-mmap + ./mangle-paxflags bad-mmap + ./bad-mmap + @echo + @echo "========================================" + @echo + ./mangle-paxflags -e bad-mmap + ./mangle-paxflags bad-mmap + ./bad-mmap + @echo + @echo "================================================================================" diff --git a/poc/bad-mmap.c b/poc/bad-mmap.c new file mode 100644 index 0000000..04df26d --- /dev/null +++ b/poc/bad-mmap.c @@ -0,0 +1,33 @@ +/* + bad-mmap.c: create 4k anonymous mmap with RWX protection + Copyright (C) 2011 Anthony G. Basile + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <errno.h> +#include <string.h> + +int +main() +{ + if( mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) != MAP_FAILED ) + printf("mmap(): succeeded\n"); + else + printf("mmap(): %s\n", strerror(errno)); + return 0; +} diff --git a/poc/mangle-paxflags.c b/poc/mangle-paxflags.c new file mode 100644 index 0000000..76fe56b --- /dev/null +++ b/poc/mangle-paxflags.c @@ -0,0 +1,181 @@ +/* + mangle-paxflags.c: check and optionally remove EI_PAX and/or PT_PAX_FLAGS + Copyright (C) 2011 Anthony G. Basile + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <error.h> + +#include <gelf.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +// From chpax.h +#define EI_PAX 14 // Index in e_ident[] where to read flags +#define HF_PAX_PAGEEXEC 1 // 0: Paging based non-exec pages +#define HF_PAX_EMUTRAMP 2 // 0: Emulate trampolines +#define HF_PAX_MPROTECT 4 // 0: Restrict mprotect() +#define HF_PAX_RANDMMAP 8 // 0: Randomize mmap() base +#define HF_PAX_RANDEXEC 16 // 1: Randomize ET_EXEC base +#define HF_PAX_SEGMEXEC 32 // 0: Segmentation based non-exec pages + + +#define PRINT(E,F,I) printf("%s: %s\n", #E, E & F ? ( I ? "enabled" : "disabled" ) : ( I ? "disabled" : "enabled" ) ); +#define CASE(N,P) case P: printf("%d: %s\n", (int)N, #P); break + + +char * +parse_cmd_args( int c, char *v[], int *flag_ei_pax, int *flag_pt_pax_flags ) +{ + int i, oc; + + if((c != 2)&&(c != 3)&&(c != 4)) + error(EXIT_FAILURE, 0, "Usage: %s [-e] [-p] elffile", v[0]); + + *flag_ei_pax = 0; + *flag_pt_pax_flags = 0; + while((oc = getopt(c, v,":ep")) != -1) + switch(oc) + { + case 'e': + *flag_ei_pax = 1; + break ; + case 'p': + *flag_pt_pax_flags = 1; + break; + case '?': + default: + error(EXIT_FAILURE, 0, "option -%c is invalid: ignored.", optopt ) ; + } + + return v[optind] ; +} + + +int +main( int argc, char *argv[]) +{ + int fd; + int flag_ei_pax, flag_pt_pax_flags; + int found_ei_pax, found_pt_pax_flags; + char *f_name; + size_t i, phnum; + + Elf *elf; + GElf_Ehdr ehdr; + GElf_Phdr phdr; + + f_name = parse_cmd_args( argc, argv, &flag_ei_pax, &flag_pt_pax_flags ); + + if(elf_version(EV_CURRENT) == EV_NONE) + error(EXIT_FAILURE, 0, "Library out of date."); + + if( flag_ei_pax || flag_pt_pax_flags ) + { + if((fd = open(f_name, O_RDWR)) < 0) + error(EXIT_FAILURE, 0, "open() fail."); + if((elf = elf_begin(fd, ELF_C_RDWR_MMAP, NULL)) == NULL) + error(EXIT_FAILURE, 0, "elf_begin() fail: %s", elf_errmsg(elf_errno())); + } + else + { + if((fd = open(f_name, O_RDONLY)) < 0) + error(EXIT_FAILURE, 0, "open() fail."); + if((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) + error(EXIT_FAILURE, 0, "elf_begin() fail: %s", elf_errmsg(elf_errno())); + } + + if(elf_kind(elf) != ELF_K_ELF) + error(EXIT_FAILURE, 0, "elf_kind() fail: this is not an elf file."); + + if(gelf_getehdr(elf,&ehdr) != &ehdr) + error(EXIT_FAILURE, 0, "gelf_getphdr(): %s", elf_errmsg(elf_errno())); + + found_ei_pax = ((u_long) ehdr.e_ident[EI_PAX + 1] << 8) + (u_long) ehdr.e_ident[EI_PAX]; + + printf("==== EI_PAX ====\n") ; + PRINT(HF_PAX_PAGEEXEC, found_ei_pax, 0); + PRINT(HF_PAX_EMUTRAMP, found_ei_pax, 1); + PRINT(HF_PAX_MPROTECT, found_ei_pax, 0); + PRINT(HF_PAX_RANDMMAP, found_ei_pax, 0); + PRINT(HF_PAX_RANDEXEC, found_ei_pax, 1); + PRINT(HF_PAX_SEGMEXEC, found_ei_pax, 0); + printf("\n"); + + if( flag_ei_pax ) + { + printf("Disabling EI_PAX\n\n"); + ehdr.e_ident[EI_PAX] = 0xFF; + ehdr.e_ident[EI_PAX + 1] = 0xFF; + if(!gelf_update_ehdr(elf, &ehdr)) + error(EXIT_FAILURE, 0, "gelf_update_ehdr(): %s", elf_errmsg(elf_errno())); + } + + printf("==== PHRDs ====\n") ; + found_pt_pax_flags = 0 ; + elf_getphdrnum(elf, &phnum); + for(i=0; i<phnum; ++i) + { + if(gelf_getphdr(elf, i, &phdr) != &phdr) + error(EXIT_FAILURE, 0, "gelf_getphdr(): %s", elf_errmsg(elf_errno())); + + switch(phdr.p_type) + { + CASE(i,PT_NULL); + CASE(i,PT_LOAD); + CASE(i,PT_DYNAMIC); + CASE(i,PT_INTERP); + CASE(i,PT_NOTE); + CASE(i,PT_SHLIB); + CASE(i,PT_PHDR); + CASE(i,PT_TLS); + CASE(i,PT_NUM); + CASE(i,PT_LOOS); + CASE(i,PT_GNU_EH_FRAME); + CASE(i,PT_GNU_STACK); + CASE(i,PT_GNU_RELRO); + CASE(i,PT_PAX_FLAGS); + CASE(i,PT_LOSUNW); + //CASE(i,PT_SUNWBSS); + CASE(i,PT_SUNWSTACK); + CASE(i,PT_HISUNW); + //CASE(i,PT_HIOS); + CASE(i,PT_LOPROC); + CASE(i,PT_HIPROC); + } + + if((phdr.p_type == PT_PAX_FLAGS) && flag_pt_pax_flags ) + { + found_pt_pax_flags = 1 ; + phdr.p_type = PT_NULL; + if(!gelf_update_phdr(elf, i, &phdr)) + error(EXIT_FAILURE, 0, "gelf_update_phdr(): %s", elf_errmsg(elf_errno())); + } + } + + if( found_pt_pax_flags ) + printf("Setting PT_PAX_FLAGS to PT_NULL\n\n"); + else + printf("\n\n"); + + elf_end(elf); + close(fd); +} |