From b47ed70442f8692650f0dbe7c3f3d1a933156167 Mon Sep 17 00:00:00 2001 From: Jason Hiser <jdhiser@gmail.com> Date: Wed, 20 Mar 2019 10:50:19 -0400 Subject: [PATCH] win extensions for specifying the file's base address --- irdb-libs/ir_builders/fix_calls.cpp | 81 +++------------------ irdb-libs/libEXEIO/src/exeio_pe.h | 10 ++- irdb-libs/libIRDB-core/include/archdesc.hpp | 4 + irdb-libs/libIRDB-core/src/fileir.cpp | 77 +++++++++++++++++++- irdb-libs/third_party/pebliss | 2 +- irdb-sdk | 2 +- tools/ps_analyze.sh | 8 +- 7 files changed, 107 insertions(+), 77 deletions(-) diff --git a/irdb-libs/ir_builders/fix_calls.cpp b/irdb-libs/ir_builders/fix_calls.cpp index f9b24351e..c66480b7e 100644 --- a/irdb-libs/ir_builders/fix_calls.cpp +++ b/irdb-libs/ir_builders/fix_calls.cpp @@ -369,9 +369,9 @@ string adjust_esp_offset(string newbits, int offset) } /* 8-bit offset */ - else if ( (unsigned char)newbits[0] == 0xff && /* ff */ - ((unsigned char)newbits[1] == 0x54 || (unsigned char)newbits[1]==0xa4) && /* /3 or /5 */ - sib_base == 0x4 ) /* base==esp */ + else if ( (unsigned char)newbits[0] == 0xff && // ff + ((unsigned char)newbits[1] == 0x54 || (unsigned char)newbits[1]==0xa4) && // /3 or /5 + sib_base == 0x4 ) // base==esp { /* We need to add 4 to the offset, but this may overflow an 8-bit quantity * (note: there's no 16-bit offset for this insn. Only 8-bit or 32-bit offsets exist for this instr) @@ -540,16 +540,7 @@ void fix_call(Instruction_t* insn, FileIR_t *firp, bool can_unpin) VirtualOffset_t next_addr=insn->getAddress()->getVirtualOffset() + insn->getDataBits().length(); /* create a new instruction and a new addresss for it that do not correspond to any original program address */ - /* - Instruction_t *callinsn=new Instruction_t(); - firp->getInstructions().insert(callinsn); - */ auto callinsn=firp->addNewInstruction(); - /* - AddressID_t *calladdr=new AddressID_t; - firp->getAddresses().insert(calladdr); - calladdr->setFileID(insn->getAddress()->getFileID()); - */ auto calladdr=firp->addNewAddress(insn->getAddress()->getFileID(),0); /* set the fields in the new instruction */ @@ -599,21 +590,8 @@ void fix_call(Instruction_t* insn, FileIR_t *firp, bool can_unpin) insn->setComment(insn->getComment()+" Push part"); /* create a relocation for this instruction */ - /* - Relocation_t* reloc=new Relocation_t; - insn->getRelocations().insert(reloc); - firp->getRelocations().insert(reloc); - */ auto reloc= firp->getArchitectureBitWidth()==32 ? firp->addNewRelocation(insn, 1, "32-bit") : - /* - reloc->setOffset(1); - reloc->setType("32-bit"); - */ firp->getArchitectureBitWidth()==64 ? firp->addNewRelocation(insn, 0, "push64") : - /* - reloc->setOffset(0); - reloc->setType("push64"); - */ throw invalid_argument("odd bit width?"); @@ -622,13 +600,6 @@ void fix_call(Instruction_t* insn, FileIR_t *firp, bool can_unpin) if(newindirtarg && !newindirtarg->getIndirectBranchTargetAddress()) { /* create a new address for the IBTA */ - /* - AddressID_t* newaddr = new AddressID_t; - assert(newaddr); - newaddr->setFileID(newindirtarg->getAddress()->getFileID()); - newaddr->setVirtualOffset(newindirtarg->getAddress()->getVirtualOffset()); - firp->getAddresses().insert(newaddr); - */ auto newaddr=firp->addNewAddress(newindirtarg->getAddress()->getFileID(), newindirtarg->getAddress()->getVirtualOffset()); /* set the instruction and include this address in the list of addrs */ @@ -650,18 +621,8 @@ void fix_call(Instruction_t* insn, FileIR_t *firp, bool can_unpin) // mark in the IR what the fallthrough of this insn is. - /* - Relocation_t* fix_call_reloc=new Relocation_t(); - callinsn->getRelocations().insert(fix_call_reloc); - firp->getRelocations().insert(fix_call_reloc); - */ auto fix_call_reloc=firp->addNewRelocation(callinsn, 0, "fix_call_fallthrough", newindirtarg); (void)fix_call_reloc; // not used, just give to IR - /* - fix_call_reloc->setOffset(0); - fix_call_reloc->setType("fix_call_fallthrough"); - fix_call_reloc->setWRT(newindirtarg); - */ } @@ -703,9 +664,12 @@ bool can_skip_safe_function(Instruction_t *call_insn) } -template <class T> struct insn_less : binary_function <T,T,bool> { - bool operator() (const T& x, const T& y) const { - return x->getBaseID() < y->getBaseID() ;} +template <class T> struct insn_less : binary_function <T,T,bool> +{ + bool operator() (const T& x, const T& y) const + { + return make_tuple(x->getBaseID(),x) < make_tuple(y->getBaseID(),y); + } }; @@ -717,14 +681,6 @@ void mark_as_unpinned_ibt(FileIR_t* firp, Instruction_t* ret_point) if( ret_point == NULL ) return; if( ret_point->getIndirectBranchTargetAddress() != NULL ) return; - /* - auto newaddr = new AddressID_t; - assert(newaddr); - newaddr->setFileID(ret_point->getAddress()->getFileID()); - newaddr->setVirtualOffset(0); // unpinne - - firp->getAddresses().insert(newaddr); - */ auto newaddr=firp->addNewAddress(ret_point->getAddress()->getFileID(),0); ret_point->setIndirectBranchTargetAddress(newaddr); @@ -859,9 +815,9 @@ void fix_other_pcrel(FileIR_t* firp, Instruction_t *insn, uintptr_t virt_offset) memcpy(cstr,data.c_str(), data.length()); void *offsetptr=&cstr[offset]; - uintptr_t disp=the_arg.getMemoryDisplacement(); - uintptr_t oldpc=virt_offset; - uintptr_t newdisp=disp+oldpc; + auto disp=the_arg.getMemoryDisplacement(); + auto oldpc=virt_offset; + auto newdisp=disp+oldpc-firp->getArchitecture()->getFileBase(); assert((uintptr_t)(offset+size)<=(uintptr_t)(data.length())); @@ -894,11 +850,6 @@ void fix_other_pcrel(FileIR_t* firp, Instruction_t *insn, uintptr_t virt_offset) } // now that we've done the rewriting, go ahead and add the reloc. - /* - auto reloc=new Relocation_t(BaseObj_t::NOT_IN_DATABASE, 0,"pcrel"); - insn->getRelocations().insert(reloc); - firp->getRelocations().insert(reloc); - */ auto reloc=firp->addNewRelocation(insn,0,"pcrel"); (void)reloc; // not used, only given to the IR @@ -916,10 +867,6 @@ void fix_safefr(FileIR_t* firp, Instruction_t *insn, uintptr_t virt_offset) assert(reloc); if( reloc->getType() == "safefr" ) { - /* - auto addr=new AddressID_t(BaseObj_t::NOT_IN_DATABASE, insn->getAddress()->getFileID(), 0); - firp->getAddresses().insert(addr); - */ auto addr=firp->addNewAddress(insn->getAddress()->getFileID(), 0); insn->setAddress(addr); } @@ -929,7 +876,6 @@ void fix_safefr(FileIR_t* firp, Instruction_t *insn, uintptr_t virt_offset) void fix_other_pcrel(FileIR_t* firp) { - for(auto insn : firp->getInstructions()) { fix_other_pcrel(firp,insn, insn->getAddress()->getVirtualOffset()); @@ -1008,7 +954,6 @@ int parseArgs(const vector<string> step_args) if(getenv("FIX_CALLS_FIX_ALL_CALLS")) fix_all=true; -// variant_id=stoi(step_args[0]); return 0; } @@ -1169,8 +1114,6 @@ shared_ptr<TransformStep_t> getTransformStep(void) { curInvocation.reset(new FixCalls_t()); return curInvocation; - - //return shared_ptr<Transform_SDK::TransformStep_t>(new FixCalls_t()); } diff --git a/irdb-libs/libEXEIO/src/exeio_pe.h b/irdb-libs/libEXEIO/src/exeio_pe.h index 868ddeec9..07162ee9c 100644 --- a/irdb-libs/libEXEIO/src/exeio_pe.h +++ b/irdb-libs/libEXEIO/src/exeio_pe.h @@ -132,7 +132,15 @@ namespace EXEIO } virtual MachineType_t getMachineType() const { - assert(0); + assert(e); + switch(e->get_machine()) + { + case 0x14c : return mtI386; + case 0x8664 : return mtX86_64; + default: assert(0); + } + assert(0); + } virtual execlass_t get_class() diff --git a/irdb-libs/libIRDB-core/include/archdesc.hpp b/irdb-libs/libIRDB-core/include/archdesc.hpp index e7299d450..d1a98ba67 100644 --- a/irdb-libs/libIRDB-core/include/archdesc.hpp +++ b/irdb-libs/libIRDB-core/include/archdesc.hpp @@ -41,11 +41,15 @@ class ArchitectureDescription_t : virtual public IRDB_SDK::ArchitectureDescripti ADMachineType_t getMachineType() const { return mt; } void setMachineType(const ADMachineType_t t) { mt=t; } + IRDB_SDK::VirtualOffset_t getFileBase() const { return file_base; } + void setFileBase(virtual_offset_t _file_base) { file_base=_file_base; } + private: size_t bits; ADFileType_t ft; ADMachineType_t mt; + IRDB_SDK::VirtualOffset_t file_base; }; } diff --git a/irdb-libs/libIRDB-core/src/fileir.cpp b/irdb-libs/libIRDB-core/src/fileir.cpp index 14502548e..e1d3fd15a 100644 --- a/irdb-libs/libIRDB-core/src/fileir.cpp +++ b/irdb-libs/libIRDB-core/src/fileir.cpp @@ -977,6 +977,8 @@ void FileIR_t::setArchitecture(const int width, const ADMachineType_t mt) archdesc=new ArchitectureDescription_t; archdesc->setBitWidth(width); archdesc->setMachineType(mt); + + archdesc->setFileBase(0); // maybe not rght for PE files? } void FileIR_t::setArchitecture() @@ -1025,12 +1027,85 @@ void FileIR_t::setArchitecture() } - if (is_pe) // libIRDB::FileIR_t::archdesc->getFileType() == IRDB_SDK::adftPE) + if (is_pe) { + // set machine/file types libIRDB::FileIR_t::archdesc->setFileType(IRDB_SDK::adftPE); // just assume x86-64 bit for Windows, o/w could also extract from file libIRDB::FileIR_t::archdesc->setBitWidth(64); libIRDB::FileIR_t::archdesc->setMachineType(IRDB_SDK::admtX86_64); + + // now we need to read the image base from the exe file + + //DOS .EXE header + struct irdb_dos_header + { + uint16_t e_magic; // Magic number + uint16_t e_cblp; // Bytes on last page of file + uint16_t e_cp; // Pages in file + uint16_t e_crlc; // Relocations + uint16_t e_cparhdr; // Size of header in paragraphs + uint16_t e_minalloc; // Minimum extra paragraphs needed + uint16_t e_maxalloc; // Maximum extra paragraphs needed + uint16_t e_ss; // Initial (relative) SS value + uint16_t e_sp; // Initial SP value + uint16_t e_csum; // Checksum + uint16_t e_ip; // Initial IP value + uint16_t e_cs; // Initial (relative) CS value + uint16_t e_lfarlc; // File address of relocation table + uint16_t e_ovno; // Overlay number + uint16_t e_res[4]; // Reserved words + uint16_t e_oemid; // OEM identifier (for e_oeminfo) + uint16_t e_oeminfo; // OEM information; e_oemid specific + uint16_t e_res2[10]; // Reserved words + int32_t e_lfanew; // File address of new exe header + }; + + struct irdb_image_pe_headers64 + { + uint32_t Signature; + uint16_t Machine; + uint16_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; + uint16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + uint32_t SizeOfCode; + uint32_t SizeOfInitializedData; + uint32_t SizeOfUninitializedData; + uint32_t AddressOfEntryPoint; + uint32_t BaseOfCode; + + // ImageBase is a uint32_t for 32-bit code. + uint64_t ImageBase; + + }; + + + // declare and init a dos header. + struct irdb_dos_header idh; + memset(&idh,0,sizeof(idh)); + struct irdb_image_pe_headers64 pe_and_opt_headers; + memset(&pe_and_opt_headers,0,sizeof(pe_and_opt_headers)); + + loa.seek(0, ios::beg); + loa.cread((char*)&idh, sizeof(idh)); + + loa.seek(idh.e_lfanew, ios::beg); + loa.cread((char*)&pe_and_opt_headers, sizeof(pe_and_opt_headers)); + + assert(pe_and_opt_headers.Signature ==0x4550 /* "PE" means pe file */); + assert(pe_and_opt_headers.Magic ==0x20b /* "8664" means 64-bits */); + /* note: if pe_and_opt_headers.Magic==0x10b that means "8632" or intel 32-bit file. not supporting yet. */ + + if(getenv("IRDB_VERBOSE")) + cout<<"Determined PE32+ file has image base: "<<hex<<pe_and_opt_headers.ImageBase<<endl; + + archdesc->setFileBase(pe_and_opt_headers.ImageBase); } else if(is_elf) { diff --git a/irdb-libs/third_party/pebliss b/irdb-libs/third_party/pebliss index d1474211e..c8a66676b 160000 --- a/irdb-libs/third_party/pebliss +++ b/irdb-libs/third_party/pebliss @@ -1 +1 @@ -Subproject commit d1474211e317b243786ec06b383fd4edb2c8cca8 +Subproject commit c8a66676b446db15e431fd53de1e2ae50ca7afd8 diff --git a/irdb-sdk b/irdb-sdk index 5e547d1df..653c5df9d 160000 --- a/irdb-sdk +++ b/irdb-sdk @@ -1 +1 @@ -Subproject commit 5e547d1dfb046cf5d353c95c46bb86f06271deaf +Subproject commit 653c5df9d09af46808330375a87bab2414fc3a02 diff --git a/tools/ps_analyze.sh b/tools/ps_analyze.sh index fd060ce22..22254af90 100755 --- a/tools/ps_analyze.sh +++ b/tools/ps_analyze.sh @@ -1038,17 +1038,17 @@ compatcheck() file $1 |egrep "ELF.*executable" > /dev/null 2>&1 if [ $? = 0 ]; then - echo Detected ELF file. + echo "Detected ELF non-PIE executable." return fi file $1 |egrep "ELF.*shared object" > /dev/null 2>&1 if [ $? = 0 ]; then - echo Detected ELF shared object. + echo "Detected ELF shared object." return fi - file $1 |egrep "CGC.*executable" > /dev/null 2>&1 + file $1 |egrep "PE32\+ executable" > /dev/null 2>&1 if [ $? = 0 ]; then - echo Detected CGCEF file. + echo "Detected PE32+ file" return fi -- GitLab