Commit 1235bdad authored by Jason Hiser's avatar Jason Hiser 🚜

Merge branch 'master' of ../irdb-xform-cookbook

parents 003f983b 08bcd50c
import os
Import('irdb_env')
# import and create a copy of the environment so we don't screw up anyone elses env.
myenv=irdb_env.Clone()
cpppath=myenv['IRDB_INC']
files=Glob( Dir('.').srcnode().abspath+"/*.cpp")
pgm="initialize_stack.exe"
LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
LIBS=Split("stars "+ myenv.subst('$BASE_IRDB_LIBS')+ " irdb-cfg irdb-util irdb-transform StructDiv ")
myenv=myenv.Clone(CPPPATH=Split(cpppath))
myenv.Append(CXXFLAGS = " -std=c++11 -Wall ")
pgm=myenv.Program(pgm, files, LIBPATH=LIBPATH, LIBS=LIBS)
install=myenv.Install("$SECURITY_TRANSFORMS_HOME/plugins_install/", pgm)
Default(install)
Return('install')
env=Environment()
Export('env')
lib=SConscript("SConscript")
/*
* Copyright (c) 2016, 2017 - 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 the University
* of Virginia.
*
* 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: University of Virginia
* e-mail: jwd@virginia.com
* URL : http://www.cs.virginia.edu/
*
*/
#include "initialize_stack.hpp"
#include <fstream>
#include <algorithm>
#include <math.h>
#define MIN_STACK_FRAME_SIZE 0
#define MAX_STACK_FRAME_SIZE 8000000
using namespace std;
using namespace IRDB_SDK;
using namespace InitStack;
InitStack_t::InitStack_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, const string& p_functionsFilename, int p_initValue, bool p_verbose)
:
Transform(p_variantIR),
m_dbinterface(p_dbinterface),
m_initValue(p_initValue),
m_verbose(p_verbose),
m_numTransformed(0)
{
if (p_functionsFilename=="")
{
cout << "Auto-initialize all functions" << endl;
m_funcsToInit = getFileIR()->getFunctions();
}
else
{
cout << "Auto-initialize functions specified in: " << p_functionsFilename << endl;
readFunctionsFromFile(p_functionsFilename);
}
}
/*
* read list of functions to auto-initialize
*
* post conditions: set of functions to auto-initialize
*/
void InitStack_t::readFunctionsFromFile(const string &p_filename)
{
std::ifstream functionsFile(p_filename);
if (!functionsFile.is_open())
throw;
std::string line;
while(functionsFile >> line)
{
for_each(getFileIR()->getFunctions().begin(), getFileIR()->getFunctions().end(), [&](Function_t* f)
{
if (f && f->getName() == line)
{
m_funcsToInit.insert(f);
cout <<"Adding " << line << " to function list" << endl;
}
});
}
functionsFile.close();
}
/*
* Execute the transform.
*
* preconditions: the FileIR is read as from the IRDB. valid file listing functions to auto-initialize
* postcondition: instructions added to auto-initialize stack for each specified function
*
*/
int InitStack_t::execute()
{
for_each(m_funcsToInit.begin(), m_funcsToInit.end(), [&](Function_t* f)
{
assert(f);
if (f->getName().substr(0, 1) == ".")
return;
initStack(f);
});
cout << "#ATTRIBUTE InitStack::numTransformed=" << m_numTransformed << endl;
return m_numTransformed>0; // true means success
}
/*
* preconditions : f is not NULL
* postconditions: stack auto-initialized if stack frame size > 0
*/
void InitStack_t::initStack(Function_t* f)
{
const auto frame_size = f->getStackFrameSize();
if (frame_size <= MIN_STACK_FRAME_SIZE || frame_size >= MAX_STACK_FRAME_SIZE)
return;
cout << "Function: " << f->getName() << " frame size: " << f->getStackFrameSize() << endl;
const auto num_locs = static_cast<uint64_t> (ceil(frame_size / 4.0));
assert (num_locs >= 0 && num_locs <= 4000000); // sanity check
const auto entry = f->getEntryPoint();
if (!entry)
return;
cout << "Function: " << f->getName() << " auto-initialize " << dec << num_locs << " stack memory locations (4 bytes at a time) with value = " << hex << m_initValue << endl;
const auto sp_reg= getFileIR()->getArchitectureBitWidth()==64 ? "rsp" : "esp";
const auto scratch_reg= getFileIR()->getArchitectureBitWidth()==64 ? "r11" : "ecx";
// assume: flags dead
auto i=entry;
insertAssemblyBefore (i, string()+"mov ["+sp_reg+"+"+to_string(-f->getStackFrameSize()-100)+"], "+scratch_reg);
i = insertAssemblyAfter (i, string()+"mov "+scratch_reg+", -" + std::to_string(num_locs));
const auto L1 = i = insertAssemblyAfter (i, string()+"mov dword ["+sp_reg+"+"+scratch_reg+"*4-4], " + std::to_string(m_initValue));
i = insertAssemblyAfter (i, string()+"inc "+scratch_reg);
i = insertAssemblyAfter (i, string()+"jnz 0", L1);
i = insertAssemblyAfter (i, string()+"mov "+scratch_reg+", ["+sp_reg+"+"+to_string(-f->getStackFrameSize()-100)+"] ");
m_numTransformed++;
}
/*
* Copyright (c) 2014, 2015, 2016, 2017 - 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 the University
* of Virginia.
*
* 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: University of Virginia
* e-mail: jwd@virginia.com
* URL : http://www.cs.virginia.edu/
*
*/
#ifndef _LIBTRANSFORM_INIT_STACK_H
#define _LIBTRANSFORM_INIT_STACK_H
#include <irdb-core>
#include <irdb-transform>
namespace InitStack
{
using namespace std;
using namespace IRDB_SDK;
#define DEFAULT_INIT_VALUE 0
// the actual transform.
class InitStack_t : public Transform
{
public:
// explicitly disable default and copy constructors
InitStack_t() = delete;
InitStack_t(const InitStack::InitStack_t&) = delete;
InitStack_t(IRDB_SDK::pqxxDB_t &p_dbinterface, IRDB_SDK::FileIR_t *p_variantIR, const std::string& p_functionFilename, int initValue = DEFAULT_INIT_VALUE, bool p_verbose = false);
int execute();
private:
void readFunctionsFromFile(const string &p_filename);
void initStack(Function_t* f);
private:
IRDB_SDK::pqxxDB_t &m_dbinterface;
set<Function_t*> m_funcsToInit;
int m_initValue;
bool m_verbose;
int m_numTransformed;
};
}
#endif
/*
* Copyright (c) 2016, 2017 - 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 the University
* of Virginia.
*
* 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: University of Virginia
* e-mail: jwd@virginia.com
* URL : http://www.cs.virginia.edu/
*
*/
#include <getopt.h>
#include "initialize_stack.hpp"
using namespace std;
using namespace IRDB_SDK;
using namespace InitStack;
void usage(char* name)
{
cerr<<"Usage: "<<name<<" <variant_id>\n";
cerr<<"\t[--functions <file> | -f <file>] Read in the functions to auto-initialize"<<endl;
cerr<<"\t[--initvalue <value> | -i <value>] Specify stack initialization value (default=0)"<<endl;
cerr<<"\t[--verbose | -v] Verbose mode "<<endl;
cerr<<"[--help,--usage,-?,-h] Display this message "<<endl;
}
int main(int argc, char **argv)
{
if(argc < 2)
{
usage(argv[0]);
exit(1);
}
string programName(argv[0]);
int variantID = atoi(argv[1]);
bool verbose=false;
string funcsFilename;
int initValue = 0;
// Parse some options for the transform
static struct option long_options[] = {
{"functions", required_argument, 0, 'f'},
{"initvalue", required_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"usage", no_argument, 0, '?'},
{0,0,0,0}
};
const char* short_opts="f:i:v?h";
while(true)
{
int index = 0;
int c = getopt_long(argc, argv, short_opts, long_options, &index);
if(c == -1)
break;
switch(c)
{
case 'f':
funcsFilename=optarg;
cout<<"Reading file with function specifiers: "<<funcsFilename<<endl;
break;
case 'i':
initValue=strtoll(optarg, NULL, 0);
cout<<" Stack initialization value: "<<hex<<initValue<<endl;
break;
case 'v':
verbose=true;
break;
case '?':
case 'h':
usage(argv[0]);
exit(1);
break;
default:
break;
}
}
/* setup the interface to the sql server */
auto pqxx_interface=pqxxDB_t::factory();
BaseObj_t::setInterface(pqxx_interface.get());
auto pidp=VariantID_t::factory(variantID);
assert(pidp->isRegistered()==true);
bool one_success = false;
for(set<File_t*>::iterator it=pidp->getFiles().begin();
it!=pidp->getFiles().end();
++it)
{
File_t* this_file = *it;
auto firp = FileIR_t::factory(pidp.get(), this_file);
cout<<"Transforming "<<this_file->getURL()<<endl;
assert(firp && pidp);
try
{
InitStack_t is(*pqxx_interface,firp.get(), funcsFilename, initValue, verbose);
int success=is.execute();
if (success)
{
cout<<"Writing changes for "<<this_file->getURL()<<endl;
one_success = true;
firp->writeToDB();
}
else
{
cout<<"Skipping (no changes) "<<this_file->getURL()<<endl;
}
}
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_success ? 0 : 2;
}
Import('irdb_env')
# import and create a copy of the environment so we don't screw up anyone elses env.
myenv=irdb_env.Clone()
cpppath=irdb_env['IRDB_INC'] + " $SECURITY_TRANSFORMS_HOME/third_party/elfio-code/ "
files=Glob( Dir('.').srcnode().abspath+"/*.cpp")
myenv.Append(CXXFLAGS = " -std=c++11 ")
pgm="kill_deads.exe"
LIBPATH="$SECURITY_TRANSFORMS_HOME/lib"
LIBS=Split("stars "+ myenv.subst('$BASE_IRDB_LIBS')+ " irdb-transform irdb-deep irdb-util ")
myenv=myenv.Clone(CPPPATH=Split(cpppath))
pgm=myenv.Program(pgm, files, LIBPATH=LIBPATH, LIBS=LIBS)
install=myenv.Install("$SECURITY_TRANSFORMS_HOME/plugins_install/", pgm)
Default(install)
Return('install')
env=Environment()
Export('env')
lib=SConscript("SConscript")
/*
* Copyright (c) 2014, 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 the University
* of Virginia.
*
* 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: University of Virginia
* e-mail: jwd@virginia.com
* URL : http://www.cs.virginia.edu/
*
*/
#include "kill_deads.hpp"
#include <assert.h>
using namespace IRDB_SDK;
using namespace std;
#if 0
static RegisterSet_t get_dead_regs(Instruction_t* insn, MEDS_AnnotationParser &meds_ap_param)
{
auto meds_ap=&meds_ap_param;
assert(meds_ap);
/* find it in the annotations */
auto ret = meds_ap->getAnnotations().equal_range(insn->getBaseID());
MEDS_DeadRegAnnotation* p_annotation;
/* for each annotation for this instruction */
for (auto it = ret.first; it != ret.second; ++it)
{
/* is this annotation a funcSafe annotation? */
p_annotation=dynamic_cast<MEDS_DeadRegAnnotation*>(it->second);
if(p_annotation==NULL)
continue;
/* bad annotation? */
if(!p_annotation->isValid())
continue;
/* that marks the function safe? */
return p_annotation->getRegisterSet();
}
/* couldn't find the annation, return an empty set.*/
return RegisterSet_t();
}
#endif
KillDeads::KillDeads(FileIR_t *p_variantIR)
:
Transform(p_variantIR)
{
}
int KillDeads::execute()
{
auto killed_flags=0L;
auto killed_regs=0L;
srand(time(0));
int kill_val=rand();
/*
STARS::IRDB_Interface_t stars_analysis_engine(dbinterface);
stars_analysis_engine.do_STARS(getFileIR());
auto &annotations=stars_analysis_engine.getAnnotations();
*/
auto de=DeepAnalysis_t::factory(getFileIR());
auto reg_mapp=de->getDeadRegisters();
auto &reg_map=*reg_mapp;
cout<<"Using random_value: "<<dec<<kill_val<<endl;
for(auto &insn : getFileIR()->getInstructions())
{
const auto &regset=reg_map[insn];
for(auto reg : regset)
{
if (reg==rn_EFLAGS)
{
// for flags, do a random compare to change them
char buf[100];
sprintf(buf," cmp rax, %d", kill_val);
cout<<"Inserting '"<<buf<<"' before '"<<insn->getDisassembly()<<"'"<<endl;
insertAssemblyBefore(insn, buf);
killed_flags++;
}
if(is64bitRegister(reg) || is32bitRegister(reg) || is16bitRegister(reg) || is8bitRegister(reg))
{
char buf[100];
sprintf(buf," mov %s, %d", registerToString(reg).c_str(), kill_val);
cout<<"Inserting '"<<buf<<"' before '"<<insn->getDisassembly()<<"'"<<endl;
insertAssemblyBefore(insn, buf);
killed_regs++;
}
}
}
assert(getenv("SELF_VALIDATE")==nullptr || killed_flags > 5);
assert(getenv("SELF_VALIDATE")==nullptr || killed_regs > 15);
// assert(getenv("SELF_VALIDATE")==nullptr || annotations.getAnnotations().size() > 15);
cout<<"#ATTRIBUTE killed_flags="<<dec<<killed_flags<<endl;
cout<<"#ATTRIBUTE killed_regs="<<dec<<killed_regs<<endl;
return 1;
}
/*
* Copyright (c) 2014, 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 the University
* of Virginia.
*
* 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: University of Virginia
* e-mail: jwd@virginia.com
* URL : http://www.cs.virginia.edu/
*
*/
#ifndef _LIBTRANSFORM_KILL_DEADS_H
#define _LIBTRANSFORM_KILL_DEADS_H
#include <irdb-core>
#include <irdb-transform>
#include <irdb-deep>
class KillDeads : public IRDB_SDK::Transform
{
public:
KillDeads(IRDB_SDK::FileIR_t *p_variantIR);
int execute();
private:
};
#endif
/*
* Copyright (c) 2014, 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 the University
* of Virginia.
*
* 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: University of Virginia
* e-mail: jwd@virginia.com
* URL : http://www.cs.virginia.edu/
*
*/
#include <stdlib.h>
#include <fstream>
#include <irdb-core>
#include <libgen.h>
#include "kill_deads.hpp"
using namespace std;
using namespace IRDB_SDK;
void usage(char* name)
{
cerr<<"Usage: "<<name<<" <variant_id>\n";
}
int main(int argc, char **argv)
{
if(argc != 2)
{
usage(argv[0]);
exit(1);
}
string programName(argv[0]);
int variantID = atoi(argv[1]);
/* setup the interface to the sql server */
auto pqxx_interface=pqxxDB_t::factory();
BaseObj_t::setInterface(pqxx_interface.get());
auto pidp=VariantID_t::factory(variantID);
assert(pidp->isRegistered()==true);
cout<<"kill_deads_driver.exe started\n";
bool one_success = false;
for(set<File_t*>::iterator it=pidp->getFiles().begin();
it!=pidp->getFiles().end();
++it)
{
File_t* this_file = *it;
auto firp = FileIR_t::factory(pidp.get(), this_file);
cout<<"Transforming "<<this_file->getURL()<<endl;
assert(firp && pidp);
try
{
KillDeads kill_deads(firp.get());
int success=kill_deads.execute();
if (success)
{
cout<<"Writing changes for "<<this_file->getURL()<<endl;
one_success = true;
firp->writeToDB();
}
else
{
cout<<"Skipping (no changes) "<<this_file->getURL()<<endl;
}
}
catch (DatabaseError_t pnide)
{
cerr << programName << ": Unexpected database error: " << pnide << "file url: " << this_file->getURL() << endl;
return 1;
}
catch (...)
{
cerr << programName << ": Unexpected error file url: " << this_file->getURL() << endl;
return 1;
}
} // end file iterator
// if any integer transforms for any files succeeded, we commit
if (one_success)
{