diff --git a/.gitattributes b/.gitattributes index 36b39ffeb9793664a4b72c3dc72278de5c72ea8b..cdf835e7b6c97828826f46d48f5a9beea15d034b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -228,6 +228,7 @@ libIRDB/include/libIRDB-syscall.hpp -text libIRDB/include/libIRDB-util.hpp -text libIRDB/include/syscall/syscall.hpp -text libIRDB/include/util/insn_preds.hpp -text +libIRDB/include/util/params.hpp -text libIRDB/include/utils.hpp -text libIRDB/install_libs.sh -text libIRDB/src/Makefile.in -text @@ -266,6 +267,7 @@ libIRDB/src/util/Makefile -text libIRDB/src/util/SConscript -text libIRDB/src/util/SConstruct -text libIRDB/src/util/insn_preds.cpp -text +libIRDB/src/util/params.cpp -text libIRDB/test/SConscript -text libIRDB/test/SConstruct -text libIRDB/test/build_callgraph.cpp -text diff --git a/libIRDB/include/libIRDB-util.hpp b/libIRDB/include/libIRDB-util.hpp index ca47f67ef3a544ccc492ed362fac8743bc34cead..829b8e0dbb22b26ad227cb573eb2463834fa2d78 100644 --- a/libIRDB/include/libIRDB-util.hpp +++ b/libIRDB/include/libIRDB-util.hpp @@ -34,6 +34,7 @@ namespace libIRDB { #include <util/insn_preds.hpp> +#include <util/params.hpp> }; diff --git a/libIRDB/include/util/params.hpp b/libIRDB/include/util/params.hpp new file mode 100644 index 0000000000000000000000000000000000000000..de6006c13459b8ef1b5635507c127630421fc5f1 --- /dev/null +++ b/libIRDB/include/util/params.hpp @@ -0,0 +1,7 @@ +#ifndef _PARAMS_H +#define _PARAMS_H + +extern bool IsParameterWrite(const libIRDB::FileIR_t *firp, libIRDB::Instruction_t* insn, std::string& output_dst); +extern bool CallFollows(libIRDB::FileIR_t *firp, libIRDB::Instruction_t* insn, const std::string& arg_str); + +#endif diff --git a/libIRDB/include/utils.hpp b/libIRDB/include/utils.hpp index 3e8262a9f1ac15ee4c42ba81d535e935187b3636..b9a2899c5facee5dd2653ec9bcfbb8b933cb8d91 100644 --- a/libIRDB/include/utils.hpp +++ b/libIRDB/include/utils.hpp @@ -119,5 +119,6 @@ inline Funct for_randomOrder_each(const IterType &b, const IterType & e, const F }); } - #endif + + diff --git a/libIRDB/src/util/SConscript b/libIRDB/src/util/SConscript index 777fc63737a9adf02c849d0a066248475afb2ba5..6bb27dc65e63018410821ac1fbd47602ed8dabf2 100644 --- a/libIRDB/src/util/SConscript +++ b/libIRDB/src/util/SConscript @@ -8,6 +8,7 @@ myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) libname="IRDB-util" files= ''' insn_preds.cpp + params.cpp ''' cpppath=''' $SECURITY_TRANSFORMS_HOME/include/ @@ -19,6 +20,7 @@ cpppath=''' #myenv.Append(CCFLAGS=" -Wall -W -Wextra -Wconversion ") myenv=myenv.Clone(CPPPATH=Split(cpppath)) +myenv.Append(CXXFLAGS = " -std=c++11 ") lib=myenv.Library(libname, Split(files)) install=env.Install("$SECURITY_TRANSFORMS_HOME/lib/", lib) diff --git a/libIRDB/src/util/params.cpp b/libIRDB/src/util/params.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43c654ee43983aa905fc3c1d7b767bf032f13e9d --- /dev/null +++ b/libIRDB/src/util/params.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014-2017 - 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/ + * + */ + + +#include <libIRDB-core.hpp> +#include <libIRDB-util.hpp> +#include <utils.hpp> + +using namespace libIRDB; +using namespace std; + +// Does instruction potentially write to a parameter to a call? +bool libIRDB::IsParameterWrite(const FileIR_t *firp, Instruction_t* insn, string& output_dst) +{ + DISASM d; + insn->Disassemble(d); + if(d.Argument1.AccessMode!=WRITE) + { + return false; + } + + /* 64 bit machines use regs to pass parameters */ + if(firp->GetArchitectureBitWidth()==64) + { + // if it's a register + if((d.Argument1.ArgType®ISTER_TYPE)==REGISTER_TYPE) + { + int regno=(d.Argument1.ArgType)&0xFFFF; + switch(regno) + { + case REG7: // rdi + case REG6: // rsi + case REG2: // rdx + case REG1: // rcx + case REG8: // r8 + case REG9: // r9 + output_dst=d.Argument1.ArgMnemonic; + return true; + + // other regsiters == no. + default: + return false; + } + + } + } + + // not a register or not 64-bit. check for [esp+k] + + // check for memory type + if((d.Argument1.ArgType&MEMORY_TYPE)!=MEMORY_TYPE) + return false; + + // check that base reg is esp. + if(d.Argument1.Memory.BaseRegister != REG4) + return false; + + // check that there's no index reg + if(d.Argument1.Memory.IndexRegister != 0) + return false; + + // get k out of [esp + k ] + unsigned int k=d.Argument1.Memory.Displacement; + + // check that we know the frame layout. + if(insn->GetFunction() == NULL) + return false; + + if(k < insn->GetFunction()->GetOutArgsRegionSize()) + { + output_dst=string("[")+d.Argument1.ArgMnemonic+string("]"); + return true; + } + + // return we didn't find a memory of the right type + return false; +} + +// is instruction originally a call? +static bool IsOrWasCall(const FileIR_t *firp, Instruction_t* insn) +{ + if (firp == NULL || insn == NULL) + return false; + + DISASM d; + insn->Disassemble(d); + if(d.Instruction.Mnemonic == string("call ")) + return true; + else { + // call may have been converted to push/jmp in previous phase + // look for "push64" type reloc + auto it = std::find_if(insn->GetRelocations().begin(),insn->GetRelocations().end(),[&](const Relocation_t* reloc) + { + if (reloc) + cout << "IsOrWasCall(): reloc: " << reloc->GetType() << endl; + return (reloc && ((reloc->GetType() == string("push64")) || reloc->GetType() == string("fix_call_fallthrough"))); + }); + + if (it != insn->GetRelocations().end()) + return true; + } + + return false; +} + +// Does a call follow the instruction? +bool libIRDB::CallFollows(FileIR_t *firp, Instruction_t* insn, const string& arg_str) +{ + for(Instruction_t* ptr=insn->GetFallthrough(); ptr!=NULL; ptr=ptr->GetFallthrough()) + { + DISASM d; + ptr->Disassemble(d); + if(IsOrWasCall(firp, ptr)) + { + // found it + return true; + } + + // found reference to argstring, assume it's a write and exit + if(string(d.CompleteInstr).find(arg_str)!= string::npos) + return false; + } + + return false; +} + diff --git a/libIRDB/test/fill_in_indtargs.cpp b/libIRDB/test/fill_in_indtargs.cpp index cca30a95c343e4f77fd4d9ef0150df546eb6da05..2747075c9c923b02067215f342128ba975013f63 100644 --- a/libIRDB/test/fill_in_indtargs.cpp +++ b/libIRDB/test/fill_in_indtargs.cpp @@ -20,6 +20,7 @@ */ #include <libIRDB-core.hpp> +#include <libIRDB-util.hpp> #include <iostream> #include <fstream> #include <limits> @@ -281,6 +282,7 @@ void mark_targets(FileIR_t *firp) } +#ifdef MOMVED bool IsParameterWrite(FileIR_t *firp,Instruction_t* insn, string& output_dst) { DISASM d; @@ -347,6 +349,7 @@ bool IsParameterWrite(FileIR_t *firp,Instruction_t* insn, string& output_dst) // return we didn't find a memory of the right type return false; } +#endif bool CallToPrintfFollows(FileIR_t *firp, Instruction_t* insn, const string& arg_str)