diff --git a/.gitattributes b/.gitattributes index 26df0c319c674f7aba13b73356ce1032b2303edf..98931638e4cd0e8892919f21a4779429fb0f44ee 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1207,6 +1207,7 @@ tools/transforms/AnnotationBoundaryGenerator.cpp -text tools/transforms/AnnotationBoundaryGenerator.hpp -text tools/transforms/DirectOffsetInference.cpp -text tools/transforms/DirectOffsetInference.hpp -text +tools/transforms/EhUpdater.hpp -text tools/transforms/General_Utility.cpp -text tools/transforms/General_Utility.hpp -text tools/transforms/Makefile.in -text diff --git a/libIRDB/include/core/baseobj.hpp b/libIRDB/include/core/baseobj.hpp index 4575331a0595c2aa8669a7a8d5bd94f36e632d2f..20b41051039dfb63eb4d71cce46dd8589b257c4b 100644 --- a/libIRDB/include/core/baseobj.hpp +++ b/libIRDB/include/core/baseobj.hpp @@ -52,6 +52,7 @@ class BaseObj_t static const db_id_t NOT_IN_DATABASE; virtual RelocationSet_t& GetRelocations() { return relocs; } + virtual const RelocationSet_t& GetRelocations() const { return relocs; } protected: diff --git a/libIRDB/include/core/eh.hpp b/libIRDB/include/core/eh.hpp index f720847133c2bcbfe67de817f2e9b4fbdfd96cbe..58b9999df359ffe8c0bf479e68a53e32aaa67b07 100644 --- a/libIRDB/include/core/eh.hpp +++ b/libIRDB/include/core/eh.hpp @@ -26,6 +26,20 @@ class EhProgram_t : public BaseObj_t { public: + EhProgram_t(const EhProgram_t& orig) + : + BaseObj_t(NULL) + { + cie_program=orig.cie_program; + fde_program=orig.fde_program; + code_alignment_factor=orig.code_alignment_factor; + data_alignment_factor=orig.data_alignment_factor; + return_register=orig.return_register; + ptrsize=orig.ptrsize; + SetBaseID(BaseObj_t::NOT_IN_DATABASE); + GetRelocations()=orig.GetRelocations(); + + } EhProgram_t(db_id_t id, const uint64_t caf, const int64_t daf, const uint8_t rr, const uint8_t p_ptrsize) : BaseObj_t(NULL), diff --git a/libIRDB/src/core/fileir.cpp b/libIRDB/src/core/fileir.cpp index d19b493fdff6237de6a586fd8cd1ed8124e6a652..23f15847c4454d3f6ce80c3ea352ce86cadfc221 100644 --- a/libIRDB/src/core/fileir.cpp +++ b/libIRDB/src/core/fileir.cpp @@ -1626,6 +1626,35 @@ void FileIR_t::SplitScoop( } } + + /* look at each relocation in the IR */ + for(auto & r : GetRelocations()) + { + if(r->GetWRT()==tosplit) + { + const auto &addend=r->GetAddend(); + const auto containing_start_offset=(containing -> GetStart()->GetVirtualOffset() - + tosplit->GetStart()->GetVirtualOffset()); + const auto containing_end_offset=containing_start_offset+containing->GetSize(); + if(needs_before && addend<before->GetSize()) + { + r->SetWRT(before); + } + else if( addend < containing_end_offset) + { + r->SetWRT(containing); + r->SetAddend(addend-containing_start_offset); + } + else + { + assert(needs_after); + const auto after_start_offset=(after -> GetStart()->GetVirtualOffset() - + tosplit->GetStart()->GetVirtualOffset()); + r->SetWRT(after); + r->SetAddend(addend-after_start_offset); + } + } + } GetAddresses().erase(tosplit->GetStart()); diff --git a/libIRDB/test/split_eh_frame.cpp b/libIRDB/test/split_eh_frame.cpp index 2e6e132b88ec64f96c0ed82bce94736209a1310b..a60b44c0c8abf19f1c4356e27e8de2243f8f36a6 100644 --- a/libIRDB/test/split_eh_frame.cpp +++ b/libIRDB/test/split_eh_frame.cpp @@ -299,7 +299,7 @@ class eh_program_insn_t } case 3: { - // case DW_CFA_offset: + // case DW_CFA_restore (register #): cout<<" cfa_restore"<<endl; break; } diff --git a/tools/transforms/EhUpdater.hpp b/tools/transforms/EhUpdater.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6f9569fdb976fa991405ed6109775e6868c58c04 --- /dev/null +++ b/tools/transforms/EhUpdater.hpp @@ -0,0 +1,33 @@ +#ifndef EhUpdater +#define EhUpdater + +#include <libIRDB-core.hpp> +#include "PNStackLayout.hpp" + +class EhUpdater_t +{ + public: + + EhUpdater_t(libIRDB::FileIR_t* p_firp, libIRDB::Function_t* p_func, PNStackLayout* p_layout) + : + m_firp(p_firp), + m_func(p_func), + m_layout(p_layout) + { + } + + bool execute(); + + private: + + bool update_instructions(); + bool update_instructions(libIRDB::Instruction_t* insn); + bool update_program(libIRDB::EhProgram_t* ehpgm); + + + libIRDB::FileIR_t* m_firp; + libIRDB::Function_t* m_func; + PNStackLayout* m_layout; +}; + +#endif diff --git a/tools/transforms/PNStackLayout.hpp b/tools/transforms/PNStackLayout.hpp index f0d5c41701071a56df3985f60b31e9c5d9cd373a..d6e28e826bfc3cf1f745eb0d2a2281c7c0fc61a3 100644 --- a/tools/transforms/PNStackLayout.hpp +++ b/tools/transforms/PNStackLayout.hpp @@ -108,7 +108,7 @@ public: virtual int GetNewOffsetESP(int ebp_offset) const; virtual int GetNewOffsetEBP(int ebp_offset) const; virtual PNStackLayout GetCanaryLayout() const; - virtual std::vector<PNRange*> GetRanges() {return mem_objects;} + virtual std::vector<PNRange*> GetRanges() const {return mem_objects;} virtual bool IsCanarySafe() const { assert(pn_options); diff --git a/tools/transforms/PNTransformDriver.cpp b/tools/transforms/PNTransformDriver.cpp index 6b10ce4744d8f45d02448255c275fd78822acbf3..59e249cd95500816eab36f6c352ba47c169397eb 100644 --- a/tools/transforms/PNTransformDriver.cpp +++ b/tools/transforms/PNTransformDriver.cpp @@ -29,6 +29,7 @@ #include <cmath> #include "globals.h" #include <libIRDB-cfg.hpp> +#include "EhUpdater.hpp" #include <fcntl.h> #include <sys/types.h> @@ -37,6 +38,7 @@ #include <sys/types.h> #include <sys/wait.h> + #ifndef PATH_MAX #define PATH_MAX 4096 #endif @@ -236,182 +238,6 @@ void PNTransformDriver::SetProtectSharedObjects(bool do_protection) } -/* - void PNTransformDriver::GenerateTransforms2(FileIR_t *virp,vector<Function_t*> funcs,string BED_script, int progid) - { - for(int i=0;i<funcs.size();++i) - { - //transform all with - - vector<PNStackLayout*> layouts = GenerateInferences(funcs[i], 0); - - if(layouts.size() == 0) - continue; - - sort(layouts.begin(),layouts.end(),CompareBoundaryNumbers); - - if(layouts[0]->CanShuffle()) - { - layouts[0]->Shuffle(); - } - - //just for now padd too - layouts[0]->AddPadding(); - - if(!Rewrite(layouts[0],funcs[i])) - { - //I need to undo instead but right now undo will undo everything - assert(false); - } - } - - //TODO: right now I am passing the first func just to test this out, change validate to accept a string - if(!Validate(virp,funcs[0],BED_script,progid)) - { - undo(undo_list,funcs[0]); - - if(funcs.size()>1) - { - vector<Function_t*> left; - vector<Function_t*> right; - - left.insert(left.begin(),funcs.begin(),funcs.begin()+(funcs.size()/2)); - right.insert(right.begin(),funcs.begin()+(funcs.size()/2),funcs.end()); - - GenerateTransforms2(virp,left,BED_script,progid); - GenerateTransforms2(virp,right,BED_script,progid); - } - else - { - vector<PNStackLayout*> layouts = GenerateInferences(funcs[0],0); - - if(layouts.size() == 0) - return; - - sort(layouts.begin(),layouts.end(),CompareBoundaryNumbers); - - //TODO: I should not have to use the first inference at this point - for(int i=0;i<layouts.size();++i) - { - if(layouts[i]->CanShuffle()) - { - layouts[i]->Shuffle(); - } - - //just for now padd too - layouts[i]->AddPadding(); - - if(!Rewrite(layouts[i],funcs[0])) - { - //I need to undo instead but right now undo will undo everything - assert(false); - } - else if(!Validate(virp,funcs[0],BED_script,progid)) - { - undo(undo_list,funcs[0]); - continue; - } - } - } - } - else - { - cerr<<"Validated "<<funcs.size()<<" functions"<<endl; - virp->WriteToDB(); - undo_list.clear(); - } - - //Call a recursive function that takes in the number of total funcs, and attempts a - //transform and validation - //Divide into N regions, initial N is total_funcs - //for each division, transform all functions, then validate. - //if validation succeeds, commit - //if validation fails, divide N by 2 (if N is odd add one first) - //Attemp transform for those divisions, when completley validated, continue on - - //recursive_validate(virp,total_funcs,BED_script, progid) - //The problem is undoing only part of the undo list - //when all validate, attempt transform again, only shuffling - //when that validates add padding, - //You must remember the most aggressive transform that did not fail in some previous - //run for each function, never use a more aggressive transform. - - //use a map to hold a pnstack layout for every function - //after validation, loop through all functions again, and use these pnstack layouts - //if the layout fails, how do I know which transform to pick next? - //Perhaps another map listing the perferences of transforms? - } -*/ - -bool PNTransformDriver::CanaryTransformHandler(PNStackLayout *layout, Function_t *func, bool validate) -{ - - bool success = false; - - if(!validate) - cerr<<"PNTransformDriver: Function "<<func->GetName()<<" is flagged to be transformed without validation"<<endl; - - cerr<<"PNTransformDriver: Function "<<func->GetName()<<" is canary safe, attempting canary rewrite"<<endl; - - layout->Shuffle(); - layout->AddRandomPadding(do_align); - - if(!Canary_Rewrite(layout,func)) - { - //Experimental code - undo(func); - - //TODO: error message - cerr<<"PNTransformDriver: canary_rewrite failure"<<endl; - } - else - { - //if(!Validate(new_virp,targ_func)) - if(validate && !Validate(orig_virp,func->GetName())) - { - //Experimental code - undo(func); - - //TODO: error message - cerr<<"PNTransformDriver: canary validation failure, rolling back"<<endl; - } - else - { - cerr<<"PNTransformDriver: Final Transformation Success: "<<layout->ToString()<<endl; - cerr<<"PNTransformDriver: Canary rewrite and validation successful."<<endl; - - //TODO: I would like to set something in the data structures to indicate - //the canary is possible, but turned off. - -// fixme jdh canaries per function? - - if(!pn_options->shouldCanaryFunction(func->GetName())) - { - cerr<<"PNTransformDriver: canary transformations turned off, removing canary from transformation."<<endl; - undo(func); - Sans_Canary_Rewrite(layout,func); - } - -// transformed_history[layout->GetLayoutName()].push_back(layout); - - // finalize_record fr; - // fr.layout = layout; - // fr.func = func; - // fr.firp = orig_virp; - // finalization_registry.push_back(fr); - // undo(func); - - success = true; - //TODO: message - - } - } - - //reset_undo(func->GetName()); - - return success; -} - bool PNTransformDriver::PaddingTransformHandler(PNStackLayout *layout, Function_t *func, bool validate) { bool success = false; @@ -546,6 +372,7 @@ void PNTransformDriver::GenerateTransformsInit() jump_table_sanitized = 0; bad_variadic_func_sanitized = 0; pic_jump_table_sanitized = 0; + eh_sanitized = 0; dynamic_frames = 0; high_coverage_count = low_coverage_count = no_coverage_count = validation_count = 0; not_transformable.clear(); @@ -761,7 +588,7 @@ Instruction_t* find_exit_insn(Instruction_t *insn, Function_t *func) { DISASM d; prev->Disassemble(d); - if(strstr(d.CompleteInstr,"ret")!=NULL) // return ret. + if(strstr(d.CompleteInstr,"ret ")!=NULL) // return ret. return prev; return NULL; // indirect branch } @@ -1270,6 +1097,18 @@ void PNTransformDriver::SanitizeFunctions() continue; } } + // if it's not already sanitized + if(sanitized.find(func)==sanitized.end()) + { + if(instr->GetEhCallSite() && + instr->GetEhCallSite()->GetLandingPad() && + instr->GetEhCallSite()->GetLandingPad()->GetFunction()!=func) + { + eh_sanitized++; + sanitized.insert(func); + continue; + } + } } // if it's not already sanitized @@ -1294,7 +1133,6 @@ void PNTransformDriver::SanitizeFunctions() continue; } } - } //TODO: print sanitized list. @@ -2024,6 +1862,7 @@ void PNTransformDriver::Print_Report() cerr<<"Blacklisted Functions \t\t"<<blacklist_funcs<<endl; cerr<<"Sanitized Functions \t\t"<<sanitized_funcs<<endl; cerr<<"Push/Pop Sanitized Functions \t\t"<<push_pop_sanitized_funcs<<endl; + cerr<<"EH-land-pad-not-in-func Sanitized Functions \t\t"<<eh_sanitized<<endl; cerr<<"Bad Variadic Sanitized Functions \t\t"<<push_pop_sanitized_funcs<<endl; cerr<<"Jump table Sanitized Functions \t\t"<<jump_table_sanitized<<endl; cerr<<"PIC Jump table Sanitized Functions \t\t"<<jump_table_sanitized<<endl; @@ -2435,6 +2274,10 @@ bool PNTransformDriver::Canary_Rewrite(PNStackLayout *orig_layout, Function_t *f orig_layout->SetBaseID(func->GetBaseID()); orig_layout->SetEntryID(func->GetEntryPoint()->GetBaseID()); + EhUpdater_t eh_update(orig_virp, func, layout); + if(!eh_update.execute()) + return false; + return true; } @@ -2464,6 +2307,9 @@ bool PNTransformDriver::Sans_Canary_Rewrite(PNStackLayout *layout, Function_t *f if(!Instruction_Rewrite(layout,instr,&cfg)) return false; } + EhUpdater_t eh_update(orig_virp, func, layout); + if(!eh_update.execute()) + return false; return true; } @@ -3110,6 +2956,7 @@ void PNTransformDriver::undo(Function_t *func) { orig_virp->UnregisterAssembly(*it); orig_virp->GetInstructions().erase(*it); + func->GetInstructions().erase(*it); delete *it; } diff --git a/tools/transforms/PNTransformDriver.hpp b/tools/transforms/PNTransformDriver.hpp index d57d5b098c7e3ecb68b0934966528f8bafadb204..acc41b3648008661a7c3d9cdfc8b20ffaf418db6 100644 --- a/tools/transforms/PNTransformDriver.hpp +++ b/tools/transforms/PNTransformDriver.hpp @@ -89,6 +89,7 @@ class PNTransformDriver int bad_variadic_func_sanitized; int jump_table_sanitized; int pic_jump_table_sanitized; + int eh_sanitized; int total_funcs; int dynamic_frames; std::vector<std::string> not_transformable; @@ -131,7 +132,7 @@ class PNTransformDriver virtual void Print_Report(); virtual void Print_Map(); - virtual bool CanaryTransformHandler(PNStackLayout *layout, libIRDB::Function_t *func,bool validate); +// virtual bool CanaryTransformHandler(PNStackLayout *layout, libIRDB::Function_t *func,bool validate); virtual bool PaddingTransformHandler(PNStackLayout *layout, libIRDB::Function_t *func,bool validate); virtual bool LayoutRandTransformHandler(PNStackLayout *layout, libIRDB::Function_t *func, bool validate); virtual void GenerateTransformsInit(); diff --git a/tools/transforms/Rewrite_Utility.cpp b/tools/transforms/Rewrite_Utility.cpp index 957333fb091d42cdeb3ee72e5704c4f5101f7645..69315e901c91c1b23eacaca79a1c8fa367875f3c 100644 --- a/tools/transforms/Rewrite_Utility.cpp +++ b/tools/transforms/Rewrite_Utility.cpp @@ -137,6 +137,8 @@ void copyInstruction(Instruction_t* src, Instruction_t* dest) dest->SetTarget(src->GetTarget()); dest->SetIBTargets(src->GetIBTargets()); dest->GetRelocations()=src->GetRelocations(); + dest->SetEhProgram(src->GetEhProgram()); + dest->SetEhCallSite(src->GetEhCallSite()); } Instruction_t* allocateNewInstruction(FileIR_t* virp, db_id_t p_fileID,Function_t* func) @@ -356,6 +358,7 @@ Instruction_t* getHandlerCode(FileIR_t* virp, Instruction_t* fallthrough, mitiga Instruction_t* insertCanaryCheckBefore(FileIR_t* virp,Instruction_t *first, unsigned int canary_val, int esp_offset, Instruction_t *fail_code) { + auto do_zero=(first->getDisassembly().find("ret")!=string::npos); stringstream ss; const char *sp_reg="esp"; if(virp->GetArchitectureBitWidth()==64) @@ -387,7 +390,9 @@ Instruction_t* insertCanaryCheckBefore(FileIR_t* virp,Instruction_t *first, unsi //TODO: move canary zero to option if(esp_neg) esp_offset *= -1; - insertCanaryZeroAfter(virp,first,esp_offset,fail_code); + + if(do_zero) + insertCanaryZeroAfter(virp,first,esp_offset,fail_code); return next; diff --git a/tools/transforms/SConscript b/tools/transforms/SConscript index bd3b7da4bfc02515670cc4ead7d587541996258b..9b49aec67392439a25ad44af02faf3b9b1be963e 100644 --- a/tools/transforms/SConscript +++ b/tools/transforms/SConscript @@ -6,9 +6,6 @@ myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) libname="IRDB-util" -files= ''' - insn_preds.cpp - ''' cpppath=''' $SECURITY_TRANSFORMS_HOME/include/ $SECURITY_TRANSFORMS_HOME/libIRDB/include/ @@ -28,7 +25,9 @@ integer_files="transformutils.cpp integertransformdriver.cpp" #myenv.Append(CFLAGS="-Wall") #myenv.Append(CCFLAGS="-Wall") -all_files="PNTransformDriver.cpp PNStackLayout.cpp PNRange.cpp Range.cpp OffsetInference.cpp DirectOffsetInference.cpp ScaledOffsetInference.cpp P1Inference.cpp PNRegularExpressions.cpp PNMain.cpp StackLayout.cpp General_Utility.cpp AnnotationBoundaryGenerator.cpp PrecedenceBoundaryInference.cpp PNIrdbManager.cpp" +myenv.Append(CXXFLAGS = " -std=c++11 ") + +all_files="PNTransformDriver.cpp PNStackLayout.cpp PNRange.cpp Range.cpp OffsetInference.cpp DirectOffsetInference.cpp ScaledOffsetInference.cpp P1Inference.cpp PNRegularExpressions.cpp PNMain.cpp StackLayout.cpp General_Utility.cpp AnnotationBoundaryGenerator.cpp PrecedenceBoundaryInference.cpp PNIrdbManager.cpp EhUpdater.cpp" myenv=myenv.Clone(CPPPATH=Split(cpppath))