Skip to content
Snippets Groups Projects
Commit 480959bf authored by Jason Hiser's avatar Jason Hiser :tractor:
Browse files

first draft

parent 2f3880a6
No related branches found
No related tags found
No related merge requests found
......@@ -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/
......
......@@ -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);
}
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment