From e2196996f9e6866f78677f5261bc28aae29aa561 Mon Sep 17 00:00:00 2001 From: jdh8d <jdh8d@git.zephyr-software.com> Date: Mon, 25 Nov 2013 22:04:02 +0000 Subject: [PATCH] Former-commit-id: 8627527a2844dfd9337db603e8d38fc9dcb88e79 --- .gitattributes | 1 + Makefile | 1 + appfw/src/Makefile | 4 +- appfw/src/appfw.cpp | 28 ++++- appfw/src/osc_hook.c | 5 +- libIRDB/test/Makefile | 14 ++- libIRDB/test/fill_in_cfg.cpp | 64 +++++------ libIRDB/test/fill_in_indtargs.cpp | 96 ++++++++-------- libIRDB/test/find_strings.cpp | 175 +++++++++++++++++------------- libIRDB/test/read_ehframe.cpp | 68 ++++-------- third_party/elfio.patch | 131 ++++++++++++++++++++++ 11 files changed, 365 insertions(+), 222 deletions(-) create mode 100644 third_party/elfio.patch diff --git a/.gitattributes b/.gitattributes index 875be3c2a..8969d62ce 100644 --- a/.gitattributes +++ b/.gitattributes @@ -301,6 +301,7 @@ third_party/beaengine166.tar.gz -text third_party/beaengine175.tar.gz -text third_party/do_bea_update.sh -text third_party/elfio-2.2.tar.gz -text +third_party/elfio.patch -text third_party/sqlite-autoconf-3071300.tar.gz -text tools/Makefile -text tools/cover/Makefile -text diff --git a/Makefile b/Makefile index 5789a389e..d53c1ebeb 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,7 @@ elfio: third_party/elfio-2.2.tar.gz cd $(ELFIO_DIR); if [ ! -f Makefile ]; then ./configure --prefix=${SECURITY_TRANSFORMS_HOME}; fi; cd $(ELFIO_DIR); make all cd $(ELFIO_DIR); make install + #cd include/; patch -p0 < ../third_party/elfio.patch elfio_clean: rm -Rf third_party/ELFIO diff --git a/appfw/src/Makefile b/appfw/src/Makefile index 38706eb9e..09f12f705 100644 --- a/appfw/src/Makefile +++ b/appfw/src/Makefile @@ -1,8 +1,8 @@ LIBAPPFW_DIR=../lib -#CFLAGS=-g -DSHOW_TAINT_MARKINGS +CFLAGS=-g -DSHOW_TAINT_MARKINGS #CFLAGS=-DSHOW_TAINT_MARKINGS -O -CFLAGS=-O -fPIC +#CFLAGS=-O -fPIC all: libappfw.so diff --git a/appfw/src/appfw.cpp b/appfw/src/appfw.cpp index f821713d0..2fd60babb 100644 --- a/appfw/src/appfw.cpp +++ b/appfw/src/appfw.cpp @@ -6,6 +6,7 @@ #include <assert.h> #include <ctype.h> #include <list> +#include <sys/time.h> extern "C" @@ -480,9 +481,17 @@ extern "C" int appfw_establish_taint_fast(const char *command, char *taint, int list<char*>::iterator next; + int list_depth=0; + + struct timeval blah; + gettimeofday(&blah,NULL); + fprintf(stdout, "start: %d:%d ", blah.tv_sec, blah.tv_usec); + /* iterate the list */ for(list<char*>::iterator it=sorted_sigs->begin(); it!=sorted_sigs->end(); it=next) { + list_depth++; + char* sig=*it; if(verbose) fprintf(stderr,"Considering sig %s\n", sig); @@ -504,15 +513,28 @@ extern "C" int appfw_establish_taint_fast(const char *command, char *taint, int if(fixed_violations) { if(verbose) + { fprintf(stderr,"fixed %d violations at %d\n", fixed_violations,pos); + fflush(stderr); + } /* move to front */ - sorted_sigs->erase(it); - sorted_sigs->push_front(sig); + if(it!=sorted_sigs->begin()) + { + fprintf(stderr,"moving to front\n"); + sorted_sigs->erase(it); + sorted_sigs->push_front(sig); + } + violations-=fixed_violations; if(violations<=0) { if(verbose) - fprintf(stderr,"fixed ALL violations at %d\n", fixed_violations,pos); + { + fprintf(stderr,"fixed ALL violations, list size=%d, iterated to %d\n", sorted_sigs->size(), list_depth); + fflush(stderr); + } + gettimeofday(&blah,NULL); + fprintf(stdout, "end: %d:%d ", blah.tv_sec, blah.tv_usec); return TRUE; } } diff --git a/appfw/src/osc_hook.c b/appfw/src/osc_hook.c index cde1a8075..2530c358c 100644 --- a/appfw/src/osc_hook.c +++ b/appfw/src/osc_hook.c @@ -20,14 +20,15 @@ int (*my_system)(const char *) = NULL; #include "oscfw.h" int system(const char *p_command) { + if(getenv("APPFW_VERBOSE")) + fprintf(stderr, "In system\n"); + char taint[MAX_COMMAND_LENGTH]; if (!my_system) my_system = dlsym(RTLD_NEXT, "system"); oscfw_init(); // will do this automagically later - if(getenv("APPFW_VERBOSE")) - fprintf(stderr, "In system\n"); if (within_osc_monitor || oscfw_verify(p_command, taint)) { diff --git a/libIRDB/test/Makefile b/libIRDB/test/Makefile index 3ce0b8d12..3fe4cf2ae 100644 --- a/libIRDB/test/Makefile +++ b/libIRDB/test/Makefile @@ -1,4 +1,8 @@ + +INCLUDES= -I ../../include -I../include/ -I../../beaengine/include +LIBS=-L ../lib/ -lIRDB-core -lIRDB-cfg -lpqxx -L ../../beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d +OPT=-g .SUFFIXES: .exe .cpp PROGS=print_variant.exe list_programs.exe create_variant.exe create_variantir.exe read_variantir.exe clone.exe ilr.exe \ @@ -9,21 +13,19 @@ all: $(PROGS) $(PROGS): ../../lib/* -#read_ehframe.exe: unwind-pe.h -# g++ -w -fpermissive -g read_ehframe.cpp -DTEST -I../include/ -I../../beaengine/include -L ../lib/ -lIRDB-core -lIRDB-cfg -lpqxx -L ../../beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d -o $@ fill_in_indtargs.exe: read_ehframe.o fill_in_indtargs.o check_thunks.o - g++ -g fill_in_indtargs.o read_ehframe.o check_thunks.o -I../include/ -I../../beaengine/include -L ../lib/ -lIRDB-core -lIRDB-cfg -lpqxx -L ../../beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d -o $@ + g++ fill_in_indtargs.o read_ehframe.o check_thunks.o $(INCLUDES) $(LIBS) $(OPT) -o $@ .o.exe: $< ../lib/libIRDB-core.a ../lib/libIRDB-cfg.a - g++ -g $< -I../include/ -I../../beaengine/include -L ../lib/ -lIRDB-core -lIRDB-cfg -lpqxx -L ../../beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d -o $@ + g++ $< $(INCLUDES) $(LIBS) $(OPT) -o $@ .cpp.o: $< - g++ -g $< -I../include/ -I../../beaengine/include -I../../include -L../lib/ -lIRDB-core -lIRDB-cfg -lpqxx -L ../../beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d -o $@ -c + g++ $< $(INCLUDES) $(LIBS) $(OPT) -o $@ -c read_ehframe.o: read_ehframe.cpp - g++ -w -fpermissive -g $^ -I../../include -I../include/ -I../../beaengine/include -L ../lib/ -lIRDB-core -lIRDB-cfg -lpqxx -L ../../beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d -o $@ -c + g++ -w -fpermissive $(INCLUDES) $(LIBS) $(OPT) $^ -o $@ -c clean: rm -f $(PROGS) *.o diff --git a/libIRDB/test/fill_in_cfg.cpp b/libIRDB/test/fill_in_cfg.cpp index 8321c580a..f082b75b5 100644 --- a/libIRDB/test/fill_in_cfg.cpp +++ b/libIRDB/test/fill_in_cfg.cpp @@ -6,10 +6,13 @@ #include <string.h> #include <map> #include <assert.h> -#include <elf.h> #include <sys/mman.h> #include <ctype.h> -#include <targ-config.h> + +#include "elfio/elfio.hpp" +#include "elfio/elfio_dump.hpp" + +#include "targ-config.h" #include "beaengine/BeaEngine.h" @@ -20,6 +23,7 @@ int bad_fallthrough_count=0; using namespace libIRDB; using namespace std; +using namespace ELFIO; set< pair<db_id_t,int> > missed_instructions; int failed_target_count=0; @@ -218,36 +222,33 @@ void add_new_instructions(FileIR_t *firp) /* get the OID of the file */ int elfoid=filep->GetELFOID(); + pqxx::largeobject lo(elfoid); + lo.to_file(pqxx_interface.GetTransaction(),"readeh_tmp_file.exe"); - IRDB_Elf_Off sec_hdr_off, sec_off; - IRDB_Elf_Half secnum, strndx, secndx; - IRDB_Elf_Word secsize; - - pqxx::largeobjectaccess loa(pqxx_interface.GetTransaction(), elfoid, PGSTD::ios::in); - + ELFIO::elfio elfiop; + elfiop.load("readeh_tmp_file.exe"); + + ELFIO::dump::header(cout,elfiop); + ELFIO::dump::section_headers(cout,elfiop); - /* allcoate memory */ - IRDB_Elf_Ehdr elfhdr; - /* Read ELF header */ - loa.cread((char*)&elfhdr, sizeof(IRDB_Elf_Ehdr)* 1); - sec_hdr_off = elfhdr.e_shoff; - secnum = elfhdr.e_shnum; - strndx = elfhdr.e_shstrndx; + Elf64_Off sec_hdr_off, sec_off; + Elf_Half secnum, strndx, secndx; + Elf_Word secsize; + + - /* Read Section headers */ - IRDB_Elf_Shdr *sechdrs=(IRDB_Elf_Shdr*)malloc(sizeof(IRDB_Elf_Shdr)*secnum); - assert(sechdrs); - loa.seek(sec_hdr_off, std::ios_base::beg); - loa.cread((char*)sechdrs, sizeof(IRDB_Elf_Shdr)* secnum); + sec_hdr_off = elfiop.get_sections_offset(); + secnum = elfiop.sections.size(); + strndx = elfiop.get_section_name_str_index(); bool found=false; /* look through each section and find the missing target*/ for (secndx=1; secndx<secnum; secndx++) { - int flags = sechdrs[secndx].sh_flags; + int flags = elfiop.sections[secndx]->get_flags(); /* not a loaded section */ if( (flags & SHF_ALLOC) != SHF_ALLOC) @@ -257,21 +258,15 @@ void add_new_instructions(FileIR_t *firp) if( (flags & SHF_EXECINSTR) != SHF_EXECINSTR) continue; - int first=sechdrs[secndx].sh_addr; - int second=sechdrs[secndx].sh_addr+sechdrs[secndx].sh_size; + Elf64_Addr first=elfiop.sections[secndx]->get_address(); + Elf64_Addr second=elfiop.sections[secndx]->get_address()+elfiop.sections[secndx]->get_size(); /* is the missed instruction in this section */ if(first<=missed_address && missed_address<=second) { - char* data=(char*)malloc(sechdrs[secndx].sh_size+16); /* +16 to account for a bogus-y instruction that wraps past the end of the section */ - assert(data); - memset(data,0, sechdrs[secndx].sh_size+16); /* bogus bits are always 0 */ - - /* grab the data from the ELF file for this section */ - loa.seek(sechdrs[secndx].sh_offset, std::ios_base::beg); - loa.read(data, sechdrs[secndx].sh_size * 1); - - int offset_into_section=missed_address-sechdrs[secndx].sh_addr; + const char* data=elfiop.sections[secndx]->get_data(); + // second=data? + int offset_into_section=missed_address-elfiop.sections[secndx]->get_address(); /* disassemble the instruction */ DISASM disasm; @@ -291,7 +286,6 @@ void add_new_instructions(FileIR_t *firp) /* if we found the instruction, but can't disassemble it, then we skip out for now */ if(instr_len==OUT_OF_RANGE || instr_len==UNKNOWN_OPCODE) { - free(data); break; } @@ -330,7 +324,6 @@ void add_new_instructions(FileIR_t *firp) cout<<"Found new instruction, "<<newinsn->GetComment()<<", at "<<std::hex<<newinsn->GetAddress()->GetVirtualOffset()<<" in file "<<"<no name yet>"<<"."<<endl; found_instructions++; - free(data); } } @@ -340,8 +333,7 @@ void add_new_instructions(FileIR_t *firp) cout<<"Cannot find address "<<std::hex<<missed_address<<" in file "<<"<no name yet>"<<"."<<endl; } - free(sechdrs); - } + } cout<<"Found a total of "<<std::dec<<found_instructions<<" new instructions."<<endl; } diff --git a/libIRDB/test/fill_in_indtargs.cpp b/libIRDB/test/fill_in_indtargs.cpp index 83370ce0d..3be5f2ff7 100644 --- a/libIRDB/test/fill_in_indtargs.cpp +++ b/libIRDB/test/fill_in_indtargs.cpp @@ -6,20 +6,28 @@ #include <string.h> #include <map> #include <assert.h> -#include <elf.h> #include <sys/mman.h> +// #include <elf.h> #include <ctype.h> -#include "targ-config.h" +#include "elfio/elfio.hpp" +#include "elfio/elfio_dump.hpp" + +#include "targ-config.h" + #include "beaengine/BeaEngine.h" + +#define arch_ptr_bytes() (firp->GetArchitectureBitWidth()/8) + int odd_target_count=0; int bad_target_count=0; int bad_fallthrough_count=0; using namespace libIRDB; using namespace std; +using namespace ELFIO; void possible_target(int p); @@ -173,9 +181,9 @@ void get_instruction_targets(FileIR_t *firp) } -void get_executable_bounds(IRDB_Elf_Shdr *shdr, pqxx::largeobjectaccess &loa, FileIR_t *firp) +void get_executable_bounds(FileIR_t *firp, const section* shdr) { - int flags = shdr->sh_flags; + int flags = shdr->get_flags(); /* not a loaded section */ if( (flags & SHF_ALLOC) != SHF_ALLOC) @@ -185,17 +193,17 @@ void get_executable_bounds(IRDB_Elf_Shdr *shdr, pqxx::largeobjectaccess &loa, Fi if( (flags & SHF_EXECINSTR) != SHF_EXECINSTR) return; - int first=shdr->sh_addr; - int second=shdr->sh_addr+shdr->sh_size; + int first=shdr->get_address(); + int second=shdr->get_address()+shdr->get_size(); bounds.insert(pair<int,int>(first,second)); } -void infer_targets(IRDB_Elf_Shdr *shdr, pqxx::largeobjectaccess &loa, FileIR_t *firp) +void infer_targets(FileIR_t *firp, section* shdr) { - int flags = shdr->sh_flags; + int flags = shdr->get_flags(); if( (flags & SHF_ALLOC) != SHF_ALLOC) /* not a loaded section */ @@ -206,26 +214,16 @@ void infer_targets(IRDB_Elf_Shdr *shdr, pqxx::largeobjectaccess &loa, FileIR_t * return; /* if the type is NOBITS, then there's no actual data to look through */ - if(shdr->sh_type==SHT_NOBITS) + if(shdr->get_type()==SHT_NOBITS) return; - char* data=(char*)malloc(shdr->sh_size); - - //fseek(fp,shdr->sh_offset, SEEK_SET); - loa.seek(shdr->sh_offset, std::ios_base::beg); - - - //int res=fread(data, shdr->sh_size, 1, fp); - loa.cread((char*)data, shdr->sh_size* 1); + const char* data=shdr->get_data() ; // C(char*)malloc(shdr->sh_size); - for(int i=0;i<=shdr->sh_size;i++) + assert(arch_ptr_bytes()==4 || arch_ptr_bytes()==8); + for(int i=0;i+arch_ptr_bytes()<=shdr->get_size();i++) { - /* careful not to overflow the segment */ - if(i+sizeof(void*)<=shdr->sh_size) - { - int p=*(int*)&data[i]; - possible_target(p); - } + int p=*(int*)&data[i]; + possible_target(p); } } @@ -323,42 +321,29 @@ void add_num_handle_fn_watches(FileIR_t * firp) } -void fill_in_indtargs(FileIR_t* firp, pqxxDB_t &pqxx_interface) +void fill_in_indtargs(FileIR_t* firp, elfio* elfiop) { // reset global vars bounds.clear(); ranges.clear(); targets.clear(); - IRDB_Elf_Off sec_hdr_off, sec_off; - IRDB_Elf_Half secnum, strndx, secndx; - IRDB_Elf_Word secsize; - - int elfoid=firp->GetFile()->GetELFOID(); - pqxx::largeobjectaccess loa(pqxx_interface.GetTransaction(), elfoid, PGSTD::ios::in); - - /* allcoate memory */ - IRDB_Elf_Ehdr elfhdr; + Elf64_Off sec_hdr_off, sec_off; + Elf_Half secnum, strndx, secndx; + Elf_Word secsize; /* Read ELF header */ - //int res=fread(&elfhdr, sizeof(IRDB_Elf_Ehdr), 1, fp); - loa.cread((char*)&elfhdr, sizeof(IRDB_Elf_Ehdr)* 1); - sec_hdr_off = elfhdr.e_shoff; - secnum = elfhdr.e_shnum; - strndx = elfhdr.e_shstrndx; - - /* Read Section headers */ - IRDB_Elf_Shdr *sechdrs=(IRDB_Elf_Shdr*)malloc(sizeof(IRDB_Elf_Shdr)*secnum); - loa.seek(sec_hdr_off, std::ios_base::beg); - loa.cread((char*)sechdrs, sizeof(IRDB_Elf_Shdr)* secnum); + sec_hdr_off = elfiop->get_sections_offset(); + secnum = elfiop->sections.size(); + strndx = elfiop->get_section_name_str_index(); /* look through each section and record bounds */ for (secndx=1; secndx<secnum; secndx++) - get_executable_bounds(&sechdrs[secndx], loa, firp); + get_executable_bounds(firp, elfiop->sections[secndx]); /* look through each section and look for target possibilities */ for (secndx=1; secndx<secnum; secndx++) - infer_targets(&sechdrs[secndx], loa, firp); + infer_targets(firp, elfiop->sections[secndx]); cout<<"========================================="<<endl; @@ -370,7 +355,7 @@ void fill_in_indtargs(FileIR_t* firp, pqxxDB_t &pqxx_interface) get_instruction_targets(firp); /* mark the entry point as a target */ - possible_target(elfhdr.e_entry); + possible_target(elfiop->get_entry()); cout<<"========================================="<<endl; @@ -379,8 +364,8 @@ void fill_in_indtargs(FileIR_t* firp, pqxxDB_t &pqxx_interface) cout<<"========================================="<<endl; /* Read the exception handler frame so that those indirect branches are accounted for */ - void read_ehframe(FileIR_t* firp, pqxxDB_t& pqxx_interface); - read_ehframe(firp, pqxx_interface); + void read_ehframe(FileIR_t* firp, elfio* ); + read_ehframe(firp, elfiop); cout<<"========================================="<<endl; cout<<"All targets from data+instruction+eh_header sections are: " << endl; @@ -466,8 +451,19 @@ main(int argc, char* argv[]) // read the db firp=new FileIR_t(*pidp, this_file); + int elfoid=firp->GetFile()->GetELFOID(); + pqxx::largeobject lo(elfoid); + lo.to_file(pqxx_interface.GetTransaction(),"readeh_tmp_file.exe"); + + ELFIO::elfio* elfiop=new ELFIO::elfio; + elfiop->load("readeh_tmp_file.exe"); + + ELFIO::dump::header(cout,*elfiop); + ELFIO::dump::section_headers(cout,*elfiop); + + // find all indirect branch targets - fill_in_indtargs(firp, pqxx_interface); + fill_in_indtargs(firp, elfiop); // write the DB back and commit our changes diff --git a/libIRDB/test/find_strings.cpp b/libIRDB/test/find_strings.cpp index a6fb7879d..5f7df4365 100644 --- a/libIRDB/test/find_strings.cpp +++ b/libIRDB/test/find_strings.cpp @@ -5,13 +5,19 @@ #include <iostream> #include <stdlib.h> #include <cctype> -#include <elf.h> #include <assert.h> + +#include "elfio/elfio.hpp" +#include "elfio/elfio_dump.hpp" + #include "targ-config.h" + using namespace libIRDB; using namespace std; +using namespace ELFIO; +#define arch_ptr_bytes() (firp->GetArchitectureBitWidth()/8) bool is_string_character(char c) { @@ -22,13 +28,12 @@ bool is_string_character(char c) /* the stuff we need for reading an elf file */ typedef struct elf_info { - IRDB_Elf_Off sec_hdr_off, sec_off; - IRDB_Elf_Half secnum, strndx; - IRDB_Elf_Ehdr elfhdr; - IRDB_Elf_Word secsize; - IRDB_Elf_Shdr *sechdrs; - char **sec_data; - IRDB_Elf_Addr got; + Elf64_Off sec_hdr_off, sec_off; + Elf_Half secnum, strndx; + Elf_Word secsize; + char const **sec_data; + Elf64_Addr got; + elfio *elfiop; } elf_info_t; void found_string(string s, void* addr) @@ -58,9 +63,9 @@ void found_string(string s, void* addr) } while (p < buff + s.length()); } -void load_section(elf_info_t &ei, int i, pqxx::largeobjectaccess &loa, bool alloc) +void load_section(elf_info_t &ei, int i, bool alloc) { - if( alloc && (ei.sechdrs[i].sh_flags & SHF_ALLOC) != SHF_ALLOC) + if( alloc && (ei.elfiop->sections[i]->get_flags() & SHF_ALLOC) != SHF_ALLOC) { cerr<<"Cannot load non-alloc section\n"; assert(0); @@ -68,22 +73,16 @@ void load_section(elf_info_t &ei, int i, pqxx::largeobjectaccess &loa, bool allo if(ei.sec_data[i]==NULL) { - ei.sec_data[i]=(char*)calloc(ei.sechdrs[i].sh_size,1); - if(ei.sechdrs[i].sh_type==SHT_NOBITS) + ei.sec_data[i]=ei.elfiop->sections[i]->get_data(); + if(ei.elfiop->sections[i]->get_type()==SHT_NOBITS) { /* no need to read anything for NOBITS sections */ - } - else - { -// cout<<"Loading section "<<std::dec<<i<<" vaddr: "<<std::hex<<ei.sechdrs[i].sh_addr<< " size: " -// <<std::dec<<ei.sechdrs[i].sh_size<< endl; - loa.seek(ei.sechdrs[i].sh_offset, std::ios_base::beg); - loa.cread((char*)ei.sec_data[i], ei.sechdrs[i].sh_size); + ei.sec_data[i]=(char*)calloc(ei.elfiop->sections[i]->get_size(),1); } } } -void check_for_string(char* p, void* addr) +void check_for_string(const char* p, void* addr) { assert(p); if(!is_string_character(*p)) @@ -100,22 +99,23 @@ void check_for_string(char* p, void* addr) found_string(s, addr); } -void is_string_pointer(void* addr, elf_info_t &ei, pqxx::largeobjectaccess &loa) +void is_string_pointer(void* addr, elf_info_t &ei) { long long int intaddr=(long long int)(addr); for(int i=0;i<ei.secnum;i++) { /* only look at loaded sections */ - if( (ei.sechdrs[i].sh_flags & SHF_ALLOC) != SHF_ALLOC) + if( (ei.elfiop->sections[i]->get_flags() & SHF_ALLOC) != SHF_ALLOC) continue; - if(ei.sechdrs[i].sh_addr <= intaddr && intaddr <= (ei.sechdrs[i].sh_addr+ei.sechdrs[i].sh_size)) + if(ei.elfiop->sections[i]->get_address() <= intaddr + && intaddr <= (ei.elfiop->sections[i]->get_address()+ei.elfiop->sections[i]->get_size())) { /* we found a pointer into a loadable segment */ - load_section(ei,i,loa,true); + load_section(ei,i,true); // cout<<"Checking address "<<std::hex<<addr<<endl; - check_for_string(ei.sec_data[i]+((long long int)addr-ei.sechdrs[i].sh_addr),addr); + check_for_string(ei.sec_data[i]+((long long int)addr-ei.elfiop->sections[i]->get_address()),addr); } } @@ -158,38 +158,31 @@ void is_string_constant(DISASM& disasm) } -void handle_argument(ARGTYPE *arg, elf_info_t &ei, pqxx::largeobjectaccess &loa) +void handle_argument(ARGTYPE *arg, elf_info_t &ei) { if( arg->ArgType == MEMORY_TYPE ) { /* Only check without GOT offset if type is executable */ - if ( ei.elfhdr.e_type == ET_EXEC ) - is_string_pointer((void*)arg->Memory.Displacement,ei,loa); + if ( ei.elfiop->get_type() == ET_EXEC ) + is_string_pointer((void*)arg->Memory.Displacement,ei); /* Check with GOT offset if present */ if ( ei.got && arg->Memory.BaseRegister == REG3 /* ebx */ ) - is_string_pointer((void*)(arg->Memory.Displacement + ei.got),ei,loa); + is_string_pointer((void*)(arg->Memory.Displacement + ei.got),ei); } } -void read_elf_info(elf_info_t &ei, FileIR_t* firp, pqxx::largeobjectaccess &loa) +void read_elf_info(elf_info_t &ei, FileIR_t* firp) { /* Read ELF header */ - loa.cread((char*)&ei.elfhdr, sizeof(IRDB_Elf_Ehdr)* 1); - ei.sec_hdr_off = ei.elfhdr.e_shoff; - ei.secnum = ei.elfhdr.e_shnum; + ei.sec_hdr_off = ei.elfiop->get_sections_offset(); + ei.secnum = ei.elfiop->sections.size(); assert(ei.secnum>0); - ei.strndx = ei.elfhdr.e_shstrndx; + ei.strndx = ei.elfiop->get_section_name_str_index(); - /* Read Section headers */ - ei.sechdrs=(IRDB_Elf_Shdr*)malloc(sizeof(IRDB_Elf_Shdr)*ei.secnum); - assert(ei.sechdrs!=NULL); - loa.seek(ei.sec_hdr_off, std::ios_base::beg); - loa.cread((char*)ei.sechdrs, sizeof(IRDB_Elf_Shdr)* ei.secnum); - - ei.sec_data=(char**)calloc(ei.secnum,sizeof(void*)); + ei.sec_data=(char const**)calloc(ei.secnum,sizeof(void*)); ei.got = 0; /* Get .got or .got.plt address, if any */ @@ -199,21 +192,22 @@ void read_elf_info(elf_info_t &ei, FileIR_t* firp, pqxx::largeobjectaccess &loa) if (ei.strndx < SHN_LORESERVE) shstr_sec = ei.strndx; else - shstr_sec = ei.sechdrs[0].sh_link; + shstr_sec = ei.elfiop->sections[0]->get_link(); assert(shstr_sec < ei.secnum); - load_section(ei,shstr_sec,loa,false); - IRDB_Elf_Shdr *shstr_sec_hdr = ei.sechdrs + shstr_sec; + load_section(ei,shstr_sec,false); +// IRDB_Elf_Shdr *shstr_sec_hdr = ei.sechdrs + shstr_sec; for (int i=0;i<ei.secnum;i++) { - assert(ei.sechdrs[i].sh_name < shstr_sec_hdr->sh_size); - if (!strcmp(ei.sec_data[shstr_sec]+ei.sechdrs[i].sh_name, ".got.plt")) +// name works oddly here. we can just get the name safely using elfio +// assert(ei.sechdrs[i].sh_name < shstr_sec_hdr->sh_size); + if (ei.elfiop->sections[i]->get_name()==".got.plt") // !strcmp(ei.sec_data[shstr_sec]+ei.sechdrs[i].sh_name, ".got.plt")) { // Prefer .got.plt to .got - ei.got = ei.sechdrs[i].sh_addr; + ei.got = ei.elfiop->sections[i]->get_address(); break; } - if (!strcmp(ei.sec_data[shstr_sec]+ei.sechdrs[i].sh_name, ".got")) - ei.got = ei.sechdrs[i].sh_addr; + if (ei.elfiop->sections[i]->get_name()==".got") // if (!strcmp(ei.sec_data[shstr_sec]+ei.sechdrs[i].sh_name, ".got")) + ei.got = ei.elfiop->sections[i]->get_address(); } } } @@ -221,13 +215,10 @@ void read_elf_info(elf_info_t &ei, FileIR_t* firp, pqxx::largeobjectaccess &loa) void free_elf_info(elf_info_t &ei) { #define FREE_IF_NOT_NULL(a) { if(a) { free(a); a=NULL; } } - FREE_IF_NOT_NULL(ei.sechdrs); - for(int i=0;i<ei.secnum;i++) - FREE_IF_NOT_NULL(ei.sec_data[i]); FREE_IF_NOT_NULL(ei.sec_data); } -void find_strings_in_instructions(FileIR_t* firp, elf_info_t& ei, pqxx::largeobjectaccess &loa) +void find_strings_in_instructions(FileIR_t* firp, elf_info_t& ei) { set<Instruction_t*> visited_insns; @@ -368,12 +359,12 @@ void find_strings_in_instructions(FileIR_t* firp, elf_info_t& ei, pqxx::largeobj assert(res); // check for immediate string pointers in non-PIC code - if ( ei.elfhdr.e_type == ET_EXEC ) - is_string_pointer((void*)disasm.Instruction.Immediat,ei,loa); + if ( ei.elfiop->get_type() == ET_EXEC ) + is_string_pointer((void*)disasm.Instruction.Immediat,ei); // always check for string pointers in memory argument displacements - handle_argument(&disasm.Argument1,ei,loa); - handle_argument(&disasm.Argument2,ei,loa); - handle_argument(&disasm.Argument3,ei,loa); + handle_argument(&disasm.Argument1,ei); + handle_argument(&disasm.Argument2,ei); + handle_argument(&disasm.Argument3,ei); // if not in a function, check for string in immediate if (visited_insns.find(insn) != visited_insns.end()) @@ -390,44 +381,63 @@ void find_strings_in_instructions(FileIR_t* firp, elf_info_t& ei, pqxx::largeobj } } -void find_strings_in_data(FileIR_t* firp, elf_info_t& ei, pqxx::largeobjectaccess &loa) + +void find_strings_in_data(FileIR_t* firp, elf_info_t& ei) { for(int i=0;i<ei.secnum;i++) { /* skip executable, hash, string table, nonloadable, and tiny sections */ - if( (ei.sechdrs[i].sh_flags & SHF_EXECINSTR) - || ei.sechdrs[i].sh_type == SHT_HASH - || ei.sechdrs[i].sh_type == SHT_GNU_HASH - || ei.sechdrs[i].sh_type == SHT_STRTAB - || (ei.sechdrs[i].sh_flags & SHF_ALLOC) != SHF_ALLOC - || ei.sechdrs[i].sh_size < sizeof(void*)) + if( (ei.elfiop->sections[i]->get_flags() & SHF_EXECINSTR) + || ei.elfiop->sections[i]->get_type() == SHT_HASH + || ei.elfiop->sections[i]->get_type() == SHT_GNU_HASH + || ei.elfiop->sections[i]->get_type() == SHT_STRTAB + || (ei.elfiop->sections[i]->get_flags() & SHF_ALLOC) != SHF_ALLOC + || ei.elfiop->sections[i]->get_size() < arch_ptr_bytes()) continue; int offset = 0; int step; /* step over relocation info */ - switch( ei.sechdrs[i].sh_type ) + switch( ei.elfiop->sections[i]->get_type() ) { case SHT_REL: - step = sizeof(IRDB_Elf_Rel); + if(arch_ptr_bytes()==4) + step = sizeof(::Elf32_Rel); + else + step = sizeof(::Elf64_Rel); break; case SHT_RELA: - step = sizeof(IRDB_Elf_Rela); + if(arch_ptr_bytes()==4) + step = sizeof(::Elf32_Rela); + else + step = sizeof(::Elf64_Rela); break; case SHT_SYMTAB: case SHT_DYNSYM: - offset = sizeof(IRDB_Elf_Word); - step = sizeof(IRDB_Elf_Sym); + if(arch_ptr_bytes()==4) + { + offset = sizeof(::Elf32_Word); + step = sizeof(::Elf32_Sym); + } + else + { + offset = sizeof(::Elf64_Word); + step = sizeof(::Elf64_Sym); + } break; default: step = 1; } - load_section(ei,i,loa,true); - for(int j=offset;j<=ei.sechdrs[i].sh_size-sizeof(void*);j+=step) + load_section(ei,i,true); + for(int j=offset;j+arch_ptr_bytes()<=ei.elfiop->sections[i]->get_size();j+=step) { - void* p=*((void**)(ei.sec_data[i]+j)); - is_string_pointer(p,ei,loa); + void* p; + if(arch_ptr_bytes()==4) + p=(void*)*((int*)(ei.sec_data[i]+j)); + else + p=*((void**)(ei.sec_data[i]+j)); + is_string_pointer(p,ei); } @@ -445,14 +455,23 @@ void find_strings(VariantID_t *pidp, FileIR_t* firp) /* get a handle to the binary file */ int elfoid=firp->GetFile()->GetELFOID(); pqxxDB_t* pqxx_interface=dynamic_cast<pqxxDB_t*>(BaseObj_t::GetInterface()); - pqxx::largeobjectaccess loa(pqxx_interface->GetTransaction(), elfoid, PGSTD::ios::in); + + pqxx::largeobject lo(elfoid); + lo.to_file(pqxx_interface->GetTransaction(),"readeh_tmp_file.exe"); + ELFIO::elfio elfiop; + elfiop.load("readeh_tmp_file.exe"); + ELFIO::dump::header(cout,elfiop); + ELFIO::dump::section_headers(cout,elfiop); + + elf_info_t ei; - read_elf_info(ei,firp,loa); + ei.elfiop=&elfiop; + read_elf_info(ei,firp); - find_strings_in_instructions(firp, ei, loa); - find_strings_in_data(firp, ei, loa); + find_strings_in_instructions(firp, ei); + find_strings_in_data(firp, ei); free_elf_info(ei); diff --git a/libIRDB/test/read_ehframe.cpp b/libIRDB/test/read_ehframe.cpp index 833b866b0..a300824cb 100644 --- a/libIRDB/test/read_ehframe.cpp +++ b/libIRDB/test/read_ehframe.cpp @@ -11,13 +11,17 @@ #include <elf.h> #include "targ-config.h" - - +#include "elfio/elfio.hpp" +#include "elfio/elfio_dump.hpp" using namespace libIRDB; using namespace std; + + + + void* eh_frame_addr; char* eh_frame_data; int eh_offset; @@ -660,11 +664,11 @@ void linear_search_fdes (struct object *ob, fde *this_fde, int offset) return; } -void read_ehframe(FileIR_t* virp, pqxxDB_t& pqxx_interface) +void read_ehframe(FileIR_t* virp, ELFIO::elfio* elfiop) { - /* get first instruction */ Instruction_t* insn=*(virp->GetInstructions().begin()); + assert(insn); /* get its file ID */ db_id_t fileid=insn->GetAddress()->GetFileID(); @@ -676,41 +680,18 @@ void read_ehframe(FileIR_t* virp, pqxxDB_t& pqxx_interface) /* get the OID of the file */ int elfoid=filep->GetELFOID(); - /* parse out the elf headers, and strtab */ - IRDB_Elf_Ehdr elfhdr; - IRDB_Elf_Off sec_hdr_off, sec_off; - IRDB_Elf_Half secnum, strndx, secndx; - IRDB_Elf_Word secsize; - - pqxx::largeobjectaccess loa(pqxx_interface.GetTransaction(), elfoid, PGSTD::ios::in); - - - /* Read ELF header */ - loa.cread((char*)&elfhdr, sizeof(IRDB_Elf_Ehdr)* 1); - - sec_hdr_off = elfhdr.e_shoff; - secnum = elfhdr.e_shnum; - strndx = elfhdr.e_shstrndx; - - /* Read Section headers */ - IRDB_Elf_Shdr *sechdrs=(IRDB_Elf_Shdr*)malloc(sizeof(IRDB_Elf_Shdr)*secnum); - loa.seek(sec_hdr_off, std::ios_base::beg); - loa.cread((char*)sechdrs, sizeof(IRDB_Elf_Shdr)* secnum); - - - /* Read Section String Table */ - sec_off = sechdrs[strndx].sh_offset; - secsize = sechdrs[strndx].sh_size; - loa.seek(sec_off, std::ios_base::beg); - char* strtab = (char *)malloc(secsize); - loa.cread(strtab, 1 * secsize); + int secndx=0; + int secnum=elfiop->sections.size(); + ELFIO::Elf_Half strndx = elfiop->get_section_name_str_index(); + const char* strtab=elfiop->sections[strndx]->get_data(); /* Locate desired section */ bool found=false; int eh_frame_index; for (secndx=1; secndx<secnum; secndx++) { - char *p=&strtab[ sechdrs[secndx].sh_name]; + // cout<<"sechdrs["<<i<<"] name index="<<sechdrs[secndx].sh_name<<endl; + const char *p=elfiop->sections[secndx]->get_name().c_str(); if (strcmp(".eh_frame",p)==0) { found = true; @@ -726,23 +707,23 @@ void read_ehframe(FileIR_t* virp, pqxxDB_t& pqxx_interface) } cout<<"Found .eh_frame is section "<<std::dec<<eh_frame_index<<endl; - char *p=&strtab[ sechdrs[secndx+1].sh_name]; +// char *p=&strtab[ sechdrs[secndx+1].sh_name]; + const char *p=elfiop->sections[secndx+1]->get_name().c_str(); if (strcmp(".gcc_except_table",p)!=0) { cout<<"Did not find .gcc_except_table immediately after .eh_frame\n"; return; } - eh_frame_addr=(void*)sechdrs[eh_frame_index].sh_addr; - int total_size= ((int)sechdrs[eh_frame_index+1].sh_addr+(int)sechdrs[eh_frame_index+1].sh_size) - (int)eh_frame_addr; + eh_frame_addr=(void*)elfiop->sections[eh_frame_index]->get_address(); + int total_size= + (elfiop->sections[eh_frame_index+1]->get_address()+ + elfiop->sections[eh_frame_index+1]->get_size() ) - (int)eh_frame_addr; - /* read the frame data */ - eh_frame_data=(char*)malloc(total_size); - loa.seek((int)sechdrs[eh_frame_index].sh_offset, std::ios_base::beg); - loa.cread(eh_frame_data, total_size); + eh_frame_data=elfiop->sections[eh_frame_index]->get_data(); - int offset; - eh_offset=offset=(int)eh_frame_addr-(int)eh_frame_data; + uintptr_t offset; + eh_offset=offset=(uintptr_t)eh_frame_addr-(uintptr_t)eh_frame_data; struct object ob; @@ -752,9 +733,6 @@ void read_ehframe(FileIR_t* virp, pqxxDB_t& pqxx_interface) linear_search_fdes (&ob,ob.u.single,offset); /* clean up memory */ - free(sechdrs); - free(strtab); - free(eh_frame_data); } diff --git a/third_party/elfio.patch b/third_party/elfio.patch new file mode 100644 index 000000000..36d5926af --- /dev/null +++ b/third_party/elfio.patch @@ -0,0 +1,131 @@ +diff -rpuN umbrella/uvadev.peasoup/security_transforms/third_party/ELFIO/elfio-2.2/elfio/elfio_header.hpp elfio/elfio_header.hpp +--- umbrella/uvadev.peasoup/security_transforms/third_party/ELFIO/elfio-2.2/elfio/elfio_header.hpp 2012-11-27 04:34:09.000000000 -0500 ++++ elfio/elfio_header.hpp 2013-11-22 10:03:00.640843581 -0500 +@@ -23,6 +23,7 @@ THE SOFTWARE. + #ifndef ELF_HEADER_HPP + #define ELF_HEADER_HPP + ++#include <istream> + #include <fstream> + + namespace ELFIO { +@@ -31,7 +32,7 @@ class elf_header + { + public: + virtual ~elf_header() {}; +- virtual bool load( std::ifstream& stream ) = 0; ++ virtual bool load( std::istream& stream ) = 0; + virtual bool save( std::ofstream& stream ) const = 0; + + // ELF header functions +@@ -98,7 +99,7 @@ template< class T > class elf_header_imp + } + + bool +- load( std::ifstream& stream ) ++ load( std::istream& stream ) + { + stream.seekg( 0 ); + stream.read( reinterpret_cast<char*>( &header ), sizeof( header ) ); +diff -rpuN umbrella/uvadev.peasoup/security_transforms/third_party/ELFIO/elfio-2.2/elfio/elfio.hpp elfio/elfio.hpp +--- umbrella/uvadev.peasoup/security_transforms/third_party/ELFIO/elfio-2.2/elfio/elfio.hpp 2013-05-16 11:37:39.000000000 -0400 ++++ elfio/elfio.hpp 2013-11-22 10:03:00.640843581 -0500 +@@ -35,6 +35,7 @@ THE SOFTWARE. + #include <algorithm> + #include <vector> + #include <typeinfo> ++#include <istream> + + #include <elfio/elf_types.hpp> + #include <elfio/elfio_utils.hpp> +@@ -99,7 +100,13 @@ class elfio + stream.open( file_name.c_str(), std::ios::in | std::ios::binary ); + if ( !stream ) { + return false; +- } ++ } ++ return load(stream); ++ } ++ bool load( std::istream &stream ) ++ { ++ clean(); ++ + + unsigned char e_ident[EI_NIDENT]; + +@@ -323,7 +330,7 @@ class elfio + } + + //------------------------------------------------------------------------------ +- Elf_Half load_sections( std::ifstream& stream ) ++ Elf_Half load_sections( std::istream& stream ) + { + Elf_Half entry_size = header->get_section_entry_size(); + Elf_Half num = header->get_sections_num(); +@@ -355,7 +362,7 @@ class elfio + } + + //------------------------------------------------------------------------------ +- bool load_segments( std::ifstream& stream ) ++ bool load_segments( std::istream& stream ) + { + Elf_Half entry_size = header->get_segment_entry_size(); + Elf_Half num = header->get_segments_num(); +diff -rpuN umbrella/uvadev.peasoup/security_transforms/third_party/ELFIO/elfio-2.2/elfio/elfio_section.hpp elfio/elfio_section.hpp +--- umbrella/uvadev.peasoup/security_transforms/third_party/ELFIO/elfio-2.2/elfio/elfio_section.hpp 2013-03-25 03:57:36.000000000 -0400 ++++ elfio/elfio_section.hpp 2013-11-22 10:03:00.640843581 -0500 +@@ -25,6 +25,7 @@ THE SOFTWARE. + + #include <string> + #include <fstream> ++#include <istream> + + namespace ELFIO { + +@@ -55,7 +56,7 @@ class section + + protected: + virtual void set_index( Elf_Half ) = 0; +- virtual void load( std::ifstream& f, ++ virtual void load( std::istream& f, + std::streampos header_offset ) = 0; + virtual void save( std::ofstream& f, + std::streampos header_offset, +@@ -203,7 +204,7 @@ class section_impl : public section + + //------------------------------------------------------------------------------ + void +- load( std::ifstream& stream, ++ load( std::istream& stream, + std::streampos header_offset ) + { + std::fill_n( reinterpret_cast<char*>( &header ), sizeof( header ), '\0' ); +diff -rpuN umbrella/uvadev.peasoup/security_transforms/third_party/ELFIO/elfio-2.2/elfio/elfio_segment.hpp elfio/elfio_segment.hpp +--- umbrella/uvadev.peasoup/security_transforms/third_party/ELFIO/elfio-2.2/elfio/elfio_segment.hpp 2013-05-01 15:17:01.000000000 -0400 ++++ elfio/elfio_segment.hpp 2013-11-22 10:03:00.640843581 -0500 +@@ -23,6 +23,7 @@ THE SOFTWARE. + #ifndef ELFIO_SEGMENT_HPP + #define ELFIO_SEGMENT_HPP + ++#include <istream> + #include <fstream> + #include <vector> + +@@ -52,7 +53,7 @@ class segment + + protected: + virtual void set_index( Elf_Half ) = 0; +- virtual void load( std::ifstream& stream, std::streampos header_offset ) const = 0; ++ virtual void load( std::istream& stream, std::streampos header_offset ) const = 0; + virtual void save( std::ofstream& f, std::streampos header_offset, + std::streampos data_offset ) = 0; + }; +@@ -142,7 +143,7 @@ class segment_impl : public segment + + //------------------------------------------------------------------------------ + void +- load( std::ifstream& stream, ++ load( std::istream& stream, + std::streampos header_offset ) const + { + stream.seekg( header_offset ); -- GitLab