Skip to content
Snippets Groups Projects
Commit 5116934c authored by jdh8d's avatar jdh8d
Browse files

first draft of safefr and ret shadow stack

Former-commit-id: 7b224df7cf2d184bfbd88da6d1fa0b811592c63e
parent 2c7253a0
No related branches found
No related tags found
No related merge requests found
Showing with 468 additions and 9 deletions
......@@ -234,16 +234,20 @@ libIRDB/test/read_variantir.cpp -text
libIRDB/test/unfix_calls.cpp -text
libIRDB/test/unwind-pe.h -text
libMEDSannotation/Makefile -text
libMEDSannotation/include/FuncExitAnnotation.hpp -text
libMEDSannotation/include/MEDS.hpp -text
libMEDSannotation/include/MEDS_AnnotationBase.hpp -text
libMEDSannotation/include/MEDS_AnnotationParser.hpp -text
libMEDSannotation/include/MEDS_FRSafeAnnotation.hpp -text
libMEDSannotation/include/MEDS_FuncAnnotation.hpp -text
libMEDSannotation/include/MEDS_InstructionCheckAnnotation.hpp -text
libMEDSannotation/include/MEDS_ProblemFuncAnnotation.hpp -text
libMEDSannotation/include/MEDS_Register.hpp -text
libMEDSannotation/include/MEDS_SafeFuncAnnotation.hpp -text
libMEDSannotation/include/VirtualOffset.hpp -text
libMEDSannotation/src/FuncExitAnnotation.cpp -text
libMEDSannotation/src/MEDS_AnnotationParser.cpp -text
libMEDSannotation/src/MEDS_FRSafeAnnotation.cpp -text
libMEDSannotation/src/MEDS_InstructionCheckAnnotation.cpp -text
libMEDSannotation/src/MEDS_ProblemFuncAnnotation.cpp -text
libMEDSannotation/src/MEDS_Register.cpp -text
......@@ -401,6 +405,8 @@ tools/ret_shadow_stack/Makefile -text
tools/ret_shadow_stack/rss_driver.cpp -text
tools/ret_shadow_stack/rss_instrument.cpp -text
tools/ret_shadow_stack/rss_instrument.hpp -text
tools/safefr/Makefile -text
tools/safefr/fill_in_safefr.cpp -text
tools/spasm/Makefile -text
tools/spasm/ben_lib.cpp -text
tools/spasm/ben_lib.h -text
......
......@@ -58,6 +58,16 @@ bool check_entry(bool &found, ControlFlowGraph_t* cfg)
bool call_needs_fix(Instruction_t* insn)
{
for(set<Relocation_t*>::iterator it=insn->GetRelocations().begin();
it!=insn->GetRelocations().end();
++it
)
{
Relocation_t* reloc=*it;
if(string("safefr") == reloc->GetType())
return false;
}
Instruction_t *target=insn->GetTarget();
Instruction_t *fallthru=insn->GetFallthrough();
DISASM disasm;
......@@ -698,6 +708,29 @@ void fix_other_pcrel(FileIR_t* firp, Instruction_t *insn, UIntPtr virt_offset)
}
}
void fix_safefr(FileIR_t* firp, Instruction_t *insn, UIntPtr virt_offset)
{
/* if this has already been fixed, we can skip it */
if(virt_offset==0 || virt_offset==-1)
return;
for(set<Relocation_t*>::iterator it=insn->GetRelocations().begin();
it!=insn->GetRelocations().end();
++it)
{
Relocation_t* reloc=*it;
assert(reloc);
if(string("safefr") == reloc->GetType())
{
AddressID_t* addr =new AddressID_t;
addr->SetFileID(insn->GetAddress()->GetFileID());
firp->GetAddresses().insert(addr);
insn->SetAddress(addr);
}
}
}
void fix_other_pcrel(FileIR_t* firp)
{
......@@ -709,6 +742,7 @@ void fix_other_pcrel(FileIR_t* firp)
{
Instruction_t* insn=*it;
fix_other_pcrel(firp,insn, insn->GetAddress()->GetVirtualOffset());
fix_safefr(firp,insn, insn->GetAddress()->GetVirtualOffset());
}
}
......
#ifndef _FUNCEXITANNOTATION_H_
#define _FUNCEXITANNOTATION_H_
#include <string>
#include "VirtualOffset.hpp"
#include "MEDS_Register.hpp"
#include "MEDS_AnnotationBase.hpp"
namespace MEDS_Annotation
{
using namespace std;
using namespace MEDS_Annotation;
//
// Class to handle one MEDS annotation
//
class MEDS_FuncExitAnnotation : public MEDS_AnnotationBase
{
public:
MEDS_FuncExitAnnotation() {};
MEDS_FuncExitAnnotation(const string &p_rawLine);
virtual ~MEDS_FuncExitAnnotation(){}
virtual const string toString() const { return "tail call: "+m_rawInputLine; }
private:
void init();
void parse();
private:
std::string m_rawInputLine;
};
}
#endif
......@@ -23,8 +23,8 @@ class MEDS_AnnotationParser
MEDS_AnnotationParser(std::istream &); /* pass opened file */
void parseFile(std::istream &);
void parseFile(const std::string &); /* pass filename */
MEDS_Annotations_t getAnnotations() { return m_annotations; }
MEDS_FuncAnnotations_t getFuncAnnotations() { return m_func_annotations; }
MEDS_Annotations_t & getAnnotations() { return m_annotations; }
MEDS_FuncAnnotations_t & getFuncAnnotations() { return m_func_annotations; }
private:
MEDS_Annotations_t m_annotations;
......
#ifndef _MEDS_FRSAFEANNOTATION_H_
#define _MEDS_FRSAFEANNOTATION_H_
#include <string>
#include "VirtualOffset.hpp"
#include "MEDS_Register.hpp"
#include "MEDS_AnnotationBase.hpp"
namespace MEDS_Annotation
{
using namespace std;
using namespace MEDS_Annotation;
//
// Class to handle one MEDS (integer vulnerability) annotation
//
class MEDS_FRSafeAnnotation : public MEDS_AnnotationBase
{
public:
MEDS_FRSafeAnnotation() {};
MEDS_FRSafeAnnotation(const string &p_rawLine);
virtual ~MEDS_FRSafeAnnotation(){}
virtual const string toString() const { return "fr safe func: "+m_rawInputLine; }
private:
void init();
void parse();
private:
std::string m_rawInputLine;
};
}
#endif
#include <stdlib.h>
#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include "MEDS_Register.hpp"
#include "FuncExitAnnotation.hpp"
using namespace std;
using namespace MEDS_Annotation;
MEDS_FuncExitAnnotation::MEDS_FuncExitAnnotation(const string &p_rawLine)
{
init();
m_rawInputLine=p_rawLine;
parse();
}
void MEDS_FuncExitAnnotation::init()
{
}
/*
Example format -- subject to change:
804925b 5 INSTR CALL TAILCALL jmp check_one_fd
*/
void MEDS_FuncExitAnnotation::parse()
{
if (m_rawInputLine.find(" INSTR ")==string::npos)
return;
if (
m_rawInputLine.find(" INSTR RETURN ")==string::npos &&
m_rawInputLine.find(" INSTR CALL TAILCALL ")==string::npos
)
{
/* INSTR that's not for a safe fast return */
return;
}
// get offset
VirtualOffset vo(m_rawInputLine);
m_virtualOffset = vo;
setValid(); // no additional info recorded for right now.
// if(getenv("VERBOSE")!=NULL)
cout<<"Found TAILCALL annotation for "<<vo.to_string()<<endl;
}
......@@ -3,8 +3,10 @@
#include "MEDS_AnnotationParser.hpp"
#include "MEDS_InstructionCheckAnnotation.hpp"
#include "FuncExitAnnotation.hpp"
#include "MEDS_SafeFuncAnnotation.hpp"
#include "MEDS_ProblemFuncAnnotation.hpp"
#include "MEDS_FRSafeAnnotation.hpp"
// @todo: multiple annotation per instruction
......@@ -62,6 +64,8 @@ void MEDS_AnnotationParser::parseFile(istream &p_inputStream)
ADD_AND_CONTINUE_IF_VALID(MEDS_InstructionCheckAnnotation);
ADD_AND_CONTINUE_IF_VALID(MEDS_SafeFuncAnnotation);
ADD_AND_CONTINUE_IF_VALID(MEDS_ProblemFuncAnnotation);
ADD_AND_CONTINUE_IF_VALID(MEDS_FRSafeAnnotation);
ADD_AND_CONTINUE_IF_VALID(MEDS_FuncExitAnnotation);
// cout<<"Found annotation: "<<annot->toString()<<endl;\
......
#include <stdlib.h>
#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include "MEDS_Register.hpp"
#include "MEDS_FRSafeAnnotation.hpp"
using namespace std;
using namespace MEDS_Annotation;
MEDS_FRSafeAnnotation::MEDS_FRSafeAnnotation(const string &p_rawLine)
{
init();
m_rawInputLine=p_rawLine;
parse();
}
void MEDS_FRSafeAnnotation::init()
{
}
/*
Example format (as of July 31, 2014 ) -- subject to change:
804b3a6 5 INSTR CALL NOFASTRETURN RAUNSAFE ZZ call frame_dummy
804c941 5 INSTR CALL FASTRETURN ZZ call _ZN7GString3cmpEPKc; GString::cmp(char const*)
804c511 3 INSTR INDIRCALL NOFASTRETURN INDIRECT ZZ call dword ptr [eax+8]
804c6fa 1 INSTR RETURN NOFASTRETURN NOCALLERS ZZ retn
*/
void MEDS_FRSafeAnnotation::parse()
{
if (m_rawInputLine.find(" INSTR ")==string::npos)
return;
if (
m_rawInputLine.find(" INSTR CALL FASTRETURN ")==string::npos &&
m_rawInputLine.find(" INSTR INDCALL FASTRETURN ")==string::npos &&
m_rawInputLine.find(" INSTR RETURN FASTRETURN ")==string::npos
)
{
/* INSTR that's not for a safe fast return */
return;
}
// get offset
VirtualOffset vo(m_rawInputLine);
m_virtualOffset = vo;
setValid(); // no additional info recorded for right now.
// if(getenv("VERBOSE")!=NULL)
cout<<"Found FASTRETURN annotation for "<<vo.to_string()<<endl;
}
LIB=../lib/libMEDSannotation.a
OBJS=VirtualOffset.o MEDS_Register.o MEDS_AnnotationParser.o MEDS_InstructionCheckAnnotation.o MEDS_SafeFuncAnnotation.o MEDS_ProblemFuncAnnotation.o
OBJS=VirtualOffset.o MEDS_Register.o MEDS_AnnotationParser.o MEDS_InstructionCheckAnnotation.o MEDS_SafeFuncAnnotation.o MEDS_ProblemFuncAnnotation.o MEDS_FRSafeAnnotation.o FuncExitAnnotation.o
all: $(OBJS)
......
......@@ -72,6 +72,7 @@ int main(int argc, char **argv)
cerr << "annotation file: " << annotationFilename << endl;
annotationParser.parseFile(annotationFilename+".annot");
annotationParser.parseFile(annotationFilename+".infoannot");
annotationParser.parseFile(annotationFilename+".STARScallreturn");
RSS_Instrument rssi(firp, &annotationParser);
......
#include "rss_instrument.hpp"
#include "MEDS_SafeFuncAnnotation.hpp"
#include "FuncExitAnnotation.hpp"
#include "MEDS_ProblemFuncAnnotation.hpp"
#include "Rewrite_Utility.hpp"
#include <stdlib.h>
......@@ -279,7 +280,24 @@ static bool add_rss_pop(FileIR_t* firp, Instruction_t* insn)
tmp=insertAssemblyAfter(firp,tmp,"mov rcx, [fs:0x12345678] "); create_tls_reloc(firp,tmp);
tmp=insertAssemblyAfter(firp,tmp,"lea rcx, [rcx-8]");
tmp=insertAssemblyAfter(firp,tmp,"mov [fs:0x12345678], rcx "); create_tls_reloc(firp,tmp);
/* if tss_print_stack is on, we want to zero the old location just for easy printing. */
/* doing so requires an extra register */
if(getenv("tss_print_stack")!=NULL)
{
tmp=insertAssemblyAfter(firp,tmp,"push rax");
tmp=insertAssemblyAfter(firp,tmp,"mov rax, rcx");
}
// load the old value
tmp=insertAssemblyAfter(firp,tmp,"mov rcx, [rcx]");
/* if tss_print_stack is on, we want to zero the old location just for easy printing. */
if(getenv("tss_print_stack")!=NULL)
{
tmp=insertAssemblyAfter(firp,tmp,"mov dword [rax], 0");
tmp=insertAssemblyAfter(firp,tmp,"pop rax");
}
tmp=insertAssemblyAfter(firp,tmp,"sub rcx, [rsp+16]");
jmp_insn=tmp=insertDataBitsAfter(firp,tmp,getJecxzDataBits()); // jecxz L1
tmp=insertAssemblyAfter(firp,tmp,"hlt");
......@@ -298,16 +316,46 @@ static bool add_rss_pop(FileIR_t* firp, Instruction_t* insn)
return true;
}
static bool is_exit_instruction(Instruction_t *insn)
static bool is_exit_instruction(Instruction_t *insn, MEDS_AnnotationParser *meds_ap)
{
DISASM d;
insn->Disassemble(d);
if(strstr(d.CompleteInstr,"ret")!=0)
return true;
assert(meds_ap);
std::pair<MEDS_Annotations_t::iterator,MEDS_Annotations_t::iterator> ret;
virtual_offset_t irdb_vo = insn->GetAddress()->GetVirtualOffset();
VirtualOffset vo(irdb_vo);
/* find it in the annotations */
ret = meds_ap->getAnnotations().equal_range(vo);
MEDS_FuncExitAnnotation annotation;
MEDS_FuncExitAnnotation* p_annotation;
/* for each annotation for this instruction */
for (MEDS_Annotations_t::iterator it = ret.first; it != ret.second; ++it)
{
/* is this annotation a funcSafe annotation? */
p_annotation=dynamic_cast<MEDS_FuncExitAnnotation*>(it->second);
if(p_annotation==NULL)
continue;
annotation = *p_annotation;
/* bad annotation? */
if(!annotation.isValid())
continue;
return true;
}
/* couldn't find this insn as a function exit. */
return false;
}
static bool add_rss_instrumentation(FileIR_t* firp, Function_t* func)
static bool add_rss_instrumentation(FileIR_t* firp, Function_t* func, MEDS_AnnotationParser *meds_ap)
{
bool success=true;
if(func->GetEntryPoint()==NULL)
......@@ -316,8 +364,6 @@ static bool add_rss_instrumentation(FileIR_t* firp, Function_t* func)
if(getenv("RSS_VERBOSE")!=NULL)
cout<<"Transforming function "<<func->GetName()<<endl;
success&=add_rss_push(firp, func->GetEntryPoint());
for(
set<Instruction_t*>::iterator it=func->GetInstructions().begin();
......@@ -326,10 +372,13 @@ static bool add_rss_instrumentation(FileIR_t* firp, Function_t* func)
)
{
Instruction_t* insn=*it;
if(is_exit_instruction(insn))
if(is_exit_instruction(insn, meds_ap))
success&=add_rss_pop(firp, insn);
}
/* need to do this second, as the function entry may actually change due to popping that may happen */
success&=add_rss_push(firp, func->GetEntryPoint());
return success;
}
......@@ -446,7 +495,7 @@ bool RSS_Instrument::execute()
if(func->GetEntryPoint())
cout<<"( "<<std::hex<<func->GetEntryPoint()->GetAddress()->GetVirtualOffset()<<")";
cout<<endl;
success|=add_rss_instrumentation(firp,func);
success|=add_rss_instrumentation(firp,func, meds_ap);
}
else
{
......
INCLUDES= -I $(SECURITY_TRANSFORMS_HOME)/include -I$(SECURITY_TRANSFORMS_HOME)/beaengine/include -I $(SECURITY_TRANSFORMS_HOME)/libIRDB/include/ -I$(SECURITY_TRANSFORMS_HOME)/libMEDSannotation/include/
LIBS= -L$(SECURITY_TRANSFORMS_HOME)/lib -lIRDB-core -lIRDB-cfg -lpqxx -L $(SECURITY_TRANSFORMS_HOME)/beaengine/lib/Linux.gnu.Debug -lBeaEngine_s_d -lMEDSannotation
OPT=-g
.SUFFIXES: .exe .cpp
PROGS=fill_in_safefr.exe
all: $(PROGS)
$(PROGS): ../../lib/*
.o.exe: $< $(SECURITY_TRANSFORMS_HOME)/lib/*.a
g++ $< $(INCLUDES) $(LIBS) $(OPT) -o $@
.cpp.o: $<
g++ $< $(INCLUDES) $(LIBS) $(OPT) -o $@ -c
clean:
rm -f $(PROGS) *.o
#include <libIRDB-core.hpp>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <cctype>
#include <assert.h>
#include "targ-config.h"
#include "MEDS_AnnotationParser.hpp"
#include "MEDS_FRSafeAnnotation.hpp"
using namespace libIRDB;
using namespace std;
using namespace MEDS_Annotation;
#define BINARY_NAME "a.ncexe"
#define SHARED_OBJECTS_DIR "shared_objects"
static void add_annotations(FileIR_t* firp)
{
char *fileBasename = basename((char*)firp->GetFile()->GetURL().c_str());
cout<<"Adding FR annotations to "<<firp->GetFile()->GetURL()<<endl;
MEDS_AnnotationParser annotationParser;
string annotationFilename;
// need to map filename to integer annotation file produced by STARS
// this should be retrieved from the IRDB but for now, we use files to store annotations
// convention from within the peasoup subdirectory is:
// a.ncexe.infoannot
// shared_objects/<shared-lib-filename>.infoannot
if (strcmp(fileBasename, BINARY_NAME) == 0)
annotationFilename = string(BINARY_NAME);
else
annotationFilename = string(SHARED_OBJECTS_DIR) + "/" + fileBasename ;
cerr << "annotation file: " << annotationFilename << endl;
annotationParser.parseFile(annotationFilename+".STARScallreturn");
// now, look through each instruction and match the insn to the annotation.
cout<< "Annot size is "<<std::dec<< annotationParser.getAnnotations().size() << endl;
for(set<Instruction_t*>::iterator it=firp->GetInstructions().begin();
it!=firp->GetInstructions().end();
++it
)
{
Instruction_t* insn=*it;
assert(insn);
/* find annotations for this insn */
std::pair<MEDS_Annotations_t::iterator,MEDS_Annotations_t::iterator> ret;
VirtualOffset vo(insn->GetAddress()->GetVirtualOffset());
cout<<"Checking annotations for "<<std::hex<<vo.to_string()<<endl;
/* find it in the annotations */
ret = annotationParser.getAnnotations().equal_range(vo);
MEDS_FRSafeAnnotation* p_annotation;
/* for each annotation for this instruction */
for (MEDS_Annotations_t::iterator it2 = ret.first; it2 != ret.second; ++it2)
{
p_annotation=dynamic_cast<MEDS_FRSafeAnnotation*>(it2->second);
if(p_annotation==NULL)
continue;
cout<<"Found safe FR annotation for "<<std::hex<<insn->GetAddress()->GetVirtualOffset()<<endl;
Relocation_t* reloc=new Relocation_t;
reloc->SetOffset(0);
reloc->SetType("safefr");
insn->GetRelocations().insert(reloc);
firp->GetRelocations().insert(reloc);
}
}
}
main(int argc, char* argv[])
{
if(argc!=2)
{
cerr<<"Usage: ilr <id>"<<endl;
exit(-1);
}
VariantID_t *pidp=NULL;
FileIR_t *firp=NULL;
/* setup the interface to the sql server */
pqxxDB_t pqxx_interface;
BaseObj_t::SetInterface(&pqxx_interface);
cout<<"Reading variant "<<string(argv[1])<<" from database." << endl;
try
{
pidp=new VariantID_t(atoi(argv[1]));
assert(pidp->IsRegistered()==true);
for(set<File_t*>::iterator it=pidp->GetFiles().begin();
it!=pidp->GetFiles().end();
++it
)
{
File_t* this_file=*it;
assert(this_file);
// read the db
firp=new FileIR_t(*pidp,this_file);
add_annotations(firp);
firp->WriteToDB();
delete firp;
}
pqxx_interface.Commit();
}
catch (DatabaseError_t pnide)
{
cout<<"Unexpected database error: "<<pnide<<endl;
exit(-1);
}
cout<<"Done!"<<endl;
delete pidp;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment