diff --git a/.gitattributes b/.gitattributes index e77d24f3ce9b03ae1ee346ae4572d99da07ce1a5..2e88f925e0e6be09a787ec70c8178630301e7dd9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -976,6 +976,11 @@ tools/c2e/SConstruct -text tools/c2e/c2e_driver.cpp -text tools/c2e/c2e_instr.cpp -text tools/c2e/c2e_instr.hpp -text +tools/cgc_buffrecv/SConscript -text +tools/cgc_buffrecv/SConstruct -text +tools/cgc_buffrecv/buffrecv_driver.cpp -text +tools/cgc_buffrecv/buffrecv_instrument.cpp -text +tools/cgc_buffrecv/buffrecv_instrument.hpp -text tools/cgc_hlx/Makefile.in -text tools/cgc_hlx/SConscript -text tools/cgc_hlx/SConstruct -text diff --git a/tools/cgc_buffrecv/SConscript b/tools/cgc_buffrecv/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..5c1c4e03072c5438adb185c7b43dea11df4c0987 --- /dev/null +++ b/tools/cgc_buffrecv/SConscript @@ -0,0 +1,33 @@ +import os + + + +Import('env') +myenv=env.Clone() +myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) + +cpppath=''' + $SECURITY_TRANSFORMS_HOME/include + $SECURITY_TRANSFORMS_HOME/libIRDB/include + $SECURITY_TRANSFORMS_HOME/libMEDSannotation/include + $SECURITY_TRANSFORMS_HOME/beaengine/include + $SECURITY_TRANSFORMS_HOME/tools/transforms + ''' + +myenv.Append(CCFLAGS=" -DCGC") + +files=Glob( Dir('.').srcnode().abspath+"/*.cpp") + + +pgm="buffrecv.exe" + +LIBPATH="$SECURITY_TRANSFORMS_HOME/lib" +LIBS=Split( env.subst('$BASE_IRDB_LIBS')+ " IRDB-cfg IRDB-syscall 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) +myenv.Alias("install", "$SECURITY_TRANSFORMS_HOME/bin/") +Default(install) + + + diff --git a/tools/cgc_buffrecv/SConstruct b/tools/cgc_buffrecv/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..c96332f0422ad5df0853931209219d9a2e20bc17 --- /dev/null +++ b/tools/cgc_buffrecv/SConstruct @@ -0,0 +1,6 @@ + + + +env=Environment() +Export('env') +lib=SConscript("SConscript") diff --git a/tools/cgc_buffrecv/buffrecv_driver.cpp b/tools/cgc_buffrecv/buffrecv_driver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca7a75ea43dab384e3dcdd072f11a0df77cc151a --- /dev/null +++ b/tools/cgc_buffrecv/buffrecv_driver.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015 - University of Virginia + * + * 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. + * + */ + +#include <stdlib.h> +#include <fstream> +#include <libgen.h> +#include <unistd.h> +#include <stdlib.h> +#include <getopt.h> + +#include <libIRDB-core.hpp> +#include "buffrecv_instrument.hpp" + +using namespace std; +using namespace libIRDB; + +void usage(char* name) +{ + cerr<<"Usage: "<<name<<" --varid=<variant_id>\n"; +} + + +int varid=0; + +int parse_args(int p_argc, char* p_argv[]) +{ + int option = 0; + char options[] = "v:"; + struct option long_options[] = { + {"varid", required_argument, NULL, 'v'}, + {NULL, no_argument, NULL, '\0'}, // end-of-array marker + }; + + while ((option = getopt_long( + p_argc, + p_argv, + options, + long_options, + NULL)) != -1) + { + printf("Found option %c\n", option); + switch (option) + { + case 'v': + { + varid=atoi(::optarg); + cout<<"Transforming variant "<<dec<<varid<<endl; + break; + } + default: + return 1; + } + } + return 0; +} + + +int main(int argc, char **argv) +{ + if(0 != parse_args(argc,argv)) + { + usage(argv[0]); + exit(1); + } + + string programName(argv[0]); + int variantID = varid; + + VariantID_t *pidp=NULL; + + /* setup the interface to the sql server */ + pqxxDB_t pqxx_interface; + BaseObj_t::SetInterface(&pqxx_interface); + + pidp=new VariantID_t(variantID); + assert(pidp->IsRegistered()==true); + + cout << argv[0] << " started\n"; + + bool success = false; + bool one_success = false; + bool one_fail=false; + + for(set<File_t*>::iterator it=pidp->GetFiles().begin(); + it!=pidp->GetFiles().end(); + ++it) + { + File_t* this_file = *it; + try + { + FileIR_t *firp = new FileIR_t(*pidp, this_file); + + cout<<"Transforming "<<this_file->GetURL()<<endl; + + assert(firp && pidp); + + BuffRecv_Instrument wsci(firp); + + success = wsci.execute(); + + if (success) + { + cout<<"Writing changes for "<<this_file->GetURL()<<endl; + one_success = true; + + firp->WriteToDB(); + } + else + { + one_fail=true; + cout<<"Skipping (no changes) "<<this_file->GetURL()<<endl; + } + + delete firp; + } + catch (DatabaseError_t pnide) + { + cerr << programName << ": Unexpected database error: " << pnide << "file url: " << this_file->GetURL() << endl; + } + catch (...) + { + cerr << programName << ": Unexpected error file url: " << this_file->GetURL() << endl; + } + } // end file iterator + + // if any transforms for any files succeeded, we commit + if (one_success) + { + cout<<"Commiting changes...\n"; + pqxx_interface.Commit(); + } + + return one_fail; +} + diff --git a/tools/cgc_buffrecv/buffrecv_instrument.cpp b/tools/cgc_buffrecv/buffrecv_instrument.cpp new file mode 100644 index 0000000000000000000000000000000000000000..81b4c33d2619268dbcc50ed1ba0e374891088b8b --- /dev/null +++ b/tools/cgc_buffrecv/buffrecv_instrument.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015 - University of Virginia + * + * 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. + * + */ + +#include <stdlib.h> +#include <string> +#include <iostream> + +#include "buffrecv_instrument.hpp" +#include "Rewrite_Utility.hpp" + + +using namespace std; +using namespace libIRDB; + +virtual_offset_t getAvailableAddress(FileIR_t *p_virp) +{ + static int counter = -16; + counter += 16; + return 0xf0080000 + counter; +} + +static Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, string p_asm) +{ + Instruction_t* newinstr; + if (p_instr) + newinstr = allocateNewInstruction(firp,p_instr->GetAddress()->GetFileID(), p_instr->GetFunction()); + else + newinstr = allocateNewInstruction(firp,BaseObj_t::NOT_IN_DATABASE, NULL); + + firp->RegisterAssembly(newinstr, p_asm); + + if (p_instr) + { + newinstr->SetFallthrough(p_instr->GetFallthrough()); + p_instr->SetFallthrough(newinstr); + } + + return newinstr; +} + +// site should be: int 0x80 instruction in receive() wrapper +bool BuffRecv_Instrument::_add_buffered_receive_instrumentation(Instruction_t *site) +{ + string bits; + bits.resize(1); + bits[0]=0x90; + site->SetDataBits(bits); // convert site to nop instruction + +//cout<<"Found syscall to instrument "<<site->getDisassembly()<<endl; + + virtual_offset_t postCallbackReturn = getAvailableAddress(firp); + char tmpbuf[100]; + sprintf(tmpbuf,"push 0x%x", postCallbackReturn); + + Instruction_t *tmp=site, *callback=NULL, *post_callback=NULL; + tmp=insertAssemblyAfter(firp,tmp,"pushf"); + tmp=insertAssemblyAfter(firp,tmp,"pusha"); + tmp=insertAssemblyAfter(firp,tmp,tmpbuf); // push <ret addr> + callback=tmp=insertAssemblyAfter(firp,tmp,"nop"); + post_callback=tmp=insertAssemblyAfter(firp,tmp,"popa"); + tmp=insertAssemblyAfter(firp,tmp,"popf"); + tmp=insertAssemblyAfter(firp,tmp,"mov eax, 0"); + post_callback->GetAddress()->SetVirtualOffset(postCallbackReturn); + callback->SetCallback("buffered_receive"); + return true; +} + +bool BuffRecv_Instrument::add_buffered_receive_instrumentation() +{ + + bool success=true; + + for(SyscallSiteSet_t::iterator it=syscalls.GetSyscalls().begin(); + it!=syscalls.GetSyscalls().end(); + ++it) + { + SyscallSite_t ss=*it; + Instruction_t *site=ss.GetSyscallSite(); + SyscallNumber_t num=ss.GetSyscallNumber(); + if(num==SNT_receive) + { + cout << "Found RECEIVE syscall - @todo: implement: " << site->getDisassembly() << " " << hex << site->GetAddress()->GetVirtualOffset() << dec << endl; +// success = success && add_buffered_receive_instrumentation(site); + } + } + + /* return an exit code */ + return success; /* success? */ +} + + +static const ARGTYPE* FindMemoryArgument(const DISASM &d) +{ + if((d.Argument1.ArgType & MEMORY_TYPE) == MEMORY_TYPE) + return &d.Argument1; + if((d.Argument2.ArgType & MEMORY_TYPE) == MEMORY_TYPE) + return &d.Argument2; + if((d.Argument3.ArgType & MEMORY_TYPE) == MEMORY_TYPE) + return &d.Argument3; + if((d.Argument4.ArgType & MEMORY_TYPE) == MEMORY_TYPE) + return &d.Argument4; + + return NULL; +} + + +static string get_memory_addr(const DISASM& d) +{ + string s=d.CompleteInstr; + size_t pos=s.find('['); + + assert(pos!=string::npos); + + s.replace(0,pos-1,""); + + pos=s.find(']'); + s.replace(pos+1,s.length(),""); + + return s; +} + +static bool has_index_register(Instruction_t* i) +{ + DISASM d; + i->Disassemble(d); + const ARGTYPE* arg=FindMemoryArgument(d); + + if(!arg) + return false; + + if(arg->Memory.Scale) + return true; + return false; + +} + +static string regToRegstring(size_t regno) +{ + switch(regno) + { + case REG0: return "eax"; + case REG1: return "ecx"; + case REG2: return "edx"; + case REG3: return "ebx"; + case REG4: return "esp"; + case REG5: return "ebp"; + case REG6: return "esi"; + case REG7: return "edi"; + default: assert(0); + } +} + +std::ostream& BuffRecv_Instrument::displayStatistics(std::ostream &os) +{ +} + +bool BuffRecv_Instrument::execute() +{ + bool success=true; + + success = success && add_buffered_receive_instrumentation(); + + return success; +} + + diff --git a/tools/cgc_buffrecv/buffrecv_instrument.hpp b/tools/cgc_buffrecv/buffrecv_instrument.hpp new file mode 100644 index 0000000000000000000000000000000000000000..20353d44e15216e337701d63d20f61bbd609ed43 --- /dev/null +++ b/tools/cgc_buffrecv/buffrecv_instrument.hpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 - University of Virginia + * + * 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. + * + */ + +#ifndef buffrecv_instrument_hpp +#define buffrecv_instrument_hpp + +#include <libIRDB-core.hpp> +#include <libIRDB-util.hpp> +#include <libIRDB-syscall.hpp> + +#include "elfio/elfio.hpp" +#include "elfio/elfio_dump.hpp" + +class BuffRecv_Instrument +{ + public: + BuffRecv_Instrument(libIRDB::FileIR_t *the_firp) : firp(the_firp), syscalls(firp) + { + int elfoid=firp->GetFile()->GetELFOID(); + pqxx::largeobject lo(elfoid); + libIRDB::pqxxDB_t *interface=dynamic_cast<libIRDB::pqxxDB_t*>(libIRDB::BaseObj_t::GetInterface()); + assert(interface); + lo.to_file(interface->GetTransaction(),"readeh_tmp_file.exe"); + + elfiop=new ELFIO::elfio; + elfiop->load("readeh_tmp_file.exe"); + ELFIO::dump::header(std::cout,*elfiop); + ELFIO::dump::section_headers(std::cout,*elfiop); + ELFIO::dump::segment_headers(std::cout,*elfiop); + } + virtual ~BuffRecv_Instrument() { delete elfiop; } + bool execute(); + + private: + // main tasks + bool _add_buffered_receive_instrumentation(libIRDB::Instruction_t *site); + bool add_buffered_receive_instrumentation(); + std::ostream& displayStatistics(std::ostream &os); + + private: + libIRDB::FileIR_t* firp; + libIRDB::Syscalls_t syscalls; + ELFIO::elfio* elfiop; +}; + +#endif +