Skip to content
Snippets Groups Projects
scfi_instr.hpp 4.86 KiB
Newer Older
an7s's avatar
an7s committed
/*
 * Copyright (c) 2014-2015 - Zephyr Software LLC
 *
 * This file may be used and modified for non-commercial purposes as long as
 * all copyright, permission, and nonwarranty notices are preserved.
 * Redistribution is prohibited without prior written consent from Zephyr
 * Software.
 *
 * Please contact the authors for restrictions applying to commercial use.
 *
 * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Author: Zephyr Software
 * e-mail: jwd@zephyr-software.com
 * URL   : http://www.zephyr-software.com/
 *
 */

jdh8d's avatar
jdh8d committed
#ifndef scfi_instrument_hpp
#define scfi_instrument_hpp

#include <libIRDB-core.hpp>
jdh8d's avatar
jdh8d committed
#include "color_map.hpp"
#include <iostream>
#include <iomanip>
jdh8d's avatar
jdh8d committed
#include <memory>
jdh8d's avatar
jdh8d committed



class SCFI_Instrument
{
	public:
		SCFI_Instrument(libIRDB::FileIR_t *the_firp, 
				bool p_do_coloring=true,
jdh8d's avatar
jdh8d committed
				bool p_do_common_slow_path=true,
				bool p_do_jumps=false,
				bool p_do_calls=true,
				bool p_do_rets=true,
				bool p_do_multimodule=false,
				bool p_do_exe_nonce_for_call=false
			: firp(the_firp), 
			  do_coloring(p_do_coloring), 
jdh8d's avatar
jdh8d committed
			  do_common_slow_path(p_do_common_slow_path), 
			  do_jumps(p_do_jumps), 
an7s's avatar
an7s committed
			  protect_safefn(p_do_safefn), 
			  do_multimodule(p_do_multimodule), 
			  do_exe_nonce_for_call(p_do_exe_nonce_for_call), 
			  ExecutableNonceValue("\x90", 1),
jdh8d's avatar
jdh8d committed
			  ret_shared(NULL),
			  zestcfi_function_entry(NULL)
		{ 
			std::cout<<std::boolalpha;
			std::cout<<"#ATTRIBUTE do_coloring="<<p_do_coloring<<std::endl;
			std::cout<<"#ATTRIBUTE do_common_slow_path="<<p_do_common_slow_path<<std::endl;
			std::cout<<"#ATTRIBUTE do_jumps="<<p_do_jumps<<std::endl;
			std::cout<<"#ATTRIBUTE do_calls="<<p_do_calls<<std::endl;
			std::cout<<"#ATTRIBUTE do_rets="<<p_do_rets<<std::endl;
			std::cout<<"#ATTRIBUTE do_safefn="<<p_do_safefn<<std::endl;
			std::cout<<"#ATTRIBUTE do_multimodule="<<p_do_multimodule<<std::endl;

			if(do_exe_nonce_for_call && p_do_coloring)
			{
				std::cerr<<"Cannot do coloring+exe_nonce_for_call!"<<std::endl;
				exit(1);
			}
jdh8d's avatar
jdh8d committed
		bool execute();

	private:

		// helpers for adding GOT entries and symbols for multi-module cfi	
		template<typename T_Elf_Sym, typename T_Elf_Rela, typename T_Elf_Dyn, int reloc_type, int rela_shift, int B>
		bool add_dl_support();

		template<typename T_Elf_Sym, typename T_Elf_Rela, typename T_Elf_Dyn, int reloc_type, int rela_shift, int B>
		bool add_libdl_as_needed_support();

		template<typename T_Elf_Sym, typename T_Elf_Rela, typename T_Elf_Dyn, int reloc_type, int rela_shift, int ptrsize>
		bool add_got_entries();

		template<typename T_Elf_Sym, typename T_Elf_Rela, typename T_Elf_Dyn, int reloc_type, int rela_shift, int ptrsize>
		libIRDB::Instruction_t* find_runtime_resolve(libIRDB::DataScoop_t* gotplt_scoop);

		template<typename T_Elf_Sym, typename T_Elf_Rela, typename T_Elf_Dyn, int reloc_type, int rela_shift, int ptrsize>
		void add_got_entry(const std::string& name);


jdh8d's avatar
jdh8d committed

		// find instrumentation points.
		bool mark_targets();
		bool instrument_jumps();

		// helper
		libIRDB::Relocation_t* create_reloc(libIRDB::Instruction_t* insn);
jdh8d's avatar
jdh8d committed
		libIRDB::Relocation_t* FindRelocation(libIRDB::Instruction_t* insn, std::string type);
		bool isSafeFunction(libIRDB::Instruction_t* insn);
an7s's avatar
an7s committed
		bool isCallToSafeFunction(libIRDB::Instruction_t* insn);
		bool is_jmp_a_fixed_call(libIRDB::Instruction_t* insn);
		bool is_plt_style_jmp(libIRDB::Instruction_t* insn);


jdh8d's avatar
jdh8d committed

		// add instrumentation
		bool add_scfi_instrumentation(libIRDB::Instruction_t* insn);
		bool needs_scfi_instrumentation(libIRDB::Instruction_t* insn);
jdh8d's avatar
jdh8d committed

		// return instrumentation
jdh8d's avatar
jdh8d committed
		void  AddReturnCFI(libIRDB::Instruction_t* insn, ColoredSlotValue_t *v=NULL);
		void  AddReturnCFIForExeNonce(libIRDB::Instruction_t* insn, ColoredSlotValue_t *v=NULL);

jdh8d's avatar
jdh8d committed
		// jump instrumentation
		void AddJumpCFI(libIRDB::Instruction_t* insn);
jdh8d's avatar
jdh8d committed

		// call instrumentation with executable nonce
		void AddCallCFIWithExeNonce(libIRDB::Instruction_t* insn);

		// for all calls
		void AddExecutableNonce(libIRDB::Instruction_t* insn);
jdh8d's avatar
jdh8d committed

		// Nonce Manipulation.
jdh8d's avatar
jdh8d committed
		NonceValueType_t GetNonce(libIRDB::Instruction_t* insn);
jdh8d's avatar
jdh8d committed
		unsigned int GetNonceSize(libIRDB::Instruction_t* insn);
jdh8d's avatar
jdh8d committed
		unsigned int GetNonceOffset(libIRDB::Instruction_t*);
jdh8d's avatar
jdh8d committed

jdh8d's avatar
jdh8d committed

		// predecessors of instructions.
		libIRDB::InstructionPredecessors_t preds;
jdh8d's avatar
jdh8d committed
	
		libIRDB::FileIR_t* firp;
jdh8d's avatar
jdh8d committed
		bool do_coloring;
jdh8d's avatar
jdh8d committed
		bool do_common_slow_path;
an7s's avatar
an7s committed
		bool protect_safefn;
		bool do_exe_nonce_for_call;
jdh8d's avatar
jdh8d committed
		std::unique_ptr<ColoredInstructionNonces_t> color_map;
		libIRDB::Instruction_t *ret_shared;
jdh8d's avatar
jdh8d committed
		libIRDB::Instruction_t *zestcfi_function_entry;
		std::string ExecutableNonceValue;
jdh8d's avatar
jdh8d committed
};

#endif