From 480959bf7a0ce1b9d606a4458fefbb9d1788cb58 Mon Sep 17 00:00:00 2001 From: Jason Hiser <jdhiser@gmail.com> Date: Fri, 25 Jan 2019 21:03:11 -0500 Subject: [PATCH] first draft --- SConscript | 2 + push64_relocs.cpp | 206 +++++++++++----------------------------------- push64_relocs.h | 42 +++++----- 3 files changed, 70 insertions(+), 180 deletions(-) diff --git a/SConscript b/SConscript index 5d33b7f9f..e5ab635a3 100644 --- a/SConscript +++ b/SConscript @@ -17,6 +17,7 @@ myenv=env myenv.Replace(SECURITY_TRANSFORMS_HOME=os.environ['SECURITY_TRANSFORMS_HOME']) myenv.Replace(ZIPR_HOME=os.environ['ZIPR_HOME']) myenv.Replace(ZIPR_SDK=os.environ['ZIPR_SDK']) +myenv.Replace(IRDB_SDK=os.environ['IRDB_SDK']) myenv.Replace(ZIPR_INSTALL=os.environ['ZIPR_INSTALL']) myenv.Replace(do_cgc=ARGUMENTS.get("do_cgc",0)) @@ -29,6 +30,7 @@ files= ''' # ELFIO needs to be first so we get the zipr version instead of the sectrans version. the zipr version is modified to include get_offset. cpppath=''' . + $IRDB_SDK/include/ $ZIPR_HOME/third_party/ELFIO/elfio-2.2 $SECURITY_TRANSFORMS_HOME/include/ $SECURITY_TRANSFORMS_HOME/libIRDB/include/ diff --git a/push64_relocs.cpp b/push64_relocs.cpp index bdbb8f512..0d1c03b63 100644 --- a/push64_relocs.cpp +++ b/push64_relocs.cpp @@ -30,32 +30,20 @@ #include <zipr_sdk.h> -#include <libIRDB-core.hpp> +#include <irdb-core> #include <string> #include <algorithm> #include "utils.hpp" #include "Rewrite_Utility.hpp" #include "push64_relocs.h" -using namespace libIRDB; +using namespace IRDB_SDK; using namespace std; using namespace Zipr_SDK; using namespace ELFIO; #define ALLOF(a) begin(a), end(a) -/* -bool arg_has_relative(const ARGTYPE &arg) -{ - // if it's relative memory, watch out! - if(arg.ArgType&MEMORY_TYPE) - if(arg.ArgType&RELATIVE_) - return true; - - return false; -} -*/ - Push64Relocs_t::Push64Relocs_t(MemorySpace_t *p_ms, elfio *p_elfio, FileIR_t *p_firp, @@ -74,15 +62,15 @@ ZiprOptionsNamespace_t *Push64Relocs_t::RegisterOptions(ZiprOptionsNamespace_t * bool Push64Relocs_t::IsRelocationWithType(Relocation_t *reloc,std::string type) { - return (reloc->GetType().find(type) != std::string::npos); + return (reloc->getType().find(type) != std::string::npos); } // would be nice to have a FindRelocation function that takes a parameterized type. Relocation_t* Push64Relocs_t::FindRelocationWithType(Instruction_t* insn, std::string type) { Instruction_t* first_slow_path_insn=NULL; - RelocationSet_t::iterator rit = insn->GetRelocations().begin(); - for(rit; rit!=insn->GetRelocations().end(); rit++) + RelocationSet_t::iterator rit = insn->getRelocations().begin(); + for(rit; rit!=insn->getRelocations().end(); rit++) { Relocation_t *reloc=*rit; if (IsRelocationWithType(reloc, type)) @@ -94,10 +82,7 @@ Relocation_t* Push64Relocs_t::FindRelocationWithType(Instruction_t* insn, std::s #define PUSH_DATA_BITS_MAX_LEN 16 void Push64Relocs_t::HandlePush64Relocation(Instruction_t *insn, Relocation_t *reloc) { - Instruction_t *add_insn = new Instruction_t; - AddressID_t *add_addr = new AddressID_t; - Instruction_t *push_insn = NULL, *jmp_insn = NULL; - Relocation_t *add_reloc = new Relocation_t; + // Instruction_t *push_insn = NULL, *jmp_insn = NULL; virtual_offset_t push_addr = 0; string databits = ""; uint8_t push_data_bits[PUSH_DATA_BITS_MAX_LEN] = {0,}; @@ -105,14 +90,14 @@ void Push64Relocs_t::HandlePush64Relocation(Instruction_t *insn, Relocation_t *r plopped_relocs.insert(insn); - push_insn = insn; - jmp_insn = insn->GetFallthrough(); + auto push_insn = insn; + auto jmp_insn = insn->getFallthrough(); assert(jmp_insn); - push_data_bits_len = push_insn->GetDataBits().length(); + push_data_bits_len = push_insn->getDataBits().length(); assert(push_data_bits_len<PUSH_DATA_BITS_MAX_LEN); memcpy(push_data_bits, - (uint8_t*)push_insn->GetDataBits().c_str(), + (uint8_t*)push_insn->getDataBits().c_str(), push_data_bits_len); /* * Because we know that this is a push instruction, @@ -127,13 +112,20 @@ void Push64Relocs_t::HandlePush64Relocation(Instruction_t *insn, Relocation_t *r /* * Step 0: Add the add instruction and its address. - */ - add_addr->SetFileID(push_insn->GetAddress()->GetFileID()); - add_insn->SetAddress(add_addr); - add_insn->SetFunction(push_insn->GetFunction()); - m_firp.GetAddresses().insert(add_addr); - m_firp.GetInstructions().insert(add_insn); + AddressID_t *add_addr = new AddressID_t; + add_addr->setFileID(push_insn->getAddress()->getFileID()); + m_firp.getAddresses().insert(add_addr); + Instruction_t *add_insn = new Instruction_t; + add_insn->setAddress(add_addr); + add_insn->setFunction(push_insn->getFunction()); + m_firp.getInstructions().insert(add_insn); + */ + auto add_addr=m_firp.addNewAddress(push_insn->getAddress()->getFileID(), 0); + auto add_insn=m_firp.addNewInstruction( + add_addr, + push_insn->getFunction() + ); /* * Step 1: Change the push to a call 0. */ @@ -145,17 +137,18 @@ void Push64Relocs_t::HandlePush64Relocation(Instruction_t *insn, Relocation_t *r databits[2] = 0x00; databits[3] = 0x00; databits[4] = 0x00; - insn->SetDataBits(databits); - insn->SetTarget(add_insn); // Comment - insn->SetFallthrough(NULL); - insn->SetComment(push_insn->GetComment()+" Thunk part"); + insn->setDataBits(databits); + insn->setTarget(add_insn); // Comment + insn->setFallthrough(NULL); + insn->setComment(push_insn->getComment()+" Thunk part"); + /* * Step 2: Create the add instruction. */ // this is OK, but could we consider the insn->Assemble() method for readability? databits = ""; - if(m_firp.GetArchitectureBitWidth()==64) + if(m_firp.getArchitectureBitWidth()==64) databits+=(char)0x48; // rex prefix to convert esp->rsp databits+=(char)0x81; databits+=(char)0x2c; @@ -164,24 +157,26 @@ void Push64Relocs_t::HandlePush64Relocation(Instruction_t *insn, Relocation_t *r databits+=(char)0xff; databits+=(char)0xff; databits+=(char)0xff; - add_insn->SetDataBits(databits); + add_insn->setDataBits(databits); /* * Step 3: Put the relocation on the add instruction. - */ + Relocation_t *add_reloc = new Relocation_t; add_reloc->SetOffset(push_addr); - add_reloc->SetType("add64"); - add_insn->GetRelocations().insert(add_reloc); - m_firp.GetRelocations().insert(add_reloc); + add_reloc->setType("add64"); + add_insn->getRelocations().insert(add_reloc); + m_firp.getRelocations().insert(add_reloc); + */ + auto add_reloc=m_firp.addNewRelocation(add_insn,push_addr,"add64"); if (m_verbose) cout << "Adding an add/sub with reloc offset 0x" - << std::hex << add_reloc->GetOffset() + << std::hex << add_reloc->getOffset() << endl; /* * Step 4: Tell the add insn to fallthrough to the call. */ - add_insn->SetFallthrough(jmp_insn); + add_insn->setFallthrough(jmp_insn); } void Push64Relocs_t::HandlePush64Relocs() @@ -189,8 +184,8 @@ void Push64Relocs_t::HandlePush64Relocs() int push64_relocations_count=0; int pcrel_relocations_count=0; // for each instruction - InstructionSet_t::iterator iit = m_firp.GetInstructions().begin(); - for(iit; iit!=m_firp.GetInstructions().end(); iit++) + InstructionSet_t::iterator iit = m_firp.getInstructions().begin(); + for(iit; iit!=m_firp.getInstructions().end(); iit++) { Instruction_t *insn=*iit; @@ -245,13 +240,13 @@ void Push64Relocs_t::UpdatePush64Adds() Relocation_t *add_reloc = NULL; call = *insn_it; - add = call->GetTarget(); + add = call->getTarget(); assert(call && add); call_addr = final_insn_locations[call]; add_addr = final_insn_locations[add]; - Instruction_t* wrt_insn=dynamic_cast<Instruction_t*>(reloc->GetWRT()); + Instruction_t* wrt_insn=dynamic_cast<Instruction_t*>(reloc->getWRT()); if(wrt_insn) wrt_addr=final_insn_locations[wrt_insn]; @@ -265,12 +260,12 @@ void Push64Relocs_t::UpdatePush64Adds() add_reloc = FindAdd64Relocation(add); assert(add_reloc && "push64:Add in Call/Add pair must have relocation."); - add_offset = add_reloc->GetOffset(); + add_offset = add_reloc->getOffset(); /* * Stupid call will push the NEXT instruction address. */ - call_addr+=call->GetDataBits().length(); + call_addr+=call->getDataBits().length(); // would this be simpler if we always used an add (or sub) @@ -301,7 +296,7 @@ void Push64Relocs_t::UpdatePush64Adds() << " as the updated offset." << endl << "Using 0x" << std::hex << add_offset << " as the base offset." << endl; - const auto rex_skip=m_firp.GetArchitectureBitWidth()==64 ? 1 : 0; + const auto rex_skip=m_firp.getArchitectureBitWidth()==64 ? 1 : 0; if (change_to_add) { char add = (char)0x04; @@ -309,113 +304,6 @@ void Push64Relocs_t::UpdatePush64Adds() } m_memory_space.PlopBytes(add_addr+rex_skip+3, (const char*)&relocated_value, 4); } -// functionality moving to unpin plug. -#if 0 - // handle basic pcrel relocations. - // zipr_unpin_plugin handles pcrel + WRT - // caution, side effect in if statement. - else if ( (reloc = FindPcrelRelocation(insn)) != NULL && reloc->GetWRT()==NULL) - { - const auto insn_addr = final_insn_locations[insn]; - if (insn_addr == 0) - { - if (m_verbose) - cout << "push64:Skipping unplopped Pcrel relocation." << endl; - continue; - } - assert(insn_addr != 0); - - const auto insn_bytes_len = sizeof(uint8_t)*insn->GetDataBits().length(); - uint8_t insn_bytes[insn_bytes_len]; // compiler disallows init on some platforms. - // but memcpy should init it sufficiently. - memcpy(insn_bytes, insn->GetDataBits().c_str(), insn_bytes_len); - - const auto d=DecodedInstruction_t(insn); - const auto operands=d.getOperands(); - const auto arg_it=find_if(ALLOF(operands),[](const DecodedOperand_t& op) { return op.isPcrel(); }); - assert(arg_it!=operands.end()); - const auto arg=*arg_it; - const auto mt=m_firp.GetArchitecture()->getMachineType(); - - if(mt==admtX86_64 || mt==admtI386) - { - assert(arg.isMemory()); // only memory operands have pcrel in x86. - auto memory_offset = d.getMemoryDisplacementOffset(arg, insn); - auto existing_offset_size = arg.getMemoryDisplacementEncodingSize(); - assert(memory_offset>=0 && memory_offset <=15); - assert(existing_offset_size==1 || existing_offset_size==2 || existing_offset_size==4 || existing_offset_size==8); - int32_t existing_offset=0; - memcpy((uint8_t*)&existing_offset, - (uint8_t*)&insn_bytes[memory_offset], - existing_offset_size); - - auto new_offset = existing_offset-insn_addr; - if (m_verbose) - { - cout << "Relocating a pcrel relocation with 0x" - << hex << existing_offset - << " existing offset at 0x" - << insn_addr << "." << endl; - cout << "Based on: " << d.getDisassembly() << endl - << "New address: 0x" << hex << new_offset << endl; - } - - // is this plugin useless? - for(auto i=0U; i< existing_offset_size; i++) - assert(m_memory_space[insn_addr+memory_offset+i]==((const char*)&new_offset)[i]); - m_memory_space.PlopBytes(insn_addr+memory_offset, - (const char*)&new_offset, - existing_offset_size); - } - else if(mt==admtAarch64) - { - const auto mnemonic=d.getMnemonic(); - const auto is_adr_type=mnemonic=="adr" || mnemonic=="adrp"; - const auto full_insn=*(uint32_t*)insn_bytes; - const auto mask2 =(1<< 2)-1; - const auto mask5 =(1<< 5)-1; - const auto mask12=(1<<12)-1; - const auto mask19=(1<<19)-1; - - if(is_adr_type) - { - // adr : 0 immlo2 10000 immhi19 Rd5 - // adrp: 1 immlo2 10000 immhi19 Rd5 - const auto op_byte=insn_bytes[3]; - assert((op_byte&mask5) == 0x10); // sanity check adr(p) opcode bytes. - const auto immlo2=(op_byte >> 5)&mask2; // gram immlo2 - const auto immhi19=(full_insn >> 5)&mask19; // gram immhi19 - const auto imm21=immhi19<<2 | immlo2; // get full immediate in one field. - const auto imm21_ext=(((int64_t)imm21)<<43) >> 43; // sign extend to 64-bit - const auto orig_insn_addr=insn->GetAddress()->GetVirtualOffset(); - const auto orig_insn_pageno=(orig_insn_addr>>12); - const auto new_insn_pageno =( insn_addr>>12); - const auto new_imm21_ext = imm21_ext + orig_insn_pageno - new_insn_pageno + reloc->GetAddend(); - // make sure no overflow. - assert( ((new_imm21_ext << 43) >> 43) == new_imm21_ext); - const auto new_immhi19=new_imm21_ext >> 2; - const auto new_immlo2 =new_imm21_ext & mask2; - const auto clean_new_insn= full_insn & ~(mask2<<29) & ~ (mask19 << 5); - const auto new_insn=clean_new_insn | (new_immlo2 << 29) | (new_immhi19<<5); - // put the new instruction in the output - m_memory_space.PlopBytes(insn_addr, (const char*)&new_insn, 4); - - if (m_verbose) - { - cout << "Relocating a pcrel relocation with orig_pageno=" << hex - << (orig_insn_pageno << 12) << " offset=(page-pc+" << imm21_ext << ")" << endl; - cout << "Based on: " << d.getDisassembly() << " originally at " << orig_insn_addr - << " now located at : 0x" << hex << insn_addr << " with offset=(page-pc + " - << new_imm21_ext << ")" << endl; - } - } - else - assert(0); - } - else - assert(0); - } -#endif } } @@ -424,8 +312,8 @@ Zipr_SDK::ZiprPluginInterface_t* GetPluginInterface( Zipr_SDK::Zipr_t* zipr_object) { Zipr_SDK::MemorySpace_t *p_ms=zipr_object->GetMemorySpace(); - ELFIO::elfio *p_elfio=zipr_object->GetELFIO(); - libIRDB::FileIR_t *p_firp=zipr_object->GetFileIR(); + ELFIO::elfio *p_elfio=zipr_object->getELFIO(); + IRDB_SDK::FileIR_t *p_firp=zipr_object->getFileIR(); Zipr_SDK::InstructionLocationMap_t *p_fil=zipr_object->GetLocationMap(); return new Push64Relocs_t(p_ms,p_elfio,p_firp,p_fil); } diff --git a/push64_relocs.h b/push64_relocs.h index 00639f1c1..636f08f53 100644 --- a/push64_relocs.h +++ b/push64_relocs.h @@ -31,14 +31,14 @@ #ifndef push_relocs_h #define push_relocs_h -#include <libIRDB-core.hpp> +#include <irdb-core> class Push64Relocs_t : public Zipr_SDK::ZiprPluginInterface_t { public: Push64Relocs_t(Zipr_SDK::MemorySpace_t *p_ms, ELFIO::elfio *p_elfio, - libIRDB::FileIR_t *p_firp, + IRDB_SDK::FileIR_t *p_firp, Zipr_SDK::InstructionLocationMap_t *p_fil); virtual void PinningBegin() { @@ -47,10 +47,10 @@ class Push64Relocs_t : public Zipr_SDK::ZiprPluginInterface_t { if(m_elfio.get_type()==ET_EXEC) { - cout<<"Push64_reloc: elide PinningEnd as type==ET_EXEC"<<endl; + std::cout<<"Push64_reloc: elide PinningEnd as type==ET_EXEC"<<std::endl; return; } - cout<<"Push64Plugin: Ending pinning, applying push64 relocs."<<endl; + std::cout<<"Push64Plugin: Ending pinning, applying push64 relocs."<<std::endl; HandlePush64Relocs(); } virtual void DollopBegin() @@ -66,10 +66,10 @@ class Push64Relocs_t : public Zipr_SDK::ZiprPluginInterface_t { if(m_elfio.get_type()==ET_EXEC) { - cout<<"Push64_reloc: elide CallbackLinkingEnd as type==ET_EXEC"<<endl; + std::cout<<"Push64_reloc: elide CallbackLinkingEnd as type==ET_EXEC"<<std::endl; return; } - cout<<"Push64Plugin: CBLinkEnd, updating adds." <<endl; + std::cout<<"Push64Plugin: CBLinkEnd, updating adds." <<std::endl; UpdatePush64Adds(); } @@ -80,30 +80,30 @@ class Push64Relocs_t : public Zipr_SDK::ZiprPluginInterface_t void UpdatePush64Adds(); // subsidiary workhorses - void HandlePush64Relocation(libIRDB::Instruction_t* insn, libIRDB::Relocation_t *reloc); + void HandlePush64Relocation(IRDB_SDK::Instruction_t* insn, IRDB_SDK::Relocation_t *reloc); // helpers - bool IsPcrelRelocation(libIRDB::Relocation_t *reloc) + bool IsPcrelRelocation(IRDB_SDK::Relocation_t *reloc) { return IsRelocationWithType(reloc,"pcrel"); } - bool IsAdd64Relocation(libIRDB::Relocation_t *reloc) + bool IsAdd64Relocation(IRDB_SDK::Relocation_t *reloc) { return IsRelocationWithType(reloc,"add64"); } - bool IsPush64Relocation(libIRDB::Relocation_t *reloc) + bool IsPush64Relocation(IRDB_SDK::Relocation_t *reloc) { return IsRelocationWithType(reloc,"push64"); } - bool Is32BitRelocation(libIRDB::Relocation_t *reloc) + bool Is32BitRelocation(IRDB_SDK::Relocation_t *reloc) { return IsRelocationWithType(reloc,"push64"); } - libIRDB::Relocation_t* FindPcrelRelocation(libIRDB::Instruction_t* insn) + IRDB_SDK::Relocation_t* FindPcrelRelocation(IRDB_SDK::Instruction_t* insn) { return FindRelocationWithType(insn,"pcrel"); } - libIRDB::Relocation_t* FindAdd64Relocation(libIRDB::Instruction_t* insn) + IRDB_SDK::Relocation_t* FindAdd64Relocation(IRDB_SDK::Instruction_t* insn) { return FindRelocationWithType(insn,"add64"); } - libIRDB::Relocation_t* FindPush64Relocation(libIRDB::Instruction_t* insn) + IRDB_SDK::Relocation_t* FindPush64Relocation(IRDB_SDK::Instruction_t* insn) { return FindRelocationWithType(insn,"push64"); } - libIRDB::Relocation_t* Find32BitRelocation(libIRDB::Instruction_t* insn) + IRDB_SDK::Relocation_t* Find32BitRelocation(IRDB_SDK::Instruction_t* insn) { return FindRelocationWithType(insn,"32-bit"); } - libIRDB::Relocation_t* FindPushRelocation(libIRDB::Instruction_t* insn) + IRDB_SDK::Relocation_t* FindPushRelocation(IRDB_SDK::Instruction_t* insn) { - libIRDB::Relocation_t* reloc=NULL; + IRDB_SDK::Relocation_t* reloc=NULL; if(reloc=FindPush64Relocation(insn)) { return reloc; @@ -115,8 +115,8 @@ class Push64Relocs_t : public Zipr_SDK::ZiprPluginInterface_t return NULL; } - bool IsRelocationWithType(libIRDB::Relocation_t *reloc, std::string type); - libIRDB::Relocation_t* FindRelocationWithType(libIRDB::Instruction_t* insn, std::string type); + bool IsRelocationWithType(IRDB_SDK::Relocation_t *reloc, std::string type); + IRDB_SDK::Relocation_t* FindRelocationWithType(IRDB_SDK::Instruction_t* insn, std::string type); @@ -124,11 +124,11 @@ class Push64Relocs_t : public Zipr_SDK::ZiprPluginInterface_t // references to input Zipr_SDK::MemorySpace_t &m_memory_space; ELFIO::elfio& m_elfio; - libIRDB::FileIR_t& m_firp; + IRDB_SDK::FileIR_t& m_firp; Zipr_SDK::InstructionLocationMap_t &final_insn_locations; // local data. - libIRDB::InstructionSet_t plopped_relocs; + IRDB_SDK::InstructionSet_t plopped_relocs; Zipr_SDK::ZiprBooleanOption_t m_verbose; -- GitLab