diff --git a/builtin_xforms/add_lib/al.cpp b/builtin_xforms/add_lib/al.cpp index 0e7ad7220a75710c131b249265b922eeda42e694..bae19b1e2176d99f88034c6d13a33b2e2f7ba15a 100644 --- a/builtin_xforms/add_lib/al.cpp +++ b/builtin_xforms/add_lib/al.cpp @@ -8,7 +8,7 @@ using namespace AddLib; AddLib_t::AddLib_t(FileIR_t* firp, const StringSet_t &p_prepended, const StringSet_t &p_appended) - : Transform (firp), prepended(p_prepended), appended(p_appended) + : Transform_t(firp), prepended(p_prepended), appended(p_appended) { } diff --git a/builtin_xforms/add_lib/al.hpp b/builtin_xforms/add_lib/al.hpp index a5821e52e2fe90bd0db35aa9dc9d2c26ecebae85..94cf60ab38a42aea6b096f3dab80bc2e6460f6ca 100644 --- a/builtin_xforms/add_lib/al.hpp +++ b/builtin_xforms/add_lib/al.hpp @@ -11,7 +11,7 @@ using namespace std; typedef set<string> StringSet_t; -class AddLib_t : Transform +class AddLib_t : Transform_t { public: AddLib_t(FileIR_t* firp, const StringSet_t &prepended, const StringSet_t &appended); diff --git a/builtin_xforms/move_globals/mg.cpp b/builtin_xforms/move_globals/mg.cpp index 9dbede0c9e15c47000b5ef25fee0b4dd3238816e..ace99181bcae28cba6f8e79791a1d07e1968abc1 100644 --- a/builtin_xforms/move_globals/mg.cpp +++ b/builtin_xforms/move_globals/mg.cpp @@ -95,7 +95,7 @@ MoveGlobals_t<T_Sym,T_Rela,T_Rel,T_Dyn,T_Extractor>::MoveGlobals_t( const bool p_aggressive, const bool p_use_stars) : - Transform(p_variantIR), + Transform_t(p_variantIR), struct_div(NULL), exe_reader(NULL), tied_unpinned(0), diff --git a/builtin_xforms/move_globals/mg.hpp b/builtin_xforms/move_globals/mg.hpp index 2cf45509367ee5de4da33bfb23388db387af5824..dc8a24df3bfdea7863949dd686991e5b0444b2f8 100644 --- a/builtin_xforms/move_globals/mg.hpp +++ b/builtin_xforms/move_globals/mg.hpp @@ -19,7 +19,7 @@ using Elf_Xword = uint64_t; using Elf_Half = uint16_t; template <class T_Sym, class T_Rela, class T_Rel, class T_Dyn, class Extractor> -class MoveGlobals_t : public IRDB_SDK::Transform +class MoveGlobals_t : public IRDB_SDK::Transform_t { public: MoveGlobals_t(IRDB_SDK::VariantID_t *p_variantID, diff --git a/builtin_xforms/resolve_callbacks/callbacks.cpp b/builtin_xforms/resolve_callbacks/callbacks.cpp index c41c6f0681abad55f32ac91522ef3eeccde84011..c29daa047bc8ec677637837b350c28e63d969660 100644 --- a/builtin_xforms/resolve_callbacks/callbacks.cpp +++ b/builtin_xforms/resolve_callbacks/callbacks.cpp @@ -10,7 +10,7 @@ using namespace IRDB_SDK; template <class T> void ignore_result(const T&){}; Callbacks::Callbacks(FileIR_t *p_variantIR) : - Transform(p_variantIR), + Transform_t(p_variantIR), m_firp(p_variantIR), m_text_offset(0) { diff --git a/builtin_xforms/resolve_callbacks/callbacks.hpp b/builtin_xforms/resolve_callbacks/callbacks.hpp index f50406c05bfa777042820c6f1953cc3e4d20d38a..7f7ecbcc0eddc5a4b0fc54e8386f57aab036a83a 100644 --- a/builtin_xforms/resolve_callbacks/callbacks.hpp +++ b/builtin_xforms/resolve_callbacks/callbacks.hpp @@ -9,7 +9,7 @@ using namespace std; using namespace IRDB_SDK; -class Callbacks : public Transform +class Callbacks : public Transform_t { public: Callbacks(FileIR_t *p_variantIR); diff --git a/irdb-libs/libIRDB-deep/src/deep.cpp b/irdb-libs/libIRDB-deep/src/deep.cpp index 1ab77bc43feb4763f7a5b09f906af7f3d2b1ebbd..1bfad4ea953c0bd5da9c669b82d4ca0777a245f1 100644 --- a/irdb-libs/libIRDB-deep/src/deep.cpp +++ b/irdb-libs/libIRDB-deep/src/deep.cpp @@ -14,7 +14,7 @@ using namespace MEDS_Annotation; StarsDeepAnalysis_t::StarsDeepAnalysis_t(IRDB_SDK::FileIR_t* firp, const vector<string>& options) - : Transform(firp) + : Transform_t(firp) { for(const auto s : options) { diff --git a/irdb-libs/libIRDB-deep/src/deep.hpp b/irdb-libs/libIRDB-deep/src/deep.hpp index 6943da676fbd16caf9b0a49d2d806617906eb284..c06bcb343e8a69d96f8ac30f792326acbf7fb520 100644 --- a/irdb-libs/libIRDB-deep/src/deep.hpp +++ b/irdb-libs/libIRDB-deep/src/deep.hpp @@ -12,7 +12,7 @@ namespace libIRDB { using namespace std; - class StarsDeepAnalysis_t : public IRDB_SDK::DeepAnalysis_t, protected IRDB_SDK::Transform + class StarsDeepAnalysis_t : public IRDB_SDK::DeepAnalysis_t, protected IRDB_SDK::Transform_t { private: StarsDeepAnalysis_t() = delete; diff --git a/irdb-libs/libIRDB-elfdep/src/elfdep.cpp b/irdb-libs/libIRDB-elfdep/src/elfdep.cpp index 78fa36b08f26ccb4cf8ed9d5c73ffe66bfa53fd5..7a58967fc3641c5fc0b01c66234fa5c554e98528 100644 --- a/irdb-libs/libIRDB-elfdep/src/elfdep.cpp +++ b/irdb-libs/libIRDB-elfdep/src/elfdep.cpp @@ -168,7 +168,7 @@ static void prefix_scoop(const string &str, IRDB_SDK::DataScoop_t* scoop, IRDB_S // constructors ElfDependencies_t::ElfDependencies_t(IRDB_SDK::FileIR_t* firp) - : Transform(firp) + : Transform_t(firp) { typedef ElfDependencies_t::ElfDependenciesImpl_t<Elf64_Sym, Elf64_Rela, Elf64_Dyn, R_X86_64_GLOB_DAT, 32, 8> ElfDependencies64_t; typedef ElfDependencies_t::ElfDependenciesImpl_t<Elf32_Sym, Elf32_Rel, Elf32_Dyn, R_386_GLOB_DAT, 8, 4> ElfDependencies32_t; diff --git a/irdb-libs/libIRDB-elfdep/src/libElfDep.hpp b/irdb-libs/libIRDB-elfdep/src/libElfDep.hpp index 4b7eb1e5f7818fdb05b0315e05afc202530ab140..d6974957f67306a2e4f8d46928e04374e8ad2f1a 100644 --- a/irdb-libs/libIRDB-elfdep/src/libElfDep.hpp +++ b/irdb-libs/libIRDB-elfdep/src/libElfDep.hpp @@ -11,7 +11,7 @@ namespace libIRDB using namespace std; -class ElfDependencies_t : public IRDB_SDK::Transform, public IRDB_SDK::ElfDependencies_t +class ElfDependencies_t : public IRDB_SDK::Transform_t, public IRDB_SDK::ElfDependencies_t { public: @@ -27,10 +27,10 @@ class ElfDependencies_t : public IRDB_SDK::Transform, public IRDB_SDK::ElfDepend private: - class ElfDependenciesBase_t : public Transform + class ElfDependenciesBase_t : public IRDB_SDK::Transform_t { public: - ElfDependenciesBase_t(IRDB_SDK::FileIR_t* firp) : Transform(firp) {} + ElfDependenciesBase_t(IRDB_SDK::FileIR_t* firp) : Transform_t(firp) {} virtual void prependLibraryDepedencies(const string &libraryName)=0; virtual void appendLibraryDepedencies(const string &libraryName)=0; virtual pair<IRDB_SDK::DataScoop_t*,int> appendGotEntry(const string &name)=0; diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/Makefile.in b/irdb-libs/libIRDB-transform/include-unused-delete-later/Makefile.in deleted file mode 100644 index 56fe02141bd2113326a9d6b1af59e3e87a7ace1b..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/Makefile.in +++ /dev/null @@ -1,18 +0,0 @@ - -CXX=@CXX@ - -LIB=../lib/libtransform.a - -OBJS=Rewrite_Utility.o transform.o integertransform.o leapattern.o integertransform64.o integertransform32.o pointercheck64.o - -all: $(OBJS) - -$(OBJS): ../include/*.hpp - -clean: - rm -f $(OBJS) - -.cpp.o: - $(CXX) -g -c -I. -I../include -I../../libIRDB/include -I../../libMEDSannotation/include -I../../beaengine/include $< - ar rc $(LIB) $@ - cp $(LIB) ../../lib/ diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/Rewrite_Utility.hpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/Rewrite_Utility.hpp deleted file mode 100644 index 7a9f1f90a0f1f02a3d981954ec78fdda87a4e81e..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/Rewrite_Utility.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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 <irdb-core> - - -namespace IRDBUtility { -using namespace IRDB_SDK; -using namespace std; - -//The "first" instruction will have its contents replaced and a duplicate of "first" will be in the follow of first. -//This duplicate is returned since the user already has a pointer to first. -Instruction_t* insertAssemblyBefore(FileIR_t* virp, Instruction_t* first, string assembly, Instruction_t *target); -Instruction_t* insertAssemblyBefore(FileIR_t* virp, Instruction_t* first, string assembly); -Instruction_t* insertDataBitsBefore(FileIR_t* virp, Instruction_t* first, string dataBits, Instruction_t *target); -Instruction_t* insertDataBitsBefore(FileIR_t* virp, Instruction_t* first, string dataBits); - -// insert new instructions after, diff types. -Instruction_t* insertAssemblyAfter(FileIR_t* virp, Instruction_t* first, string assembly, Instruction_t *target); -Instruction_t* insertAssemblyAfter(FileIR_t* virp, Instruction_t* first, string assembly); -Instruction_t* insertDataBitsAfter(FileIR_t* virp, Instruction_t* first, string dataBits, Instruction_t *target); -Instruction_t* insertDataBitsAfter(FileIR_t* virp, Instruction_t* first, string dataBits); - -// add new instructions of diff types. -Instruction_t* addNewDatabits(FileIR_t* firp, Instruction_t *p_instr, string p_bits); -Instruction_t* addNewAssembly(FileIR_t* firp, Instruction_t *p_instr, string p_asm); - - -//Does not insert into any variant, just copies data about the instruction itself, see the copyInstruction(src,dest) to see what is copied. -Instruction_t* copyInstruction(Instruction_t* instr); - -Instruction_t* copyInstruction(FileIR_t* virp, Instruction_t* instr); -//copy src to destination -void copyInstruction(Instruction_t* src, Instruction_t* dest); - -Instruction_t* allocateNewInstruction(FileIR_t* virp, DatabaseID_t p_fileID,Function_t* func); -Instruction_t* allocateNewInstruction(FileIR_t* virp, Instruction_t *template_instr); -void setInstructionAssembly(FileIR_t* virp,Instruction_t *p_instr, string p_assembly, Instruction_t *p_fallThrough, Instruction_t *p_target); - - -} diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform.cpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform.cpp deleted file mode 100644 index b72c5f7941fc2a8a4f5ff688466dabf2bc06c415..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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 <assert.h> -#include "integertransform.hpp" -#include "leapattern.hpp" - - -/* - * Find the first occurrence of find in s, ignore case. - */ -static char * -my_strcasestr(const char* s, const char *find) -{ - char c, sc; - size_t len; - - if ((c = *find++) != 0) { - c = tolower((unsigned char)c); - len = strlen(find); - do { - do { - if ((sc = *s++) == 0) - return (NULL); - } while ((char)tolower((unsigned char)sc) != c); - } while (strncasecmp(s, find, len) != 0); - s--; - } - return ((char *)s); -} - - -// -// For list of blacklisted functions, see: isBlacklisted() -// - -using namespace libTransform; - -IntegerTransform::IntegerTransform(VariantID_t *p_variantID, FileIR_t *p_fileIR, -// std::multimap<VirtualOffset, MEDS_AnnotationBase> -MEDS_Annotations_t *p_annotations, -set<std::string> *p_filteredFunctions, set<VirtualOffset> *p_benignFalsePositives) : Transform(p_variantID, p_fileIR, p_filteredFunctions) -{ - m_benignFalsePositives = p_benignFalsePositives; - m_policySaturatingArithmetic = false; - m_policyWarningsOnly = false; - m_pathManipulationDetected = false; - m_instrumentIdioms = false; - - m_annotations = p_annotations; - - m_numAnnotations = 0; - m_numIdioms = 0; - m_numBlacklisted = 0; - m_numBenign = 0; - m_numFP = 0; - - m_numTotalOverflows = 0; - m_numTotalUnderflows = 0; - m_numTotalTruncations = 0; - m_numTotalSignedness = 0; - - m_numOverflows = 0; - m_numUnderflows = 0; - m_numTruncations = 0; - m_numSignedness = 0; - - m_numOverflowsSkipped = 0; - m_numUnderflowsSkipped = 0; - m_numTruncationsSkipped = 0; - m_numSignednessSkipped = 0; - - m_instrumentSP = false; - m_instrumentFP = false; -} - -bool IntegerTransform::isBlacklisted(Function_t *func) -{ - if (!func) return false; - - const char *funcName = func->GetName().c_str(); - return (my_strcasestr(funcName, "hash") || - my_strcasestr(funcName, "compress") || - my_strcasestr(funcName, "encode") || - my_strcasestr(funcName, "decode") || - my_strcasestr(funcName, "crypt") || - my_strcasestr(funcName, "yyparse") || - my_strcasestr(funcName, "yyerror") || - my_strcasestr(funcName, "yydestruct") || - my_strcasestr(funcName, "yyrestart") || - my_strcasestr(funcName, "yylex") || - my_strcasestr(funcName, "yyparse") || - my_strcasestr(funcName, "yyerror") || - my_strcasestr(funcName, "yydestruct") || - my_strcasestr(funcName, "yyrestart") || - my_strcasestr(funcName, "yylex") || - my_strcasestr(funcName, "yy_")); -} - -void IntegerTransform::logStats() -{ - std::string fileURL = getFileIR()->GetFile()->GetURL(); - - std::cerr << "# ATTRIBUTE intx::file_name=" << fileURL << std::endl; - std::cerr << "# ATTRIBUTE intx::num_annotations_processed=" << dec << m_numAnnotations << std::endl; - std::cerr << "# ATTRIBUTE intx::num_idioms=" << m_numIdioms << std::endl; - std::cerr << "# ATTRIBUTE intx::num_blacklisted=" << m_numBlacklisted << std::endl; - std::cerr << "# ATTRIBUTE intx::num_benign=" << m_numBenign << std::endl; - - std::cerr << "# ATTRIBUTE intx::num_total_overflows=" << m_numTotalOverflows << std::endl; - std::cerr << "# ATTRIBUTE intx::num_overflows_instrumented=" << m_numOverflows << std::endl; - std::cerr << "# ATTRIBUTE intx::num_overflows_skipped=" << m_numOverflowsSkipped << std::endl; - std::cerr << "# ATTRIBUTE intx::overflows_coverage=" << (double)m_numOverflows/(double)m_numTotalOverflows << std::endl; - - std::cerr << "# ATTRIBUTE intx::num_total_underflows=" << m_numTotalUnderflows << std::endl; - std::cerr << "# ATTRIBUTE intx::num_underflows_instrumented=" << m_numUnderflows << std::endl; - std::cerr << "# ATTRIBUTE intx::num_underflows_skipped=" << m_numUnderflowsSkipped << std::endl; - std::cerr << "# ATTRIBUTE intx::underflows_coverage=" << (double)m_numUnderflows/(double)m_numTotalUnderflows << std::endl; - - std::cerr << "# ATTRIBUTE intx::num_total_truncations=" << m_numTotalTruncations << std::endl; - std::cerr << "# ATTRIBUTE intx::num_truncations_instrumented=" << m_numTruncations << std::endl; - std::cerr << "# ATTRIBUTE intx::num_truncations_skipped=" << m_numTruncationsSkipped << std::endl; - std::cerr << "# ATTRIBUTE intx::truncation_coverage=" << (double)m_numTruncations/(double)m_numTotalTruncations << std::endl; - - std::cerr << "# ATTRIBUTE intx::num_total_signedness=" << m_numTotalSignedness << std::endl; - std::cerr << "# ATTRIBUTE intx::num_signedness_instrumented=" << m_numSignedness << std::endl; - std::cerr << "# ATTRIBUTE intx::num_signedness_skipped=" << m_numSignednessSkipped << std::endl; - std::cerr << "# ATTRIBUTE intx::signedness_coverage=" << (double)m_numSignedness/(double)m_numTotalSignedness << std::endl; - - std::cerr << "# ATTRIBUTE intx::num_floating_point=" << m_numFP << std::endl; -} diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform.hpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform.hpp deleted file mode 100644 index ce9e5f361147bfff01d5ee0bb31a25dcc7138724..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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_INTEGERTRANSFORM_H_ -#define _LIBTRANSFORM_INTEGERTRANSFORM_H_ - -#include "transform.hpp" -#include "MEDS_Register.hpp" -#include "MEDS_AnnotationParser.hpp" -#include "VirtualOffset.hpp" - -namespace libTransform -{ - -using namespace std; -using namespace libIRDB; - -const int IDIOM_POINTER_NUMERIC_WEAKNESS = 18; - -class IntegerTransform : public Transform -{ - public: - IntegerTransform(VariantID_t *, FileIR_t*, MEDS_Annotations_t *p_annotations, set<std::string> *p_filteredFunctions, set<VirtualOffset> *p_warnings); - virtual int execute() = 0; - - void setSaturatingArithmetic(bool p_satArithmetic) { m_policySaturatingArithmetic = p_satArithmetic; } - bool isSaturatingArithmetic() { return m_policySaturatingArithmetic; } - void setPathManipulationDetected(bool p_pathManip) { m_pathManipulationDetected = p_pathManip; } - bool isPathManipulationDetected() { return m_pathManipulationDetected; } - void setWarningsOnly(bool p_warn) { m_policyWarningsOnly = p_warn; } - bool isWarningsOnly() { return m_policyWarningsOnly; } - void setInstrumentIdioms(bool p_idioms) { m_instrumentIdioms = p_idioms; } - bool isInstrumentIdioms() { return m_instrumentIdioms; } - void logStats(); - bool isBlacklisted(Function_t *func); - - protected: - void setInstrumentSP(bool sp) { m_instrumentSP = sp; } - bool instrumentSP() const { return m_instrumentSP; } - void setInstrumentFP(bool fp) { m_instrumentFP = fp; } - bool instrumentFP() const { return m_instrumentFP; } - - protected: - MEDS_Annotations_t* getAnnotations() { return m_annotations; } - - std::set<VirtualOffset>* m_benignFalsePositives; - bool m_policySaturatingArithmetic; - bool m_policyWarningsOnly; - bool m_pathManipulationDetected; - bool m_instrumentIdioms; - MEDS_Annotations_t *m_annotations; - - unsigned m_numAnnotations; - unsigned m_numIdioms; - unsigned m_numBlacklisted; - unsigned m_numBenign; - - unsigned m_numTotalOverflows; - unsigned m_numOverflows; - unsigned m_numOverflowsSkipped; - - unsigned m_numTotalUnderflows; - unsigned m_numUnderflows; - unsigned m_numUnderflowsSkipped; - - unsigned m_numTotalTruncations; - unsigned m_numTruncations; - unsigned m_numTruncationsSkipped; - - unsigned m_numTotalSignedness; - unsigned m_numSignedness; - unsigned m_numSignednessSkipped; - - unsigned m_numFP; - - bool m_instrumentSP; - bool m_instrumentFP; -}; - -} - -#endif diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform32.cpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform32.cpp deleted file mode 100644 index 3f63ef75561fff2b9d8086393e3ec25ac69819b5..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform32.cpp +++ /dev/null @@ -1,2175 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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 <assert.h> -#include "integertransform32.hpp" -#include "leapattern.hpp" - -// -// For list of blacklisted functions, see: isBlacklisted() -// - -// -// MEDS has the following annotation types: -// - OVERFLOW (SIGNED|UNSIGNED|UNKNOWN) (32,16,8) -// - UNDERFLOW (SIGNED|UNSIGNED|UNKNOWN) (32,16,8) -// - SIGNEDNESS SIGNED (32,16,8) -// - TRUNCATION (SIGNED|UNSIGNED|UNKNOWN) (32,16,8) -// - XXX_NOFLAG (Many forms, handles LEA) -// -// Saturating arithmetic implemented for: -// - OVERFLOW (when destination is a register) -// - UNDERFLOW (when destination is a register) -// - SIGNEDNESS -// - TRUNCATION -// -// ============= TO DO ============= -// Saturating arithmetic to do: -// - OVERFLOW (dest. is not a register) -// - UNDERFLOW (dest. is not a register) -// -// Instrumentation: -// - TRUNCATION (16->8) no test cases available -// - LEA only reg32+reg32 case implemented -// 20130409 Anh fixed lea reg+reg bug (we were assuming that annotation matched instruction exactly) -// 20130410 Anh implemented shared library support -- added outer loop to iterate over all files in the driver program -// 20130411 Anh skip instrumentation where there's no fallthrough for an instruction -// -using namespace libTransform; - -IntegerTransform32::IntegerTransform32(VariantID_t *p_variantID, FileIR_t *p_fileIR, -MEDS_Annotations_t *p_annotations, set<std::string> *p_filteredFunctions, set<VirtualOffset> *p_benignFalsePositives) : IntegerTransform(p_variantID, p_fileIR, p_annotations, p_filteredFunctions, p_benignFalsePositives) -{ -} - -// iterate through all functions -// filter those functions that should be ignored -// iterate through all instructions in function -// if MEDS annotation says to instrument -// add instrumentation -int IntegerTransform32::execute() -{ - if (isSaturatingArithmetic()) - cerr << "IntegerTransform32: Saturating Arithmetic is enabled" << endl; - else - cerr << "IntegerTransform32: Saturating Arithmetic is disabled" << endl; - - if (isPathManipulationDetected()) - cerr << "IntegerTransform32: Exit on truncation" << endl; - - if (isWarningsOnly()) - cerr << "IntegerTransform32: Warnings only mode" << endl; - - for( - set<Function_t*>::const_iterator itf=getFileIR()->GetFunctions().begin(); - itf!=getFileIR()->GetFunctions().end(); - ++itf - ) - { - Function_t* func=*itf; - - if (getFilteredFunctions()->find(func->GetName()) != getFilteredFunctions()->end()) - { - continue; - } - - if (isBlacklisted(func)) - { - cerr << "Heuristic filter: " << func->GetName() << endl; - m_numBlacklisted++; - continue; - } - - logMessage(__func__, "processing fn: " + func->GetName()); - - for( - set<Instruction_t*>::const_iterator it=func->GetInstructions().begin(); - it!=func->GetInstructions().end(); - ++it) - { - Instruction_t* insn=*it; - - if (insn && insn->getAddress()) - { - int policy = POLICY_DEFAULT; // use Strata default settings - virtual_offset_t irdb_vo = insn->getAddress()->GetVirtualOffset(); - if (irdb_vo == 0) continue; - - VirtualOffset vo(irdb_vo); - - if(insn->GetDataBits().c_str()[0]==(char)0xDF || insn->GetDataBits().c_str()[0]==(char)0xDB){ - handleFISTTruncation(insn); - } - - if (isSaturatingArithmetic()) - { - // saturating arithmetic is enabled - // only use if instruction is not a potential false positive - policy = POLICY_CONTINUE_SATURATING_ARITHMETIC; - } - - // takes precedence over saturation if conflict - if (isWarningsOnly()) - { - policy = POLICY_CONTINUE; - } - - // overwrite the above if needed - if (isPathManipulationDetected()) - { - policy = POLICY_EXIT; - } - - if (m_benignFalsePositives && m_benignFalsePositives->count(vo)) - { - // potential benign false positives - m_numBenign++; - policy = POLICY_CONTINUE; - } - - -/* - MEDS_InstructionCheckAnnotation annotation = (*getAnnotations())[vo]; - if (!annotation.isValid()) - continue; -*/ - if (getAnnotations()->count(vo) == 0) - continue; - - std::pair< MEDS_Annotations_t::iterator, MEDS_Annotations_t::iterator > ret; - ret = getAnnotations()->equal_range(vo); - MEDS_InstructionCheckAnnotation annotation; - MEDS_InstructionCheckAnnotation* p_annotation; - for ( MEDS_Annotations_t::iterator it = ret.first; it != ret.second; ++it) - { - MEDS_AnnotationBase *b = (it->second); - p_annotation=dynamic_cast<MEDS_InstructionCheckAnnotation*>(b); - if(!p_annotation) - continue; - annotation=*p_annotation; - if (!annotation.isValid()) - continue; - else - break; // let's just handle one annotation for now and see how it goes - } - - if (!annotation.isValid()) - continue; - - logMessage(__func__, annotation, "-- instruction: " + insn->getDisassembly()); - m_numAnnotations++; - - if (annotation.isIdiom()) - { - logMessage(__func__, "skip IDIOM"); - m_numIdioms++; - continue; - } - - if (!insn->getFallthrough()) - { - logMessage(__func__, "Warning: no fall through for instruction -- skipping"); - continue; - } - - if (annotation.isOverflow()) - { - // nb: safe with respect to esp (except for lea) - m_numTotalOverflows++; - handleOverflowCheck(insn, annotation, policy); - } - else if (annotation.isUnderflow() && !annotation.isNoFlag()) - { - m_numTotalUnderflows++; - // nb: safe with respect to esp - handleUnderflowCheck(insn, annotation, policy); - } - else if (annotation.isTruncation()) - { - m_numTotalTruncations++; - handleTruncation(insn, annotation, policy); - } - else if (annotation.isSignedness()) - { - m_numTotalSignedness++; - if (annotation.isUnknownSign()) - { - logMessage(__func__, "annotation has unknown sign: skipping"); - continue; - } - handleSignedness(insn, annotation, policy); - } - else if (annotation.isInfiniteLoop()) - { - handleInfiniteLoop(insn, annotation, POLICY_EXIT); - } - else - { - logMessage(__func__, "unknown annotation"); - } - } - } // end iterate over all instructions in a function - } // end iterate over all functions - - return 0; -} - -void IntegerTransform32::handleSignedness(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - if (p_annotation.isSigned() || p_annotation.isUnsigned()) - addSignednessCheck(p_instruction, p_annotation, p_policy); - else - logMessage(__func__, "case not yet handled"); -} - -// 8048576 5 INSTR CHECK SIGNEDNESS SIGNED 16 AX ZZ mov [esp+28h], ax -// <save flags> -// TEST ax, ax -// jns L1 -// invoke conversion handler -// (optional) mov ax, MAX_16 ; saturating arithmetic (Max for bit width/sign/unsigned) -// -// L1: <restore flags> -// mov [esp+28h], ax -// -// 20120414 We may want to saturate the destination instead. This would mean putting the saturation code -// after the instruction being instrumented -void IntegerTransform32::addSignednessCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - // sanity checks - assert(getFileIR() && p_instruction); - assert (p_annotation.isValid()); - if ( - !(p_annotation.getBitWidth() == 32 && Register::is32bit(p_annotation.getRegister())) && - !(p_annotation.getBitWidth() == 16 && (Register::is16bit(p_annotation.getRegister()) || - p_annotation.getRegister() == rn_ESI || p_annotation.getRegister() == rn_EDI || p_annotation.getRegister() == rn_EBP)) && - !(p_annotation.getBitWidth() == 8 && Register::is8bit(p_annotation.getRegister())) - ) - { - logMessage(__func__, "unexpected bit width and register combination: skipping"); - m_numSignednessSkipped++; - return; - } - - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* test_i = allocateNewInstruction(fileID, func); - Instruction_t* jns_i = allocateNewInstruction(fileID, func); - Instruction_t* nop_i = allocateNewInstruction(fileID, func); - Instruction_t* popf_i = allocateNewInstruction(fileID, func); - - addPushf(pushf_i, test_i); - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, pushf_i); - pushf_i->setFallthrough(test_i); - pushf_i->setComment("-- in signedness check"); - addTestRegister(test_i, p_annotation.getRegister(), jns_i); - addJns(jns_i, nop_i, popf_i); - addNop(nop_i, popf_i); - - string detector; - if (p_annotation.getBitWidth() == 32) - detector = string(SIGNEDNESS_DETECTOR_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(SIGNEDNESS_DETECTOR_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(SIGNEDNESS_DETECTOR_8); - - // sanity filter - if (p_annotation.getRegister() == rn_UNKNOWN) - p_policy = POLICY_DEFAULT; - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - // implement saturating arithmetic on register, i.e.: mov <reg>, value - Instruction_t* saturate_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - - addCallbackHandler(detector, originalInstrumentInstr, nop_i, saturate_i, p_policy, p_instruction->getAddress()); - if (p_annotation.isSigned()) - addMaxSaturation(saturate_i, p_annotation.getRegister(), p_annotation, popf_i); - else - addZeroSaturation(saturate_i, p_annotation.getRegister(), popf_i); - } - else - { - addCallbackHandler(detector, originalInstrumentInstr, nop_i, popf_i, p_policy, p_instruction->getAddress()); - } - addPopf(popf_i, originalInstrumentInstr); - - m_numSignedness++; -} - -void IntegerTransform32::handleOverflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - if (p_annotation.isUnknownSign() && !p_annotation.isNoFlag()) - { - addOverflowCheckUnknownSign(p_instruction, p_annotation, p_policy); - } - else if (p_annotation.isNoFlag()) - { - // handle lea - addOverflowCheckNoFlag(p_instruction, p_annotation, p_policy); - } - else if (isMultiplyInstruction(p_instruction) || p_annotation.isUnderflow() || p_annotation.isOverflow()) - { - // handle signed/unsigned add/sub overflows (non lea) - addOverflowCheck(p_instruction, p_annotation, p_policy); - } - else - { - m_numOverflowsSkipped++; - logMessage(__func__, "OVERFLOW type not yet handled"); - } -} - -void IntegerTransform32::handleUnderflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - if (p_annotation.isUnderflow()) - { - addUnderflowCheck(p_instruction, p_annotation, p_policy); - } - else - { - m_numUnderflowsSkipped++; - logMessage(__func__, "UNDERFLOW type not yet handled"); - } -} - -/* - NOFLAGUNKNOWNSIGN 32 ESI+EDX ZZ lea eax, [esi+edx] - NOFLAGUNSIGNED 32 EDX+ESI+1900 ZZ lea esi, [edx+esi+76Ch] - NOFLAGUNSIGNED 32 EAX+382 ZZ lea esi, [eax+17Eh] - NOFLAGUNKNOWNSIGN 32 EDX*8 ZZ lea eax, ds:0[edx*8] - NOFLAGUNSIGNED 32 ECX+ECX*4 ZZ lea ebx, [ecx+ecx*4] - NOFLAGUNSIGNED 32 EDI+-66 ZZ lea eax, [edi-42h] - NOFLAGSIGNED 32 ESI+100 ZZ lea ecx, [esi+64h] - - possible patterns after the bit width field: - rpr: <reg>+<reg> - rpc: <reg>+-<constant> - rpc: <reg>+<constant> - rtc: <reg>*constant - - - not yet handling these: - rprpc: <reg>+<reg>+<constant> - rprpc: <reg>+<reg>+-<constant> - rprtc: <reg>+<reg>*<constant> -*/ -void IntegerTransform32::addOverflowCheckNoFlag(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - LEAPattern leaPattern(p_annotation); - - if (!leaPattern.isValid()) - { - logMessage(__func__, "invalid or unhandled lea pattern - skipping: "); - m_numOverflowsSkipped++; - return; - } - - if (leaPattern.getRegister1() == rn_UNKNOWN || - leaPattern.getRegister1() == rn_ESP || - leaPattern.getRegister1() == rn_EBP) - { - logMessage(__func__, "destination register is unknown, esp or ebp -- skipping: "); - m_numOverflowsSkipped++; - return; - } - - if (leaPattern.isRegisterPlusRegister()) - { - RegisterName reg1 = leaPattern.getRegister1(); - RegisterName reg2 = leaPattern.getRegister2(); - RegisterName target = getTargetRegister(p_instruction); - - if (reg1 == rn_UNKNOWN || reg2 == rn_UNKNOWN || target == rn_UNKNOWN) - { - logMessage(__func__, "lea reg+reg pattern: error retrieving register: reg1: " + Register::toString(reg1) + " reg2: " + Register::toString(reg2) + " target: " + Register::toString(target)); - m_numOverflowsSkipped++; - return; - } - else if (reg2 == rn_ESP) - { - logMessage(__func__, "source register is esp -- skipping: "); - m_numOverflowsSkipped++; - return; - } - else - { - addOverflowCheckNoFlag_RegPlusReg(p_instruction, p_annotation, reg1, reg2, target, p_policy); - } - } - else if (leaPattern.isRegisterPlusConstant()) - { - RegisterName reg1 = leaPattern.getRegister1(); - int value = leaPattern.getConstant(); - RegisterName target = getTargetRegister(p_instruction); - - if (p_annotation.isUnsigned() && value < 0) - { - logMessage(__func__, "lea reg+neg constant pattern: skip this annotation type (prone to false positives)"); - m_numOverflowsSkipped++; - return; - } - else if (reg1 == rn_UNKNOWN || target == rn_UNKNOWN) - { - logMessage(__func__, "lea reg+constant pattern: error retrieving register: reg1: " + Register::toString(reg1) + " target: " + Register::toString(target)); - m_numOverflowsSkipped++; - return; - } - else - { - addOverflowCheckNoFlag_RegPlusConstant(p_instruction, p_annotation, reg1, value, target, p_policy); - } - } - else if (leaPattern.isRegisterTimesConstant()) - { - RegisterName reg1 = leaPattern.getRegister1(); - int value = leaPattern.getConstant(); - RegisterName target = getTargetRegister(p_instruction); - - if (reg1 == rn_UNKNOWN || target == rn_UNKNOWN) - { - logMessage(__func__, "lea reg*constant pattern: error retrieving register: reg1: " + Register::toString(reg1) + " target: " + Register::toString(target)); - m_numOverflowsSkipped++; - return; - } - else - { - m_numOverflowsSkipped++; - addOverflowCheckNoFlag_RegTimesConstant(p_instruction, p_annotation, reg1, value, target, p_policy); - } - } - else - { - logMessage(__func__, "pattern not yet handled"); - m_numOverflowsSkipped++; - return; - } -} - -// Example annotation to handle -// 804852e 3 INSTR CHECK OVERFLOW NOFLAGSIGNED 32 EDX+EAX ZZ lea eax, [edx+eax] Reg1: EDX Reg2: EAX -void IntegerTransform32::addOverflowCheckNoFlag_RegPlusReg(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const RegisterName& p_reg2, const RegisterName& p_reg3, int p_policy) -{ - cerr << __func__ << ": reg+constant: r1: " << Register::toString(p_reg1) << " r2: " << Register::toString(p_reg2) << " target register: " << Register::toString(p_reg3) << " annotation: " << p_annotation.toString() << endl; - - // orig: lea r3, [r1+r2] - // <originalNext> - // - // Instrumentation: - // push r1 ; save r1 - // pushf ; save flags - // add r1, r2 ; r1 = r1 + r2 - // <overflowcheck> ; check for overflow as dictated by annotation - // (jno|jnc <restore>) ; SIGNED|UNSIGNED - // fallthrough--><saturate> - // (jno&jnc <restore>) ; UNKNOWNSIGN both flags - // fallthrough--><saturate> - // - // <restore> - // popf ; restore flags - // pop r1 ; restore register - // - // <orig>: lea r3, [r1+r2] ; original instruction - // <originalNext> ; original next instruction - // - // <saturate> ; optional saturation code - // popf ; restore flags - // pop r1 ; restore register - // saturateMax(r3) ; - // fallthrough-->originalNext - // - - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - - Instruction_t* pushr1_i = allocateNewInstruction(fileID, func); - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* addRR_i = allocateNewInstruction(fileID, func); - Instruction_t* popf_i = allocateNewInstruction(fileID, func); - Instruction_t* popr1_i = allocateNewInstruction(fileID, func); - - // reuse annotation info when checking for overflow - MEDS_InstructionCheckAnnotation addRR_annot; - addRR_annot.setValid(); - addRR_annot.setBitWidth(32); - addRR_annot.setOverflow(); - if (p_annotation.isSigned()) - addRR_annot.setSigned(); - else if (p_annotation.isUnsigned()) - addRR_annot.setUnsigned(); - else - addRR_annot.setUnknownSign(); - - string msg = "Originally: " + p_instruction->getDisassembly(); - Instruction_t* originalNextInstr = p_instruction->getFallthrough(); - AddressID_t *originalAddress = p_instruction->getAddress(); - - addPushRegister(pushr1_i, p_reg1, pushf_i); - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, pushr1_i); - pushr1_i->setFallthrough(pushf_i); - pushr1_i->setComment("-- carefullyInsertBefore NoFlagRegPlusReg"); - - addPushf(pushf_i, addRR_i); - - addAddRegisters(addRR_i, p_reg1, p_reg2, popf_i); - addRR_i->setComment(msg); - - addPopf(popf_i, popr1_i); - addPopRegister(popr1_i, p_reg1, originalInstrumentInstr); - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - // add r1, r2 ; r1 = r1 + r2 - // (jno|jnc <restore>) ; SIGNED|UNSIGNED - // fallthrough--><saturate> - // (jno&jnc <restore>) ; UNKNOWNSIGN both flags - // fallthrough--><saturate> - // - // <restore> - // popf ; restore flags - // pop r1 ; restore register - // - // <orig>: lea r3, [r1+r2] ; original instruction - // <originalNext> ; original next instruction - // - // <saturate> ; optional saturation code - // popf ; restore flags - // pop r1 ; restore register - // saturateMax(r3) ; - // fallthrough-->originalNext - - Instruction_t* j_i = allocateNewInstruction(fileID, func); - Instruction_t* jnc_i = NULL; - Instruction_t* popfsat_i = allocateNewInstruction(fileID, func); - Instruction_t* popR1sat_i = allocateNewInstruction(fileID, func); - Instruction_t* saturate_i = allocateNewInstruction(fileID, func); - - addRR_i->setFallthrough(j_i); - - if (p_annotation.isSigned()) - { - addJno(j_i, popfsat_i, popf_i); - } - else if (p_annotation.isUnsigned()) - { - addJnc(j_i, popfsat_i, popf_i); - } - else - { - jnc_i = allocateNewInstruction(fileID, func); - addJno(j_i, jnc_i, popf_i); - addJnc(jnc_i, popfsat_i, popf_i); - } - - addOverflowCheckForLea(addRR_i, addRR_annot, p_policy, originalAddress); - - addPopf(popfsat_i, popR1sat_i); - addPopRegister(popR1sat_i, p_reg1, saturate_i); - addMaxSaturation(saturate_i, p_reg3, p_annotation, originalNextInstr); - } - else - { - addOverflowCheckForLea(addRR_i, addRR_annot, p_policy, originalAddress); - } - - m_numOverflows++; -} - -void IntegerTransform32::addOverflowCheckNoFlag_RegPlusConstant(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const int p_constantValue, const RegisterName& p_reg3, int p_policy) -{ - if (!p_instruction) - return; - - if (p_instruction->GetIndirectBranchTargetAddress()) - cerr << "IBTA set: "; - else - cerr << "no IBTA: "; - - cerr << __func__ << ": reg+constant: register: " << Register::toString(p_reg1) << " constant: " << dec << p_constantValue << " target register: " << Register::toString(p_reg3) << " annotation: " << p_annotation.toString() << endl; - - // - // Original instruction is of the form: - // lea r3, [r1+constant] - // lea r3, [r1-constant] - // <originalNext> - // - // Example annotation: - // 8049410 3 INSTR CHECK OVERFLOW NOFLAGUNSIGNED 32 EAX+-15 ZZ lea ebx, [eax-0Fh] - // - // In this example: - // r3 = ebx - // r1 = eax - // constant = -15 - // - // Instrumentation: - // push r3 ; save register - // pushf ; save flags - // mov r3, r1 ; r3 = r1 - // add r3, constant ; r3 = r1 + constant; - // <overflowCheck> ; reuse overflow code - // (jno|jnc <restore>) ; SIGNED|UNSIGNED - // fallthrough--><saturate> - // (jno&jnc <restore>) ; UNKNOWNSIGN both flags - // fallthrough--><saturate> - // <restore> - // popf ; restore flags - // pop r3 ; restore register - // - // - // <orig>: lea r3, [r1+constant] ; original instruction - // <originalNext> ; original next instruction - // - // <saturate> ; optional saturation code - // popf ; restore flags - // pop r3 ; restore register - // saturateMax(r3) ; - // fallthrough-->originalNext - // - // - // Note: if r3 == r1, code still works (though inefficiently) - // - - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - - Instruction_t* pushR3_i = allocateNewInstruction(fileID, func); - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* movR3R1_i = allocateNewInstruction(fileID, func); - Instruction_t* addR3Constant_i = allocateNewInstruction(fileID, func); - Instruction_t* popf_i = allocateNewInstruction(fileID, func); - Instruction_t* popR3_i = allocateNewInstruction(fileID, func); - - MEDS_InstructionCheckAnnotation addR3Constant_annot; - addR3Constant_annot.setValid(); - addR3Constant_annot.setBitWidth(32); - addR3Constant_annot.setOverflow(); - if (p_annotation.isSigned()) - addR3Constant_annot.setSigned(); - else if (p_annotation.isUnsigned()) - addR3Constant_annot.setUnsigned(); - else - addR3Constant_annot.setUnknownSign(); - - string msg = "Originally: " + p_instruction->getDisassembly(); - Instruction_t* originalNextInstr = p_instruction->getFallthrough(); - - AddressID_t *originalAddress = p_instruction->getAddress(); - - addPushRegister(pushR3_i, p_reg3, pushf_i); - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, pushR3_i); - pushR3_i->setComment("in lea -- RegPlusConstant"); - pushR3_i->setFallthrough(pushf_i); - addPushf(pushf_i, movR3R1_i); - - addMovRegisters(movR3R1_i, p_reg3, p_reg1, addR3Constant_i); - addAddRegisterConstant(addR3Constant_i, p_reg3, p_constantValue, popf_i); - addPopf(popf_i, popR3_i); - addPopRegister(popR3_i, p_reg3, originalInstrumentInstr); - - addR3Constant_i->setComment(msg); - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - // (jno|jnc <restore>) ; SIGNED|UNSIGNED - // fallthrough--><saturate> - // (jno&jnc <restore>) ; UNKNOWNSIGN both flags - // fallthrough--><saturate> - // - // <restore> - // popf ; restore flags - // pop r3 ; restore register - // - // <saturate> - // popf ; restore flags - // pop r3 ; restore register - // saturateMax(r3) ; - // fallthrough-->originalNext - Instruction_t* j_i = allocateNewInstruction(fileID, func); - Instruction_t* jnc_i = NULL; - Instruction_t* popfsat_i = allocateNewInstruction(fileID, func); - Instruction_t* popR3sat_i = allocateNewInstruction(fileID, func); - Instruction_t* saturate_i = allocateNewInstruction(fileID, func); - - addR3Constant_i->setFallthrough(j_i); - - if (p_annotation.isSigned()) - { - addJno(j_i, popfsat_i, popf_i); - } - else if (p_annotation.isUnsigned()) - { - addJnc(j_i, popfsat_i, popf_i); - } - else - { - jnc_i = allocateNewInstruction(fileID, func); - addJno(j_i, jnc_i, popf_i); - addJnc(jnc_i, popfsat_i, popf_i); - } - - addOverflowCheckForLea(addR3Constant_i, addR3Constant_annot, p_policy, originalAddress); - - addPopf(popfsat_i, popR3sat_i); - addPopRegister(popR3sat_i, p_reg3, saturate_i); - addMaxSaturation(saturate_i, p_reg3, p_annotation, originalNextInstr); - } - else - { - addOverflowCheckForLea(addR3Constant_i, addR3Constant_annot, p_policy, originalAddress); - } - m_numOverflows++; -} - -void IntegerTransform32::addOverflowCheckNoFlag_RegTimesConstant(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const int p_constantValue, const RegisterName& p_reg3, int p_policy) -{ - cerr << __func__ << ": reg*constant: register: " << Register::toString(p_reg1) << " constant: " << p_constantValue << " target register: " << Register::toString(p_reg3) << " annotation: " << p_annotation.toString() << endl; - - // - // Original instruction is of the form: - // lea r3, [r1*constant] - // <originalNext> - // - // Instrumentation: - // push r3 ; save register - // pushf ; save flags - // mov r3, r1 ; r3 = r1 - // imul r3, constant ; r3 = r1 * constant; - // <overflowCheck> ; emit diagnostics - // (jo <saturate>) ; optional saturation code - // popf ; restore flags - // pop r3 ; restore register - // - // <orig>: lea r3, [r1*constant] ; original instruction - // <originalNext> ; original next instruction - // - // ; optional saturation code - // <saturate> - // popf ; restore flags - // pop r3 ; restore register - // saturateMax(r3) ; - // fallthrough-->originalNext - // - // Note: if r3 == r1, code still works (though inefficiently) - // - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - - Instruction_t* pushR3_i = allocateNewInstruction(fileID, func); - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* movR3R1_i = allocateNewInstruction(fileID, func); - Instruction_t* mulR3Constant_i = allocateNewInstruction(fileID, func); - Instruction_t* popf_i = allocateNewInstruction(fileID, func); - Instruction_t* popR3_i = allocateNewInstruction(fileID, func); - - MEDS_InstructionCheckAnnotation mulR3Constant_annot; - mulR3Constant_annot.setValid(); - mulR3Constant_annot.setBitWidth(32); - mulR3Constant_annot.setOverflow(); - if (p_annotation.isSigned()) - mulR3Constant_annot.setSigned(); - else if (p_annotation.isUnsigned()) - mulR3Constant_annot.setUnsigned(); - else - mulR3Constant_annot.setUnknownSign(); - - string msg = "Originally: " + p_instruction->getDisassembly(); - Instruction_t* originalNextInstr = p_instruction->getFallthrough(); - - AddressID_t *originalAddress = p_instruction->getAddress(); - - addPushRegister(pushR3_i, p_reg3, pushf_i); - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, pushR3_i); - pushR3_i->setFallthrough(pushf_i); - pushR3_i->setComment("in lea -- Reg * Constant"); - addPushf(pushf_i, movR3R1_i); - - addMovRegisters(movR3R1_i, p_reg3, p_reg1, mulR3Constant_i); - addMulRegisterConstant(mulR3Constant_i, p_reg3, p_constantValue, popf_i); - addPopf(popf_i, popR3_i); - addPopRegister(popR3_i, p_reg3, originalInstrumentInstr); - - mulR3Constant_i->setComment(msg); - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - // (jo <saturate>) ; optional saturation code - // popf ; restore flags - // - // <saturate> - // popf ; restore flags - // pop r3 ; restore register - // saturateMax(r3) ; - // fallthrough-->originalNext - Instruction_t* jo_i = allocateNewInstruction(fileID, func); - Instruction_t* popfsat_i = allocateNewInstruction(fileID, func); - Instruction_t* popR3sat_i = allocateNewInstruction(fileID, func); - Instruction_t* saturate_i = allocateNewInstruction(fileID, func); - - mulR3Constant_i->setFallthrough(jo_i); - addOverflowCheckForLea(mulR3Constant_i, mulR3Constant_annot, p_policy, originalAddress); - - addJo(jo_i, popf_i, popfsat_i); - addPopf(popfsat_i, popR3sat_i); - addPopRegister(popR3sat_i, p_reg3, saturate_i); - addMaxSaturation(saturate_i, p_reg3, p_annotation, originalNextInstr); - } - else - { - // fallthrough was set previously to popf_i - addOverflowCheckForLea(mulR3Constant_i, mulR3Constant_annot, p_policy, originalAddress); - } - m_numOverflows++; -} - - -void IntegerTransform32::handleFISTTruncation(Instruction_t *p_instruction){ - cerr << "IntegerTransform32::handleFISTTruncation(): instr: " << p_instruction->getDisassembly() << " address: " - << p_instruction->getAddress() << endl; - int len=0; - - //We skip the qword case. - if(p_instruction->getDisassembly().find("qword")!=std::string::npos){ - len = 64; - } - else if(p_instruction->getDisassembly().find("dword")!=std::string::npos){ - len = 32; - } - else if(p_instruction->getDisassembly().find(" word")!=std::string::npos){ - len = 16; - } - if(p_instruction->getDisassembly().substr(0,5)=="fistp"){ - cerr << "IntegerTransform32::addFistpTruncationCheck(): instr: " << p_instruction->getDisassembly() << " len= " - << len << endl; - addFistpTruncationCheck(p_instruction, len); - } - else if (p_instruction->getDisassembly().substr(0,4)=="fist"){ - cerr << "IntegerTransform32::addFistTruncationCheck(): instr: " << p_instruction->getDisassembly() << " len= " - << len << endl; - addFistTruncationCheck(p_instruction, len); - } -} - -void IntegerTransform32::addFistpTruncationCheck(Instruction_t *p_instruction, int len){ - if(len!=32 && len!=16) return; - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - string dataBits; - - //Fistp dword [esp+0x28]; - - /* - pusha - pushf - sub esp, 0x70 - fstp dword [esp] - fsave [esp+4] - push_ret //call some_func - frstor [esp+4] - test eax, 0 - jz_eax_0 label0 - - test eax, 1 - jz_eax_1 label1 - - label2: - add esp, 0x70 - ;; negtive min - mov [esp+0x28], 0x80000000 - - - label0: - - add esp, 0x70 - popf - popa - Fistp dword [esp+0x28] - - label1: ;;positive max - add esp, 0x70 - popf - popa - mov [esp+0x28], 0x7FFFFFFF - //fistp [] - */ - - Instruction_t* pusha_i = allocateNewInstruction(fileID, func); - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* sub_esp_0x70 = allocateNewInstruction(fileID, func); //81 ec 70 00 00 00 - Instruction_t* fst_esp = allocateNewInstruction(fileID, func);//d9 14 24 - // fsave [esp+4] - Instruction_t* fsave_wait = allocateNewInstruction(fileID, func);//9b - Instruction_t* fsave_esp_4 = allocateNewInstruction(fileID, func);//dd 74 24 04 - Instruction_t* pushretaddress = allocateNewInstruction(fileID, func); - Instruction_t* frstor_esp_4 = allocateNewInstruction(fileID, func);//dd 64 24 04 - - Instruction_t* test_eax_0 = allocateNewInstruction(fileID, func); - Instruction_t* test_eax_1 = allocateNewInstruction(fileID, func); - - Instruction_t* jz_eax_0 = allocateNewInstruction(fileID, func); - Instruction_t* jz_eax_1 = allocateNewInstruction(fileID, func); - - - Instruction_t* add_esp_0x70_label0 = allocateNewInstruction(fileID, func); //81 c4 70 00 00 00 - Instruction_t* add_esp_0x70_label1 = allocateNewInstruction(fileID, func); - Instruction_t* add_esp_0x70_label2 = allocateNewInstruction(fileID, func); - - Instruction_t* popf_label0 = allocateNewInstruction(fileID, func); - Instruction_t* popa_label0 = allocateNewInstruction(fileID, func); - - Instruction_t* popf_label1 = allocateNewInstruction(fileID, func); - Instruction_t* popa_label1 = allocateNewInstruction(fileID, func); - - Instruction_t* popf_label2 = allocateNewInstruction(fileID, func); - Instruction_t* popa_label2 = allocateNewInstruction(fileID, func); - Instruction_t* nop = allocateNewInstruction(fileID, func); - - - addPusha(pusha_i, pushf_i);//pusha - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, pusha_i); - pusha_i->setFallthrough(pushf_i); - - addPushf(pushf_i, sub_esp_0x70);//pushf - - dataBits.resize(6);//sub esp,0x70 - dataBits[0] = 0x81; - dataBits[1] = 0xec; - dataBits[2] = 0x70; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - dataBits[5] = 0x00; - sub_esp_0x70->setFallthrough(fst_esp); - sub_esp_0x70->setDataBits(dataBits); - sub_esp_0x70->setComment(sub_esp_0x70->getDisassembly()); - addInstruction(sub_esp_0x70, dataBits, fst_esp, NULL); - - dataBits.resize(3);//fst [esp] - dataBits[0] = 0xd9; - dataBits[1] = 0x14; - dataBits[2] = 0x24; - fst_esp->setFallthrough(fsave_esp_4); - fst_esp->setDataBits(dataBits); - fst_esp->setComment(fst_esp->getDisassembly()); - addInstruction(fst_esp, dataBits, fsave_esp_4, NULL); - dataBits.resize(1);//fsave [esp+4] - dataBits[0] = 0x9b; - fsave_esp_4->setFallthrough(pushretaddress); - fsave_esp_4->setDataBits(dataBits); - fsave_esp_4->setComment(fsave_wait->getDisassembly()); - addInstruction(fsave_wait, dataBits, fsave_esp_4, NULL); - dataBits.resize(4); - dataBits[0] = 0xdd; - dataBits[1] = 0x74; - dataBits[2] = 0x24; - dataBits[3] = 0x04; - fsave_esp_4->setFallthrough(pushretaddress); - fsave_esp_4->setDataBits(dataBits); - fsave_esp_4->setComment(fsave_esp_4->getDisassembly()); - addInstruction(fsave_esp_4, dataBits, pushretaddress, NULL); - - virtual_offset_t AfterTheCheckerReturn = getAvailableAddress(); - nop->getAddress()->SetVirtualOffset(AfterTheCheckerReturn); - nop->getAddress()->SetFileID(BaseObj_t::NOT_IN_DATABASE); - - dataBits.resize(5);//push return_address - dataBits[0] = 0x68; - virtual_offset_t *tmp; - tmp = (virtual_offset_t *) &dataBits[1]; - *tmp = AfterTheCheckerReturn; - pushretaddress->setDataBits(dataBits); - pushretaddress->setComment(pushretaddress->getDisassembly()); - pushretaddress->setFallthrough(nop); - - - dataBits.resize(1);//nop - dataBits[0] = 0x90; - nop->setDataBits(dataBits); - nop->setComment(nop->getDisassembly() + " -- with callback to floating number check") ; - nop->setFallthrough(frstor_esp_4); - nop->SetIndirectBranchTargetAddress(nop->getAddress()); - if(len==32) - nop->SetCallback(string("FloatingRangeCheck32")); - else - nop->SetCallback(string("FloatingRangeCheck16")); - - dataBits.resize(4);//frstor [esp+4] - dataBits[0] = 0xdd; - dataBits[1] = 0x64; - dataBits[2] = 0x24; - dataBits[3] = 0x04; - frstor_esp_4->setDataBits(dataBits); - frstor_esp_4->setFallthrough(test_eax_0); - frstor_esp_4->setComment(frstor_esp_4->getDisassembly()); - dataBits.resize(2);//test eax, eax - dataBits[0] = 0x85; - dataBits[1] = 0xC0; - test_eax_0->setDataBits(dataBits); - test_eax_0->setFallthrough(jz_eax_0); - addInstruction(test_eax_0, dataBits, jz_eax_0, NULL); - addJz(jz_eax_0, test_eax_1, add_esp_0x70_label0); - - - //label 0: - Instruction_t* jmpOriginalInst = allocateNewInstruction(fileID, func); - - dataBits.resize(6);//add esp,0x70 - dataBits[0] = 0x81; - dataBits[1] = 0xc4; - dataBits[2] = 0x70; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - dataBits[5] = 0x00; - add_esp_0x70_label0->setFallthrough(popf_label0); - add_esp_0x70_label0->setDataBits(dataBits); - add_esp_0x70_label0->setComment(add_esp_0x70_label0->getDisassembly()); - addInstruction(add_esp_0x70_label0, dataBits, popf_label0, NULL); - - addPopf(popf_label0, popa_label0); - addPopa(popa_label0, jmpOriginalInst); - - - dataBits.resize(2); - dataBits[0] = 0xeb; - jmpOriginalInst->setComment("Jump to original Inst"); - addInstruction(jmpOriginalInst,dataBits,NULL, originalInstrumentInstr); - - //label 1: - - dataBits.resize(5);//test eax, 1 - dataBits[0] = 0xA9; - dataBits[1] = 0x01; - dataBits[2] = 0x00; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - test_eax_1->setDataBits(dataBits); - test_eax_1->setComment(test_eax_1->getDisassembly()) ; - test_eax_1->setFallthrough(jz_eax_1); - addInstruction(test_eax_1, dataBits, jz_eax_1, NULL); - addJz(jz_eax_1, add_esp_0x70_label1, add_esp_0x70_label2); - - - dataBits.resize(6);//add esp,0x70 - dataBits[0] = 0x81; - dataBits[1] = 0xc4; - dataBits[2] = 0x70; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - dataBits[5] = 0x00; - add_esp_0x70_label1->setFallthrough(popf_label1); - add_esp_0x70_label1->setDataBits(dataBits); - add_esp_0x70_label1->setComment(add_esp_0x70_label1->getDisassembly()); - addInstruction(add_esp_0x70_label1, dataBits, popf_label1, NULL); - addPopf(popf_label1, popa_label1); - - if(len==32){ - Instruction_t* mov0x7FFFFFFF = allocateNewInstruction(fileID, func); - Instruction_t* fstpST0 =allocateNewInstruction(fileID, func); - Instruction_t* jmpOriginalInstNext = allocateNewInstruction(fileID, func); - - addPopa(popa_label1, mov0x7FFFFFFF); - string instrStr= originalInstrumentInstr->getDisassembly(); - string addExpr = instrStr.substr(instrStr.find(" ")+1); - mov0x7FFFFFFF->Assemble("mov "+ addExpr + ", 0x7FFFFFFF"); - mov0x7FFFFFFF->setComment(mov0x7FFFFFFF->getDisassembly()); - addInstruction(mov0x7FFFFFFF, mov0x7FFFFFFF->GetDataBits(), fstpST0, NULL); - popa_label1->setComment("just before " + mov0x7FFFFFFF->getDisassembly()); - - dataBits.resize(2);//fstp st(0) - dataBits[0] = 0xDD; - dataBits[1] = 0xD8; - fstpST0->setDataBits(dataBits); - fstpST0->setFallthrough(jmpOriginalInstNext); - addInstruction(fstpST0, dataBits, jmpOriginalInstNext, NULL); - - dataBits.resize(2); - dataBits[0] = 0xeb; - addInstruction(jmpOriginalInstNext,dataBits,NULL, originalInstrumentInstr->getFallthrough()); - } - else{ - Instruction_t* mov0x7FFF = allocateNewInstruction(fileID, func); - Instruction_t* fstpST0 =allocateNewInstruction(fileID, func); - Instruction_t* jmpOriginalInstNext = allocateNewInstruction(fileID, func); - - addPopa(popa_label1, mov0x7FFF); - string instrStr= originalInstrumentInstr->getDisassembly(); - string addExpr = instrStr.substr(instrStr.find(" ")+1); - mov0x7FFF->Assemble("mov "+ addExpr + ", 0x7FFF"); - mov0x7FFF->setComment(mov0x7FFF->getDisassembly()); - - //mov0x7FFF->setFallthrough(fstpST0); - addInstruction(mov0x7FFF, mov0x7FFF->GetDataBits(), fstpST0, NULL); - - dataBits.resize(2);//fstp st(0) - dataBits[0] = 0xDD; - dataBits[1] = 0xD8; - - fstpST0->setDataBits(dataBits); - fstpST0->setFallthrough(jmpOriginalInstNext); - addInstruction(fstpST0, dataBits, jmpOriginalInstNext, NULL); - - dataBits.resize(2); - dataBits[0] = 0xeb; - addInstruction(jmpOriginalInstNext,dataBits,NULL, originalInstrumentInstr->getFallthrough()); - } - - dataBits.resize(6);//add esp,0x70 - dataBits[0] = 0x81; - dataBits[1] = 0xc4; - dataBits[2] = 0x70; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - dataBits[5] = 0x00; - add_esp_0x70_label2->setFallthrough(popf_label2); - add_esp_0x70_label2->setDataBits(dataBits); - add_esp_0x70_label2->setComment(add_esp_0x70_label2->getDisassembly()); - addInstruction(add_esp_0x70_label2, dataBits, popf_label2, NULL); - - addPopf(popf_label2, popa_label2); - if(len==32){ - Instruction_t* mov0x80000000 = allocateNewInstruction(fileID, func); - Instruction_t* fstpST0 =allocateNewInstruction(fileID, func); - Instruction_t* jmpOriginalInstNext = allocateNewInstruction(fileID, func); - - addPopa(popa_label2, mov0x80000000); - string instrStr= originalInstrumentInstr->getDisassembly(); - string addExpr = instrStr.substr(instrStr.find(" ")+1); - mov0x80000000->Assemble("mov "+ addExpr + ", 0x80000001"); - mov0x80000000->setComment(mov0x80000000->getDisassembly()); - mov0x80000000->setFallthrough(fstpST0); - addInstruction(mov0x80000000, mov0x80000000->GetDataBits(), fstpST0, NULL); - - dataBits.resize(2);//fstp st(0) - dataBits[0] = 0xDD; - dataBits[1] = 0xD8; - - addInstruction(fstpST0, dataBits, jmpOriginalInstNext, NULL); - - dataBits.resize(2); - dataBits[0] = 0xeb; - addInstruction(jmpOriginalInstNext,dataBits,NULL, originalInstrumentInstr->getFallthrough()); - } - else{ - Instruction_t* mov0x8000 = allocateNewInstruction(fileID, func); - Instruction_t* fstpST0 =allocateNewInstruction(fileID, func); - Instruction_t* jmpOriginalInstNext = allocateNewInstruction(fileID, func); - - addPopa(popa_label2, mov0x8000); - string instrStr= originalInstrumentInstr->getDisassembly(); - string addExpr = instrStr.substr(instrStr.find(" ")+1); - mov0x8000->Assemble("mov "+ addExpr + ", 0x8001"); - mov0x8000->setComment(mov0x8000->getDisassembly()); - - addInstruction(mov0x8000, mov0x8000->GetDataBits(), fstpST0, NULL); - - dataBits.resize(2);//fstp st(0) - dataBits[0] = 0xDD; - dataBits[1] = 0xD8; - - addInstruction(fstpST0, dataBits, jmpOriginalInstNext, NULL); - dataBits.resize(2); - dataBits[0] = 0xeb; - addInstruction(jmpOriginalInstNext,dataBits,NULL, originalInstrumentInstr->getFallthrough()); - } - - m_numFP++; - return; -} - -void IntegerTransform32::addFistTruncationCheck(Instruction_t *p_instruction, int len){ - if(len!=32 && len!=16) return; - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - string dataBits; - - //Fist dword [esp+0x28]; - - /* - pusha - pushf - sub esp, 4 - fstp dword [esp] - push_ret //call some_func - test eax, 0 - jz_eax_0 label0 - - test eax, 1 - jz_eax_1 label1 - - label2: - add esp, 4 - ;; negtive min - mov [esp+0x28], 0x80000001 - - - label0: - - add esp, 4 - popf - popa - Fist dword [esp+0x28] - - label1: ;;positive max - add esp, 4 - popf - popa - mov [esp+0x28], 0x7FFFFFFF - - */ - - Instruction_t* pusha_i = allocateNewInstruction(fileID, func); - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* sub_esp_0x70 = allocateNewInstruction(fileID, func); //81 ec 70 00 00 00 - Instruction_t* fst_esp = allocateNewInstruction(fileID, func);//d9 14 24 - // fsave [esp+4] - Instruction_t* fsave_wait = allocateNewInstruction(fileID, func);//9b - Instruction_t* fsave_esp_4 = allocateNewInstruction(fileID, func);//dd 74 24 04 - Instruction_t* pushretaddress = allocateNewInstruction(fileID, func); - Instruction_t* frstor_esp_4 = allocateNewInstruction(fileID, func);//67 dd 64 24 04 - - Instruction_t* test_eax_0 = allocateNewInstruction(fileID, func); - Instruction_t* test_eax_1 = allocateNewInstruction(fileID, func); - - Instruction_t* jz_eax_0 = allocateNewInstruction(fileID, func); - Instruction_t* jz_eax_1 = allocateNewInstruction(fileID, func); - - - Instruction_t* add_esp_0x70_label0 = allocateNewInstruction(fileID, func); - Instruction_t* add_esp_0x70_label1 = allocateNewInstruction(fileID, func); - Instruction_t* add_esp_0x70_label2 = allocateNewInstruction(fileID, func); - - Instruction_t* popf_label0 = allocateNewInstruction(fileID, func); - Instruction_t* popa_label0 = allocateNewInstruction(fileID, func); - - Instruction_t* popf_label1 = allocateNewInstruction(fileID, func); - Instruction_t* popa_label1 = allocateNewInstruction(fileID, func); - - Instruction_t* popf_label2 = allocateNewInstruction(fileID, func); - Instruction_t* popa_label2 = allocateNewInstruction(fileID, func); - Instruction_t* nop = allocateNewInstruction(fileID, func); - - - addPusha(pusha_i, pushf_i);//pusha - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, pusha_i); - pusha_i->setFallthrough(pushf_i); - - addPushf(pushf_i, sub_esp_0x70);//pushf - - dataBits.resize(6);//sub esp,0x70 - dataBits[0] = 0x81; - dataBits[1] = 0xec; - dataBits[2] = 0x70; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - dataBits[5] = 0x00; - sub_esp_0x70->setFallthrough(fst_esp); - sub_esp_0x70->setDataBits(dataBits); - sub_esp_0x70->setComment(sub_esp_0x70->getDisassembly()); - addInstruction(sub_esp_0x70, dataBits, fst_esp, NULL); - - dataBits.resize(3);//fst [esp] - dataBits[0] = 0xd9; - dataBits[1] = 0x14; - dataBits[2] = 0x24; - fst_esp->setFallthrough(fsave_esp_4); - fst_esp->setDataBits(dataBits); - fst_esp->setComment(fst_esp->getDisassembly()); - addInstruction(fst_esp, dataBits, fsave_esp_4, NULL); - dataBits.resize(1);//fsave [esp+4] - dataBits[0] = 0x9b; - fsave_esp_4->setFallthrough(pushretaddress); - fsave_esp_4->setDataBits(dataBits); - fsave_esp_4->setComment(fsave_wait->getDisassembly()); - addInstruction(fsave_wait, dataBits, fsave_esp_4, NULL); - dataBits.resize(4); - dataBits[0] = 0xdd; - dataBits[1] = 0x74; - dataBits[2] = 0x24; - dataBits[3] = 0x04; - fsave_esp_4->setFallthrough(pushretaddress); - fsave_esp_4->setDataBits(dataBits); - fsave_esp_4->setComment(fsave_esp_4->getDisassembly()); - addInstruction(fsave_esp_4, dataBits, pushretaddress, NULL); - - virtual_offset_t AfterTheCheckerReturn = getAvailableAddress(); - nop->getAddress()->SetVirtualOffset(AfterTheCheckerReturn); - nop->getAddress()->SetFileID(BaseObj_t::NOT_IN_DATABASE); - - dataBits.resize(5);//push return_address - dataBits[0] = 0x68; - virtual_offset_t *tmp; - tmp = (virtual_offset_t *) &dataBits[1]; - *tmp = AfterTheCheckerReturn; - pushretaddress->setDataBits(dataBits); - pushretaddress->setComment(pushretaddress->getDisassembly()); - pushretaddress->setFallthrough(nop); - - - dataBits.resize(1);//nop - dataBits[0] = 0x90; - nop->setDataBits(dataBits); - nop->setComment(nop->getDisassembly() + " -- with callback to floating number check") ; - nop->setFallthrough(frstor_esp_4); - nop->SetIndirectBranchTargetAddress(nop->getAddress()); - if(len==32) - nop->SetCallback(string("FloatingRangeCheck32")); - else - nop->SetCallback(string("FloatingRangeCheck16")); - - dataBits.resize(4);//frstor [esp+4] - dataBits[0] = 0xdd; - dataBits[1] = 0x64; - dataBits[2] = 0x24; - dataBits[3] = 0x04; - frstor_esp_4->setDataBits(dataBits); - frstor_esp_4->setFallthrough(test_eax_0); - frstor_esp_4->setComment(frstor_esp_4->getDisassembly()); - dataBits.resize(2);//test eax, eax - dataBits[0] = 0x85; - dataBits[1] = 0xC0; - test_eax_0->setDataBits(dataBits); - test_eax_0->setFallthrough(jz_eax_0); - addInstruction(test_eax_0, dataBits, jz_eax_0, NULL); - addJz(jz_eax_0, test_eax_1, add_esp_0x70_label0); - - - //label 0: - Instruction_t* jmpOriginalInst = allocateNewInstruction(fileID, func); - - dataBits.resize(6);//add esp,0x70 - dataBits[0] = 0x81; - dataBits[1] = 0xc4; - dataBits[2] = 0x70; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - dataBits[5] = 0x00; - add_esp_0x70_label0->setFallthrough(popf_label0); - add_esp_0x70_label0->setDataBits(dataBits); - add_esp_0x70_label0->setComment(add_esp_0x70_label0->getDisassembly()); - addInstruction(add_esp_0x70_label0, dataBits, popf_label0, NULL); - - addPopf(popf_label0, popa_label0); - addPopa(popa_label0, jmpOriginalInst); - - - dataBits.resize(2); - dataBits[0] = 0xeb; - jmpOriginalInst->setComment("Jump to original Inst"); - addInstruction(jmpOriginalInst,dataBits,NULL, originalInstrumentInstr); - - //label 1: - - dataBits.resize(5);//test eax, 1 - dataBits[0] = 0xA9; - dataBits[1] = 0x01; - dataBits[2] = 0x00; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - test_eax_1->setDataBits(dataBits); - test_eax_1->setComment(test_eax_1->getDisassembly()) ; - test_eax_1->setFallthrough(jz_eax_1); - addInstruction(test_eax_1, dataBits, jz_eax_1, NULL); - addJz(jz_eax_1, add_esp_0x70_label1, add_esp_0x70_label2); - - - dataBits.resize(6);//add esp,0x70 - dataBits[0] = 0x81; - dataBits[1] = 0xc4; - dataBits[2] = 0x70; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - dataBits[5] = 0x00; - add_esp_0x70_label1->setFallthrough(popf_label1); - add_esp_0x70_label1->setDataBits(dataBits); - add_esp_0x70_label1->setComment(add_esp_0x70_label1->getDisassembly()); - addInstruction(add_esp_0x70_label1, dataBits, popf_label1, NULL); - addPopf(popf_label1, popa_label1); - - if(len==32){ - Instruction_t* mov0x7FFFFFFF = allocateNewInstruction(fileID, func); - //Instruction_t* fstpST0 =allocateNewInstruction(fileID, func); - Instruction_t* jmpOriginalInstNext = allocateNewInstruction(fileID, func); - - addPopa(popa_label1, mov0x7FFFFFFF); - string instrStr= originalInstrumentInstr->getDisassembly(); - string addExpr = instrStr.substr(instrStr.find(" ")+1); - mov0x7FFFFFFF->Assemble("mov "+ addExpr + ", 0x7FFFFFFF"); - mov0x7FFFFFFF->setComment(mov0x7FFFFFFF->getDisassembly()); - addInstruction(mov0x7FFFFFFF, mov0x7FFFFFFF->GetDataBits(), jmpOriginalInstNext, NULL); - popa_label1->setComment("just before " + mov0x7FFFFFFF->getDisassembly()); - - //dataBits.resize(2);//fstp st(0) - //dataBits[0] = 0xDD; - //dataBits[1] = 0xD8; - //fstpST0->setDataBits(dataBits); - //fstpST0->setFallthrough(jmpOriginalInstNext); - //addInstruction(fstpST0, dataBits, jmpOriginalInstNext, NULL); - - dataBits.resize(2); - dataBits[0] = 0xeb; - addInstruction(jmpOriginalInstNext,dataBits,NULL, originalInstrumentInstr->getFallthrough()); - } - else{ - Instruction_t* mov0x7FFF = allocateNewInstruction(fileID, func); - //Instruction_t* fstpST0 =allocateNewInstruction(fileID, func); - Instruction_t* jmpOriginalInstNext = allocateNewInstruction(fileID, func); - - addPopa(popa_label1, mov0x7FFF); - string instrStr= originalInstrumentInstr->getDisassembly(); - string addExpr = instrStr.substr(instrStr.find(" ")+1); - mov0x7FFF->Assemble("mov "+ addExpr + ", 0x7FFF"); - mov0x7FFF->setComment(mov0x7FFF->getDisassembly()); - - //mov0x7FFF->setFallthrough(fstpST0); - addInstruction(mov0x7FFF, mov0x7FFF->GetDataBits(), jmpOriginalInstNext, NULL); - - //dataBits.resize(2);//fstp st(0) - //dataBits[0] = 0xDD; - //dataBits[1] = 0xD8; - - //fstpST0->setDataBits(dataBits); - //fstpST0->setFallthrough(jmpOriginalInstNext); - //addInstruction(fstpST0, dataBits, jmpOriginalInstNext, NULL); - - dataBits.resize(2); - dataBits[0] = 0xeb; - addInstruction(jmpOriginalInstNext,dataBits,NULL, originalInstrumentInstr->getFallthrough()); - } - - dataBits.resize(6);//add esp,0x70 - dataBits[0] = 0x81; - dataBits[1] = 0xc4; - dataBits[2] = 0x70; - dataBits[3] = 0x00; - dataBits[4] = 0x00; - dataBits[5] = 0x00; - add_esp_0x70_label2->setFallthrough(popf_label2); - add_esp_0x70_label2->setDataBits(dataBits); - add_esp_0x70_label2->setComment(add_esp_0x70_label2->getDisassembly()); - addInstruction(add_esp_0x70_label2, dataBits, popf_label2, NULL); - - addPopf(popf_label2, popa_label2); - if(len==32){ - Instruction_t* mov0x80000000 = allocateNewInstruction(fileID, func); - //Instruction_t* fstpST0 =allocateNewInstruction(fileID, func); - Instruction_t* jmpOriginalInstNext = allocateNewInstruction(fileID, func); - - addPopa(popa_label2, mov0x80000000); - string instrStr= originalInstrumentInstr->getDisassembly(); - string addExpr = instrStr.substr(instrStr.find(" ")+1); - mov0x80000000->Assemble("mov "+ addExpr + ", 0x80000001"); - mov0x80000000->setComment(mov0x80000000->getDisassembly()); - //mov0x80000000->setFallthrough(fstpST0); - addInstruction(mov0x80000000, mov0x80000000->GetDataBits(), jmpOriginalInstNext, NULL); - - //dataBits.resize(2);//fstp st(0) - //dataBits[0] = 0xDD; - //dataBits[1] = 0xD8; - - //addInstruction(fstpST0, dataBits, jmpOriginalInstNext, NULL); - - dataBits.resize(2); - dataBits[0] = 0xeb; - addInstruction(jmpOriginalInstNext,dataBits,NULL, originalInstrumentInstr->getFallthrough()); - } - else{ - Instruction_t* mov0x8000 = allocateNewInstruction(fileID, func); - Instruction_t* fstpST0 =allocateNewInstruction(fileID, func); - Instruction_t* jmpOriginalInstNext = allocateNewInstruction(fileID, func); - - addPopa(popa_label2, mov0x8000); - string instrStr= originalInstrumentInstr->getDisassembly(); - string addExpr = instrStr.substr(instrStr.find(" ")+1); - mov0x8000->Assemble("mov "+ addExpr + ", 0x8001"); - mov0x8000->setComment(mov0x8000->getDisassembly()); - - addInstruction(mov0x8000, mov0x8000->GetDataBits(), jmpOriginalInstNext, NULL); - - //dataBits.resize(2);//fstp st(0) - //dataBits[0] = 0xDD; - //dataBits[1] = 0xD8; - - //addInstruction(fstpST0, dataBits, jmpOriginalInstNext, NULL); - dataBits.resize(2); - dataBits[0] = 0xeb; - addInstruction(jmpOriginalInstNext,dataBits,NULL, originalInstrumentInstr->getFallthrough()); - } - - m_numFP++; - return; -} - -void IntegerTransform32::handleTruncation(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - if (p_annotation.getTruncationFromWidth() == 32) - { - if (p_annotation.getTruncationToWidth() == 8 || p_annotation.getTruncationToWidth() == 16) - { - addTruncationCheck(p_instruction, p_annotation, p_policy); - } - else - { - cerr << __func__ << ": TRUNCATION annotation not yet handled: " << p_annotation.toString() << "fromWidth: " << p_annotation.getTruncationFromWidth() << " toWidth: " << p_annotation.getTruncationToWidth() << endl; - } - } -} - -// -// before: after: -// <inst> nop (with callback handler) -// <inst> -// -void IntegerTransform32::handleInfiniteLoop(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - assert(getFileIR() && p_instruction); - - logMessage(__func__, "handling infinite loop"); - - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - - AddressID_t *originalAddress = p_instruction->getAddress(); - Instruction_t* nop_i = allocateNewInstruction(fileID, func); - - addNop(nop_i, p_instruction); - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, nop_i); - - addCallbackHandler(string(INFINITE_LOOP_DETECTOR), originalInstrumentInstr, nop_i, nop_i->getFallthrough(), p_policy, originalAddress); -} - -// -// <instruction to instrument> -// jno <originalFallthroughInstruction> -// pusha -// pushf -// push_arg <address original instruction> -// push L1 -// ... setup detector ... -// L1: pop_arg -// popf -// popa -// -// 20111024 Current policy: -// imul, mul -- always check using jno -// add, sub -- use signedness information annotation to emit either jno, jnc -// -// p_addressOriginalInstruction is set when we call method from lea instrumentation -void IntegerTransform32::addOverflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - assert(getFileIR() && p_instruction && p_instruction->getFallthrough()); - - RegisterName targetReg = getTargetRegister(p_instruction); - if (targetReg == rn_UNKNOWN) - { - logMessage(__func__, "OVERFLOW UNKNOWN SIGN: unknown register -- skip instrumentation"); - if (p_annotation.isUnderflow()) - m_numUnderflowsSkipped++; - else - m_numOverflowsSkipped++; - return; - } - -cerr << __func__ << ": instr: " << p_instruction->getDisassembly() << " address: " << std::hex << p_instruction->getAddress() << " annotation: " << p_annotation.toString() << " policy: " << p_policy << endl; - - string detector(INTEGER_OVERFLOW_DETECTOR); - string dataBits; - - // old style of setting up these params - // update to cleaner style - Function_t* origFunction = p_instruction->GetFunction(); - AddressID_t *jncond_a =new AddressID_t; - jncond_a->SetFileID(p_instruction->getAddress()->getFileID()); - Instruction_t* jncond_i = new Instruction_t; - jncond_i->SetFunction(origFunction); - jncond_i->SetAddress(jncond_a); - - // set fallthrough for the original instruction - Instruction_t* nextOrig_i = p_instruction->getFallthrough(); - p_instruction->setFallthrough(jncond_i); - - // jncond - dataBits.resize(2); - if (isMultiplyInstruction(p_instruction)) - { - dataBits[0] = 0x71; // jno - dataBits[1] = 0x00; // value doesn't matter, we will fill it in later - if (p_annotation.getBitWidth() == 32) - detector = string(MUL_OVERFLOW_DETECTOR_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(MUL_OVERFLOW_DETECTOR_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(MUL_OVERFLOW_DETECTOR_8); - cerr << "integertransform: MUL OVERFLOW: " << detector << endl; - } - else if (p_annotation.isUnsigned()) - { - dataBits[0] = 0x73; // jnc - dataBits[1] = 0x00; // value doesn't matter, we will fill it in later - - if (p_annotation.getBitWidth() == 32) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_8); - cerr << "integertransform: UNSIGNED OVERFLOW: " << detector << endl; - } - else - { - dataBits[0] = 0x71; // jno - dataBits[1] = 0x00; // value doesn't matter, we will fill it in later - - if (p_annotation.getBitWidth() == 32) - detector = string(ADDSUB_OVERFLOW_DETECTOR_SIGNED_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(ADDSUB_OVERFLOW_DETECTOR_SIGNED_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(ADDSUB_OVERFLOW_DETECTOR_SIGNED_8); - cerr << "integertransform: SIGNED OVERFLOW: " << detector << endl; - } - - jncond_i->setDataBits(dataBits); - jncond_i->setComment(jncond_i->getDisassembly()); - jncond_i->setTarget(nextOrig_i); - - p_instruction->setFallthrough(jncond_i); - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - // implement saturating arithmetic, e.g.: - // mov <reg>, value - Instruction_t* saturate_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - - if (p_annotation.flowsIntoCriticalSink() && p_annotation.getBitWidth() == 32) - { - logMessage(__func__, "OVERFLOW UNSIGNED 32: CRITICAL SINK: saturate by masking"); - - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* popf_i = allocateNewInstruction(fileID, func); - addCallbackHandler(detector, p_instruction, jncond_i, pushf_i, p_policy); - addPushf(pushf_i, saturate_i); - addAndRegister32Mask(saturate_i, targetReg, 0x00FFFFFF, popf_i); - addPopf(popf_i, nextOrig_i); - } - else - { - addCallbackHandler(detector, p_instruction, jncond_i, saturate_i, p_policy); - addMaxSaturation(saturate_i, targetReg, p_annotation, nextOrig_i); - } - } - else - { - addCallbackHandler(detector, p_instruction, jncond_i, nextOrig_i, p_policy); - } - - getFileIR()->getAddresses().insert(jncond_a); - getFileIR()->GetInstructions().insert(jncond_i); - - if (p_annotation.isUnderflow()) - m_numUnderflows++; - else - m_numOverflows++; -} - -// -// <instruction to instrument> -// jno <originalFallthroughInstruction> -// pusha -// pushf -// push_arg <address original instruction> -// push L1 -// ... setup detector ... -// L1: pop_arg -// popf -// popa -// -// 20111024 Current policy: -// add, sub -- use signedness information annotation to emit either jno, jnc -// -void IntegerTransform32::addUnderflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - assert(getFileIR() && p_instruction); - - RegisterName targetReg = getTargetRegister(p_instruction); - if (targetReg == rn_UNKNOWN) - { - cerr << "IntegerTransform32::addUnderflowCheck(): instr: " << p_instruction->getDisassembly() << " address: " << p_instruction->getAddress() << " annotation: " << p_annotation.toString() << "-- SKIP b/c no target registers" << endl; - m_numUnderflowsSkipped++; - return; - } - - cerr << "IntegerTransform32::addUnderflowCheck(): instr: " << p_instruction->getDisassembly() << " address: " << p_instruction->getAddress() << " annotation: " << p_annotation.toString() << endl; - - string detector(INTEGER_OVERFLOW_DETECTOR); - string dataBits; - - // old style of setting up these params - // update to cleaner style - Function_t* origFunction = p_instruction->GetFunction(); - AddressID_t *jncond_a =new AddressID_t; - jncond_a->SetFileID(p_instruction->getAddress()->getFileID()); - Instruction_t* jncond_i = new Instruction_t; - jncond_i->SetFunction(origFunction); - jncond_i->SetAddress(jncond_a); - - // set fallthrough for the original instruction - Instruction_t* nextOrig_i = p_instruction->getFallthrough(); - p_instruction->setFallthrough(jncond_i); - - // jncond - dataBits.resize(2); - if (p_annotation.isUnsigned()) - { - dataBits[0] = 0x73; // jnc - dataBits[1] = 0x00; // value doesn't matter, we will fill it in later - - if (p_annotation.getBitWidth() == 32) - detector = string(UNDERFLOW_DETECTOR_UNSIGNED_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(UNDERFLOW_DETECTOR_UNSIGNED_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(UNDERFLOW_DETECTOR_UNSIGNED_8); - cerr << "integertransform: UNSIGNED OVERFLOW: " << detector << endl; - } - else if (p_annotation.isSigned()) - { - dataBits[0] = 0x71; // jno - dataBits[1] = 0x00; // value doesn't matter, we will fill it in later - - if (p_annotation.getBitWidth() == 32) - detector = string(UNDERFLOW_DETECTOR_SIGNED_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(UNDERFLOW_DETECTOR_SIGNED_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(UNDERFLOW_DETECTOR_SIGNED_8); - - cerr << "integertransform: SIGNED UNDERFLOW: " << detector << endl; - } - else - { - dataBits[0] = 0x71; // jno - dataBits[1] = 0x00; // value doesn't matter, we will fill it in later - - if (p_annotation.getBitWidth() == 32) - detector = string(UNDERFLOW_DETECTOR_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(UNDERFLOW_DETECTOR_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(UNDERFLOW_DETECTOR_8); - cerr << "integertransform: UNDERFLOW UNKONWN: assume signed for now: " << detector << endl; - } - - jncond_i->setDataBits(dataBits); - jncond_i->setComment(jncond_i->getDisassembly()); - jncond_i->setTarget(nextOrig_i); - - p_instruction->setFallthrough(jncond_i); - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - // implement saturating arithmetic, e.g.: - // mov <reg>, value - Instruction_t* saturate_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - - addCallbackHandler(detector, p_instruction, jncond_i, saturate_i, p_policy); - addMinSaturation(saturate_i, targetReg, p_annotation, nextOrig_i); - } - else - { - addCallbackHandler(detector, p_instruction, jncond_i, nextOrig_i, p_policy); - } - - getFileIR()->getAddresses().insert(jncond_a); - getFileIR()->GetInstructions().insert(jncond_i); - - m_numUnderflows++; -} - - -// -// STARS has extensive discussion of the logic behind truncation and -// signedness annotations in module SMPInstr.cpp, method EmitIntegerErrorAnnotation(). -// The possible combinations are categorized in terms of the instrumentation -// needed at run time: -// CHECK TRUNCATION UNSIGNED : discarded bits must be all zeroes. -// CHECK TRUNCATION SIGNED: discarded bits must be sign-extension of stored bits. -// CHECK TRUNCATION UNKNOWNSIGN: discarded bits must be all zeroes, OR must -// be the sign-extension of the stored bits. -// All truncation annotations are emitted on stores (mov opcodes in x86). -// Other possibilities might be handled in the future. -// -void IntegerTransform32::addTruncationCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - assert(getFileIR() && p_instruction); - assert(p_annotation.getTruncationFromWidth() == 32 && p_annotation.getTruncationToWidth() == 8 || p_annotation.getTruncationToWidth() == 16); - - cerr << __func__ << ": instr: " << p_instruction->getDisassembly() << " address: " << p_instruction->getAddress() << " annotation: " << p_annotation.toString() << " policy: " << p_policy << endl; - - string detector; - - // Complicated case: - // 80484ed 3 INSTR CHECK TRUNCATION UNKNOWNSIGN 32 EAX 8 AL ZZ mov [ebp+var_4], al - // example: for unknownsign truncation - 8 bit on AL - // it's ok if 24 upper bits are sign-extension or all 0's - // Re-phrased: upper 24 are 0s, upper 25 are 0s, upper 25 are 1s - // are all OK in the UNKNOWNSIGN case - // Note that upper 24 are 0's means no need to check for the - // case where the upper 25 are 0's; already OK. - // - // <save flags> - // test eax, 0xFFFFFF00 ; (for 8 bit) - // jz <continue> ; upper 24 bits are 0's - // - // cmp eax, 0xFFFFFF80 ;(for 8 bit) - // jae continue ; upper 25 bits are 1's - // (invoke truncation handler) - // nop ; truncation handler returns here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // mov [ebp+var_4], al ; <originalInstruction> - // - - // Unsigned case: - // 80484ed 3 INSTR CHECK TRUNCATION UNSIGNED 32 EAX 8 AL ZZ mov [ebp+var_4], al - // example: for unsigned truncation - 8 bit on AL - // it's ok if 24 upper bits are all 0's - // - // <save flags> - // test eax, 0xFFFFFF00 ; (for 8 bit) - // jz <continue> ; upper 24 bits are 0's - // - // (invoke truncation handler) - // nop ; truncation handler returns here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // mov [ebp+var_4], al ; <originalInstruction> - // - - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - AddressID_t *saveAddress = p_instruction->getAddress(); - - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* test_i = allocateNewInstruction(fileID, func); - Instruction_t* jz_i = allocateNewInstruction(fileID, func); - Instruction_t* saturate_i = NULL; - Instruction_t* popf_i = allocateNewInstruction(fileID, func); - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) { - saturate_i = allocateNewInstruction(fileID, func); - addMaxSaturation(saturate_i, p_annotation.getRegister(), p_annotation, popf_i); - } - - addPushf(pushf_i, test_i); - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, pushf_i); - pushf_i->setFallthrough(test_i); - pushf_i->setComment("-- in truncation"); - originalInstrumentInstr->setComment("-- in truncation (was original)"); - - unsigned mask = 0; - unsigned mask2 = 0; - if (p_annotation.getTruncationToWidth() == 16) { - mask = 0xFFFF0000; - mask2 = 0xFFFF8000; - if(p_annotation.flowsIntoCriticalSink()){ - cerr <<"find flowsIntoCriticalSink in addTruncationCheck" <<endl; - detector = "forceSoupToExit"; - } - else if (p_annotation.isUnsigned()) - detector = string(TRUNCATION_DETECTOR_UNSIGNED_32_16); - else if (p_annotation.isSigned()) - detector = string(TRUNCATION_DETECTOR_SIGNED_32_16); - else - detector = string(TRUNCATION_DETECTOR_32_16); - } - else if (p_annotation.getTruncationToWidth() == 8) { - mask = 0xFFFFFF00; - mask2 = 0xFFFFFF80; - if(p_annotation.flowsIntoCriticalSink()){ - cerr <<"find flowsIntoCriticalSink in addTruncationCheck" <<endl; - detector = "forceSoupToExit"; - } - else if (p_annotation.isUnsigned()) - detector = string(TRUNCATION_DETECTOR_UNSIGNED_32_8); - else if (p_annotation.isSigned()) - detector = string(TRUNCATION_DETECTOR_SIGNED_32_8); - else - detector = string(TRUNCATION_DETECTOR_32_8); - } - - if (p_annotation.isUnsigned()) { - addTestRegisterMask(test_i, p_annotation.getRegister(), mask, jz_i); - Instruction_t* nop_i = allocateNewInstruction(fileID, func); - addJz(jz_i, nop_i, popf_i); // target = popf_i, fall-through = nop_i - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) { - addNop(nop_i, saturate_i); - nop_i->setComment("UNSIGNED TRUNC: fallthrough: saturating arithmetic instruction"); - addCallbackHandler(detector, originalInstrumentInstr, nop_i, saturate_i, p_policy, saveAddress); - } - else { - addNop(nop_i, popf_i); - nop_i->setComment(string("UNSIGNED TRUNC: fallthrough: popf")); - addCallbackHandler(detector, originalInstrumentInstr, nop_i, popf_i, p_policy, saveAddress); - } - } - else { - // Signed and unknown signed cases are almost identical: - // 80484ed 3 INSTR CHECK TRUNCATION SIGNED 32 EAX 8 AL ZZ mov [ebp+var_4], al - // 80484ed 3 INSTR CHECK TRUNCATION UNKNOWNSIGN 32 EAX 8 AL ZZ mov [ebp+var_4], al - // example: for signed truncation - 8 bit on AL - // it's ok if 25 upper bits are all 1's or all 0's - // example: for unknownsign truncation - 8 bit on AL - // it's ok if 25 upper bits are all 1's or 24 upper bits all 0's - // - // <save flags> - // test eax, 0xFFFFFF80 ; (for 8 bit) 0xFFFFFF00 for UNKNOWN - // jz <continue> ; upper 25 bits are 0's - // - // cmp eax, 0xFFFFFF80 ;(for 8 bit) - // jae continue ; upper 25 bits are 1's - // (invoke truncation handler) - // nop ; truncation handler callback here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // mov [ebp+var_4], al ; <originalInstruction> - // - - if (p_annotation.isSigned()) { - addTestRegisterMask(test_i, p_annotation.getRegister(), mask2, jz_i); - } - else { // must be UNKNOWNSIGN - addTestRegisterMask(test_i, p_annotation.getRegister(), mask, jz_i); - } - Instruction_t* nop_i = allocateNewInstruction(fileID, func); - Instruction_t* s_cmp_i = allocateNewInstruction(fileID, func); - Instruction_t* s_jae_i = allocateNewInstruction(fileID, func); - - addJz(jz_i, s_cmp_i, popf_i); // target = popf_i, fall-through = s_cmp_i - jz_i->setComment(string("jz - SIGNED or UNKNOWNSIGN TRUNC")); - addCmpRegisterMask(s_cmp_i, p_annotation.getRegister(), mask2, s_jae_i); - addJae(s_jae_i, nop_i, popf_i); // target = popf_i, fall-through = nop_i - s_jae_i->setComment(string("jae - SIGNED or UNKNOWNSIGN TRUNC")); - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) { - addNop(nop_i, saturate_i); - nop_i->setComment("SIGNED or UNKNOWNSIGN TRUNC: fallthrough: saturating arithmetic instruction"); - addCallbackHandler(detector, originalInstrumentInstr, nop_i, saturate_i, p_policy, saveAddress); - } - else { - addNop(nop_i, popf_i); - nop_i->setComment(string("SIGNED or UNKNOWNSIGN TRUNC: fallthrough: popf")); - addCallbackHandler(detector, originalInstrumentInstr, nop_i, popf_i, p_policy, saveAddress); - } - } // end of SIGNED and UNKNOWNSIGN case - addPopf(popf_i, originalInstrumentInstr); // common to all cases - - m_numTruncations++; - // cerr << "addTruncationCheck(): --- END ---" << endl; -} - -void IntegerTransform32::addSaturation(Instruction_t *p_instruction, RegisterName p_reg, unsigned p_value, const MEDS_InstructionCheckAnnotation& p_annotation, Instruction_t *p_fallthrough) -{ - assert(getFileIR() && p_instruction); - - p_instruction->setFallthrough(p_fallthrough); - - addMovRegisterUnsignedConstant(p_instruction, p_reg, p_value, p_fallthrough); -} - -void IntegerTransform32::addZeroSaturation(Instruction_t *p_instruction, RegisterName p_reg, Instruction_t *p_fallthrough) -{ - assert(getFileIR() && p_instruction); - - p_instruction->setFallthrough(p_fallthrough); - - addMovRegisterUnsignedConstant(p_instruction, p_reg, 0, p_fallthrough); -} - -// -// <instruction to instrument> -// jno <originalFallthroughInstruction> -// jnc <originalFallthroughInstruction> -// nop [attach callback handler] -// saturate target register (if policy dictates) -// <originalFallthroughInstruction> -// -void IntegerTransform32::addOverflowCheckUnknownSign(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - assert(getFileIR() && p_instruction && p_instruction->getFallthrough()); - - RegisterName targetReg = getTargetRegister(p_instruction); - if (targetReg == rn_UNKNOWN) - { - cerr << "integertransform: OVERFLOW UNKNOWN SIGN: unknown register -- skip instrumentation" << endl; - m_numOverflowsSkipped++; - return; - } - -cerr << __func__ << ": instr: " << p_instruction->getDisassembly() << " address: " << std::hex << p_instruction->getAddress() << " annotation: " << p_annotation.toString() << " policy: " << p_policy << endl; - - // set detector/handler - string detector(OVERFLOW_UNKNOWN_SIGN_DETECTOR); - if (!isMultiplyInstruction(p_instruction)) - { - if (p_annotation.getBitWidth() == 32) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_8); - } - - // for now assume we're dealing with add/sub 32 bit - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->GetFunction(); - - Instruction_t* jno_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - Instruction_t* jnc_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - Instruction_t* nop_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - - // save fallthrough from original instruction - Instruction_t* nextOrig_i = p_instruction->getFallthrough(); - - // instrument for both jno and jnc - // redundant for imul, but that's ok, optimize later - p_instruction->setFallthrough(jno_i); - addJno(jno_i, jnc_i, nextOrig_i); - addJnc(jnc_i, nop_i, nextOrig_i); - addNop(nop_i, nextOrig_i); - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - Instruction_t* saturate_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - addCallbackHandler(detector, p_instruction, nop_i, saturate_i, p_policy); - addMaxSaturation(saturate_i, targetReg, p_annotation, nextOrig_i); - } - else - { - addCallbackHandler(detector, p_instruction, nop_i, nextOrig_i, p_policy); - } - - m_numOverflows++; -} - -// -// <instruction to instrument> -// jno|jnc <originalFallthroughInstruction> -// jnc <originalFallthroughInstruction> [UNKNOWNSIGN] -// pusha -// pushf -// push_arg <address original instruction> -// push L1 -// ... setup detector ... -// L1: pop_arg -// popf -// popa -// -// 20111024 Current policy: -// imul, mul -- always check using jno -// add, sub -- use signedness information annotation to emit either jno, jnc -// -// p_addressOriginalInstruction is set when we call method from lea instrumentation -void IntegerTransform32::addOverflowCheckForLea(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy, AddressID_t *p_addressOriginalInstruction) -{ - assert(getFileIR() && p_instruction && p_instruction->getFallthrough()); - -cerr << __func__ << ": comment: " << p_instruction->GetComment() << " annotation: " << p_annotation.toString() << " policy: " << p_policy << endl; - - Instruction_t* jnc_i = NULL; - string detector(INTEGER_OVERFLOW_DETECTOR); - - // this will be either jno or jnc - Instruction_t* jncond_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - - // set fallthrough for the original instruction - Instruction_t* nextOrig_i = p_instruction->getFallthrough(); - p_instruction->setFallthrough(jncond_i); - - // jncond - int isMultiply = isMultiplyInstruction(p_instruction); - if (isMultiply) - { - // fallthrough will be set by the callback handler - addJno(jncond_i, NULL, nextOrig_i); - if (p_annotation.getBitWidth() == 32) - detector = string(MUL_OVERFLOW_DETECTOR_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(MUL_OVERFLOW_DETECTOR_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(MUL_OVERFLOW_DETECTOR_8); - } - else if (p_annotation.isSigned()) - { - // fallthrough will be set by the callback handler - addJno(jncond_i, NULL, nextOrig_i); - if (p_annotation.getBitWidth() == 32) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_8); - } - else if (p_annotation.isUnsigned()) - { - // fallthrough will be set by the callback handler - addJnc(jncond_i, NULL, nextOrig_i); - if (p_annotation.getBitWidth() == 32) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_8); - } - else - { - if (p_annotation.getBitWidth() == 32) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_32); - else if (p_annotation.getBitWidth() == 16) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_16); - else if (p_annotation.getBitWidth() == 8) - detector = string(ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_8); - - jnc_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - - addJno(jncond_i, jnc_i, nextOrig_i); - addJnc(jnc_i, NULL, nextOrig_i); // fallthrough will be set by the callback handler - } - - logMessage(__func__, "detector: " + detector); - - if (jnc_i) // unknown add/sub - { - logMessage(__func__, "add callback handler for unknown add/sub"); - addCallbackHandler(detector, p_instruction, jnc_i, nextOrig_i, p_policy, p_addressOriginalInstruction); - } - else - { - // mul, or signed/unsigned add/sub - logMessage(__func__, "add callback handler for mul, or signed/unsigned add/sub"); - addCallbackHandler(detector, p_instruction, jncond_i, nextOrig_i, p_policy, p_addressOriginalInstruction); - } -} - diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform32.hpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform32.hpp deleted file mode 100644 index 4617ecfdfb3bd2195a667e5a13ed0f8ab503e43b..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform32.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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_INTEGERTRANSFORM32_H_ -#define _LIBTRANSFORM_INTEGERTRANSFORM32_H_ - -#include "integertransform.hpp" - -namespace libTransform -{ - -using namespace std; -using namespace libIRDB; - -class IntegerTransform32 : public IntegerTransform -{ - public: - IntegerTransform32(VariantID_t *, FileIR_t*, - MEDS_Annotations_t *p_annotations, set<std::string> *p_filteredFunctions, - set<VirtualOffset> *p_warnings); - - virtual int execute(); - virtual int executePointerInstrumentation() { assert(0); } // not yet implemented - - private: - void handleOverflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void handleUnderflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void handleSignedness(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void handleTruncation(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void handleFISTTruncation(Instruction_t *p_instruction); - - void addFistpTruncationCheck(Instruction_t *p_instruction, int len); - void addFistTruncationCheck(Instruction_t *p_instruction, int len); - - void handleInfiniteLoop(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - - void addSignednessCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void addTruncationCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - - void addOverflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void addOverflowCheckForLea(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy, AddressID_t *p_original); - void addOverflowCheckUnknownSign(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - - void addUnderflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - - void addOverflowCheckNoFlag(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void addOverflowCheckNoFlag_RegPlusReg(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName&, const RegisterName&, const RegisterName&, int p_policy); - void addOverflowCheckNoFlag_RegPlusConstant(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName&, int p_constantValue, const RegisterName&, int p_policy); - void addOverflowCheckNoFlag_RegTimesConstant(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName&, int p_constantValue, const RegisterName&, int p_policy); - - void addSaturation(Instruction_t *p_instruction, RegisterName p_reg, unsigned p_value, const MEDS_InstructionCheckAnnotation& p_annotation, Instruction_t *p_fallthrough); - void addZeroSaturation(Instruction_t *p_instruction, RegisterName p_reg, Instruction_t *p_fallthrough); - -}; - -// make sure these match the function names in $STRATA/src/posix/x86_linux/detector_number_handling/overflow_detector.c - -#define INTEGER_OVERFLOW_DETECTOR "integer_overflow_detector" - -#define ADDSUB_OVERFLOW_DETECTOR_SIGNED_32 "addsub_overflow_detector_signed_32" -#define ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_32 "addsub_overflow_detector_unsigned_32" -#define ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_32 "addsub_overflow_detector_unknown_32" - -#define ADDSUB_OVERFLOW_DETECTOR_SIGNED_16 "addsub_overflow_detector_signed_16" -#define ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_16 "addsub_overflow_detector_unsigned_16" -#define ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_16 "addsub_overflow_detector_unknown_16" - -#define ADDSUB_OVERFLOW_DETECTOR_SIGNED_8 "addsub_overflow_detector_signed_8" -#define ADDSUB_OVERFLOW_DETECTOR_UNSIGNED_8 "addsub_overflow_detector_unsigned_8" -#define ADDSUB_OVERFLOW_DETECTOR_UNKNOWN_8 "addsub_overflow_detector_unknown_8" - -#define MUL_OVERFLOW_DETECTOR_32 "mul_overflow_detector_32" -#define MUL_OVERFLOW_DETECTOR_16 "mul_overflow_detector_16" -#define MUL_OVERFLOW_DETECTOR_8 "mul_overflow_detector_8" -#define TRUNCATION_DETECTOR "truncation_detector" -#define TRUNCATION_DETECTOR_32_16 "truncation_detector_32_16" -#define TRUNCATION_DETECTOR_32_8 "truncation_detector_32_8" -#define TRUNCATION_DETECTOR_16_8 "truncation_detector_16_8" -#define TRUNCATION_DETECTOR_UNSIGNED_32_16 "truncation_detector_unsigned_32_16" -#define TRUNCATION_DETECTOR_UNSIGNED_32_8 "truncation_detector_unsigned_32_8" -#define TRUNCATION_DETECTOR_UNSIGNED_16_8 "truncation_detector_unsigned_32_8" -#define TRUNCATION_DETECTOR_SIGNED_32_16 "truncation_detector_signed_32_16" -#define TRUNCATION_DETECTOR_SIGNED_32_8 "truncation_detector_signed_32_8" -#define TRUNCATION_DETECTOR_SIGNED_16_8 "truncation_detector_signed_32_8" -#define SIGNEDNESS_DETECTOR_32 "signedness_detector_32" -#define SIGNEDNESS_DETECTOR_16 "signedness_detector_16" -#define SIGNEDNESS_DETECTOR_8 "signedness_detector_8" -#define UNDERFLOW_DETECTOR_32 "underflow_detector_32" -#define UNDERFLOW_DETECTOR_16 "underflow_detector_16" -#define UNDERFLOW_DETECTOR_8 "underflow_detector_8" -#define UNDERFLOW_DETECTOR_UNSIGNED_32 "underflow_detector_unsigned_32" -#define UNDERFLOW_DETECTOR_UNSIGNED_16 "underflow_detector_unsigned_16" -#define UNDERFLOW_DETECTOR_UNSIGNED_8 "underflow_detector_unsigned_8" -#define UNDERFLOW_DETECTOR_SIGNED_32 "underflow_detector_signed_32" -#define UNDERFLOW_DETECTOR_SIGNED_16 "underflow_detector_signed_16" -#define UNDERFLOW_DETECTOR_SIGNED_8 "underflow_detector_signed_8" -#define INFINITE_LOOP_DETECTOR "infinite_loop_detector" -#define OVERFLOW_UNKNOWN_SIGN_DETECTOR "overflow_unknown_sign_detector" -} - -#endif diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform64.cpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform64.cpp deleted file mode 100644 index 06315471f9fce669110366d7a760a1de0fb4d58c..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform64.cpp +++ /dev/null @@ -1,1702 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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 <assert.h> -#include <sstream> -#include "leapattern.hpp" -#include "integertransform64.hpp" -#include "Rewrite_Utility.hpp" - -#define INSTRUMENT_LEA -#define INSTRUMENT_OVERFLOW -#define INSTRUMENT_UNDERFLOW -#define INSTRUMENT_TRUNCATION -#define INSTRUMENT_SIGNEDNESS - -using namespace libTransform; - -/** -* 64 bit implementation status of the integer transform -* 20140228 64-bit overflows on multiply, signed/unsigned add/sub -* 20140422 callback handlers added -* -* 64-bit signed unsigned unknown -* -------- ------ -------- ------- -* add, sub of c of,c -* mul of of of -* lea @todo @todo @todo -* -* 32-bit signed unsigned unknown -* -------- ------ -------- ------- -* add, sub @todo @todo @todo -* mul of of of -* lea @todo @todo @todo - -* @todo: -* - test unknown -* - test warnings only mode -* - handle LEA instructions -* -**/ - -IntegerTransform64::IntegerTransform64(VariantID_t *p_variantID, FileIR_t *p_fileIR, MEDS_Annotations_t *p_annotations, set<std::string> *p_filteredFunctions, set<VirtualOffset> *p_benignFalsePositives) : IntegerTransform(p_variantID, p_fileIR, p_annotations, p_filteredFunctions, p_benignFalsePositives) -{ -} - -// iterate through all functions -// filter those functions that should be ignored -// iterate through all instructions in function -// if MEDS annotation says to instrument -// add instrumentation -int IntegerTransform64::execute() -{ - if (isWarningsOnly()) - logMessage(__func__, "warnings only mode"); - if (isInstrumentIdioms()) - logMessage(__func__, "override annotations -- instrument IDIOMS"); - - for( - set<Function_t*>::const_iterator itf=getFileIR()->GetFunctions().begin(); - itf!=getFileIR()->GetFunctions().end(); - ++itf - ) - { - Function_t* func=*itf; - - if (getFilteredFunctions()->find(func->GetName()) != getFilteredFunctions()->end()) - { - logMessage(__func__, "filter out: " + func->GetName()); - continue; - } - - if (isBlacklisted(func)) - { - logMessage(__func__, "blacklisted: " + func->GetName()); - m_numBlacklisted++; - continue; - } - - logMessage(__func__, "processing fn: " + func->GetName()); - - for( - set<Instruction_t*>::const_iterator it=func->GetInstructions().begin(); - it!=func->GetInstructions().end(); - ++it) - { - Instruction_t* insn=*it; - - if (insn && insn->getAddress()) - { - int policy = POLICY_DEFAULT; - - if (isSaturatingArithmetic()) - { - // saturating arithmetic is enabled - // only use if instruction is not a potential false positive - policy = POLICY_CONTINUE_SATURATING_ARITHMETIC; - } - - // takes precedence over saturation if conflict - if (isWarningsOnly()) - { - policy = POLICY_CONTINUE; - } - - virtual_offset_t irdb_vo = insn->getAddress()->GetVirtualOffset(); - if (irdb_vo == 0) continue; - - VirtualOffset vo(irdb_vo); - - if (getAnnotations()->count(vo) == 0) - continue; - - std::pair<MEDS_Annotations_t::iterator,MEDS_Annotations_t::iterator> ret; - ret = getAnnotations()->equal_range(vo); - MEDS_InstructionCheckAnnotation annotation; - MEDS_InstructionCheckAnnotation* p_annotation; - for ( MEDS_Annotations_t::iterator it = ret.first; it != ret.second; ++it) - { - MEDS_AnnotationBase *base_type=(it->second); - p_annotation = dynamic_cast<MEDS_InstructionCheckAnnotation*>(base_type); - if( p_annotation == NULL) - continue; - annotation = *p_annotation; - if (!annotation.isValid()) - continue; - else - break; // let's just handle one annotation for now and see how it goes - } - - logMessage(__func__, annotation, "-- instruction: " + insn->getDisassembly()); - m_numAnnotations++; - - if (annotation.isIdiom() && !isInstrumentIdioms()) - { - logMessage(__func__, "skip IDIOM"); - m_numIdioms++; - continue; - } - - if (!insn->getFallthrough()) - { - logMessage(__func__, "Warning: no fall through for instruction -- skipping"); - continue; - } - - if (annotation.isOverflow()) - { -#ifdef INSTRUMENT_OVERFLOW - m_numTotalOverflows++; - handleOverflowCheck(insn, annotation, policy); -#endif - } -#ifdef INSTRUMENT_UNDERFLOW - else - if (annotation.isUnderflow()) - { - m_numTotalUnderflows++; - handleUnderflowCheck(insn, annotation, policy); - } -#endif -#ifdef INSTRUMENT_TRUNCATION - else if (annotation.isTruncation()) - { - m_numTotalTruncations++; - handleTruncation(insn, annotation, policy); - } -#endif -#ifdef INSTRUMENT_SIGNEDNESS - else if (annotation.isSignedness()) - { - m_numTotalSignedness++; - handleSignedness(insn, annotation, policy); - } -#endif - } - } // end iterate over all instructions in a function - } // end iterate over all functions - - return 0; -} - -void IntegerTransform64::handleOverflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - bool result = false; - - if (isMultiplyInstruction(p_instruction) || (p_annotation.isOverflow() && !p_annotation.isNoFlag())) - { - // handle signed/unsigned add/sub overflows (non lea) - result = addOverflowUnderflowCheck(p_instruction, p_annotation, p_policy); - } -#ifdef INSTRUMENT_LEA - else - if (p_annotation.isNoFlag()) - { - // handle lea - if ((p_annotation.getBitWidth() == 64 || p_annotation.getBitWidth() == 32)) - { - result = addOverflowCheckNoFlag(p_instruction, p_annotation, p_policy); - } - } -#endif - - if (result) - { - m_numOverflows++; - } - else - { - m_numOverflowsSkipped++; - logMessage(__func__, "OVERFLOW type not yet handled"); - } -} - -void IntegerTransform64::handleUnderflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - bool success = false; - - if (p_annotation.isUnderflow() && !p_annotation.isNoFlag()) - success = addOverflowUnderflowCheck(p_instruction, p_annotation, p_policy); - - if (success) - { - m_numUnderflows++; - } - else - { - m_numUnderflowsSkipped++; - logMessage(__func__, "UNDERFLOW type not yet handled"); - } -} - -void IntegerTransform64::handleTruncation(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - bool success = false; - - if (!isMovInstruction(p_instruction)) - { - logMessage(__func__, "We only instrument MOV instructions for TRUNCATION annotations"); - return; - } - - if (p_annotation.getTruncationFromWidth() == 64) - { - if (p_annotation.getTruncationToWidth() == 32 || p_annotation.getTruncationToWidth() == 16 || p_annotation.getTruncationToWidth() == 8) - { - success = addTruncationCheck64(p_instruction, p_annotation, p_policy); - } - else - { - logMessage(__func__, "Truncation type not yet handled (64)"); - } - } - else if (p_annotation.getTruncationFromWidth() == 32) - { - if (p_annotation.getTruncationToWidth() == 16 || p_annotation.getTruncationToWidth() == 8) - { - success = addTruncationCheck32(p_instruction, p_annotation, p_policy); - } - else - { - logMessage(__func__, "Truncation type not yet handled (32)"); - } - } - - if (success) - m_numTruncations++; - else - { - m_numTruncationsSkipped++; - logMessage(__func__, "Truncation type not yet handled (2)"); - } -} - -void IntegerTransform64::handleSignedness(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - if (addSignednessCheck(p_instruction, p_annotation, p_policy)) - { - m_numSignedness++; - } - else - { - logMessage(__func__, "SIGNEDNESS: error: skip instrumentation"); - m_numSignednessSkipped++; - } -} - - -// -// Saturation Policy -// mul a, b ; <instruction to instrument> -// jno <OrigNext> ; if no overflows, jump to original fallthrough instruction -// mov a, MIN/MAX ; policy = min-saturate (underflow) / max-saturate (overflow) -// of64/uf64 handler ; call the callback handler (handle diagnostics) -// OrigNext: <nextInstruction> ; original fallthrugh -// -bool IntegerTransform64::addOverflowUnderflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - char tmpbuf[1024]; - - assert(getFileIR() && p_instruction && p_instruction->getFallthrough()); - RegisterName targetReg = getTargetRegister(p_instruction); - if (targetReg == rn_UNKNOWN) - { - logMessage(__func__, p_annotation, "unknown target register"); - return false; - } - else if (!instrumentSP() && (targetReg == rn_RSP || targetReg == rn_ESP)) - { - logMessage(__func__, "target register is esp/rsp -- skipping: "); - return false; - } - else if (!instrumentFP() && (targetReg == rn_RBP || targetReg == rn_EBP)) - { - logMessage(__func__, "target register is ebp/rbp -- skipping: "); - return false; - } - - Instruction_t* jncond_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - Instruction_t* nop_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - Instruction_t* policy_i; - - Instruction_t* next_i = p_instruction->getFallthrough(); - p_instruction->setFallthrough(jncond_i); - - setAssembly(nop_i, "nop"); - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - policy_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - } - else - { - policy_i = nop_i; - } - - if (p_annotation.isSigned() || isMultiplyInstruction(p_instruction)) - { - addJno(jncond_i, policy_i, next_i); - } - else if (p_annotation.isUnsigned()) - { - addJnc(jncond_i, policy_i, next_i); - } - else - { // unknown sign - Instruction_t* jnc_i = allocateNewInstruction(p_instruction->getAddress()->getFileID(), p_instruction->GetFunction()); - addJno(jncond_i, jnc_i, next_i); - addJnc(jnc_i, policy_i, next_i); - } - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - // @todo: - // saturating signed multiply overflow should take into account - // the signs of the operand. If multiplying negative by positive #, - // then we want to sature to MIN_SIGNED_INT - - if (p_annotation.isUnderflow()) - addMinSaturation(policy_i, targetReg, p_annotation, nop_i); - else - addMaxSaturation(policy_i, targetReg, p_annotation, nop_i); - } - - std::string detector = p_annotation.isOverflow() ? OVERFLOW64_DETECTOR : UNDERFLOW64_DETECTOR; - - Instruction_t* cb = addCallbackHandlerSequence(p_instruction, next_i, detector, p_policy); - nop_i->setFallthrough(cb); - cb->setComment("underflow callback/instrumentation"); - - return true; -} - -bool IntegerTransform64::addOverflowCheckNoFlag(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - LEAPattern leaPattern(p_annotation); - - if (!leaPattern.isValid()) - { - logMessage(__func__, "invalid or unhandled lea pattern - skipping: "); - return false; - } - - if (leaPattern.getRegister1() == rn_UNKNOWN) - { - logMessage(__func__, "destination register is unknown -- skipping: "); - return false; - } - else if(!instrumentSP() && (leaPattern.getRegister1() == rn_RSP || leaPattern.getRegister1() == rn_ESP)) - { - logMessage(__func__, "destination register is r/esp -- skipping: "); - return false; - } - else if(!instrumentFP() && (leaPattern.getRegister1() == rn_RBP || leaPattern.getRegister1() == rn_EBP)) - { - logMessage(__func__, "destination register is r/ebp -- skipping: "); - return false; - } - - if (leaPattern.isRegisterPlusRegister() || leaPattern.isRegisterTimesRegister()) - { - RegisterName reg1 = leaPattern.getRegister1(); - RegisterName reg2 = leaPattern.getRegister2(); - RegisterName target = getTargetRegister(p_instruction); - - if (reg1 == rn_UNKNOWN || reg2 == rn_UNKNOWN || target == rn_UNKNOWN) - { - logMessage(__func__, "lea reg reg pattern: error retrieving register: reg1: " + Register::toString(reg1) + " reg2: " + Register::toString(reg2) + " target: " + Register::toString(target)); - return false; - } - else if (!instrumentSP() && (reg2 == rn_RSP || reg2 == rn_ESP || reg1 == rn_RSP || reg1 == rn_ESP )) - { - logMessage(__func__, "source or target register is esp/rsp -- skipping: "); - return false; - } - else if (!instrumentFP() && (reg2 == rn_RBP || reg2 == rn_EBP || reg1 == rn_RBP || reg1 == rn_EBP )) - { - logMessage(__func__, "source or target register is ebp/rbp -- skipping: "); - return false; - } - else - { - if (leaPattern.isRegisterPlusRegister()) - addOverflowCheckNoFlag_RegPlusReg(p_instruction, p_annotation, reg1, reg2, target, p_policy); - else if (leaPattern.isRegisterTimesRegister()) - addOverflowCheckNoFlag_RegTimesReg(p_instruction, p_annotation, reg1, reg2, target, p_policy); - } - return true; - } - else if (leaPattern.isRegisterPlusConstant() || leaPattern.isRegisterTimesConstant()) - { - RegisterName reg1 = leaPattern.getRegister1(); - int k = leaPattern.getConstant(); - RegisterName target = getTargetRegister(p_instruction); - - if (reg1 == rn_UNKNOWN || target == rn_UNKNOWN) - { - logMessage(__func__, "lea reg const pattern: error retrieving register: reg1: " + Register::toString(reg1) + " target: " + Register::toString(target)); - return false; - } - else if (!instrumentSP() && (target == rn_RSP || target == rn_ESP)) - { - logMessage(__func__, "target register is esp/rsp -- skipping: "); - return false; - } - else if (!instrumentFP() && (target == rn_RBP || target == rn_EBP)) - { - logMessage(__func__, "target register is ebp/rbp -- skipping: "); - return false; - } - else - { - if (leaPattern.isRegisterPlusConstant()) - addOverflowCheckNoFlag_RegPlusConstant(p_instruction, p_annotation, reg1, k, target, p_policy); - else if (leaPattern.isRegisterTimesConstant()) - addOverflowCheckNoFlag_RegTimesConstant(p_instruction, p_annotation, reg1, k, target, p_policy); - } - return true; - } - logMessage(__func__, "not yet handling lea -- placeholder"); - return false; -} - -// -// p_orig original instruction being instrumented -// p_fallthrough fallthrough once we're done with the callback handlers/detectors -// p_detector callback handler function to call -// p_policy instrumentation policy (e.g.: terminate, saturate, ...) -// -// returns first instruction of callback handler sequence -// -Instruction_t* IntegerTransform64::addCallbackHandlerSequence(Instruction_t *p_orig, Instruction_t *p_fallthrough, std::string p_detector, int p_policy) -{ - char tmpbuf[1024]; - - Instruction_t* lea = addNewAssembly("lea rsp, [rsp-128]"); // red zone - lea->setComment("callback: " + p_detector); - - // must save flags as strata will perturb them - Instruction_t* saveFlags = addNewAssembly(lea, "pushf"); - - // pass in PC of instrumented instruction - // pass in p_policy - sprintf(tmpbuf,"push 0x%08x", p_policy); - Instruction_t* instr = addNewAssembly(saveFlags, tmpbuf); - sprintf(tmpbuf,"push 0x%08x", p_orig->getAddress()->GetVirtualOffset()); - instr = addNewAssembly(instr, tmpbuf); - - Instruction_t* call = allocateNewInstruction(p_orig->getAddress()->getFileID(), p_orig->GetFunction()); - instr->setFallthrough(call); - setAssembly(call, "call 0"); - - addCallbackHandler64(call, p_detector, 2); // 2 args for now - - assert(call->getTarget()); - - instr = addNewAssembly(call, "lea rsp, [rsp+16]"); - instr = addNewAssembly(instr, "popf"); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(p_fallthrough); - - return lea; -} - -// Example annotation to handle -// 804852e 3 INSTR CHECK OVERFLOW NOFLAGSIGNED 32 EDX+EAX ZZ lea eax, [edx+eax] Reg1: EDX Reg2: EAX -// Need to handle both 32-bit and 64-bit versions -// -// Original: -// lea r3, [r1+r2] -// <originalNext> -// -// Instrumentation: -// push r1 ; save r1 -// pushf ; save flags -// add r1, r2 ; r1 = r1 + r2 -// <overflowcheck> ; check for overflow -// (jno|jnc <restore>) ; SIGNED|UNSIGNED -// fallthrough--><policy> -// (jno&jnc <restore>) ; UNKNOWNSIGN check both flags -// fallthrough--><policy> -// -// <restore> -// popf ; restore flags -// pop r1 ; restore register -// -// <orig>: lea r3, [r1+r2] ; original instruction -// <originalNext> ; original next instruction -// -// <policy> -// () callback handler -// popf ; restore flags -// pop r1 ; restore register -// fallthrough-->originalNext (if no saturation) -// saturateMax(r3) ; optional saturation -// fallthrough-->originalNext -// -void IntegerTransform64::addOverflowCheckNoFlag_RegPlusReg(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const RegisterName& p_reg2, const RegisterName& p_reg3, int p_policy) -{ - assert(p_instruction && p_instruction->getFallthrough()); - - cerr << __func__ << ": r3 <-- r1+r2: r1: " << Register::toString(p_reg1) << " r2: " << Register::toString(p_reg2) << " target register: " << Register::toString(p_reg3) << " annotation: " << p_annotation.toString() << endl; - - Instruction_t *origFallthrough = p_instruction->getFallthrough(); - Instruction_t *instr, *first, *saturation_policy; - Instruction_t *restore = addNewAssembly("popf"); - - saturation_policy = addNewAssembly("nop"); - saturation_policy->setComment("lea overflow instrumentation(reg+reg): policy code sequence"); - - // Original code sequence: - // lea r3, [r1+r2] - // <originalNext> - // - // Instrumentation: - // push r1 ; save r1 - // pushf ; save flags - // add r1, r2 ; r1 = r1 + r2 - // <overflowcheck> ; check for overflow - // (jno|jnc <restore>) ; SIGNED|UNSIGNED - // fallthrough--><policy> - // (jno&jnc <restore>) ; UNKNOWNSIGN check both flags - // fallthrough--><policy> - // -// first = addNewAssembly("push " + Register::toString(p_reg1)); -// first->setComment("lea overflow instrumentation(reg+reg): start"); -// Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, first); - - Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, "lea rsp, [rsp-128]" , NULL); - p_instruction->setComment("lea overflow instrumentation(reg+reg): start"); - instr = addNewAssembly(p_instruction, std::string("push ") + Register::toString(p_reg1)); - instr = addNewAssembly(instr, "pushf"); - - instr = addNewAssembly(instr, "add " + Register::toString(p_reg1) + "," + Register::toString(p_reg2)); - if (p_annotation.isSigned()) - { - instr = addNewAssembly(instr, "jno 0x22"); - instr->setFallthrough(saturation_policy); - instr->setTarget(restore); - instr->setComment("signed: lea: reg+reg"); - } - else if (p_annotation.isUnsigned()) - { - instr = addNewAssembly(instr, "jnc 0x22"); - instr->setFallthrough(saturation_policy); - instr->setTarget(restore); - } - else - { - Instruction_t *instr2 = addNewAssembly(instr, "jno 0x22"); // this generates bogus assembly code, why? - instr2->setTarget(restore); - instr = addNewAssembly(instr2, "jnc 0x22"); - instr->setFallthrough(saturation_policy); - instr->setTarget(restore); - } - - // <policy> - // nop ; - // () callback handler ; - // popf ; restore flags - // pop r1 ; restore register - // fallthrough-->originalNext (if no saturation) - // saturateMax(r3) ; optional saturation - // fallthrough-->originalNext - // - // assume 64 bit for now - // - Instruction_t *popf = addNewAssembly("popf"); - Instruction_t *callback = addCallbackHandlerSequence(p_instruction, popf, OVERFLOW64_DETECTOR, p_policy); - saturation_policy->setFallthrough(callback); - instr = addNewAssembly(popf, "pop " + Register::toString(p_reg1)); - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - instr = addNewMaxSaturation(instr, p_reg3, p_annotation); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(origFallthrough); - } - else - { - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); - } - - // <restore> - // popf ; restore flags - // pop r1 ; restore register - // - // <orig>: lea r3, [r1+r2] ; original instruction - // <originalNext> ; original next instruction - // - restore->setComment("lea overflow instrumentation(reg+reg): restore"); - instr = addNewAssembly(restore, "pop " + Register::toString(p_reg1)); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); -} - -// Example annotation to handle -// 804852e 3 INSTR CHECK OVERFLOW NOFLAGSIGNED 32 EDX+EAX ZZ lea eax, [edx+eax] Reg1: EDX Reg2: EAX -// Need to handle both 32-bit and 64-bit versions -// -// Original: -// lea r3, [r1+r2] -// <originalNext> -// -// Instrumentation: -// push r1 ; save r1 -// pushf ; save flags -// imul r1, r2 ; r1 = r1 * r2 -// <overflowcheck> ; check for overflow -// (jno|jnc <restore>) ; SIGNED|UNSIGNED -// fallthrough--><policy> -// (jno&jnc <restore>) ; UNKNOWNSIGN check both flags -// fallthrough--><policy> -// -// <restore> -// popf ; restore flags -// pop r1 ; restore register -// -// <orig>: lea r3, [r1+r2] ; original instruction -// <originalNext> ; original next instruction -// -// <policy> -// () callback handler -// popf ; restore flags -// pop r1 ; restore register -// fallthrough-->originalNext (if no saturation) -// saturateMax(r3) ; optional saturation -// fallthrough-->originalNext -// -void IntegerTransform64::addOverflowCheckNoFlag_RegTimesReg(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const RegisterName& p_reg2, const RegisterName& p_reg3, int p_policy) -{ - assert(p_instruction && p_instruction->getFallthrough()); - - cerr << __func__ << ": r3 <-- r1*r2: r1: " << Register::toString(p_reg1) << " r2: " << Register::toString(p_reg2) << " target register: " << Register::toString(p_reg3) << " annotation: " << p_annotation.toString() << endl; - - Instruction_t *origFallthrough = p_instruction->getFallthrough(); - Instruction_t *instr, *first, *saturation_policy; - Instruction_t *restore = addNewAssembly("popf"); - saturation_policy = addNewAssembly("nop"); - saturation_policy->setComment("lea overflow instrumentation(reg*reg): policy code sequence"); - - - // Original code sequence: - // lea r3, [r1*r2] - // <originalNext> - // - // Instrumentation: - // push r1 ; save r1 - // pushf ; save flags - // imul r1, r2 ; r1 = r1 * r2 - // <overflowcheck> ; check for overflow - // jno <restore> ; - // fallthrough--><policy> - // - Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, "lea rsp, [rsp-128]" , NULL); - p_instruction->setComment("lea overflow instrumentation(reg*reg): start"); - instr = addNewAssembly(p_instruction, std::string("push ") + Register::toString(p_reg1)); - instr = addNewAssembly(instr, "pushf"); - - instr = addNewAssembly(instr, "imul " + Register::toString(p_reg1) + "," + Register::toString(p_reg2)); - instr = addNewAssembly(instr, "jno 0x22"); - instr->setFallthrough(saturation_policy); - instr->setTarget(restore); - - // <policy> - // nop ; - // () callback handler ; - // popf ; restore flags - // pop r1 ; restore register - // fallthrough-->originalNext (if no saturation) - // saturateMax(r3) ; optional saturation - // fallthrough-->originalNext - // - // assume 64 bit for now - // - Instruction_t *popf = addNewAssembly("popf"); - Instruction_t *callback = addCallbackHandlerSequence(p_instruction, popf, OVERFLOW64_DETECTOR, p_policy); - saturation_policy->setFallthrough(callback); - instr = addNewAssembly(popf, "pop " + Register::toString(p_reg1)); - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - instr = addNewMaxSaturation(instr, p_reg3, p_annotation); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(origFallthrough); - } - else - { - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); - } - - // <restore> - // popf ; restore flags - // pop r1 ; restore register - // - // <orig>: lea r3, [r1*r2] ; original instruction - // <originalNext> ; original next instruction - // - restore->setComment("lea overflow instrumentation(reg*reg): restore"); - instr = addNewAssembly(restore, "pop " + Register::toString(p_reg1)); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); -} - -// Example annotation to handle -// 804852e 3 INSTR CHECK OVERFLOW NOFLAGSIGNED 32 EDX+EAX ZZ lea eax, [edx+k] Reg1: EDX Reg3: EAX -// Need to handle both 32-bit and 64-bit versions -// -// Original: -// lea r3, [r1+k] -// <originalNext> -// -// Instrumentation: -// push r1 ; save r1 -// pushf ; save flags -// add r1, k ; r1 = r1 + k -// <overflowcheck> ; check for overflow -// (jno|jnc <restore>) ; SIGNED|UNSIGNED -// fallthrough--><policy> -// (jno&jnc <restore>) ; UNKNOWNSIGN check both flags -// fallthrough--><policy> -// -// <restore> -// popf ; restore flags -// pop r1 ; restore register -// -// <orig>: lea r3, [r1+k] ; original instruction -// <originalNext> ; original next instruction -// -// <policy> -// () callback handler -// popf ; restore flags -// pop r1 ; restore register -// fallthrough-->originalNext (if no saturation) -// saturateMax(r3) ; optional saturation -// fallthrough-->originalNext -// -void IntegerTransform64::addOverflowCheckNoFlag_RegPlusConstant(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const int p_constant, const RegisterName& p_reg3, int p_policy) -{ - assert(p_instruction && p_instruction->getFallthrough()); - - if (p_annotation.isUnsigned() && (p_constant < 0)) { - logMessage(__func__, "lea reg+neg constant pattern: skip this annotation type (prone to false positives)"); - m_numOverflowsSkipped++; - return; - } - - cerr << __func__ << ": r3 <-- r1+k: r1: " << Register::toString(p_reg1) << " k: " << p_constant << " target register: " << Register::toString(p_reg3) << " annotation: " << p_annotation.toString() << endl; - - Instruction_t *origFallthrough = p_instruction->getFallthrough(); - Instruction_t *instr, *first, *saturation_policy; - Instruction_t *restore = addNewAssembly("popf"); - saturation_policy = addNewAssembly("nop"); - saturation_policy->setComment("lea overflow instrumentation(reg+k): policy code sequence"); - - // Original code sequence: - // lea r3, [r1+k] - // <originalNext> - // - // Instrumentation: - // push r1 ; save r1 - // pushf ; save flags - // add r1, k ; r1 = r1 + k - // (or sub r1,-k ; r1 = r1 - (-k) for k < 0) - // <overflowcheck> ; check for overflow - // (jno|jnc <restore>) ; SIGNED|UNSIGNED - // fallthrough--><policy> - // (jno&jnc <restore>) ; UNKNOWNSIGN check both flags - // fallthrough--><policy> - // -/* - first = addNewAssembly("push " + Register::toString(p_reg1)); - first->setComment("lea overflow instrumentation(reg+k): start"); - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, first); - instr = addNewAssembly(first, "pushf"); - */ - - Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, "lea rsp, [rsp-128]" , NULL); - p_instruction->setComment("lea overflow instrumentation(reg+k): start"); - instr = addNewAssembly(p_instruction, std::string("push ") + Register::toString(p_reg1)); - instr = addNewAssembly(instr, "pushf"); -//------------------- - // make sure we set the fallthrough post careful insertion -// first->setFallthrough(instr); - - std::ostringstream s; - if (p_constant >= 0) { - s << "add " << Register::toString(p_reg1) << "," << p_constant; - } - else { - // NOTE: We are short-circuiting this case currently; see top of - // this function. Should never get here. - s << "sub " << Register::toString(p_reg1) << "," << (-p_constant); - } - instr = addNewAssembly(instr, s.str()); - if (p_annotation.isSigned()) - { - instr = addNewAssembly(instr, "jno 0x22"); - instr->setFallthrough(saturation_policy); - instr->setTarget(restore); - } - else if (p_annotation.isUnsigned()) - { - instr = addNewAssembly(instr, "jnc 0x22"); - instr->setFallthrough(saturation_policy); - instr->setTarget(restore); - } - else - { - Instruction_t *instr2 = addNewAssembly(instr, "jno 0x22"); - instr2->setTarget(restore); - instr = addNewAssembly(instr2, "jnc 0x22"); - instr->setFallthrough(saturation_policy); - instr->setTarget(restore); - } - - // <policy> - // nop ; - // () callback handler ; - // popf ; restore flags - // pop r1 ; restore register - // fallthrough-->originalNext (if no saturation) - // saturateMax(r3) ; optional saturation - // fallthrough-->originalNext - // - // assume 64 bit for now - // - Instruction_t *popf = addNewAssembly("popf"); - Instruction_t *callback = addCallbackHandlerSequence(p_instruction, popf, OVERFLOW64_DETECTOR, p_policy); - saturation_policy->setFallthrough(callback); - instr = addNewAssembly(popf, "pop " + Register::toString(p_reg1)); - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - instr = addNewMaxSaturation(instr, p_reg3, p_annotation); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(origFallthrough); - } - else - { - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); - } - - // <restore> - // popf ; restore flags - // pop r1 ; restore register - // - // <orig>: lea r3, [r1+k] ; original instruction - // <originalNext> ; original next instruction - // - restore->setComment("lea overflow instrumentation(reg+k): restore"); - instr = addNewAssembly(restore, "pop " + Register::toString(p_reg1)); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); - originalInstrumentInstr->setFallthrough(origFallthrough); -} - - -// Example annotation to handle -// 804852e 3 INSTR CHECK OVERFLOW NOFLAGSIGNED 32 EDX+EAX ZZ lea eax, [edx+eax] Reg1: EDX Reg2: EAX -// Need to handle both 32-bit and 64-bit versions -// -// Original: -// lea r3, [r1*k] -// <originalNext> -// -// Instrumentation: -// push r1 ; save r1 -// pushf ; save flags -// imul r1, r2 ; r1 = r1 * r2 -// <overflowcheck> ; check for overflow -// (jno <restore>) ; -// fallthrough--><policy> -// -// <restore> -// popf ; restore flags -// pop r1 ; restore register -// -// <orig>: lea r3, [r1*k] ; original instruction -// <originalNext> ; original next instruction -// -// <policy> -// () callback handler -// popf ; restore flags -// pop r1 ; restore register -// fallthrough-->originalNext (if no saturation) -// saturateMax(r3) ; optional saturation -// fallthrough-->originalNext -// -void IntegerTransform64::addOverflowCheckNoFlag_RegTimesConstant(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const int p_constant, const RegisterName& p_reg3, int p_policy) -{ - assert(p_instruction && p_instruction->getFallthrough()); - - cerr << __func__ << ": r3 <-- r1*k: r1: " << Register::toString(p_reg1) << " k: " << p_constant << " target register: " << Register::toString(p_reg3) << " annotation: " << p_annotation.toString() << endl; - - Instruction_t *origFallthrough = p_instruction->getFallthrough(); - Instruction_t *instr, *first, *saturation_policy; - Instruction_t *restore = addNewAssembly("popf"); - saturation_policy = addNewAssembly("nop"); - saturation_policy->setComment("lea overflow instrumentation(reg*k): policy code sequence"); - - // Original code sequence: - // lea r3, [r1*k] - // <originalNext> - // - // Instrumentation: - // push r1 ; save r1 - // pushf ; save flags - // imul r1, k ; r1 = r1 * k - // <overflowcheck> ; check for overflow - // jno <restore> ; - // fallthrough--><policy> - // - /* - first = addNewAssembly("push " + Register::toString(p_reg1)); - first->setComment("lea overflow instrumentation(reg*k): start"); - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, first); - instr = addNewAssembly(first, "pushf"); - */ - - Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, "lea rsp, [rsp-128]" , NULL); - p_instruction->setComment("lea overflow instrumentation(reg*k): start"); - instr = addNewAssembly(p_instruction, std::string("push ") + Register::toString(p_reg1)); - instr = addNewAssembly(instr, "pushf"); -/*--------------*/ - // make sure we set the fallthrough post careful insertion -// first->setFallthrough(instr); - - std::ostringstream s; - s << "imul " << Register::toString(p_reg1) << "," << p_constant; - instr = addNewAssembly(instr, s.str()); - instr = addNewAssembly(instr, "jno 0x22"); - instr->setFallthrough(saturation_policy); - instr->setTarget(restore); - - // <policy> - // nop ; - // () callback handler ; - // popf ; restore flags - // pop r1 ; restore register - // fallthrough-->originalNext (if no saturation) - // saturateMax(r3) ; optional saturation - // fallthrough-->originalNext - // - // assume 64 bit for now - // - Instruction_t *popf = addNewAssembly("popf"); - Instruction_t *callback = addCallbackHandlerSequence(p_instruction, popf, OVERFLOW64_DETECTOR, p_policy); - saturation_policy->setFallthrough(callback); - instr = addNewAssembly(popf, "pop " + Register::toString(p_reg1)); - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - instr = addNewMaxSaturation(instr, p_reg3, p_annotation); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(origFallthrough); - } - else - { - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); - } - - // <restore> - // popf ; restore flags - // pop r1 ; restore register - // - // <orig>: lea r3, [r1*k] ; original instruction - // <originalNext> ; original next instruction - // - restore->setComment("lea overflow instrumentation(reg*reg): restore"); - instr = addNewAssembly(restore, "pop " + Register::toString(p_reg1)); - instr = addNewAssembly(instr, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); - originalInstrumentInstr->setFallthrough(origFallthrough); -} - -// -// STARS has extensive discussion of the logic behind truncation and -// signedness annotations in module SMPInstr.cpp, method EmitIntegerErrorAnnotation(). -// The possible combinations are categorized in terms of the instrumentation -// needed at run time: -// CHECK TRUNCATION UNSIGNED: discarded bits must be all zeroes. -// CHECK TRUNCATION SIGNED: discarded bits must be sign-extension of stored bits. -// CHECK TRUNCATION UNKNOWNSIGN: discarded bits must be all zeroes, OR must -// be the sign-extension of the stored bits. -// All truncation annotations are emitted on stores (mov opcodes in x86). -// Other possibilities might be handled in the future. -// - -bool IntegerTransform64::addTruncationCheck32(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - assert(p_instruction && p_instruction->getFallthrough() && - p_annotation.getTruncationFromWidth() == 32 && - (p_annotation.getTruncationToWidth() == 16 || p_annotation.getTruncationToWidth() == 8) && - isMovInstruction(p_instruction)); - - // Complicated case: - // 80484ed 3 INSTR CHECK TRUNCATION UNKNOWNSIGN 32 EAX 8 AL ZZ mov [ebp+var_4], al - // example: for unknownsign truncation - 8 bit on AL - // it's ok if 24 upper bits are sign-extension or all 0's - // Re-phrased: upper 24 are 0s, upper 25 are 0s, upper 25 are 1s - // are all OK in the UNKNOWNSIGN case - // Note that upper 24 are 0's means no need to check for the - // case where the upper 25 are 0's; already OK. - // - // <save flags> - // test eax, 0xFFFFFF00 ; (for 8 bit) - // jz <continue> ; upper 24 bits are 0's - // - // cmp eax, 0xFFFFFF80 ;(for 8 bit) - // jae continue ; upper 25 bits are 1's - // (invoke truncation handler) - // nop ; truncation handler returns here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // mov [ebp+var_4], al ; <originalInstruction> - // - - // Unsigned case: - // 80484ed 3 INSTR CHECK TRUNCATION UNSIGNED 32 EAX 8 AL ZZ mov [ebp+var_4], al - // example: for unsigned truncation - 8 bit on AL - // it's ok if 24 upper bits are all 0's - // - // <save flags> - // test eax, 0xFFFFFF00 ; (for 8 bit) - // jz <continue> ; upper 24 bits are 0's - // - // (invoke truncation handler) - // nop ; truncation handler returns here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // mov [ebp+var_4], al ; <originalInstruction> - // - - string detector; - unsigned mask = 0, mask2 = 0; - string saturationValue = "0x0"; - - p_instruction->setComment("monitor for truncation32"); - - if (p_annotation.getTruncationToWidth() == 16) - { - mask = 0xFFFF0000; - mask2 = 0xFFFF8000; - - if(p_annotation.flowsIntoCriticalSink()) - { - detector = TRUNCATION64_FORCE_EXIT; - } - else if (p_annotation.isUnsigned()) - { - saturationValue = "0xFFFF"; - detector = string(TRUNCATION64_DETECTOR_UNSIGNED_32_16); - } - else if (p_annotation.isSigned()) - { - saturationValue = "0x7FFF"; - detector = string(TRUNCATION64_DETECTOR_SIGNED_32_16); - } - else - { - saturationValue = "0x7FFF"; - detector = string(TRUNCATION64_DETECTOR_UNKNOWN_32_16); - } - } - else if (p_annotation.getTruncationToWidth() == 8) - { - mask = 0xFFFFFF00; - mask2 = 0xFFFFFF80; - if(p_annotation.flowsIntoCriticalSink()) - { - detector = TRUNCATION64_FORCE_EXIT; - } - else if (p_annotation.isUnsigned()) - { - saturationValue = "0xFF"; - detector = string(TRUNCATION64_DETECTOR_UNSIGNED_32_8); - } - else if (p_annotation.isSigned()) - { - saturationValue = "0x7F"; - detector = string(TRUNCATION64_DETECTOR_SIGNED_32_8); - } - else - { - saturationValue = "0x7F"; - detector = string(TRUNCATION64_DETECTOR_UNKNOWN_32_8); - } - } - - // <save flags> - // test eax, 0xFFFFFF00 ; (for 8 bit) - // jz <continue> ; upper 24 bits are 0's - // - // (invoke truncation handler) - // nop ; truncation handler returns here - // SAT: mov [ebp+var_4], <saturate> ; optional - // jmp origFT - // - // continue: <restore flags> - // mov [ebp+var_4], al ; <originalInstruction> - // origFT: <originalFallThroughInstruction> - // - - char buf[MAX_ASSEMBLY_SIZE]; - Instruction_t *origFallthrough = p_instruction->getFallthrough(); - Instruction_t *instr, *save, *test; - Instruction_t *restore = addNewAssembly("popf"); - restore->setComment("trunc: restore flags"); - -/* - save = addNewAssembly("pushf"); - save->setComment("start truncation sequence"); -*/ - - if (p_annotation.isSigned()) - { - sprintf(buf, "test %s, 0x%8x", Register::toString(p_annotation.getRegister()).c_str(), mask2); - } - else - { - sprintf(buf, "test %s, 0x%8x", Register::toString(p_annotation.getRegister()).c_str(), mask); - } - logMessage(__func__, buf); - -/* - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, save); - test = addNewAssembly(save, buf); -*/ -/*--------------*/ -// Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, std::string("pushf"), NULL); - Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, "lea rsp, [rsp-128]" , NULL); - p_instruction->setComment("start truncation sequence"); - instr = addNewAssembly(p_instruction, "pushf"); - test = addNewAssembly(instr, buf); -/*--------------*/ - // p_instruction->setFallthrough(test); - -// save->setFallthrough(test); - - instr = addNewAssembly(restore, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); - - if (p_annotation.isUnsigned()) - { - logMessage(__func__, "unsigned annotation"); - Instruction_t *nop = addNewAssembly("nop"); - - instr = addNewAssembly(test, "jz 0x22"); // bogus jump target for now - instr->setTarget(restore); - instr->setFallthrough(nop); - - Instruction_t *callback; - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - string saturationInstruction = "mov " + p_annotation.getTarget2() + ", " + saturationValue; - Instruction_t *saturation = addNewAssembly(saturationInstruction); - saturation->setComment("trunc/unsigned/saturate"); - - callback = addCallbackHandlerSequence(p_instruction, saturation, detector, p_policy); - nop->setFallthrough(callback); - saturation->setFallthrough(restore); - } - else - { - callback = addCallbackHandlerSequence(p_instruction, restore, detector, p_policy); - nop->setFallthrough(callback); - } - } - else - { - // Signed and unknown signed cases are almost identical: - // 80484ed 3 INSTR CHECK TRUNCATION SIGNED 32 EAX 8 AL ZZ mov [ebp+var_4], al - // 80484ed 3 INSTR CHECK TRUNCATION UNKNOWNSIGN 32 EAX 8 AL ZZ mov [ebp+var_4], al - // example: for signed truncation - 8 bit on AL - // it's ok if 25 upper bits are all 1's or all 0's - // example: for unknownsign truncation - 8 bit on AL - // it's ok if 25 upper bits are all 1's or 24 upper bits all 0's - // - // <save flags> - // test eax, 0xFFFFFF80 ; (for 8 bit) 0xFFFFFF00 for UNKNOWN - // jz <continue> ; upper 25 bits are 0's - // - // cmp eax, 0xFFFFFF80 ;(for 8 bit) - // jae continue ; upper 25 bits are 1's - // (invoke truncation handler) - // nop ; truncation handler callback here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // mov [ebp+var_4], al ; <originalInstruction> - // - logMessage(__func__, "signed/unknown annotation"); - Instruction_t *nop = addNewAssembly("nop"); - - instr = addNewAssembly(test, "jz 0x22"); // bogus jump target for now - instr->setTarget(restore); - - std::ostringstream s; - s << "cmp " << Register::toString(p_annotation.getRegister()) << ", 0x" << hex << mask2 << dec; - instr = addNewAssembly(instr, s.str()); - - instr = addNewAssembly(instr, "jae 0x22"); - instr->setTarget(restore); - instr->setFallthrough(nop); - - Instruction_t *callback; - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - string saturationInstruction = "mov " + p_annotation.getTarget2() + ", " + saturationValue; - Instruction_t *saturation = addNewAssembly(saturationInstruction); - if (p_annotation.isSigned()) - saturation->setComment("trunc/signed/saturate"); - else - saturation->setComment("trunc/unknown/saturate"); - - callback = addCallbackHandlerSequence(p_instruction, saturation, detector, p_policy); - nop->setFallthrough(callback); - saturation->setFallthrough(restore); - } - else - { - callback = addCallbackHandlerSequence(p_instruction, restore, detector, p_policy); - nop->setFallthrough(callback); - } - } - - return true; -} - -// we want: 32->16 movzx edx, ax --> movzx edx, 0xFFFF -// 32->8 movzx edx, al --> movzx edx, 0xFF -// -// let's handle 2-operand instructions of the form: -// mov *, <reg> -// - -string IntegerTransform64::buildSaturationAssembly(Instruction_t *p_instruction, string p_pattern, string p_value) -{ - // @todo: verify 2 operands! - - string i = p_instruction->getDisassembly(); - - convertToLowercase(i); - convertToLowercase(p_pattern); - convertToLowercase(p_value); - - size_t commaPos = i.find_last_of(','); - if (commaPos != string::npos) - i.replace(i.find(p_pattern, commaPos), p_pattern.size(), p_value); - else - i.replace(i.find(p_pattern), p_pattern.size(), p_value); - return i; -} - -// -// STARS has extensive discussion of the logic behind truncation and -// signedness annotations in module SMPInstr.cpp, method EmitIntegerErrorAnnotation(). -// The possible combinations are categorized in terms of the instrumentation -// needed at run time: -// CHECK TRUNCATION UNSIGNED: discarded bits must be all zeroes. -// CHECK TRUNCATION SIGNED: discarded bits must be sign-extension of stored bits. -// CHECK TRUNCATION UNKNOWNSIGN: discarded bits must be all zeroes, OR must -// be the sign-extension of the stored bits. -// All truncation annotations are emitted on stores (mov opcodes in x86). -// Other possibilities might be handled in the future. -// - -bool IntegerTransform64::addTruncationCheck64(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - assert(p_instruction && p_instruction->getFallthrough() && - p_annotation.getTruncationFromWidth() == 64 && - (p_annotation.getTruncationToWidth() == 32 || p_annotation.getTruncationToWidth() == 16 || p_annotation.getTruncationToWidth() == 8) && - isMovInstruction(p_instruction)); - - std::set<RegisterName> takenRegs; - takenRegs.insert(p_annotation.getRegister()); - takenRegs.insert(p_annotation.getRegister2()); - takenRegs.insert(rn_RSP); // don't mess with the stack pointer - takenRegs.insert(rn_RBP); // don't mess with the frame pointer - RegisterName borrowReg = Register::getFreeRegister64(takenRegs); - - if (borrowReg == rn_UNKNOWN) - { - logMessage(__func__, "Could not borrow a 64-bit register"); - return false; - } - - // Main difference between TRUNCATION annotation for 64 bits vs. 32 bits - // is that we need to use a register as IA X86-64 doesn't support 64 bit constants - // for most instructions - - // Complicated case: - // 80484ed 3 INSTR CHECK TRUNCATION UNKNOWNSIGN 32 EAX 8 AL ZZ mov [ebp+var_4], al - // example: for unknownsign truncation - 8 bit on AL - // it's ok if 24 upper bits are sign-extension or all 0's - // Re-phrased: upper 24 are 0s, upper 25 are 0s, upper 25 are 1s - // are all OK in the UNKNOWNSIGN case - // Note that upper 24 are 0's means no need to check for the - // case where the upper 25 are 0's; already OK. - // - // <save reg> - // <save flags> - // mov <reg>, 0xFFFFFFFFFFFFFF00 ; // need to grab register - // test eax, <reg> ; (for 8 bit) - // jz <continue> ; upper 56 bits are 0's - // - // cmp eax, 0xFFFFFFFFFFFFFF80 ; (for 8 bit) - // jae continue ; upper 57 bits are 1's - // (invoke truncation handler) - // nop ; truncation handler returns here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // <restore reg> - // mov [ebp+var_4], al ; <originalInstruction> - // - - // Unsigned case: - // 80484ed 3 INSTR CHECK TRUNCATION UNSIGNED 64 RAX 32 EAX ZZ mov [ebp+var_4], al - // - // <save reg> - // <save flags> - // mov <reg>, 0xFFFFFFFFFFFFFF00 ; // need to grab register - // test eax, <reg>; (for 64->32 bit) - // jz <continue> ; upper 32 bits are 0's - // - // (invoke truncation handler) - // nop ; truncation handler returns here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // <restore reg> - // mov [ebp+var_4], al ; <originalInstruction> - // - - string detector; - long long unsigned mask = 0, mask2 = 0; - string saturationValue = "0x0"; - - p_instruction->setComment("monitor for truncation64"); - - if (p_annotation.getTruncationToWidth() == 32) - { - mask = 0xFFFFFFFF00000000; - mask2 = 0xFFFFFFFF80000000; - - if(p_annotation.flowsIntoCriticalSink()) - { - detector = TRUNCATION64_FORCE_EXIT; - } - else if (p_annotation.isUnsigned()) - { - saturationValue = "0xFFFFFFFF"; - detector = string(TRUNCATION64_DETECTOR_UNSIGNED_64_32); - } - else if (p_annotation.isSigned()) - { - saturationValue = "0x7FFFFFFF"; - detector = string(TRUNCATION64_DETECTOR_SIGNED_64_32); - } - else - { - saturationValue = "0x7FFFFFFF"; - detector = string(TRUNCATION64_DETECTOR_UNKNOWN_64_32); - } - } - else if (p_annotation.getTruncationToWidth() == 16) - { - mask = 0xFFFFFFFFFFFF0000; - mask2 = 0xFFFFFFFFFFFF8000; - - if(p_annotation.flowsIntoCriticalSink()) - { - detector = TRUNCATION64_FORCE_EXIT; - } - else if (p_annotation.isUnsigned()) - { - saturationValue = "0xFFFF"; - detector = string(TRUNCATION64_DETECTOR_UNSIGNED_64_16); - } - else if (p_annotation.isSigned()) - { - saturationValue = "0x7FFF"; - detector = string(TRUNCATION64_DETECTOR_SIGNED_64_16); - } - else - { - saturationValue = "0x7FFF"; - detector = string(TRUNCATION64_DETECTOR_UNKNOWN_64_16); - } - } - else if (p_annotation.getTruncationToWidth() == 8) - { - mask = 0xFFFFFFFFFFFFFF00; - mask2 = 0xFFFFFFFFFFFFFF80; - if(p_annotation.flowsIntoCriticalSink()) - { - detector = TRUNCATION64_FORCE_EXIT; - } - else if (p_annotation.isUnsigned()) - { - saturationValue = "0xFF"; - detector = string(TRUNCATION64_DETECTOR_UNSIGNED_64_8); - } - else if (p_annotation.isSigned()) - { - saturationValue = "0x7F"; - detector = string(TRUNCATION64_DETECTOR_SIGNED_64_8); - } - else - { - saturationValue = "0x7F"; - detector = string(TRUNCATION64_DETECTOR_UNKNOWN_64_8); - } - } - - // <save reg> - // <save flags> - // mov <reg>, 0xFFFFFFFFFFFFFF00 ; // need to grab register - // test eax, <reg> ; (for 8 bit) - // jz <continue> ; upper 24 bits are 0's - // - // (invoke truncation handler) - // nop ; truncation handler returns here - // SAT: mov [ebp+var_4], <saturate> ; optional - // jmp origFT - // - // continue: <restore flags> - // <restore reg> - // mov [ebp+var_4], al ; <originalInstruction> - // origFT: <originalFallThroughInstruction> - // - - char buf[MAX_ASSEMBLY_SIZE]; - Instruction_t *origFallthrough = p_instruction->getFallthrough(); - Instruction_t *instr, *save, *test, *pushf; - Instruction_t *restore = addNewAssembly("popf"); - restore->setComment("trunc: restore flags"); - Instruction_t *restoreReg = addNewAssembly("pop " + Register::toString(borrowReg)); - -/* - save = addNewAssembly("push " + Register::toString(borrowReg)); - save->setComment("start truncation sequence"); - - pushf = addNewAssembly(save, "pushf"); - - if (p_annotation.isSigned()) - sprintf(buf, "mov %s, 0x%16llx", Register::toString(borrowReg).c_str(), mask2); - else - sprintf(buf, "mov %s, 0x%16llx", Register::toString(borrowReg).c_str(), mask); - - instr = addNewAssembly(pushf, buf); - - sprintf(buf, "test %s, %s", Register::toString(p_annotation.getRegister()).c_str(), Register::toString(borrowReg).c_str()); - -*/ - -/* - Instruction_t* originalInstrumentInstr = carefullyInsertBefore(p_instruction, save); - test = addNewAssembly(instr, buf); - */ -/*--------------*/ -// Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, std::string("push ") + Register::toString(borrowReg), NULL); -// Instruction_t* lea = addNewAssembly("lea rsp, [rsp-128]"); // red zone - Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, "lea rsp, [rsp-128]" , NULL); - p_instruction->setComment("start truncation sequence"); - instr = addNewAssembly(p_instruction, std::string("push ") + Register::toString(borrowReg)); - instr = addNewAssembly(instr, "pushf"); - if (p_annotation.isSigned()) - sprintf(buf, "mov %s, 0x%16llx", Register::toString(borrowReg).c_str(), mask2); - else - sprintf(buf, "mov %s, 0x%16llx", Register::toString(borrowReg).c_str(), mask); - instr = addNewAssembly(instr, buf); - sprintf(buf, "test %s, %s", Register::toString(p_annotation.getRegister()).c_str(), Register::toString(borrowReg).c_str()); - test = addNewAssembly(instr, buf); - // <save reg> - // <save flags> - // mov <reg>, 0xFFFFFFFFFFFFFF00 ; // need to grab register - // test eax, <reg> ; (for 8 bit) -/*--------------*/ - -// save->setFallthrough(pushf); - - restore->setFallthrough(restoreReg); - instr = addNewAssembly(restoreReg, "lea rsp, [rsp+128]"); - instr->setFallthrough(originalInstrumentInstr); - - if (p_annotation.isUnsigned()) - { - logMessage(__func__, "unsigned annotation"); - Instruction_t *nop = addNewAssembly("nop"); - - instr = addNewAssembly(test, "jz 0x22"); // bogus jump target for now - instr->setTarget(restore); - instr->setFallthrough(nop); - - Instruction_t *callback; - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - string saturationInstruction = "mov " + p_annotation.getTarget2() + ", " + saturationValue; - Instruction_t *saturation = addNewAssembly(saturationInstruction); - saturation->setComment("trunc/unsigned/saturate"); - - callback = addCallbackHandlerSequence(p_instruction, saturation, detector, p_policy); - nop->setFallthrough(callback); - saturation->setFallthrough(restore); - } - else - { - callback = addCallbackHandlerSequence(p_instruction, restore, detector, p_policy); - nop->setFallthrough(callback); - } - } - else - { - // Signed and unknown signed cases are almost identical: - // 80484ed 3 INSTR CHECK TRUNCATION SIGNED 32 EAX 8 AL ZZ mov [ebp+var_4], al - // 80484ed 3 INSTR CHECK TRUNCATION UNKNOWNSIGN 32 EAX 8 AL ZZ mov [ebp+var_4], al - // example: for signed truncation - 8 bit on AL - // it's ok if 25 upper bits are all 1's or all 0's - // example: for unknownsign truncation - 8 bit on AL - // it's ok if 25 upper bits are all 1's or 24 upper bits all 0's - // - // <save reg> - // <save flags> - // mov <reg>, 0xFFFFFFFFFFFFFF80 - // test eax, <reg> ; (for 8 bit) 0xFFFFFFFFFFFFFF00 for UNKNOWN - // jz <continue> ; upper 57 bits are 0's - // - // cmp eax, 0xFFFFFFFFFFFFFF80 ;(for 8 bit) - // jae continue ; upper 57 bits are 1's - // (invoke truncation handler) - // nop ; truncation handler callback here - // SAT: saturating-arithmetic ; optional - // - // continue: <restore flags> - // <restore reg> - // mov [ebp+var_4], al ; <originalInstruction> - // - logMessage(__func__, "signed/unknown annotation"); - Instruction_t *nop = addNewAssembly("nop"); - - instr = addNewAssembly(test, "jz 0x22"); // bogus jump target for now - instr->setTarget(restore); - - std::ostringstream s; - s << "mov " << Register::toString(borrowReg) << ", 0x" << hex << mask2 << dec; - instr = addNewAssembly(instr, s.str()); - - std::ostringstream s2; - s2 << "cmp " << Register::toString(p_annotation.getRegister()) << "," << Register::toString(borrowReg); - instr = addNewAssembly(instr, s2.str()); - - instr = addNewAssembly(instr, "jae 0x22"); - instr->setTarget(restore); - instr->setFallthrough(nop); - - Instruction_t *callback; - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - string saturationInstruction = "mov " + p_annotation.getTarget2() + ", " + saturationValue; - Instruction_t *saturation = addNewAssembly(saturationInstruction); - if (p_annotation.isSigned()) - saturation->setComment("trunc/signed/saturate"); - else - saturation->setComment("trunc/unknown/saturate"); - - callback = addCallbackHandlerSequence(p_instruction, saturation, detector, p_policy); - nop->setFallthrough(callback); - saturation->setFallthrough(restore); - } - else - { - callback = addCallbackHandlerSequence(p_instruction, restore, detector, p_policy); - nop->setFallthrough(callback); - } - } - - return true; -} - -// 8048576 5 INSTR CHECK SIGNEDNESS SIGNED 16 AX ZZ mov [esp+28h], ax -// <save flags> -// TEST ax, ax -// jns L1 -// invoke callback handler -// (optional) mov ax, MAX_16 ; saturating arithmetic (Max for bit width/sign/unsigned) -// -// L1: <restore flags> -// mov [esp+28h], ax -// -bool IntegerTransform64::addSignednessCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy) -{ - if (p_annotation.getRegister() == rn_UNKNOWN) - return false; - - string detector = p_annotation.isSigned() ? SIGNEDNESS64_DETECTOR_SIGNED : SIGNEDNESS64_DETECTOR_UNSIGNED; - Instruction_t *origFallthrough = p_instruction->getFallthrough(); - - Instruction_t* originalInstrumentInstr = IRDBUtility::insertAssemblyBefore(getFileIR(), p_instruction, std::string("lea rsp, [rsp-128]"), NULL); - Instruction_t *save = addNewAssembly(p_instruction, "pushf"); - // TEST <reg>, <reg> - std::ostringstream s; - s << "test " << Register::toString(p_annotation.getRegister()) << "," << Register::toString(p_annotation.getRegister()); - Instruction_t *test = addNewAssembly(save, s.str()); - originalInstrumentInstr->setFallthrough(origFallthrough); - - Instruction_t *jns = addNewAssembly(test, "jns 0x22"); - Instruction_t *nop = addNewAssembly(jns, "nop"); - Instruction_t *restore = addNewAssembly("popf"); - Instruction_t *learestore = addNewAssembly(restore, "lea rsp, [rsp+128]"); - learestore->setFallthrough(originalInstrumentInstr); - - jns->setTarget(restore); - - Instruction_t *callback = NULL; - - if (p_policy == POLICY_CONTINUE_SATURATING_ARITHMETIC) - { - // what value should we saturate with for 64 and 32 bits? - Instruction_t *saturation = addNewMaxSaturation(nop, p_annotation.getRegister(), p_annotation); - - if (p_annotation.isSigned()) - saturation->setComment("signedness/signed/saturate"); - else - saturation->setComment("signedness/unsigned/saturate"); - - callback = addCallbackHandlerSequence(p_instruction, saturation, detector, p_policy); - nop->setFallthrough(callback); - saturation->setFallthrough(restore); - } - else - { - callback = addCallbackHandlerSequence(p_instruction, restore, detector, p_policy); - nop->setFallthrough(callback); - } - - return true; -} diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform64.hpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform64.hpp deleted file mode 100644 index 655042e99b4800d10d3e3183b60699ea582fdd6a..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/integertransform64.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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_INTEGERTRANSFORM64_H_ -#define _LIBTRANSFORM_INTEGERTRANSFORM64_H_ - -#include "integertransform.hpp" - -namespace libTransform -{ - -using namespace std; -using namespace libIRDB; - -class IntegerTransform64 : public IntegerTransform -{ - public: - IntegerTransform64(VariantID_t *, FileIR_t*, MEDS_Annotations_t *p_annotations, set<std::string> *p_filteredFunctions, set<VirtualOffset> *p_warnings); - - virtual int execute(); - - protected: - virtual Instruction_t* addCallbackHandlerSequence(Instruction_t *p_orig, Instruction_t *p_fallthrough, std::string p_detector, int p_policy); - void handleOverflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void handleUnderflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void handleTruncation(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void handleSignedness(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - - bool addOverflowUnderflowCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - - void saturateSignedMultiplyOverflow(Instruction_t *p_orig, Instruction_t *p_instruction, Instruction_t* p_fallthrough); - bool addOverflowCheckNoFlag(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - void addOverflowCheckNoFlag_RegPlusReg(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const RegisterName& p_reg2, const RegisterName& p_reg3, int p_policy); - void addOverflowCheckNoFlag_RegTimesReg(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const RegisterName& p_reg2, const RegisterName& p_reg3, int p_policy); - void addOverflowCheckNoFlag_RegPlusConstant(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const int p_constant, const RegisterName& p_reg3, int p_policy); - void addOverflowCheckNoFlag_RegTimesConstant(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, const RegisterName& p_reg1, const int p_constant, const RegisterName& p_reg3, int p_policy); - bool addTruncationCheck32(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - bool addTruncationCheck64(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - bool addSignednessCheck(Instruction_t *p_instruction, const MEDS_InstructionCheckAnnotation& p_annotation, int p_policy); - - string buildSaturationAssembly(Instruction_t *p_instruction, string p_pattern, string p_value); -}; - - -} // end namespace - -#define OVERFLOW64_DETECTOR "overflow_detector_64" -#define UNDERFLOW64_DETECTOR "underflow_detector_64" - -#define TRUNCATION64_DETECTOR_UNSIGNED_64_32 "truncation_detector_64_32" -#define TRUNCATION64_DETECTOR_SIGNED_64_32 "truncation_detector_64_32" -#define TRUNCATION64_DETECTOR_UNKNOWN_64_32 "truncation_detector_64_32" - -#define TRUNCATION64_DETECTOR_UNSIGNED_64_16 "truncation_detector_64_16" -#define TRUNCATION64_DETECTOR_SIGNED_64_16 "truncation_detector_64_16" -#define TRUNCATION64_DETECTOR_UNKNOWN_64_16 "truncation_detector_64_16" - -#define TRUNCATION64_DETECTOR_UNSIGNED_64_8 "truncation_detector_64_8" -#define TRUNCATION64_DETECTOR_SIGNED_64_8 "truncation_detector_64_8" -#define TRUNCATION64_DETECTOR_UNKNOWN_64_8 "truncation_detector_64_8" - -#define TRUNCATION64_DETECTOR_UNSIGNED_32_16 "truncation_detector_32_16" -#define TRUNCATION64_DETECTOR_SIGNED_32_16 "truncation_detector_32_16" -#define TRUNCATION64_DETECTOR_UNKNOWN_32_16 "truncation_detector_32_16" - -#define TRUNCATION64_DETECTOR_UNSIGNED_32_8 "truncation_detector_32_8" -#define TRUNCATION64_DETECTOR_SIGNED_32_8 "truncation_detector_32_8" -#define TRUNCATION64_DETECTOR_UNKNOWN_32_8 "truncation_detector_32_8" - -#define TRUNCATION64_FORCE_EXIT "truncation_force_exit" - -#define SIGNEDNESS64_DETECTOR_SIGNED "signedness_detector_signed" -#define SIGNEDNESS64_DETECTOR_UNSIGNED "signedness_detector_unsigned" - -#endif diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/leapattern.cpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/leapattern.cpp deleted file mode 100644 index d8a16c304346a126d88473b627dd2e001bc43248..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/leapattern.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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 <iostream> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <stdio.h> -#include <sstream> - -#include "leapattern.hpp" - -using namespace std; -using namespace libTransform; - -// -// Supported patterns: -// reg+reg -// reg+k -// reg*reg -// reg*k -// -// Not (yet) supported: -// reg+reg+k -// -LEAPattern::LEAPattern(const MEDS_InstructionCheckAnnotation& p_annotation) -{ - m_isValid = false; - m_isRegPlusReg = false; - m_isRegPlusConstant = false; - m_isRegTimesConstant = false; - m_isRegTimesReg = false; - m_reg1 = rn_UNKNOWN; - m_reg2 = rn_UNKNOWN; - m_constant = 0; - - if(regcomp(&m_regex_reg_plus_reg ,"[eax|ebx|ecx|edx|esi|edi|ebp|rax|rbx|rcx|rdx|rbp|rsi|rdi|r8|r9|r10|r11|r12|r13|r14|r15]\\+[eax|ebx|ecx|edx|esi|edi|ebp|rax|rbx|rcx|rdx|rbp|rsi|rdi|r8|r9|r10|r11|r12|r13|r14|r15]", REG_EXTENDED | REG_ICASE) !=0) - cerr << "Error: regular expression for reg+reg failed" << endl; - - if(regcomp(&m_regex_reg_times_reg ,"[eax|ebx|ecx|edx|esi|edi|ebp|rax|rbx|rcx|rdx|rbp|rsi|rdi|r8|r9|r10|r11|r12|r13|r14|r15]\\*[eax|ebx|ecx|edx|esi|edi|ebp|rax|rbx|rcx|rdx|rbp|rsi|rdi|r8|r9|r10|r11|r12|r13|r14|r15]", REG_EXTENDED | REG_ICASE) !=0) - cerr << "Error: regular expression for reg*reg failed" << endl; - - if(regcomp(&m_regex_reg_plus_constant ,"[eax|ebx|ecx|edx|esi|edi|ebp|rax|rbx|rcx|rdx|rbp|rsi|rdi|r8|r9|r10|r11|r12|r13|r14|r15]\\+[0-9+]", REG_EXTENDED | REG_ICASE) !=0) - cerr << "Error: regular expression for reg+constant failed" << endl; - - if(regcomp(&m_regex_reg_plus_negconstant ,"[eax|ebx|ecx|edx|esi|edi|ebp|rax|rbx|rcx|rdx|rbp|rsi|rdi|r8|r9|r10|r11|r12|r13|r14|r15]\\+\\-[0-9+]", REG_EXTENDED | REG_ICASE) !=0) - cerr << "Error: regular expression for reg+constant failed" << endl; - - if(regcomp(&m_regex_reg_times_constant ,"[eax|ebx|ecx|edx|esi|edi|ebp|rax|rbx|rcx|rdx|rbp|rsi|rdi|r8|r9|r10|r11|r12|r13|r14|r15]\\*[0-9+]", REG_EXTENDED | REG_ICASE) !=0) - cerr << "Error: regular expression for reg+constant failed" << endl; - - const int max = 5; - regmatch_t pmatch[max]; - int countMatch = 0; - - if(regexec(&m_regex_reg_plus_reg, p_annotation.getTarget().c_str(), max, pmatch, 0)==0) - { - // pattern is of the form reg+reg, e.g.: EDX+EAX - // r8+rbp - // r8+r9 - // rax+r9 - string r1, r2; - extractOperands(p_annotation.getTarget(), r1, r2); - cerr << "leapattern: extract ops: " << r1 << " " << r2 << endl; - m_reg1 = Register::getRegister(r1); - m_reg2 = Register::getRegister(r2); - - if (m_reg1 != rn_UNKNOWN && m_reg2 != rn_UNKNOWN) - { - countMatch++; - m_isRegPlusReg = true; - m_isValid = true; - cerr << "leapattern: reg+reg:" << Register::toString(m_reg1) << " " << Register::toString(m_reg2) << endl; - } - } - - if(regexec(&m_regex_reg_times_reg, p_annotation.getTarget().c_str(), max, pmatch, 0)==0) - { - // pattern is of the form reg*reg, e.g.: EDX*EAX - // nb: is this even a valid pattern -- not used - string r1, r2; - extractOperands(p_annotation.getTarget(), r1, r2); - m_reg1 = Register::getRegister(r1); - m_reg2 = Register::getRegister(r2); - cerr << "leapattern: extract ops: " << r1 << " " << r2 << endl; - - if (m_reg1 != rn_UNKNOWN && m_reg2 != rn_UNKNOWN) - { - countMatch++; - m_isRegTimesReg = true; - m_isValid = true; - cerr << "leapattern: reg*reg:" << Register::toString(m_reg1) << " " << Register::toString(m_reg2) << endl; - } - } - -// integertransform: reg+constant: register: EDX constant: 80 target register: EAX annotation: 805525b 6 INSTR CHECK OVERFLOW NOFLAGUNSIGNED 32 EDX+128 ZZ lea eax, [edx+80h] - - if(regexec(&m_regex_reg_plus_constant, p_annotation.getTarget().c_str(), max, pmatch, 0)==0 || - regexec(&m_regex_reg_plus_negconstant, p_annotation.getTarget().c_str(), max, pmatch, 0)==0) - { - // pattern is of the form: reg+constant, e.g.: EDX+16 - // pattern is of the form: reg+-constant, e.g.: EAX+-16 - // note that constant value of annotation is in decimal (not hex) - string r1, k; - extractOperands(p_annotation.getTarget(), r1, k); - m_reg1 = Register::getRegister(r1); - cerr << "leapattern: extract ops: " << r1 << " " << k << endl; - - stringstream constantSS(k); - if (constantSS >> m_constant) - { - m_isRegPlusConstant = true; - m_isValid = true; - countMatch++; - cerr << "leapattern: reg+-constant: stream: " << Register::toString(m_reg1) << " constant: " << dec << m_constant << " annotation: " << p_annotation.toString() << endl; - } - } - - if(regexec(&m_regex_reg_times_constant, p_annotation.getTarget().c_str(), max, pmatch, 0)==0) - { - // pattern is of the form: reg*constant, e.g.: EDX*4 - // note that constant value of annotation is in decimal (not hex) - string r1, k; - extractOperands(p_annotation.getTarget(), r1, k); - cerr << "leapattern: extract ops: " << r1 << " " << k << endl; - m_reg1 = Register::getRegister(r1); - stringstream constantSS(k); - if (constantSS >> m_constant) - { - countMatch++; - cerr << "leapattern: reg*constant: stream: " << p_annotation.getTarget().substr(4) << " constant: " << dec << m_constant << " annotation: " << p_annotation.toString() << endl; - m_isValid = true; - m_isRegTimesConstant = true; - } - } - - if (countMatch == 0 || countMatch > 1) - { - cerr << "leapattern: matching patterns = " << countMatch << " : " << p_annotation.toString() << endl; - m_isValid = false; - } -} - -bool LEAPattern::isValid() const -{ - return m_isValid; -} - -bool LEAPattern::isRegisterPlusRegister() const -{ - return m_isRegPlusReg; -} - -bool LEAPattern::isRegisterTimesRegister() const -{ - return m_isRegTimesReg; -} - -bool LEAPattern::isRegisterPlusConstant() const -{ - return m_isRegPlusConstant; -} - -bool LEAPattern::isRegisterTimesConstant() const -{ - return m_isRegTimesConstant; -} - -RegisterName LEAPattern::getRegister1() const -{ - return m_reg1; -} - -RegisterName LEAPattern::getRegister2() const -{ - return m_reg2; -} - -int LEAPattern::getConstant() const -{ - return m_constant; -} - -// assume is of the form: -// <operand><sign>[minus]<operand> -// where <operand> is a register or constant, -// <sign> is * or + -void LEAPattern::extractOperands(const string target, string& op1, string& op2) -{ - int multiplyPos = target.find('*'); - int plusPos = target.find('+'); - int minusPos = target.find('-'); - - int signPos = -1; - if (multiplyPos >= 0) signPos = multiplyPos; - if (plusPos >= 0) signPos = plusPos; - - op1 = op2 = ""; - - if (signPos < 0) return; - - int op1len = signPos; - int op2len; - - if (minusPos >= 0) - op2len = target.size() - minusPos - 1; - else - op2len = target.size() - signPos - 1; - - op1 = target.substr(0, op1len); - - if (minusPos >= 0) - op2 = target.substr(signPos+2, op2len); // e.g., rax+-5 - else - op2 = target.substr(signPos+1, op2len); -} diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/leapattern.hpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/leapattern.hpp deleted file mode 100644 index 7b25314ad9efba376deda26cb47a760d065b1ae8..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/leapattern.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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 _LEA_PATTERN_H_ -#define _LEA_PATTERN_H_ - -#include <regex.h> - -#include "MEDS_InstructionCheckAnnotation.hpp" -#include "MEDS_Register.hpp" - -using namespace MEDS_Annotation; - -namespace libTransform { - -class LEAPattern { - public: - LEAPattern(const MEDS_InstructionCheckAnnotation& p_annotation); - bool isValid() const; - - bool isRegisterPlusRegister() const; - bool isRegisterPlusConstant() const; - bool isRegisterTimesConstant() const; - bool isRegisterTimesRegister() const; // not used - - RegisterName getRegister1() const; - RegisterName getRegister2() const; - int getConstant() const; - - private: - void extractOperands(const string target, string& op1, string& op2); - - private: - bool m_isValid; - bool m_isRegPlusReg; - bool m_isRegPlusConstant; - bool m_isRegTimesReg; - bool m_isRegTimesConstant; - RegisterName m_reg1; - RegisterName m_reg2; - int m_constant; - - regex_t m_regex_reg_plus_reg; - regex_t m_regex_reg_times_reg; - regex_t m_regex_reg_plus_constant; - regex_t m_regex_reg_plus_negconstant; - regex_t m_regex_reg_times_constant; -}; - -} - -#endif diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/pointercheck64.cpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/pointercheck64.cpp deleted file mode 100644 index 3c4ba7d64f82de8ecb949cf94719ef4d69e51ac4..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/pointercheck64.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2015 - Zephyr Software LLC - * - * 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 LLC - * URL : http://www.zephyr-software.com/ - * - */ - -#include <assert.h> -#include <sstream> -#include "pointercheck64.hpp" - -using namespace libTransform; - - -PointerCheck64::PointerCheck64(VariantID_t *p_variantID, FileIR_t *p_fileIR, MEDS_Annotations_t *p_annotations, set<std::string> *p_filteredFunctions, set<VirtualOffset> *p_benignFalsePositives) : IntegerTransform64(p_variantID, p_fileIR, p_annotations, p_filteredFunctions, p_benignFalsePositives) -{ -} - -Instruction_t* PointerCheck64::addCallbackHandlerSequence(Instruction_t *p_orig, Instruction_t *p_fallthrough, std::string p_detector, int p_policy) -{ - if (p_policy == POLICY_EXIT) - { - // exit program - Instruction_t* exit_sequence = addNewAssembly("mov rax, 60"); - Instruction_t* i = addNewAssembly(exit_sequence, "mov rdi, 25"); - i = addNewAssembly(i, "syscall"); - i->setFallthrough(p_fallthrough); - return exit_sequence; - } - else - return IntegerTransform64::addCallbackHandlerSequence(p_orig, p_fallthrough, p_detector, p_policy); -} - -int PointerCheck64::execute() -{ - for( - set<Function_t*>::const_iterator itf=getFileIR()->GetFunctions().begin(); - itf!=getFileIR()->GetFunctions().end(); - ++itf - ) - { - Function_t* func=*itf; - - if (getFilteredFunctions()->find(func->GetName()) != getFilteredFunctions()->end()) - { - logMessage(__func__, "filter out: " + func->GetName()); - continue; - } - - if (isBlacklisted(func)) - { - logMessage(__func__, "blacklisted: " + func->GetName()); - m_numBlacklisted++; - continue; - } - - logMessage(__func__, "processing fn: " + func->GetName()); - - for( - set<Instruction_t*>::const_iterator it=func->GetInstructions().begin(); - it!=func->GetInstructions().end(); - ++it) - { - Instruction_t* insn=*it; - - if (insn && insn->getAddress()) - { - int policy = POLICY_EXIT; - - virtual_offset_t irdb_vo = insn->getAddress()->GetVirtualOffset(); - if (irdb_vo == 0) continue; - - VirtualOffset vo(irdb_vo); - - if (getAnnotations()->count(vo) == 0) - continue; - - std::pair<MEDS_Annotations_t::iterator,MEDS_Annotations_t::iterator> ret; - ret = getAnnotations()->equal_range(vo); - MEDS_InstructionCheckAnnotation annotation; - MEDS_InstructionCheckAnnotation* p_annotation; - for ( MEDS_Annotations_t::iterator it = ret.first; it != ret.second; ++it) - { - MEDS_AnnotationBase *base_type=(it->second); - p_annotation = dynamic_cast<MEDS_InstructionCheckAnnotation*>(base_type); - if(p_annotation == NULL) - continue; - annotation = *p_annotation; - if (!annotation.isValid()) - continue; - else - break; // let's just handle one annotation for now and see how it goes - } - - m_numAnnotations++; - - if (!annotation.isIdiom() || annotation.getIdiomNumber() != IDIOM_POINTER_NUMERIC_WEAKNESS) - { - logMessage(__func__, "skip IDIOM"); - m_numIdioms++; - continue; - } - - if (!insn->getFallthrough()) - { - logMessage(__func__, "Warning: no fall through for instruction -- skipping"); - continue; - } - - if (annotation.isIdiom() && !isInstrumentIdioms()) - { - logMessage(__func__, "skip IDIOM"); - m_numIdioms++; - continue; - } - - // this idiom deals with pointers ==> unsigned - if (!annotation.isUnsigned()) - { - logMessage(__func__, "Warning: only instrument UNSIGNED for this idiom -- skipping"); - continue; - } - - logMessage(__func__, annotation, "-- instruction: " + insn->getDisassembly()); - - if (annotation.isOverflow()) - { - m_numTotalOverflows++; - handleOverflowCheck(insn, annotation, policy); - } - - if (annotation.isUnderflow()) - { - m_numTotalUnderflows++; - handleUnderflowCheck(insn, annotation, policy); - } - } - } // end iterate over all instructions in a function - } // end iterate over all functions - - return 0; -} - diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/pointercheck64.hpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/pointercheck64.hpp deleted file mode 100644 index b7593b966a241e2b210dcc7d545de930390a7cc2..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/pointercheck64.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2015 - Zephyr Software LLC - * - * 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 LLC - * URL : http://www.zephyr-software.com/ - */ - -#ifndef _LIBTRANSFORM_POINTERCHECK64_H_ -#define _LIBTRANSFORM_POINTERCHECK64_H_ - -#include "integertransform64.hpp" - -namespace libTransform -{ - -using namespace std; -using namespace libIRDB; - -class PointerCheck64 : public IntegerTransform64 -{ - public: - PointerCheck64(VariantID_t *, FileIR_t*, MEDS_Annotations_t *p_annotations, set<std::string> *p_filteredFunctions, set<VirtualOffset> *p_warnings); - - virtual int execute(); - virtual Instruction_t* addCallbackHandlerSequence(Instruction_t *p_orig, Instruction_t *p_fallthrough, std::string p_detector, int p_policy); - -}; - -} // end namespace - -#endif diff --git a/irdb-libs/libIRDB-transform/include-unused-delete-later/transform.hpp b/irdb-libs/libIRDB-transform/include-unused-delete-later/transform.hpp deleted file mode 100644 index 325fa40d6e1ae85a3b92efa8b9ad6813543a453c..0000000000000000000000000000000000000000 --- a/irdb-libs/libIRDB-transform/include-unused-delete-later/transform.hpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2013, 2014 - 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_TRANSFORM_H -#define _LIBTRANSFORM_TRANSFORM_H - -#include <string> -#include <set> -#include <map> - -#include <irdb-core> - -#include "MEDS_InstructionCheckAnnotation.hpp" -#include "VirtualOffset.hpp" - -#define MAX_ASSEMBLY_SIZE 2048 - -namespace libIRDB -{ - class FileIR_t; -} -namespace libTransform -{ -using namespace std; -using namespace IRDB_SDK; -using namespace MEDS_Annotation; - - -class Transform -{ - - public: - Transform(VariantID_t *, FileIR_t *, set<std::string> *p_filteredFunctions); - - protected: - void setAssembly(Instruction_t *p_instr, string p_asm); - Instruction_t* addNewAssembly(string p_asm); - Instruction_t* addNewAssembly(Instruction_t *p_instr, string p_asm); - Instruction_t* registerCallbackHandler64(string p_callbackHandler, int p_numArgs); - void addCallbackHandler64(Instruction_t *p_instr, string p_callbackHandler, int p_numArgs); - void addInstruction(Instruction_t *p_instr, string p_dataBits, Instruction_t *p_fallThrough, Instruction_t *p_target); - Instruction_t* carefullyInsertBefore(Instruction_t* &p_target, Instruction_t* &p_new); - Instruction_t* insertAssemblyBefore(Instruction_t* before, const string &the_asm, Instruction_t* target=nullptr); - Instruction_t* insertAssemblyAfter(Instruction_t* after, const string &the_asm, Instruction_t* target=nullptr); - - void addPushRegister(Instruction_t *p_instr, RegisterName, Instruction_t *p_fallThrough); - void addPopRegister(Instruction_t *p_instr, RegisterName, Instruction_t *p_fallThrough); - void addPusha(Instruction_t *p_instr, Instruction_t *p_fallThrough); - void addPushf(Instruction_t *p_instr, Instruction_t *p_fallThrough); - void addPopa(Instruction_t *p_instr, Instruction_t *p_fallThrough); - void addPopf(Instruction_t *p_instr, Instruction_t *p_fallThrough); - void addNop(Instruction_t *p_instr, Instruction_t *p_fallThrough); - - void addCallbackHandler(string p_detector, Instruction_t *p_instrumented, Instruction_t *p_instr, Instruction_t *p_fallThrough, int p_policy, AddressID_t *addressOriginal = NULL); - - void addTestRegister(Instruction_t *p_instr, RegisterName, Instruction_t *p_fallThrough); - void addTestRegisterMask(Instruction_t *p_instr, RegisterName, unsigned p_mask, Instruction_t *p_fallThrough); - void addCmpRegisterMask(Instruction_t *p_instr, RegisterName, unsigned p_mask, Instruction_t *p_fallThrough); - - void addJns(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target); - void addJz(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target); - void addJo(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target); - void addJno(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target); - void addJc(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target); - void addJnc(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target); - void addJnz(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target); - void addJae(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target); - void addNot(Instruction_t *p_instr, RegisterName, Instruction_t *p_fallThrough); - void addHlt(Instruction_t *p_instr, Instruction_t *p_fallThrough); - - void addAddRegisters(Instruction_t *p_instr, RegisterName p_regTgt, RegisterName p_regSrc, Instruction_t *p_fallThrough); - void addAddRegisterConstant(Instruction_t *p_instr, RegisterName p_regTgt, int p_constantValue, Instruction_t *p_fallThrough); - void addMulRegisterConstant(Instruction_t *p_instr, RegisterName p_regTgt, int p_constantValue, Instruction_t *p_fallThrough); - void addMovRegisters(Instruction_t *p_instr, RegisterName p_regTgt, RegisterName p_regSrc, Instruction_t *p_fallThrough); - - Instruction_t* allocateNewInstruction(DatabaseID_t p_fileID=BaseObj_t::NOT_IN_DATABASE, Function_t* p_func=NULL); - - VirtualOffset_t getAvailableAddress(); - - VariantID_t* getVariantID() { return m_variantID; } - FileIR_t* getFileIR(); // { return dynamic_cast<FileIR_t*>(m_fileIR); } - set<std::string>* getFilteredFunctions() { return m_filteredFunctions; } - - Instruction_t* addNewMaxSaturation(Instruction_t *p_prev, RegisterName p_reg, const MEDS_InstructionCheckAnnotation p_annotation); - void addMinSaturation(Instruction_t *p_instruction, RegisterName p_reg, const MEDS_InstructionCheckAnnotation& p_annotation, Instruction_t *p_fallthrough); - void addMaxSaturation(Instruction_t *p_instruction, RegisterName p_reg, const MEDS_InstructionCheckAnnotation& p_annotation, Instruction_t *p_fallthrough); - void addMovRegisterUnsignedConstant(Instruction_t *p_instr, RegisterName p_regTgt, unsigned long p_constant, Instruction_t *p_fallThrough); - void addMovRegisterSignedConstant(Instruction_t *p_instr, RegisterName p_regTgt, long int p_constant, Instruction_t *p_fallThrough); - void addAndRegister32Mask(Instruction_t *p_instr, RegisterName p_regTgt, unsigned int p_mask, Instruction_t *p_fallThrough); - - protected: - void logMessage(const std::string &p_method, const std::string &p_msg); - void logMessage(const std::string &p_method, const MEDS_InstructionCheckAnnotation&, const std::string &p_msg); - - private: - void addTestRegister8(Instruction_t *p_instr, RegisterName, Instruction_t *p_fallThrough); - void addTestRegister16(Instruction_t *p_instr, RegisterName, Instruction_t *p_fallThrough); - void addTestRegister32(Instruction_t *p_instr, RegisterName, Instruction_t *p_fallThrough); - void addTestRegisterMask32(Instruction_t *p_instr, RegisterName, unsigned p_mask, Instruction_t *p_fallThrough); - void addCmpRegisterMask32(Instruction_t *p_instr, RegisterName, unsigned p_mask, Instruction_t *p_fallThrough); - - VariantID_t *m_variantID; - libIRDB::FileIR_t *m_fileIR; - set<std::string> *m_filteredFunctions; - std::map<std::string, Instruction_t*> m_handlerMap; -}; - -// make sure these match values in detector_handlers.h in the strata library -#define POLICY_DEFAULT 0 -#define POLICY_CONTINUE 1 -#define POLICY_EXIT 2 -#define POLICY_CONTINUE_SATURATING_ARITHMETIC 3 - -#define DEBUG_CALLBACK_HANDLER "debug_handler" - -// utility function -void convertToLowercase(string&); - -} - -#endif - diff --git a/irdb-libs/libIRDB-transform/src/transform.cpp b/irdb-libs/libIRDB-transform/src/transform.cpp index fb70acbcdd23e41ad6abf9b94c90eb4997d289fa..7b4217b500d16e741e9206183b31e18a147374c2 100644 --- a/irdb-libs/libIRDB-transform/src/transform.cpp +++ b/irdb-libs/libIRDB-transform/src/transform.cpp @@ -22,1569 +22,62 @@ using namespace IRDB_SDK; -Transform::Transform(FileIR_t *p_fileIR) +Transform_t::Transform_t(FileIR_t *p_fileIR) : m_fileIR (p_fileIR) { assert(m_fileIR); } -FileIR_t* Transform::getFileIR() +FileIR_t* Transform_t::getFileIR() { return m_fileIR; } -const FileIR_t* Transform::getFileIR() const +const FileIR_t* Transform_t::getFileIR() const { return m_fileIR; } -Instruction_t* Transform::insertAssemblyBefore(Instruction_t* before, const string &the_asm, Instruction_t* target) +Instruction_t* Transform_t::insertAssemblyBefore(Instruction_t* before, const string &the_asm, Instruction_t* target) { return IRDB_SDK::insertAssemblyBefore(getFileIR(), before, the_asm, target); } -Instruction_t* Transform::insertAssemblyAfter(Instruction_t* before, const string &the_asm, Instruction_t* target) +Instruction_t* Transform_t::insertAssemblyAfter(Instruction_t* before, const string &the_asm, Instruction_t* target) { return IRDB_SDK::insertAssemblyAfter(getFileIR(), before, the_asm, target); } -Instruction_t* Transform::insertDataBitsBefore(Instruction_t* before, const string &the_asm, Instruction_t* target) +Instruction_t* Transform_t::insertDataBitsBefore(Instruction_t* before, const string &the_asm, Instruction_t* target) { return IRDB_SDK::insertDataBitsBefore(getFileIR(), before, the_asm, target); } -Instruction_t* Transform::insertDataBitsAfter(Instruction_t* before, const string &the_asm, Instruction_t* target) +Instruction_t* Transform_t::insertDataBitsAfter(Instruction_t* before, const string &the_asm, Instruction_t* target) { return IRDB_SDK::insertDataBitsAfter(getFileIR(), before, the_asm, target); } -Instruction_t* Transform::addNewDataBits(const string& p_bits) +Instruction_t* Transform_t::addNewDataBits(const string& p_bits) { return IRDB_SDK::addNewDataBits(getFileIR(), p_bits); } -Instruction_t* Transform::addNewAssembly(const string& p_bits) +Instruction_t* Transform_t::addNewAssembly(const string& p_bits) { return IRDB_SDK::addNewAssembly(getFileIR(), p_bits); } -void Transform::setInstructionAssembly(Instruction_t* instr, const string& p_asm, Instruction_t *p_new_fallthrough, Instruction_t* p_new_target) +void Transform_t::setInstructionAssembly(Instruction_t* instr, const string& p_asm, Instruction_t *p_new_fallthrough, Instruction_t* p_new_target) { return IRDB_SDK::setInstructionAssembly(getFileIR(), instr, p_asm, p_new_fallthrough, p_new_target); } -void Transform::setInstructionAssembly(Instruction_t* instr, const string& p_asm) +void Transform_t::setInstructionAssembly(Instruction_t* instr, const string& p_asm) { return IRDB_SDK::setInstructionAssembly(getFileIR(), instr, p_asm); } - -#if 0 -void Transform::addInstruction(Instruction_t *p_instr, string p_dataBits, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - if (p_instr == NULL) return; - - p_instr->setDataBits(p_dataBits); - p_instr->setComment(p_instr->getDisassembly()); - p_instr->setFallthrough(p_fallThrough); - p_instr->setTarget(p_target); - m_fileIR->GetAddresses().insert(p_instr->getAddress()); - m_fileIR->GetInstructions().insert(p_instr); -} - -#define BENSWAY - -// -// Before: After: -// <p_instrumented> ["mov edx,1"] <p_newInstr> [] -// <dupInstr> ["mov edx,1"] <-- returns -// -Instruction_t* Transform::carefullyInsertBefore(Instruction_t* &p_instrumented, Instruction_t * &p_newInstr) -{ - -//For all insertBefore functions: -//The "first" instruction will have its contents replaced and a duplicate of "first" will be in the follow of first. -//This duplicate is returned since the user already has a pointer to first. -//To insert before an instruction is the same as modifying the original instruction, and inserting after it -//a copy of the original instruction - -#ifdef BENSWAY - Instruction_t* i2 = IRDBUtility::insertAssemblyBefore(m_fileIR, p_instrumented, m_fileIR->lookupAssembly(p_newInstr), p_newInstr->getTarget()); -cerr << "carefullyInsertBefore (Ben's Way): @: 0x" << std::hex << p_instrumented->getAddress() << std::dec << " old instruction: " << p_instrumented->getDisassembly() << " new instruction: " << m_fileIR->lookupAssembly(p_newInstr) << endl; - return i2; -#else - DatabaseID_t fileID = p_instrumented->getAddress()->getFileID(); - Function_t* func = p_instrumented->getFunction(); - - assert(p_instrumented && p_newInstr && p_instrumented->getAddress()); - -// why is old instrunction blank? -cerr << "(1) carefullyInsertBefore: @: 0x" << std::hex << p_instrumented->getAddress() << std::dec << " old instruction: " << p_instrumented->getDisassembly() << " new instruction: " << m_fileIR->lookupAssembly(p_newInstr) << endl; - - // duplicate old instrumented instruction - Instruction_t* dupInstr = allocateNewInstruction(fileID, func); - - dupInstr->setDataBits(p_instrumented->GetDataBits()); - dupInstr->setComment(p_instrumented->getComment()); - dupInstr->setCallback(p_instrumented->getCallback()); - dupInstr->setFallthrough(p_instrumented->getFallthrough()); - dupInstr->setTarget(p_instrumented->getTarget()); - dupInstr->setOriginalAddressID(p_instrumented->getOriginalAddressID()); - AddressID_t *saveIBTA = p_instrumented->GetIndirectBranchTargetAddress(); - dupInstr->setIndirectBranchTargetAddress(NULL); - - // - // pre: p_instrument --> "mov edx, 1" - // - // post: p_instrument no longer in map - // new --> "mov edx, 1" - // - // this function is equivalent to: - // m_fileIR->UnregisterAssembly(p_instrumented); - // m_fileIR->registerAssembly(dupInstr, newAssemblyCode); - // - m_fileIR->ChangeRegistryKey(p_instrumented, dupInstr); - - if (p_newInstr->GetDataBits().size() == 0) - m_fileIR->registerAssembly(p_instrumented, m_fileIR->lookupAssembly(p_newInstr)); - else - p_instrumented->setDataBits(p_newInstr->GetDataBits()); - - p_instrumented->setComment(p_newInstr->getComment()); - p_instrumented->setCallback(p_newInstr->getCallback()); - p_instrumented->setFallthrough(dupInstr); - - p_instrumented->setOriginalAddressID(BaseObj_t::NOT_IN_DATABASE); - p_instrumented->setIndirectBranchTargetAddress(saveIBTA); - p_instrumented->GetRelocations().clear(); - - p_newInstr = p_instrumented; - -cerr << "(2) carefullyInsertBefore: @: 0x" << std::hex << p_instrumented->getAddress() << std::dec << " old instruction: " << dupInstr->getDisassembly() << " new instruction: " << m_fileIR->lookupAssembly(p_newInstr) << endl; - return dupInstr; -#endif -} - - -void Transform::addPushf(Instruction_t *p_pushf_i, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(1); - dataBits[0] = 0x9c; - addInstruction(p_pushf_i, dataBits, p_fallThrough, NULL); -} - -void Transform::addPushRegister(Instruction_t *p_instr, RegisterName p_reg, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(1); - - if (p_reg == rn_EAX || p_reg == rn_RAX) - { - dataBits[0] = 0x50; - } - else if (p_reg == rn_EBX || p_reg == rn_RBX) - { - dataBits[0] = 0x53; - } - else if (p_reg == rn_ECX || p_reg == rn_RCX) - { - dataBits[0] = 0x51; - } - else if (p_reg == rn_EDX || p_reg == rn_RDX) - { - dataBits[0] = 0x52; - } - else if (p_reg == rn_ESI || p_reg == rn_RSI) - { - dataBits[0] = 0x56; - } - else if (p_reg == rn_EDI || p_reg == rn_RDI) - { - dataBits[0] = 0x57; - } - else if (p_reg == rn_EBP || p_reg == rn_RBP) - { - dataBits[0] = 0x55; - } - else if (p_reg == rn_ESP || p_reg == rn_RSP) - { - dataBits[0] = 0x54; - } - else - { - dataBits.resize(2); - dataBits[0] = 0x41; - if (p_reg == rn_R8) - { - dataBits[1] = 0x50; - } - else if (p_reg == rn_R9) - { - dataBits[1] = 0x51; - } - else if (p_reg == rn_R10) - { - dataBits[1] = 0x52; - } - else if (p_reg == rn_R11) - { - dataBits[1] = 0x53; - } - else if (p_reg == rn_R12) - { - dataBits[1] = 0x54; - } - else if (p_reg == rn_R13) - { - dataBits[1] = 0x55; - } - else if (p_reg == rn_R14) - { - dataBits[1] = 0x56; - } - else if (p_reg == rn_R15) - { - dataBits[1] = 0x57; - } - else - { - cerr << "Transform::addPushRegister: unhandled register: " << p_reg << endl; - assert(0); - return; - } - } - - addInstruction(p_instr, dataBits, p_fallThrough, NULL); -} - -void Transform::addPopRegister(Instruction_t *p_instr, RegisterName p_reg, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(1); - - if (p_reg == rn_EAX || p_reg == rn_RAX) - { - dataBits[0] = 0x58; - } - else if (p_reg == rn_EBX || p_reg == rn_RBX) - { - dataBits[0] = 0x5b; - } - else if (p_reg == rn_ECX || p_reg == rn_RCX) - { - dataBits[0] = 0x59; - } - else if (p_reg == rn_EDX || p_reg == rn_RDX) - { - dataBits[0] = 0x5a; - } - else if (p_reg == rn_ESI || p_reg == rn_RSI) - { - dataBits[0] = 0x5e; - } - else if (p_reg == rn_EDI || p_reg == rn_RDI) - { - dataBits[0] = 0x5f; - } - else if (p_reg == rn_EBP || p_reg == rn_RBP) - { - dataBits[0] = 0x5d; - } - else if (p_reg == rn_ESP || p_reg == rn_RSP) - { - dataBits[0] = 0x5c; - } - else - { - dataBits.resize(2); - dataBits[0] = 0x41; - if (p_reg == rn_R8) - { - dataBits[1] = 0x58; - } - else if (p_reg == rn_R9) - { - dataBits[1] = 0x59; - } - else if (p_reg == rn_R10) - { - dataBits[1] = 0x5a; - } - else if (p_reg == rn_R11) - { - dataBits[1] = 0x5b; - } - else if (p_reg == rn_R12) - { - dataBits[1] = 0x5c; - } - else if (p_reg == rn_R13) - { - dataBits[1] = 0x5d; - } - else if (p_reg == rn_R14) - { - dataBits[1] = 0x5e; - } - else if (p_reg == rn_R15) - { - dataBits[1] = 0x5f; - } - else - { - cerr << "Transform::addPopRegister: unhandled register"; - assert(0); - return; - } - } - - addInstruction(p_instr, dataBits, p_fallThrough, NULL); -} - -void Transform::addPusha(Instruction_t *p_pusha_i, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(1); - dataBits[0] = 0x60; - addInstruction(p_pusha_i, dataBits, p_fallThrough, NULL); -} - -void Transform::addPopf(Instruction_t *p_popf_i, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(1); - dataBits[0] = 0x9d; - addInstruction(p_popf_i, dataBits, p_fallThrough, NULL); -} - -void Transform::addPopa(Instruction_t *p_popa_i, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(1); - dataBits[0] = 0x61; - addInstruction(p_popa_i, dataBits, p_fallThrough, NULL); -} - -void Transform::addNop(Instruction_t *p_nop_i, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(1); - dataBits[0] = 0x90; - p_nop_i->setComment(string("NOP")); - addInstruction(p_nop_i, dataBits, p_fallThrough, NULL); -} - -Instruction_t* Transform::allocateNewInstruction(DatabaseID_t p_fileID, Function_t* p_func) -{ - Instruction_t *instr = new libIRDB::Instruction_t(); - AddressID_t *a = new libIRDB::AddressID_t(); - - a->setFileID(p_fileID); - - instr->setFunction(p_func); - instr->setAddress(a); - - m_fileIR->GetInstructions().insert(instr); - m_fileIR->GetAddresses().insert(a); - return instr; -} - -VirtualOffset_t Transform::getAvailableAddress() -{ -/* - // traverse all instructions - // grab address - - // @todo: lookup instruction size so that we don't waste any space - // for some reason the max available address is incorrect! was ist los? - - VirtualOffset_t availableAddressOffset = 0; - for( - set<Instruction_t*>::const_iterator it=p_virp->GetInstructions().begin(); - it!=p_virp->GetInstructions().end(); - ++it - ) - { - Instruction_t* insn=*it; - if (!insn) continue; - - AddressID_t* addr = insn->getAddress(); - VirtualOffset_t offset = addr->setVirtualOffset(); - - if (offset > availableAddressOffset) - { - availableAddressOffset = offset; - } - } -// availableAddressOffset + 16; -*/ - - static int counter = -16; - counter += 16; - return 0xf0000000 + counter; -} - -void Transform::addCallbackHandler(string p_detector, Instruction_t *p_instrumentedInstruction, Instruction_t *p_instruction, Instruction_t *p_fallThrough, int p_policy, AddressID_t *p_addressOriginalInstruction) -{ - - assert(getFileIR() && p_instruction && p_fallThrough); - - string dataBits; - - DatabaseID_t fileID = p_instruction->getAddress()->getFileID(); - Function_t* func = p_instruction->getFunction(); - - // create and register new instructions (and addresses) - Instruction_t* pushf_i = allocateNewInstruction(fileID, func); - Instruction_t* pusha_i = allocateNewInstruction(fileID, func); - Instruction_t* pushPolicy_i = allocateNewInstruction(fileID, func); - Instruction_t* pusharg_i = allocateNewInstruction(fileID, func); - Instruction_t* pushret_i = allocateNewInstruction(fileID, func); - Instruction_t* poparg_i = allocateNewInstruction(fileID, func); - Instruction_t* popPolicy_i = allocateNewInstruction(fileID, func); - Instruction_t* popa_i = allocateNewInstruction(fileID, func); - Instruction_t* popf_i = allocateNewInstruction(fileID, func); - - // pin the poparg instruction - VirtualOffset_t postDetectorReturn = getAvailableAddress(); - poparg_i->getAddress()->setVirtualOffset(postDetectorReturn); - - // link callback handler sequence to instrumented instruction - p_instruction->setFallthrough(pushf_i); - p_instruction->setComment(p_instruction->getComment() + " -- start of callback handler sequence"); - - // pushf - addPushf(pushf_i, pusha_i); - - // pusha - addPusha(pusha_i, pushPolicy_i); - - // push detector exit policy - // 0 - default - // 1 - continue - // 2 - exit - // 3 - saturating arithmetic - dataBits.resize(5); - dataBits[0] = 0x68; - int *tmpi = (int *) &dataBits[1]; - *tmpi = p_policy; - pushPolicy_i->setDataBits(dataBits); - pushPolicy_i->setComment(pushPolicy_i->getDisassembly() + string(" - policy spec")); - pushPolicy_i->setFallthrough(pusharg_i); - - // push (PC of instrumented instruction) - dataBits.resize(5); - dataBits[0] = 0x68; - VirtualOffset_t *tmp = (VirtualOffset_t *) &dataBits[1]; - if (p_addressOriginalInstruction) - *tmp = p_addressOriginalInstruction->getVirtualOffset(); - else - *tmp = p_instrumentedInstruction->getAddress()->getVirtualOffset(); - pusharg_i->setDataBits(dataBits); - pusharg_i->setComment(pusharg_i->getDisassembly()); - pusharg_i->setFallthrough(pushret_i); - - // pushret - dataBits.resize(5); - dataBits[0] = 0x68; - tmp = (VirtualOffset_t *) &dataBits[1]; - *tmp = postDetectorReturn; - pushret_i->setDataBits(dataBits); - pushret_i->setComment(pushret_i->getDisassembly()); - pushret_i->setFallthrough(poparg_i); - - // poparg - dataBits.resize(1); - dataBits[0] = 0x58; - poparg_i->setDataBits(dataBits); - poparg_i->setComment(poparg_i->getDisassembly() + " -- with callback to " + p_detector + " orig: " + p_instruction->getComment()) ; - poparg_i->setFallthrough(popPolicy_i); - poparg_i->setCallback(p_detector); - auto poparg_i_indTarg =new libIRDB::AddressID_t(); - m_fileIR->GetAddresses().insert(poparg_i_indTarg); - poparg_i_indTarg->setVirtualOffset(poparg_i->getAddress()->getVirtualOffset()); - poparg_i_indTarg->setFileID(BaseObj_t::NOT_IN_DATABASE); - poparg_i->setIndirectBranchTargetAddress(poparg_i_indTarg); - - // popPolicy - dataBits.resize(1); - dataBits[0] = 0x58; - popPolicy_i->setDataBits(dataBits); - popPolicy_i->setFallthrough(popa_i); - - // popa - addPopa(popa_i, popf_i); - - // popf - addPopf(popf_i, p_fallThrough); -} - - -#if 0 -// returns true if BeaEngine says arg1 of the instruction is a register -bool Transform::hasTargetRegister(Instruction_t *p_instruction, int p_argNo) -{ - if (!p_instruction) - return false; - - DISASM disasm; - Disassemble(p_instruction,disasm); - - if (p_argNo == 1) - return disasm.Argument1.ArgType & 0xFFFF0000 & REGISTER_TYPE; - else if (p_argNo == 2) - return disasm.Argument2.ArgType & 0xFFFF0000 & REGISTER_TYPE; - else if (p_argNo == 3) - return disasm.Argument3.ArgType & 0xFFFF0000 & REGISTER_TYPE; - else - return false; -} - - -RegisterName Transform::getTargetRegister(Instruction_t *p_instruction, int p_argNo) -{ - if (hasTargetRegister(p_instruction, p_argNo)) - { - DISASM disasm; - Disassemble(p_instruction,disasm); - - if (p_argNo == 1) - return Register::getRegister(disasm.Argument1.ArgMnemonic); - else if (p_argNo == 2) - return Register::getRegister(disasm.Argument2.ArgMnemonic); - else if (p_argNo == 3) - return Register::getRegister(disasm.Argument3.ArgMnemonic); - } - else - return rn_UNKNOWN; -} - -// -// Returns true iff instruction is MUL (according to BeaEngine) -// -bool Transform::isMultiplyInstruction(Instruction_t *p_instruction) -{ - if (!p_instruction) - return false; - - std::string assembly = m_fileIR->lookupAssembly(p_instruction); - if (assembly.length() > 0) - { - return my_strcasestr(assembly.c_str(), "MUL") != NULL; - } - - DISASM disasm; - Disassemble(p_instruction,disasm); - - // beaengine adds space at the end of the mnemonic string - return my_strcasestr(disasm.Instruction.Mnemonic, "MUL ") != NULL; -} - - -// -// Returns true iff instruction is a MOV (according to BeaEngine) -// -bool Transform::isMovInstruction(Instruction_t *p_instruction) -{ - if (!p_instruction) - return false; - - std::string assembly = m_fileIR->lookupAssembly(p_instruction); - if (assembly.length() > 0) - { - return my_strcasestr(assembly.c_str(), "MOV") != NULL; - } - - DISASM disasm; - Disassemble(p_instruction,disasm); - - // nb: beaengine adds space at the end of the mnemonic string - return my_strcasestr(disasm.Instruction.Mnemonic, "MOV") != NULL; -} - -// -// Returns true iff instruction is ADD or SUB (according to BeaEngine) -// -bool Transform::isAddSubNonEspInstruction(Instruction_t *p_instruction) -{ - if (!p_instruction) - return false; - - DISASM disasm; - Disassemble(p_instruction,disasm); - - // beaengine adds space at the end of the mnemonic string - if (my_strcasestr(disasm.Instruction.Mnemonic, "ADD ")) - { - return true; - } - else if (my_strcasestr(disasm.Instruction.Mnemonic, "SUB ")) - { - if (my_strcasestr(disasm.Argument1.ArgMnemonic,"esp") && - (disasm.Argument2.ArgType & 0xFFFF0000 & (CONSTANT_TYPE | ABSOLUTE_))) - { - // optimization: filter out "sub esp, K" - return false; - } - return true; - } - - return false; -} -#endif - -void Transform::addTestRegister8(Instruction_t *p_instr, RegisterName p_reg, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(2); - if (p_reg == rn_AL) - { - dataBits[0] = 0x84; - dataBits[1] = 0xc0; - } - else if (p_reg == rn_BL) - { - dataBits[0] = 0x84; - dataBits[1] = 0xdb; - } - else if (p_reg == rn_CL) - { - dataBits[0] = 0x84; - dataBits[1] = 0xc9; - } - else if (p_reg == rn_DL) - { - dataBits[0] = 0x84; - dataBits[1] = 0xd2; - } - else if (p_reg == rn_AH) - { - dataBits[0] = 0x84; - dataBits[1] = 0xe4; - } - else if (p_reg == rn_BH) - { - dataBits[0] = 0x84; - dataBits[1] = 0xff; - } - else if (p_reg == rn_CH) - { - dataBits[0] = 0x84; - dataBits[1] = 0xed; - } - else if (p_reg == rn_DH) - { - dataBits[0] = 0x84; - dataBits[1] = 0xf6; - } - else - { - cerr << "Transform::addTestRegister8(): unhandled register" << endl; - assert(0); - return; - } - - addInstruction(p_instr, dataBits, p_fallThrough, NULL); -} - -void Transform::addTestRegister16(Instruction_t *p_instr, RegisterName p_reg, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(3); - if (p_reg == rn_AX) - { - dataBits[0] = 0x66; - dataBits[1] = 0x85; - dataBits[2] = 0xc0; - } - else if (p_reg == rn_BX) - { - dataBits[0] = 0x66; - dataBits[1] = 0x85; - dataBits[2] = 0xdb; - } - else if (p_reg == rn_CX) - { - dataBits[0] = 0x66; - dataBits[1] = 0x85; - dataBits[2] = 0xc9; - } - else if (p_reg == rn_DX) - { - dataBits[0] = 0x66; - dataBits[1] = 0x85; - dataBits[2] = 0xd2; - } - else if (p_reg == rn_BP) - { - assert(0); - } - else if (p_reg == rn_SP) - { - assert(0); - } - else if (p_reg == rn_SI) - { - assert(0); - } - else if (p_reg == rn_DI) - { - assert(0); - } - else - { - cerr << "Transform::addTestRegister16(): unhandled register" << endl; - assert(0); - return; - } - - addInstruction(p_instr, dataBits, p_fallThrough, NULL); -} - -// test <reg32>, <reg32> -void Transform::addTestRegister32(Instruction_t *p_instr, RegisterName p_reg, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(2); - if (p_reg == rn_EAX) - { - dataBits[0] = 0x85; - dataBits[1] = 0xc0; - } - else if (p_reg == rn_EBX) - { - dataBits[0] = 0x85; - dataBits[1] = 0xdb; - } - else if (p_reg == rn_ECX) - { - dataBits[0] = 0x85; - dataBits[1] = 0xc9; - } - else if (p_reg == rn_EDX) - { - dataBits[0] = 0x85; - dataBits[1] = 0xd2; - } - else if (p_reg == rn_ESI) - { - dataBits[0] = 0x85; - dataBits[1] = 0xf6; - } - else if (p_reg == rn_EDI) - { - dataBits[0] = 0x85; - dataBits[1] = 0xff; - } - else if (p_reg == rn_EBP) - { - dataBits[0] = 0x85; - dataBits[1] = 0xed; - } - else if (p_reg == rn_ESP) - { - dataBits[0] = 0x85; - dataBits[1] = 0xe4; - } - else - { - cerr << "Transform::addTestRegister32(): unhandled register" << endl; - assert(0); - return; - } - - addInstruction(p_instr, dataBits, p_fallThrough, NULL); -} - - -void Transform::addTestRegister(Instruction_t *p_instr, RegisterName p_reg, Instruction_t *p_fallThrough) -{ - if (Register::is8bit(p_reg)) - addTestRegister8(p_instr, p_reg, p_fallThrough); - else if (Register::is16bit(p_reg)) - addTestRegister16(p_instr, p_reg, p_fallThrough); - else if (Register::is32bit(p_reg)) - addTestRegister32(p_instr, p_reg, p_fallThrough); -} - -void Transform::addTestRegisterMask(Instruction_t *p_instr, RegisterName p_reg, unsigned p_mask, Instruction_t *p_fallThrough) -{ - if (Register::is32bit(p_reg)) - addTestRegisterMask32(p_instr, p_reg, p_mask, p_fallThrough); -} - -void Transform::addTestRegisterMask32(Instruction_t *p_instr, RegisterName p_reg, unsigned p_mask, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(6); // all but EAX take 6 bytes - unsigned *tmp; - - if (p_reg == rn_EAX) - { - dataBits.resize(5); - dataBits[0] = 0xa9; - tmp = (unsigned *) &dataBits[1]; - *tmp = p_mask; - } - else if (p_reg == rn_EBX) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xc3; - tmp = (unsigned *) &dataBits[2]; - *tmp = p_mask; - } - else if (p_reg == rn_ECX) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xc1; - tmp = (unsigned *) &dataBits[2]; - *tmp = p_mask; - } - else if (p_reg == rn_EDX) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xc2; - tmp = (unsigned *) &dataBits[2]; - *tmp = p_mask; - } - else if (p_reg == rn_ESI) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xc6; - tmp = (unsigned *) &dataBits[2]; - *tmp = p_mask; - } - else if (p_reg == rn_EDI) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xc7; - tmp = (unsigned *) &dataBits[2]; - *tmp = p_mask; - } - else if (p_reg == rn_EBP) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xc5; - tmp = (unsigned *) &dataBits[2]; - *tmp = p_mask; - } - else if (p_reg == rn_ESP) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xc4; - tmp = (unsigned *) &dataBits[2]; - *tmp = p_mask; - } - else - { - cerr << "Transform::addTestRegisterMask32(): unhandled register: " << p_reg << endl; - assert(0); - return; - } - - addInstruction(p_instr, dataBits, p_fallThrough, NULL); -} - -void Transform::addCmpRegisterMask(Instruction_t *p_instr, RegisterName p_reg, unsigned p_mask, Instruction_t *p_fallThrough) -{ - if (Register::is32bit(p_reg)) - addCmpRegisterMask32(p_instr, p_reg, p_mask, p_fallThrough); -} - -void Transform::addCmpRegisterMask32(Instruction_t *p_instr, RegisterName p_reg, unsigned p_mask, Instruction_t *p_fallThrough) -{ - string dataBits; - unsigned *tmp; - - if (p_reg == rn_EAX) - { - dataBits.resize(5); // EAX gets compact encoding - dataBits[0] = 0x3d; - tmp = (unsigned *) &dataBits[1]; - *tmp = p_mask; - } - else - { // common code for non-EAX cases first - dataBits.resize(6); // all but EAX take 6 bytes - dataBits[0] = 0x81; - tmp = (unsigned *) &dataBits[2]; - *tmp = p_mask; - if (p_reg == rn_EBX) - { - dataBits[1] = 0xfb; - } - else if (p_reg == rn_ECX) - { - dataBits[1] = 0xf9; - } - else if (p_reg == rn_EDX) - { - dataBits[1] = 0xfa; - } - else if (p_reg == rn_EBP) - { - dataBits[1] = 0xfd; - } - else if (p_reg == rn_ESI) - { - dataBits[1] = 0xfe; - } - else if (p_reg == rn_EDI) - { - dataBits[1] = 0xff; - } - else - { - cerr << "Transform::addCmpRegisterMask32(): unhandled register" << endl; - assert(0); - return; - } - } - - addInstruction(p_instr, dataBits, p_fallThrough, NULL); -} - -// jns - jump not signed -void Transform::addJns(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - string dataBits; - dataBits.resize(2); - dataBits[0] = 0x79; - dataBits[1] = 0x00; // value doesn't matter -- we will fill it in later - addInstruction(p_instr, dataBits, p_fallThrough, p_target); -} - -// jz - jump zero (same as je - jump if equal) -void Transform::addJz(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - string dataBits; - dataBits.resize(2); - dataBits[0] = 0x74; - dataBits[1] = 0x00; // value doesn't matter -- we will fill it in later - - addInstruction(p_instr, dataBits, p_fallThrough, p_target); -} - -// jnz - jump not zero (same as jne - jump if not equal) -void Transform::addJnz(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - string dataBits; - dataBits.resize(2); - dataBits[0] = 0x75; - dataBits[1] = 0x00; // value doesn't matter -- we will fill it in later - - addInstruction(p_instr, dataBits, p_fallThrough, p_target); -} - -// jae - jump if above or equal (unsigned) (same as jnb and jnc) -void Transform::addJae(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - string dataBits; - dataBits.resize(2); - dataBits[0] = 0x73; - dataBits[1] = 0x00; // value doesn't matter -- we will fill it in later - - addInstruction(p_instr, dataBits, p_fallThrough, p_target); -} - -// jo - jump overflow -void Transform::addJo(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - string dataBits; - dataBits.resize(2); - dataBits[0] = 0x70; - dataBits[1] = 0x00; // value doesn't matter -- we will fill it in later - - addInstruction(p_instr, dataBits, p_fallThrough, p_target); -} -// jc - jump carry -void Transform::addJc(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - string dataBits; - dataBits.resize(2); - dataBits[0] = 0x72; - dataBits[1] = 0x00; // value doesn't matter -- we will fill it in later - - addInstruction(p_instr, dataBits, p_fallThrough, p_target); -} - -// not <reg> -- negate register -void Transform::addNot(Instruction_t *p_instr, RegisterName p_reg, Instruction_t *p_fallThrough) -{ - string dataBits; - dataBits.resize(2); - - if (p_reg == rn_EAX) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xd0; - } - else if (p_reg == rn_EBX) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xd3; - } - else if (p_reg == rn_ECX) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xd1; - } - else if (p_reg == rn_EDX) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xd2; - } - else if (p_reg == rn_ESI) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xd6; - } - else if (p_reg == rn_EDI) - { - dataBits[0] = 0xf7; - dataBits[1] = 0xd7; - } - else if (p_reg == rn_AX) - { - dataBits.resize(3); - dataBits[0] = 0x66; - dataBits[1] = 0xf7; - dataBits[2] = 0xd0; - } - else if (p_reg == rn_BX) - { - dataBits.resize(3); - dataBits[0] = 0x66; - dataBits[1] = 0xf7; - dataBits[2] = 0xd3; - } - else if (p_reg == rn_CX) - { - dataBits.resize(3); - dataBits[0] = 0x66; - dataBits[1] = 0xf7; - dataBits[2] = 0xd1; - } - else if (p_reg == rn_DX) - { - dataBits.resize(3); - dataBits[0] = 0x66; - dataBits[1] = 0xf7; - dataBits[2] = 0xd2; - } - else if (p_reg == rn_AL) - { - dataBits[0] = 0xf6; - dataBits[1] = 0xd0; - } - else if (p_reg == rn_BL) - { - dataBits[0] = 0xf6; - dataBits[1] = 0xd3; - } - else if (p_reg == rn_CL) - { - dataBits[0] = 0xf6; - dataBits[1] = 0xd1; - } - else if (p_reg == rn_DL) - { - dataBits[0] = 0xf6; - dataBits[1] = 0xd2; - } - else if (p_reg == rn_AH) - { - dataBits[0] = 0xf6; - dataBits[1] = 0xd4; - } - else if (p_reg == rn_BH) - { - dataBits[0] = 0xf6; - dataBits[1] = 0xd7; - } - else if (p_reg == rn_CH) - { - dataBits[0] = 0xf6; - dataBits[1] = 0xd5; - } - else if (p_reg == rn_DH) - { - dataBits[0] = 0xf6; - dataBits[1] = 0xd6; - } - - else - { - cerr << "Transform::addNot(): unhandled register" << endl; - assert(0); - return; - } - - addInstruction(p_instr, dataBits, p_fallThrough, NULL); -} - -// add r1, r2 -void Transform::addAddRegisters(Instruction_t *p_instr, RegisterName p_regTgt, RegisterName p_regSrc, Instruction_t *p_fallThrough) -{ - // too many combinations, just use the assembler - string assembly = "add " + Register::toString(p_regTgt) + ", " + Register::toString(p_regSrc); -#ifdef OPTIMIZE_ASSEMBLY - m_fileIR->registerAssembly(p_instr, assembly); -#else - if (!p_instr->assemble(assembly)) - { - cerr << "addAddRegisters(): error in assembling instruction: " << assembly << endl; - assert(0); - return; - } -#endif - - p_instr->setFallthrough(p_fallThrough); -} - -// add r1, constant -void Transform::addAddRegisterConstant(Instruction_t *p_instr, RegisterName p_reg, int p_constantValue, Instruction_t *p_fallThrough) -{ - // too many combinations, just use the assembler - char buf[256]; - sprintf(buf, "add %s, %d", Register::toString(p_reg).c_str(), p_constantValue); - string assembly(buf); -#ifdef OPTIMIZE_ASSEMBLY - m_fileIR->registerAssembly(p_instr, assembly); -#else - if (!p_instr->assemble(assembly)) - { - cerr << "Transform::addAddConstant(): error in assembling instruction: " << assembly << endl; - assert(0); - return; - } -#endif - -// cerr << "Transform::addAddConstant(): " << p_instr->getDisassembly() << endl; - p_instr->setFallthrough(p_fallThrough); -} - -// imul r1, constant -void Transform::addMulRegisterConstant(Instruction_t *p_instr, RegisterName p_reg, int p_constantValue, Instruction_t *p_fallThrough) -{ - // too many combinations, just use the assembler - char buf[256]; - sprintf(buf, "imul %s, %d", Register::toString(p_reg).c_str(), p_constantValue); - string assembly(buf); -#ifdef OPTIMIZE_ASSEMBLY - m_fileIR->registerAssembly(p_instr, assembly); -#else - if (!p_instr->Assemble(assembly)) - { - cerr << "Transform::addMulRegisterConstant(): error in assembling instruction: " << assembly << endl; - assert(0); - return; - } -#endif - -// cerr << "Transform::addMulRegisterConstant(): " << p_instr->getDisassembly() << endl; - p_instr->setFallthrough(p_fallThrough); -} - - -// mov r1, r2 -void Transform::addMovRegisters(Instruction_t *p_instr, RegisterName p_regTgt, RegisterName p_regSrc, Instruction_t *p_fallThrough) -{ - // too many combinations, just use the assembler - string assembly = "mov " + Register::toString(p_regTgt) + ", " + Register::toString(p_regSrc); -#ifdef OPTIMIZE_ASSEMBLY - m_fileIR->registerAssembly(p_instr, assembly); -#else - if (!p_instr->Assemble(assembly)) - { - cerr << "addMovRegisters(): error in assembling instruction: " << assembly << endl; - assert(0); - return; - } -#endif - p_instr->setFallthrough(p_fallThrough); -// cerr << "addMovRegisters(): " << p_instr->getDisassembly() << endl; -} - -void Transform::addMovRegisterSignedConstant(Instruction_t *p_instr, RegisterName p_regTgt, long int p_constant, Instruction_t *p_fallThrough) -{ - p_instr->setFallthrough(p_fallThrough); - - char buf[128]; - - sprintf(buf,"mov %s, %ld", Register::toString(p_regTgt).c_str(), p_constant); - - string assembly(buf); - m_fileIR->registerAssembly(p_instr, assembly); - - p_instr->setComment("Saturating arithmetic"); -} - -void Transform::addMovRegisterUnsignedConstant(Instruction_t *p_instr, RegisterName p_regTgt, unsigned long int p_constant, Instruction_t *p_fallThrough) -{ - p_instr->setFallthrough(p_fallThrough); - - char buf[128]; - sprintf(buf,"mov %s, %lu", Register::toString(p_regTgt).c_str(), p_constant); - - string assembly(buf); - m_fileIR->registerAssembly(p_instr, assembly); - - p_instr->setComment("Saturating arithmetic"); -} - -void Transform::addAndRegister32Mask(Instruction_t *p_instr, RegisterName p_regTgt, unsigned int p_mask, Instruction_t *p_fallThrough) -{ - p_instr->setFallthrough(p_fallThrough); - - char buf[128]; - sprintf(buf,"and %s, 0x%08X", Register::toString(p_regTgt).c_str(), p_mask); - - string assembly(buf); - cerr << "addAndRegisterMask(): assembling instruction: " << assembly << endl; -#ifdef OPTIMIZE_ASSEMBLY - m_fileIR->registerAssembly(p_instr, assembly); -#else - if (!p_instr->Assemble(assembly)) - { - cerr << "addAndRegisterMask(): error in assembling instruction: " << assembly << endl; - assert(0); - return; - } -#endif - - p_instr->setComment("Saturating arithmetic by masking"); -} - -//----------------------------------------------------- -// known to be used on x86-64 -//----------------------------------------------------- - -// hlt -void Transform::addHlt(Instruction_t *p_instr, Instruction_t *p_fallThrough) -{ - string assembly("hlt"); - m_fileIR->registerAssembly(p_instr, assembly); - p_instr->setFallthrough(p_fallThrough); -} - -// jno - jump not overflow -void Transform::addJno(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - string assembly("jno 0x22"); - m_fileIR->registerAssembly(p_instr, assembly); - p_instr->setFallthrough(p_fallThrough); - p_instr->setTarget(p_target); -} - -// jnc - jump not carry -void Transform::addJnc(Instruction_t *p_instr, Instruction_t *p_fallThrough, Instruction_t *p_target) -{ - string assembly("jnc 0x22"); - m_fileIR->registerAssembly(p_instr, assembly); - p_instr->setFallthrough(p_fallThrough); - p_instr->setTarget(p_target); -} - -Instruction_t* Transform::addNewMaxSaturation(Instruction_t *p_prev, RegisterName p_reg, const MEDS_InstructionCheckAnnotation p_annotation) -{ - Instruction_t *mov = allocateNewInstruction(p_prev->getAddress()->getFileID(), p_prev->getFunction()); - if (p_prev) - p_prev->setFallthrough(mov); - addMaxSaturation(mov, p_reg, p_annotation, NULL); - return mov; -} - -void Transform::addMaxSaturation(Instruction_t *p_instruction, RegisterName p_reg, const MEDS_InstructionCheckAnnotation& p_annotation, Instruction_t *p_fallthrough) -{ -#if 0 - assert(getFileIR() && p_instruction); - - p_instruction->setFallthrough(p_fallthrough); - - if (p_annotation.isUnsigned()) - { - // use MAX_UNSIGNED for the bit width - switch (Register::getBitWidth(p_reg)) - { - case 64: - addMovRegisterUnsignedConstant(p_instruction, p_reg, 0xFFFFFFFFFFFFFFFF, p_fallthrough); - break; - case 32: - addMovRegisterUnsignedConstant(p_instruction, p_reg, 0xFFFFFFFF, p_fallthrough); - break; - case 16: - addMovRegisterUnsignedConstant(p_instruction, p_reg, 0xFFFF, p_fallthrough); - break; - case 8: - addMovRegisterUnsignedConstant(p_instruction, p_reg, 0xFF, p_fallthrough); - break; - default: - cerr << "Transform::addMaxSaturation(): invalid bit width: " << p_annotation.getBitWidth() << endl; - break; - } - } - else - { - // treat unknown and signed the same way for overflows - // use MAX_SIGNED for the bit width - switch (Register::getBitWidth(p_reg)) - { - case 64: - addMovRegisterSignedConstant(p_instruction, p_reg, 0x7FFFFFFFFFFFFFFF, p_fallthrough); - break; - case 32: - addMovRegisterSignedConstant(p_instruction, p_reg, 0x7FFFFFFF, p_fallthrough); - break; - case 16: - addMovRegisterSignedConstant(p_instruction, p_reg, 0x7FFF, p_fallthrough); - break; - case 8: - addMovRegisterSignedConstant(p_instruction, p_reg, 0x7F, p_fallthrough); - break; - default: - cerr << "Transform::addMaxSaturation(): invalid bit width: " << p_annotation.getBitWidth() << endl; - break; - } - } -#else - // not used, and had compiler errors. - assert(0); -#endif -} - -void Transform::addMinSaturation(Instruction_t *p_instruction, RegisterName p_reg, const MEDS_InstructionCheckAnnotation& p_annotation, Instruction_t *p_fallthrough) -{ -#if 0 - assert(getFileIR() && p_instruction); - - p_instruction->setFallthrough(p_fallthrough); - - if (p_annotation.isUnsigned()) - { - // use MIN_UNSIGNED - addMovRegisterUnsignedConstant(p_instruction, p_reg, 0, p_fallthrough); - } - else - { - // treat unknown and signed the same way for overflows - // use MIN_SIGNED for the bit width - switch (Register::getBitWidth(p_reg)) - { - case 64: - addMovRegisterSignedConstant(p_instruction, p_reg, 0x8000000000000000, p_fallthrough); - break; - case 32: - addMovRegisterSignedConstant(p_instruction, p_reg, 0x80000000, p_fallthrough); - break; - case 16: - addMovRegisterSignedConstant(p_instruction, p_reg, 0x8000, p_fallthrough); - break; - case 8: - addMovRegisterSignedConstant(p_instruction, p_reg, 0x80, p_fallthrough); - break; - default: - cerr << "Transform::addMinSaturation(): invalid bit width: " << p_annotation.getBitWidth() << endl; - break; - } - } -#else - // not used, and had compiler errors. - assert(0); -#endif -} - -void Transform::setAssembly(Instruction_t *p_instr, string p_asm) -{ - m_fileIR->registerAssembly(p_instr, p_asm); -} - -// -// Allocate and add new instruction given its assembly form -// If <p_instr> not NULL, then set fallthrough appropriately -// -// Returns the newly added instruction -// -// <p_instr> defined: -// <p_instr> <p_instr> -// <fallthrough> ==> <newinstr>(<p_asm>) -// <fallthrough> -// -// <p_instr> is NULL: -// ==> <newinstr>(<p_asm>) -// -Instruction_t* Transform::addNewAssembly(Instruction_t *p_instr, string p_asm) -{ - Instruction_t* newinstr; - if (p_instr) - newinstr = allocateNewInstruction(p_instr->getAddress()->getFileID(), p_instr->getFunction()); - else - newinstr = allocateNewInstruction(m_fileIR->getFile()->getFileID(), NULL); - - m_fileIR->registerAssembly(newinstr, p_asm); - - if (p_instr) - { - newinstr->setFallthrough(p_instr->getFallthrough()); - p_instr->setFallthrough(newinstr); - } - else - { - newinstr->setFallthrough(NULL); - } - - return newinstr; -} - -// register instruction in IRDB -// 20140421 -Instruction_t* Transform::addNewAssembly(string p_asm) -{ - return addNewAssembly(NULL, p_asm); -} - -// x86-64 -// 20140421 -void Transform::addCallbackHandler64(Instruction_t *p_orig, string p_callbackHandler, int p_numArgs) -{ - // nb: if first time, register and cache callback handler sequence - if (m_handlerMap.count(p_callbackHandler) == 0) - { - m_handlerMap[p_callbackHandler] = registerCallbackHandler64(p_callbackHandler, p_numArgs); - } - - if (p_orig) - p_orig->setTarget(m_handlerMap[p_callbackHandler]); -} - -// x86-64 -// register callback handler sequence -// -// This following note is slightly out of date. -// We DO save flags here so that our callbacks are -// able to look at register values using a reg_values_t. -// HOWEVER, the caller of this function should still be sure -// to save flags themselves. -// -// nb: strata semantics is that it does not save flags, so we don't bother -// saving/restoring flags either in the callback handler -// saving/restoring flags must be done outside of this routine -// 20140416 -Instruction_t* Transform::registerCallbackHandler64(string p_callbackHandler, int p_numArgs) -{ - Instruction_t *instr; - Instruction_t *first; - char tmpbuf[1024]; - - // save flags and 16 registers (136 bytes) - // call pushes 8 bytes - // Total: 8 * 18 = 144 - first = instr = addNewAssembly("push rsp"); - instr = addNewAssembly(instr, "push rbp"); - instr = addNewAssembly(instr, "push rdi"); - instr = addNewAssembly(instr, "push rsi"); - instr = addNewAssembly(instr, "push rdx"); - instr = addNewAssembly(instr, "push rcx"); - instr = addNewAssembly(instr, "push rbx"); - instr = addNewAssembly(instr, "push rax"); - instr = addNewAssembly(instr, "push r8"); - instr = addNewAssembly(instr, "push r9"); - instr = addNewAssembly(instr, "push r10"); - instr = addNewAssembly(instr, "push r11"); - instr = addNewAssembly(instr, "push r12"); - instr = addNewAssembly(instr, "push r13"); - instr = addNewAssembly(instr, "push r14"); - instr = addNewAssembly(instr, "push r15"); - instr = addNewAssembly(instr, "pushf"); - - // handle the arguments (if any): rdi, rsi, rdx, rcx, r8, r9 - // first arg starts at byte +144 - // now at +136??? b/c we took out the push - instr = addNewAssembly(instr, "mov rdi, rsp"); - - if (p_numArgs >= 1) - instr = addNewAssembly(instr, "mov rsi, [rsp+136]"); - if (p_numArgs >= 2) - instr = addNewAssembly(instr, "mov rdx, [rsp+144]"); - if (p_numArgs >= 3) - instr = addNewAssembly(instr, "mov rcx, [rsp+152]"); - if (p_numArgs >= 4) - instr = addNewAssembly(instr, "mov r8, [rsp+160]"); - if (p_numArgs > 4) - assert(0); // only handle up to 5 args - - // pin the instruction that follows the callback handler - Instruction_t* postCallback = allocateNewInstruction(); - VirtualOffset_t postCallbackReturn = getAvailableAddress(); - postCallback->getAddress()->setVirtualOffset(postCallbackReturn); - - // push the address to return to once the callback handler is invoked - sprintf(tmpbuf,"mov rax, 0x%x", (uint32_t)postCallbackReturn); - instr = addNewAssembly(instr, tmpbuf); - - instr = addNewAssembly(instr, "push rax"); - - // use a nop instruction for the actual callback - instr = addNewAssembly(instr, "nop"); - instr->setComment(" -- callback: " + p_callbackHandler); - instr->setCallback(p_callbackHandler); - instr->setFallthrough(postCallback); - - // need to make sure the post callback address is pinned - // (so that ILR and other transforms do not relocate it) - AddressID_t *indTarg = new libIRDB::AddressID_t(); - m_fileIR->GetAddresses().insert(indTarg); - indTarg->setVirtualOffset(postCallback->getAddress()->getVirtualOffset()); - indTarg->setFileID(BaseObj_t::NOT_IN_DATABASE); // SPRI global namespace - postCallback->setIndirectBranchTargetAddress(indTarg); - - // restore registers - setAssembly(postCallback, "popf"); - instr = addNewAssembly(postCallback, "pop r15"); - instr = addNewAssembly(instr, "pop r14"); - instr = addNewAssembly(instr, "pop r13"); - instr = addNewAssembly(instr, "pop r12"); - instr = addNewAssembly(instr, "pop r11"); - instr = addNewAssembly(instr, "pop r10"); - instr = addNewAssembly(instr, "pop r9"); - instr = addNewAssembly(instr, "pop r8"); - instr = addNewAssembly(instr, "pop rax"); - instr = addNewAssembly(instr, "pop rbx"); - instr = addNewAssembly(instr, "pop rcx"); - instr = addNewAssembly(instr, "pop rdx"); - instr = addNewAssembly(instr, "pop rsi"); - instr = addNewAssembly(instr, "pop rdi"); - instr = addNewAssembly(instr, "pop rbp"); - instr = addNewAssembly(instr, "lea rsp, [rsp+8]"); - - instr = addNewAssembly(instr, "ret"); - - // return first instruction in the callback handler chain - return first; -} - -void Transform::logMessage(const std::string &p_method, const std::string &p_msg) -{ - std::cerr << p_method << ": " << p_msg << std::endl; -} - -void Transform::logMessage(const std::string &p_method, const MEDS_InstructionCheckAnnotation& p_annotation, const std::string &p_msg) -{ - logMessage(p_method, p_msg + " annotation: " + p_annotation.toString()); -} - -void libTransform::convertToLowercase(string &str) -{ - for (auto i = 0U; i < str.length(); ++i) - { - str[i] = tolower(str[i]); - } -} - -#endif - - diff --git a/irdb-sdk b/irdb-sdk index dd1ec536daf04863d614cabbfb7b07aabcc6643e..09d6d2f18d70230122cc8a0c49fd2093f4b36785 160000 --- a/irdb-sdk +++ b/irdb-sdk @@ -1 +1 @@ -Subproject commit dd1ec536daf04863d614cabbfb7b07aabcc6643e +Subproject commit 09d6d2f18d70230122cc8a0c49fd2093f4b36785