From 95cfa65fb84514f7d6c389fd631b61264431ffca Mon Sep 17 00:00:00 2001 From: jdh8d <jdh8d@git.zephyr-software.com> Date: Sun, 27 Dec 2015 01:29:51 +0000 Subject: [PATCH] updates to handle ICFS better. Former-commit-id: f66e63420631190271a4540d85026cd85d64d3fe --- .gitattributes | 2 + libIRDB/include/core/icfs.hpp | 16 +--- libIRDB/include/core/instruction.hpp | 66 ++++++------- libIRDB/test/SConscript | 4 + libIRDB/test/fill_in_indtargs.cpp | 34 ++++--- tools/selective_cfi/SConscript | 2 +- tools/selective_cfi/color_map.cpp | 83 +++++++++++++++++ tools/selective_cfi/color_map.hpp | 133 +++++++++++++++++++++++++++ tools/selective_cfi/scfi_driver.cpp | 15 ++- tools/selective_cfi/scfi_instr.cpp | 113 ++++++++++++++++++----- tools/selective_cfi/scfi_instr.hpp | 11 ++- 11 files changed, 391 insertions(+), 88 deletions(-) create mode 100644 tools/selective_cfi/color_map.cpp create mode 100644 tools/selective_cfi/color_map.hpp diff --git a/.gitattributes b/.gitattributes index 2e88f925e..df19ed873 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1109,6 +1109,8 @@ tools/safefr/fill_in_safefr.cpp -text tools/selective_cfi/Makefile.in -text tools/selective_cfi/SConscript -text tools/selective_cfi/SConstruct -text +tools/selective_cfi/color_map.cpp -text +tools/selective_cfi/color_map.hpp -text tools/selective_cfi/scfi_driver.cpp -text tools/selective_cfi/scfi_instr.cpp -text tools/selective_cfi/scfi_instr.hpp -text diff --git a/libIRDB/include/core/icfs.hpp b/libIRDB/include/core/icfs.hpp index 3331c6326..78b4f6c5a 100644 --- a/libIRDB/include/core/icfs.hpp +++ b/libIRDB/include/core/icfs.hpp @@ -33,21 +33,9 @@ class ICFS_t : public InstructionSet_t, public BaseObj_t } std::string WriteToDB(File_t *fid); - ICFS_t& operator=(const InstructionSet_t &other) + void SetTargets(const InstructionSet_t &other) { - if (this == &other) - return *this; - - this->clear(); - - for (InstructionSet_t::const_iterator it = other.begin(); - it != other.end(); ++it) - { - this->insert(*it); - } - - return *this; - + InstructionSet_t::operator=(other); } void SetComplete(bool complete) { is_complete = complete; } bool IsComplete() const { return is_complete; } diff --git a/libIRDB/include/core/instruction.hpp b/libIRDB/include/core/instruction.hpp index 674588b66..ebe3f4507 100644 --- a/libIRDB/include/core/instruction.hpp +++ b/libIRDB/include/core/instruction.hpp @@ -28,40 +28,40 @@ typedef std::set<Relocation_t*> RelocationSet_t; // The basic instruction of a variant. class Instruction_t : public BaseObj_t { - public: + public: Instruction_t(); Instruction_t(db_id_t id, AddressID_t *addr, Function_t *func, db_id_t orig_id, std::string data, std::string callback, std::string comment, AddressID_t *my_indTarg, db_id_t doip_id); - AddressID_t* GetAddress() const { return my_address; } - Function_t* GetFunction() const { return my_function; } - db_id_t GetOriginalAddressID() const { return orig_address_id; } - Instruction_t* GetFallthrough() const { return fallthrough; } - Instruction_t* GetTarget() const { return target; } + AddressID_t* GetAddress() const { return my_address; } + Function_t* GetFunction() const { return my_function; } + db_id_t GetOriginalAddressID() const { return orig_address_id; } + Instruction_t* GetFallthrough() const { return fallthrough; } + Instruction_t* GetTarget() const { return target; } ICFS_t* GetIBTargets() const { return icfs; } - std::string GetDataBits() const { return data; } - std::string GetCallback() const { return callback; } - std::string GetComment() const { return comment; } + std::string GetDataBits() const { return data; } + std::string GetCallback() const { return callback; } + std::string GetComment() const { return comment; } - void SetAddress(AddressID_t* newaddr) { my_address=newaddr; } - void SetFunction(Function_t* func ) { my_function=func;} - void SetOriginalAddressID(db_id_t origid) { orig_address_id=origid; /* you shouldn't do this, unless you know what you're doing! */} - void SetFallthrough(Instruction_t* i) { fallthrough=i; } - void SetTarget(Instruction_t* i) { target=i; } - void SetIBTargets(ICFS_t *p_icfs) { icfs=p_icfs; } - void SetDataBits(std::string orig) { data=orig; } - void SetCallback(std::string orig) { callback=orig; } - void SetComment(std::string orig) { comment=orig; } + void SetAddress(AddressID_t* newaddr) { my_address=newaddr; } + void SetFunction(Function_t* func ) { my_function=func;} + void SetOriginalAddressID(db_id_t origid) { orig_address_id=origid; /* you shouldn't do this, unless you know what you're doing! */} + void SetFallthrough(Instruction_t* i) { fallthrough=i; } + void SetTarget(Instruction_t* i) { target=i; } + void SetIBTargets(ICFS_t *p_icfs) { icfs=p_icfs; } + void SetDataBits(std::string orig) { data=orig; } + void SetCallback(std::string orig) { callback=orig; } + void SetComment(std::string orig) { comment=orig; } - AddressID_t* GetIndirectBranchTargetAddress() { return indTarg; } + AddressID_t* GetIndirectBranchTargetAddress() { return indTarg; } void SetIndirectBranchTargetAddress(AddressID_t* myIndTarg) { indTarg=myIndTarg; } void WriteToDB() { assert(0); } - std::string WriteToDB(File_t *fid, db_id_t newid, bool p_withHeader); - int Disassemble(DISASM &d) const; + std::string WriteToDB(File_t *fid, db_id_t newid, bool p_withHeader); + int Disassemble(DISASM &d) const; std::string getDisassembly() const; - bool Assemble(std::string assembly); + bool Assemble(std::string assembly); bool IsFunctionExit() const; @@ -72,16 +72,16 @@ class Instruction_t : public BaseObj_t bool IsSyscall() { return getDisassembly().find("int 0x80") != std::string::npos; } - private: - AddressID_t* my_address; - Function_t* my_function; - db_id_t orig_address_id; // const, should not change. - Instruction_t* fallthrough; - Instruction_t* target; - std::string data; - std::string callback; // name of callback handler (if any) - std::string comment; - AddressID_t* indTarg; + private: + AddressID_t* my_address; + Function_t* my_function; + db_id_t orig_address_id; // const, should not change. + Instruction_t* fallthrough; + Instruction_t* target; + std::string data; + std::string callback; // name of callback handler (if any) + std::string comment; + AddressID_t* indTarg; RelocationSet_t relocs; - ICFS_t* icfs; + ICFS_t* icfs; }; diff --git a/libIRDB/test/SConscript b/libIRDB/test/SConscript index 0f831fd8a..8d3ef63ca 100644 --- a/libIRDB/test/SConscript +++ b/libIRDB/test/SConscript @@ -20,7 +20,11 @@ print LIBS myenv=myenv.Clone(CPPPATH=Split(cpppath)) ehframe=myenv.Object("read_ehframe.cpp"); + pgm=myenv.Program("fill_in_indtargs.exe", ehframe+Split("fill_in_indtargs.cpp check_thunks.cpp"), LIBPATH=LIBPATH, LIBS=LIBS) +install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm) +Default(install) + pgm=myenv.Program("fix_calls.exe", ehframe+Split("fix_calls.cpp"), LIBPATH=LIBPATH, LIBS=LIBS) install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm) Default(install) diff --git a/libIRDB/test/fill_in_indtargs.cpp b/libIRDB/test/fill_in_indtargs.cpp index 648f8cf31..1543dae19 100644 --- a/libIRDB/test/fill_in_indtargs.cpp +++ b/libIRDB/test/fill_in_indtargs.cpp @@ -62,10 +62,10 @@ set<virtual_offset_t> targets; set< pair< virtual_offset_t, virtual_offset_t> > ranges; // a way to map an instruction to its set of predecessors. -map< Instruction_t* , set<Instruction_t*> > preds; +map< Instruction_t* , InstructionSet_t > preds; // keep track of jmp tables -map< Instruction_t*, set<Instruction_t*> > jmptables; +map< Instruction_t*, InstructionSet_t > jmptables; void check_for_PIC_switch_table32_type2(Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases); void check_for_PIC_switch_table32_type3(Instruction_t* insn, DISASM disasm, EXEIO::exeio* elfiop, const set<virtual_offset_t>& thunk_bases); @@ -240,11 +240,11 @@ Instruction_t *lookupInstruction(FileIR_t *firp, virtual_offset_t virtual_offset void mark_jmptables(FileIR_t *firp) { - map< Instruction_t*, set<Instruction_t*> >::iterator it; + map< Instruction_t*, InstructionSet_t >::iterator it; for (it = jmptables.begin(); it != jmptables.end(); ++it) { Instruction_t* instr = it->first; - set<Instruction_t*> instruction_targets = it->second; + const InstructionSet_t &instruction_targets = it->second; // ignore if instr already marked complete. // FIXME: assert that fill_in_indtarg analysis matches already complete analysis. @@ -254,7 +254,7 @@ void mark_jmptables(FileIR_t *firp) assert(instruction_targets.size() > 0); ICFS_t* new_icfs = new ICFS_t(next_icfs_set_id++, true); - *new_icfs = instruction_targets; + new_icfs->SetTargets(instruction_targets); firp->GetAllICFS().insert(new_icfs); instr->SetIBTargets(new_icfs); @@ -1457,8 +1457,15 @@ void icfs_set_indirect_calls(FileIR_t* const firp, ICFS_t* const targets) ) { Function_t *func=*it; + + // no entry point, doesn't count if(!func->GetEntryPoint()) continue; + + // if it's no an indirectly called function, it doesn't count + if(!func->GetEntryPoint()->GetIndirectBranchTargetAddress()) + continue; + targets->insert(func->GetEntryPoint()); } } @@ -1489,6 +1496,7 @@ void check_for_ret(FileIR_t* const firp, Instruction_t* const insn) if(strstr(d.Instruction.Mnemonic, "ret")==NULL) return; + // already analysed by ida. if(insn->GetIBTargets() && insn->GetIBTargets()->IsComplete()) return; @@ -1496,10 +1504,17 @@ void check_for_ret(FileIR_t* const firp, Instruction_t* const insn) insn->SetIBTargets(hellnode_tgts); } +// find any indirect jumps in the pgm and mark them as having a hell node ICFS if they don't +// already have a complete ICFS. void check_for_indirect_jmp(FileIR_t* const firp, Instruction_t* const insn) { + cout<<"In check_for_indirect_jmp, whta?!"<<endl; assert(firp && insn); + // already analysed by ida. + if(insn->GetIBTargets() && insn->GetIBTargets()->IsComplete()) + return; + DISASM d; insn->Disassemble(d); @@ -1508,17 +1523,10 @@ void check_for_indirect_jmp(FileIR_t* const firp, Instruction_t* const insn) if(d.Argument1.ArgType®ISTER_TYPE) { - // already analysed by ida. - if(insn->GetIBTargets() && insn->GetIBTargets()->IsComplete()) - return; insn->SetIBTargets(hellnode_tgts); } - else if(d.Argument1.ArgType&MEMORY_TYPE && - (!d.Argument1.ArgType&RELATIVE_)) + else if(d.Argument1.ArgType&MEMORY_TYPE) { - // already analysed by ida. - if(insn->GetIBTargets() && insn->GetIBTargets()->IsComplete()) - return; insn->SetIBTargets(hellnode_tgts); } } diff --git a/tools/selective_cfi/SConscript b/tools/selective_cfi/SConscript index f7748b1ad..5f94194fb 100644 --- a/tools/selective_cfi/SConscript +++ b/tools/selective_cfi/SConscript @@ -24,7 +24,7 @@ LIBPATH="$SECURITY_TRANSFORMS_HOME/lib" LIBS=Split( env.subst('$BASE_IRDB_LIBS')+ " IRDB-cfg IRDB-util transform rewrite MEDSannotation ") myenv=myenv.Clone(CPPPATH=Split(cpppath)) pgm=myenv.Program(pgm, files, LIBPATH=LIBPATH, LIBS=LIBS) -install=myenv.Install("$SECURITY_TRANSFORMS_HOME/bin/", pgm) +install=myenv.Install("$SECURITY_TRANSFORMS_HOME/plugins_install/", pgm) Default(install) diff --git a/tools/selective_cfi/color_map.cpp b/tools/selective_cfi/color_map.cpp new file mode 100644 index 000000000..c01212218 --- /dev/null +++ b/tools/selective_cfi/color_map.cpp @@ -0,0 +1,83 @@ + +#include "color_map.hpp" + +using namespace std; +using namespace libIRDB; + + +bool ColoredInstructionNonces_t::create() +{ + UniqueICFSSet_t unique_icfs; + + assert(firp); + const ICFSSet_t& all_icfs=firp->GetAllICFS(); + for(ICFSSet_t::iterator it=all_icfs.begin(); it!=all_icfs.end(); ++it) + { + ICFS_t* p=*it; + assert(p); + unique_icfs.insert( *p ); + } + + ColoredSlotValue_t v; + for(UniqueICFSSet_t::iterator it=unique_icfs.begin(); it!=unique_icfs.end(); ++it) + { + const ICFS_t& the_icfs=*it; + + for(int slot_no=0; ; slot_no++) + { + // check if we need to allocate a new slot + if(slot_no<slots_used.size()) + { + // skip any slots that are full. + if(!slots_used[slot_no].CanReserve()) + goto next_slot; + } + else + { + // allocate slot + slots_used.push_back(ColoredSlotAllocator_t(slot_no,slot_values)); + } + + // check if any of the targets for this branch already have a slot filled. + for(ICFS_t::iterator it2=the_icfs.begin(); it2!=the_icfs.end(); ++it2) + { + Instruction_t* target=*it2; + if(color_assignments[target][slot_no].IsValid()) + goto next_slot; + } + + // if we get here, the slot is valid for all targets, we can reserve it. + v=slots_used[slot_no].Reserve(); + + // and record the reservation for each target. + slot_assignments[the_icfs]=v; + for(ICFS_t::iterator it2=the_icfs.begin(); it2!=the_icfs.end(); ++it2) + { + Instruction_t* target=*it2; + color_assignments[target][slot_no]=v; + cout<<"Setting [slot][color] for "<<target->GetBaseID()<<":"<<target->getDisassembly() + <<"=["<<v.GetPosition()<<"]["<<hex<<v.GetNonceValue()<<dec<<"]"<<endl; + } + + // and we're done with this ICFS + break; + + + // inc the slot no and try again. + next_slot: + // try next; + ; // neded statement for compiler to accept + } + + } + + // output stats + cout<<"#ATTRIBUTE slots_used="<<slots_used.size()<<endl; + for(int slot_no=0; slot_no<slots_used.size(); slot_no++) + { + cout<<"#ATTRIBUTE used_slot"<<slot_no<<"="<<slots_used[slot_no].SlotsUsed()<<endl; + } + + return true; +} + diff --git a/tools/selective_cfi/color_map.hpp b/tools/selective_cfi/color_map.hpp new file mode 100644 index 000000000..d577e3f61 --- /dev/null +++ b/tools/selective_cfi/color_map.hpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014-2015 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +#ifndef color_map_hpp +#define color_map_hpp + +#include <libIRDB-core.hpp> +#include <stdint.h> + + +typedef int64_t NonceValueType_t; + +class ColoredSlotValue_t +{ + public: + ColoredSlotValue_t(int np, NonceValueType_t nv) : position(np), nonce_value(nv), valid(true) { }; + ColoredSlotValue_t() : valid(false) {} + + // void SetPosition(int pos) { slot_position=pos; } + int GetPosition() const { return position;} + + // void SetNonceValue(NonceValueType_t p_nv) { nonce_value=p_nv; } + NonceValueType_t const GetNonceValue() { return nonce_value; } + + bool IsValid() const { return valid; } + + private: + int position; + NonceValueType_t nonce_value; + bool valid; +}; + +class ColoredSlotAllocator_t +{ + public: + ColoredSlotAllocator_t(int sn, int mv) : slot_number(sn), used(0), max_value(mv) { } + + bool CanReserve() const { return used < max_value; } + ColoredSlotValue_t Reserve() + { + assert(CanReserve()); + return ColoredSlotValue_t(slot_number, used++); + } + int SlotsUsed() const { return used ; } + + + private: + int slot_number; + int used; + int max_value; +}; + +typedef std::map<int,ColoredSlotValue_t> ColoredSlotValues_t; + + +class ColoredInstructionNonces_t +{ + public: + ColoredInstructionNonces_t(libIRDB::FileIR_t *the_firp) + : firp(the_firp) { } + + ColoredSlotValues_t GetColorsOfIBT (libIRDB::Instruction_t* i) + { return color_assignments[i]; } + + ColoredSlotValue_t GetColorOfIB (libIRDB::Instruction_t* i) + { assert(i->GetIBTargets()); return slot_assignments[*i->GetIBTargets()]; } + + int NumberSlotsUsed() { return slots_used.size(); } + + bool build() { return create(); } + + private: + + // helper to assign colors to slots. + bool create(); + + // the IR we're working on. + libIRDB::FileIR_t* firp; + + // used to describe how big a nonce slot is. for now, 1 byte. + const int slot_size=1; + const int slot_values=255; + + // information for each slot we've used. + std::vector<ColoredSlotAllocator_t> slots_used; + + // information for each IBT. + // a map for each instruction, which contains a ColorSlotValue_t for each slot used. + // instruction -> ( int-> slot_value ) + std::map<libIRDB::Instruction_t*, ColoredSlotValues_t> color_assignments; + + // information for each IB (as indexed by the IBs ICFS). + // the slot that each IB uses. ICFS_t -> slot_value + std::map<libIRDB::ICFS_t, ColoredSlotValue_t> slot_assignments; + + +}; + + +// a simple way to sort ICFS. + +class UniqueICFSSetSorter_t; +typedef std::set<libIRDB::ICFS_t, UniqueICFSSetSorter_t> UniqueICFSSet_t; + +class UniqueICFSSetSorter_t +{ + public: + bool operator() (const libIRDB::ICFS_t& a, const libIRDB::ICFS_t& b) const + { + if(a.size() == b.size()) return a<b; + return a.size() < b.size() ; + } +}; + +#endif + diff --git a/tools/selective_cfi/scfi_driver.cpp b/tools/selective_cfi/scfi_driver.cpp index 45c82f5c6..b1eb37d87 100644 --- a/tools/selective_cfi/scfi_driver.cpp +++ b/tools/selective_cfi/scfi_driver.cpp @@ -35,12 +35,12 @@ using namespace libIRDB; void usage(char* name) { - cerr<<"Usage: "<<name<<" <variant_id>\n"; + cerr<<"Usage: "<<name<<" <variant_id> (--color|--no-color)\n"; } int main(int argc, char **argv) { - if(argc != 2) + if(argc < 2) { usage(argv[0]); exit(1); @@ -52,6 +52,15 @@ int main(int argc, char **argv) exit(1); } + bool do_coloring=false; + for(int i=0;i<argc;i++) + { + if(string(argv[i])=="--color") + do_coloring=true; + else if(string(argv[i])=="--no-color") + do_coloring=false; + } + string programName(argv[0]); int variantID = atoi(argv[1]); @@ -80,7 +89,7 @@ int main(int argc, char **argv) try { - SCFI_Instrument scfii(firp); + SCFI_Instrument scfii(firp, do_coloring); int success=scfii.execute(); diff --git a/tools/selective_cfi/scfi_instr.cpp b/tools/selective_cfi/scfi_instr.cpp index 7f03a4b81..ed4936668 100644 --- a/tools/selective_cfi/scfi_instr.cpp +++ b/tools/selective_cfi/scfi_instr.cpp @@ -22,7 +22,9 @@ #include "utils.hpp" #include "scfi_instr.hpp" #include "Rewrite_Utility.hpp" +#include "color_map.hpp" #include <stdlib.h> +#include <memory> @@ -252,11 +254,25 @@ bool SCFI_Instrument::needs_scfi_instrumentation(Instruction_t* insn) } +unsigned int SCFI_Instrument::GetNonceOffset(Instruction_t* insn) +{ + if(color_map) + { + assert(insn->GetIBTargets()); + return color_map->GetColorOfIB(insn).GetPosition() * GetNonceSize(insn); + } + return GetNonceSize(insn); +} -unsigned int SCFI_Instrument::GetNonce(Instruction_t* insn) +NonceValueType_t SCFI_Instrument::GetNonce(Instruction_t* insn) { /* in time we look up the nonce category for this insn */ /* for now, it's just f4 as the nonce */ + if(color_map) + { + assert(insn->GetIBTargets()); + return color_map->GetColorOfIB(insn).GetNonceValue(); + } return 0xf4; } @@ -280,13 +296,34 @@ bool SCFI_Instrument::mark_targets() { ind_targets++; string type; - type="cfi_nonce="; - type+=to_string(GetNonce(insn)); - - Relocation_t* reloc=create_reloc(insn); - reloc->SetOffset(-GetNonceSize(insn)); - reloc->SetType(type); - cout<<"Found indtarget for "<<std::dec<<insn->GetBaseID()<<":"<<insn->GetComment()<<endl; + if(do_coloring) + { + ColoredSlotValues_t v=color_map->GetColorsOfIBT(insn); + int size=1; + for(int i=0;i<v.size();i++) + { + if(!v[i].IsValid()) + continue; + int position=v[i].GetPosition(); + NonceValueType_t noncevalue=v[i].GetNonceValue(); + type=string("cfi_nonce=(pos=") + to_string(position) + ",nv=" + + to_string(noncevalue) + ",sz="+ to_string(size)+ ")"; + Relocation_t* reloc=create_reloc(insn); + reloc->SetOffset(-position*size); + reloc->SetType(type); + cout<<"Created reloc='"+type+"' for "<<std::dec<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl; + } + } + else + { + type="cfi_nonce="; + type+=to_string(GetNonce(insn)); + + Relocation_t* reloc=create_reloc(insn); + reloc->SetOffset(-GetNonceOffset(insn)); + reloc->SetType(type); + cout<<"Found nonce="+type+" for "<<std::dec<<insn->GetBaseID()<<":"<<insn->getDisassembly()<<endl; + } } } cout<<"# ATTRIBUTE ind_targets_found="<<std::dec<<ind_targets<<endl; @@ -355,17 +392,20 @@ void mov_reloc(Instruction_t* from, Instruction_t* to, string type ) void SCFI_Instrument::AddJumpCFI(Instruction_t* insn) { + ColoredSlotValue_t v2; + if(insn->GetIBTargets() && color_map) + v2=color_map->GetColorOfIB(insn); + ColoredSlotValue_t *v=&v2; string reg="ecx"; // 32-bit reg if(firp->GetArchitectureBitWidth()==64) reg="rcx"; // 64-bit reg. -#ifdef CGC - // insert the pop/checking code. string pushbits=change_to_push(insn); - cout<<"Converting ' "<<insn->getDisassembly()<<"' to '"; Instruction_t* after=insertDataBitsBefore(firp,insn,pushbits); - cout<<insn->getDisassembly()<<"'"<<endl; +#ifdef CGC + // insert the pop/checking code. + cout<<insn->getDisassembly()<<"+jmp slowpath'"<<endl; string jmpBits=getJumpDataBits(); after->SetDataBits(jmpBits); @@ -375,25 +415,33 @@ void SCFI_Instrument::AddJumpCFI(Instruction_t* insn) after->SetTarget(after); return; #else - string pushbits=change_to_push(insn); - cout<<"Converting ' "<<insn->getDisassembly()<<"' to '"; - Instruction_t* after=insertDataBitsBefore(firp,insn,pushbits); after->SetDataBits(getRetDataBits()); - cout <<insn->getDisassembly()<<" + ret "<<endl ; + cout <<insn->getDisassembly()<<" + ret' "<<endl ; // move any pc-rel relocation bits to the push, which will access memory now mov_reloc(after,insn,"pcrel"); + after->SetIBTargets(insn->GetIBTargets()); + insn->SetIBTargets(NULL); - AddReturnCFI(after); + AddReturnCFI(after,v); // cout<<"Warning, JUMPS not CFI's yet"<<endl; return; #endif } -void SCFI_Instrument::AddReturnCFI(Instruction_t* insn) +void SCFI_Instrument::AddReturnCFI(Instruction_t* insn, ColoredSlotValue_t *v) { + + ColoredSlotValue_t v2; + if(v==NULL && color_map) + { + v2=color_map->GetColorOfIB(insn); + v=&v2; + } + + string reg="ecx"; // 32-bit reg if(firp->GetArchitectureBitWidth()==64) reg="r11"; // 64-bit reg. @@ -420,14 +468,23 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn) if(sp_adjust>0) { sprintf(buf, "lea %s, [%s+%d]", rspreg.c_str(), rspreg.c_str(), sp_adjust); - Instruction_t* newinsn=insertAssemblyAfter(firp,insn,buf); } - // rewrite the "old" isntruction, as that's what insertAssemblyBefore returns insn=newafter; } + int size=1; + string slow_cfi_path_reloc_string="slow_cfi_path=(1,0xf4,1)"; + if( v && v->IsValid()) + { + slow_cfi_path_reloc_string="slow_cfi_path=("+ to_string(v->GetPosition()) +"," + + to_string(v->GetNonceValue())+","+ to_string(size) +")"; + } + cout<<"Cal'd (unused) slow-path cfi reloc as: "<<slow_cfi_path_reloc_string<<endl; +// fixme: would like to mark a slow path per nonce type using the variables calc'd above. + + #ifdef CGC // insert the pop/checking code. @@ -446,6 +503,7 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn) string decoration=""; int nonce_size=GetNonceSize(insn); + int nonce_offset=GetNonceOffset(insn); unsigned int nonce=GetNonce(insn); Instruction_t* jne=NULL, *tmp=NULL; @@ -484,6 +542,7 @@ void SCFI_Instrument::AddReturnCFI(Instruction_t* insn) jne->SetTarget(jne); // needed so spri/spasm/irdb don't freak out about missing target for new insn. Relocation_t* reloc=create_reloc(jne); reloc->SetType("slow_cfi_path"); +// fixme: record nonce value for each slot. reloc->SetOffset(0); return; @@ -494,7 +553,7 @@ bool SCFI_Instrument::instrument_jumps() { int cfi_checks=0; - // we do this in two passes. first pass: find instructions. + // for each instruction for(InstructionSet_t::iterator it=firp->GetInstructions().begin(); it!=firp->GetInstructions().end(); ++it) @@ -551,11 +610,23 @@ bool SCFI_Instrument::execute() bool success=true; + if(do_coloring) + { + color_map=new ColoredInstructionNonces_t(firp); + assert(color_map); + success = success && color_map->build(); + + } + success = success && instrument_jumps(); // to handle moving of relocs properly if // an insn is both a IBT and a IB, // we instrument first, then add relocs for targets success = success && mark_targets(); + + delete color_map; + color_map=NULL; + return success; } diff --git a/tools/selective_cfi/scfi_instr.hpp b/tools/selective_cfi/scfi_instr.hpp index 44e704621..d0d62991a 100644 --- a/tools/selective_cfi/scfi_instr.hpp +++ b/tools/selective_cfi/scfi_instr.hpp @@ -22,13 +22,15 @@ #define scfi_instrument_hpp #include <libIRDB-core.hpp> +#include "color_map.hpp" class SCFI_Instrument { public: - SCFI_Instrument(libIRDB::FileIR_t *the_firp) : firp(the_firp) {} + SCFI_Instrument(libIRDB::FileIR_t *the_firp, bool p_do_coloring=true) + : firp(the_firp), do_coloring(p_do_coloring), color_map(NULL) {} bool execute(); private: @@ -47,19 +49,22 @@ class SCFI_Instrument bool needs_scfi_instrumentation(libIRDB::Instruction_t* insn); // return instrumentation - void AddReturnCFI(libIRDB::Instruction_t* insn); + void AddReturnCFI(libIRDB::Instruction_t* insn, ColoredSlotValue_t *v=NULL); // jump instrumentation void AddJumpCFI(libIRDB::Instruction_t* insn); // Nonce Manipulation. - unsigned int GetNonce(libIRDB::Instruction_t* insn); + NonceValueType_t GetNonce(libIRDB::Instruction_t* insn); unsigned int GetNonceSize(libIRDB::Instruction_t* insn); + unsigned int GetNonceOffset(libIRDB::Instruction_t*); libIRDB::FileIR_t* firp; + bool do_coloring; + ColoredInstructionNonces_t *color_map; }; -- GitLab