Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • opensrc/zipr
  • whh8b/zipr
2 results
Show changes
Commits on Source (14)
Subproject commit bbdd7856d55d503584789132787d151628ffc423
Subproject commit 1937bc5ab305f4d5ae5cecf4d27e244420349a5b
......@@ -28,6 +28,12 @@
#include "elfio/elfio.hpp"
#include "split_eh_frame.hpp"
#include "back_search.hpp"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include <pe_bliss.h>
#include <pe_structures.h>
#pragma GCC diagnostic pop
using namespace std;
using namespace EXEIO;
......@@ -68,7 +74,9 @@ void PopulateCFG::populate_instruction_map
void PopulateCFG::set_fallthrough
(
InstructionMap_t &insnMap,
DecodedInstruction_t *disasm, Instruction_t *insn, FileIR_t *firp
DecodedInstruction_t *disasm,
Instruction_t *insn,
FileIR_t *firp
)
{
assert(disasm);
......@@ -77,14 +85,20 @@ void PopulateCFG::set_fallthrough
if(insn->getFallthrough())
return;
// check for branches with targets
if(
(disasm->isUnconditionalBranch() ) || // it is a unconditional branch
(disasm->isReturn()) // or a return
)
const auto is_mips = firp->getArchitecture()->getMachineType() == admtMips32;
// always set fallthrough for mips
// other platforms can end fallthroughs ofr uncond branches and returns
if(!is_mips)
{
// this is a branch with no fallthrough instruction
return;
// check for branches with targets
if(
(disasm->isUnconditionalBranch() ) || // it is a unconditional branch
(disasm->isReturn()) // or a return
)
{
// this is a branch with no fallthrough instruction
return;
}
}
/* get the address of the next instrution */
......@@ -127,17 +141,14 @@ void PopulateCFG::set_delay_slots
if(!is_mips)
return;
for(auto &insn : firp->getInstructions())
// using df=DecodedInstruction_t::factory;
const auto d=DecodedInstruction_t::factory(insn);
if(d->isBranch())
{
// using df=DecodedInstruction_t::factory;
const auto d=DecodedInstruction_t::factory(insn);
if(d->isBranch())
{
const auto branch_addr = insn->getAddress();
const auto delay_slot_insn = insnMap[ {branch_addr->getFileID(), branch_addr->getVirtualOffset() + 4}];
assert(delay_slot_insn);
(void)firp->addNewRelocation(insn,0,"delay_slot1", delay_slot_insn, 0);
}
const auto branch_addr = insn->getAddress();
const auto delay_slot_insn = insnMap[ {branch_addr->getFileID(), branch_addr->getVirtualOffset() + 4}];
assert(delay_slot_insn);
(void)firp->addNewRelocation(insn,0,"delay_slot1", delay_slot_insn, 0);
}
}
......@@ -679,60 +690,7 @@ void PopulateCFG::detect_scoops_in_code(FileIR_t *firp)
void PopulateCFG::ctor_detection(FileIR_t *firp)
{
assert(firp);
if(do_ctor_detection == cdt_NO) return;
const auto is_pe = firp->getArchitecture()->getFileType() == adftPE ;
if(do_ctor_detection == cdt_PE32AUTO && !is_pe) return;
// is either a PE file and we are in auto detect mode
// or ctor_detection is yes.
assert(is_pe || do_ctor_detection == cdt_YES);
auto find_ctor_start=[&](const exeio_section_t* sec, const VirtualOffset_t end_of_ctor) -> VirtualOffset_t
{
// values needed later for various things
const auto ptrsize = firp->getArchitectureBitWidth() / 8 ;
const auto sec_data = sec->get_data();
const auto sec_start = sec->get_address();
// check for a null terminator at the stated end of table
const auto null_term_addr=end_of_ctor-ptrsize;
const auto null_term_value =
ptrsize == 8 ? *(uint64_t*)(sec_data+null_term_addr-sec_start) :
ptrsize == 4 ? *(uint32_t*)(sec_data+null_term_addr-sec_start) :
throw invalid_argument("Unknown ptrsize");
// not found, return this isn't sane.
if(null_term_value!=0) return 0;
// now scan the table in reverse order for 1) valid entries, or 2) a -1 terminator.
auto next_addr=null_term_addr-ptrsize;
while(true)
{
// check for flowing
if(next_addr<sec_start) return 0;
// get the table entry
const auto ctor_entry_value =
ptrsize == 8 ? *(uint64_t*)(sec_data+next_addr-sec_start) :
ptrsize == 4 ? *(uint32_t*)(sec_data+next_addr-sec_start) :
throw invalid_argument("Unknown ptrsize");
// check for the -1 terminator
if(ptrsize == 8 && (int64_t)ctor_entry_value==int64_t(-1)) return next_addr;
if(ptrsize == 4 && (int32_t)ctor_entry_value==int32_t(-1)) return next_addr;
// check if the table entry isn't a valid address
const auto is_before_start = ctor_entry_value < sec->get_address() ;
const auto is_after_end = ctor_entry_value > (sec->get_address()+sec->get_size());
if(is_before_start || is_after_end) return 0;
next_addr -= ptrsize;
}
};
auto create_ctor_scoop=[&](const string& name, const VirtualOffset_t& start_vo, const VirtualOffset_t& end_vo)
const auto create_text_scoop=[&](const string& name, const VirtualOffset_t& start_vo, const VirtualOffset_t& end_vo)
{
auto startaddr = firp->addNewAddress(firp->getFile()->getBaseID(), start_vo); // start and end address
auto endaddr = firp->addNewAddress(firp->getFile()->getBaseID(), end_vo);
......@@ -752,19 +710,196 @@ void PopulateCFG::ctor_detection(FileIR_t *firp)
cout << "Added ctor/dtor scoop called " << name << " at " << hex << start_vo << "-" << end_vo << endl;
};
const auto text_sec = exeiop->sections[".text"];
if(text_sec == nullptr) return;
const auto text_end_addr = text_sec->get_address()+text_sec->get_size();
const auto dtor_end = text_end_addr-1;
const auto dtor_start = find_ctor_start(text_sec,text_end_addr);
if(dtor_start==0) return;
create_ctor_scoop(".dtor", dtor_start, dtor_end);
const auto ctor_end = dtor_start-1;
const auto ctor_start = find_ctor_start(text_sec,dtor_start);
if(ctor_start==0) return;
create_ctor_scoop(".ctor", ctor_start, ctor_end);
return;
const auto gnustyle = [&]() -> bool
{
assert(firp);
if(do_ctor_detection == cdt_NO) return false;
const auto is_pe = firp->getArchitecture()->getFileType() == adftPE ;
if(do_ctor_detection == cdt_PE32AUTO && !is_pe) return false;
// is either a PE file and we are in auto detect mode
// or ctor_detection is yes.
assert(is_pe || do_ctor_detection == cdt_YES);
auto find_ctor_start=[&](const exeio_section_t* sec, const VirtualOffset_t end_of_ctor) -> VirtualOffset_t
{
// values needed later for various things
const auto ptrsize = firp->getArchitectureBitWidth() / 8 ;
const auto sec_data = sec->get_data();
const auto sec_start = sec->get_address();
// check for a null terminator at the stated end of table
const auto null_term_addr=end_of_ctor-ptrsize;
const auto null_term_value =
ptrsize == 8 ? *(uint64_t*)(sec_data+null_term_addr-sec_start) :
ptrsize == 4 ? *(uint32_t*)(sec_data+null_term_addr-sec_start) :
throw invalid_argument("Unknown ptrsize");
// not found, return this isn't sane.
if(null_term_value!=0) return 0;
// now scan the table in reverse order for 1) valid entries, or 2) a -1 terminator.
auto next_addr=null_term_addr-ptrsize;
while(true)
{
// check for flowing
if(next_addr<sec_start) return 0;
// get the table entry
const auto ctor_entry_value =
ptrsize == 8 ? *(uint64_t*)(sec_data+next_addr-sec_start) :
ptrsize == 4 ? *(uint32_t*)(sec_data+next_addr-sec_start) :
throw invalid_argument("Unknown ptrsize");
// check for the -1 terminator
if(ptrsize == 8 && (int64_t)ctor_entry_value==int64_t(-1)) return next_addr;
if(ptrsize == 4 && (int32_t)ctor_entry_value==int32_t(-1)) return next_addr;
// check if the table entry isn't a valid address
const auto is_before_start = ctor_entry_value < sec->get_address() ;
const auto is_after_end = ctor_entry_value > (sec->get_address()+sec->get_size());
if(is_before_start || is_after_end) return 0;
next_addr -= ptrsize;
}
};
const auto text_sec = exeiop->sections[".text"];
if(text_sec == nullptr) return false;
const auto text_end_addr = text_sec->get_address()+text_sec->get_size();
const auto dtor_end = text_end_addr-1;
const auto dtor_start = find_ctor_start(text_sec,text_end_addr);
if(dtor_start==0) return false;
create_text_scoop(".dtor", dtor_start, dtor_end);
const auto ctor_end = dtor_start-1;
const auto ctor_start = find_ctor_start(text_sec,dtor_start);
if(ctor_start==0) return false;
create_text_scoop(".ctor", ctor_start, ctor_end);
return true;
};
#if 0
const auto winstyle = [&]() -> bool
{
const auto reloc_sec = exeiop->sections[".reloc"];
if(reloc_sec == nullptr) return false;
const auto reloc_data = string(reloc_sec->get_data(), reloc_sec->get_size());
const auto peblissp = static_cast<pe_bliss::pe_base*>(exeiop->get_pebliss());
if(peblissp == nullptr) return false;
const auto pe_image_base = peblissp->get_image_base_64();
// for each block in the reloc section
using reloc_block_header_t =
struct
{
uint32_t page;
uint32_t block_size;
};
using reloc_block_t =
struct
{
uint16_t offset:12; // lower bits
uint16_t type:4; // higher bits than offset?
};
static_assert(sizeof(reloc_block_header_t)==8, "size of reloc_block_header is wrong");
static_assert(sizeof(reloc_block_t)==2, "size of reloc_block is wrong");
// start at block 0
auto current_offset = VirtualOffset_t(0);
while(true)
{
// stop if we fall off the end of the section.
if(current_offset + sizeof(reloc_block_header_t) > static_cast<size_t>(reloc_sec->get_size()))
break;
// read the header
auto header = reloc_block_header_t();
memcpy(&header, &reloc_data.c_str()[current_offset], sizeof(header));
// start counting the length after we've read the header.
auto current_length = size_t(sizeof(header));
// for each entry in the block
while(true)
{
// stop if we exceed the block
if(current_length + sizeof(reloc_block_t) > header.block_size)
break;
// stop if we exceed the section
if(current_offset + current_length + sizeof(reloc_block_t) > static_cast<size_t>(reloc_sec->get_size()))
break;
// read the block
auto block = reloc_block_t();
memcpy(&block, &reloc_data.c_str()[current_offset+current_length], sizeof(block));
current_length += sizeof(block);
// for now, just log
const auto rva = pe_image_base + header.page + block.offset;
cout << "reloc rva = " << hex << rva << " type = " << block.type << '\n';
switch(block.type)
{
case pe_bliss::pe_win::image_rel_based_absolute: /* ignored */
break;
case pe_bliss::pe_win::image_rel_based_dir64: /* dir64 */
{
const auto relocd_sec = exeiop->sections.findByAddress(rva);
if(!relocd_sec) throw runtime_error("Unexpected relocation address?");
const auto relocd_sec_name = relocd_sec->get_name();
if(relocd_sec_name != ".text") // no need to pin anything besides the text seg.
continue; // try next block
const auto new_name = "winstyle_scoop_"+to_string(rva);
create_text_scoop(new_name, rva, rva+8);
break;
}
default:
throw runtime_error("Cannot handle PE relocation.");
}
}
// update to the next block
current_offset += current_length;
}
return true;
};
const auto scoopify_data_dir_sections = [&]()
{
const auto peblissp = static_cast<pe_bliss::pe_base*>(exeiop->get_pebliss());
for(auto dir=0u; dir<15; dir++)
{
if(!peblissp->directory_exists(dir))
continue;
const auto dir_rva = peblissp->get_directory_rva (dir);
const auto dir_size = peblissp->get_directory_size(dir);
cout << "Directory " << dec << dir << " is at " << hex << dir_rva << " - " << dir_rva+dir_size << '\n';
}
};
#endif
// scoopify_data_dir_sections();
if(gnustyle()) return;
// if(winstyle()) return;
cerr << "Caution! Could not find any reloc handling for ctor/dtor and/or plts." << endl;
}
......
......@@ -4114,12 +4114,17 @@ int executeStep()
}
catch (DatabaseError_t pnide)
{
cout<<"Unexpected database error: "<<pnide<<endl;
cout << "Unexpected database error: " << pnide << endl;
return -1;
}
catch (const exception& e)
{
cout << "Unexpected error: " << e.what() << endl;
return -1;
}
catch(...)
{
cerr<<"Unexpected error"<<endl;
cerr << "Unexpected error" << endl;
return -1;
}
......
......@@ -572,9 +572,15 @@ split_eh_frame_impl_t<ptrsize>::split_eh_frame_impl_t(FileIR_t* p_firp)
eh_frame_hdr_scoop=lookup_scoop_by_name(".eh_frame_hdr");
gcc_except_table_scoop=lookup_scoop_by_name(".gcc_except_table");
const auto endian_type =
firp->getArchitecture()->getMachineType() == admtMips32 ? EHP::BIG :
EHP::LITTLE;
eh_frame_parser=EHFrameParser_t::factory
(
ptrsize,
endian_type,
scoop_contents(eh_frame_scoop), scoop_address(eh_frame_scoop),
scoop_contents(eh_frame_hdr_scoop), scoop_address(eh_frame_hdr_scoop),
scoop_contents(gcc_except_table_scoop), scoop_address(gcc_except_table_scoop)
......@@ -636,7 +642,10 @@ class pe_eh_split_t
cout << "\tfp reg " << +exc.get_frame_pointer_register_number() << endl;
cout << "\tscaled rsp offset " << +exc.get_scaled_rsp_offset() << endl;
const auto unwind_addr = exc.get_unwind_info_address();
const auto unwind_addr = exc.get_unwind_info_address();
if(unwind_addr == 0)
continue; // no unwind info
const auto &unwind_sec = peb_obj->section_from_rva(unwind_addr);
const auto next_unwind_addr = i < edd.size() ? // last element?
edd[i+1].get_unwind_info_address() : // yes: value from start of next unwind info entry
......@@ -742,7 +751,7 @@ void split_eh_frame(FileIR_t* firp, exeio *exeiop)
{
if( firp->getArchitecture()->getFileType()==adftPE )
{
pe_eh_split_t<64>(firp,exeiop).split_pe_file();
// pe_eh_split_t<64>(firp,exeiop).split_pe_file();
}
else
......
......@@ -163,7 +163,7 @@ namespace EXEIO
virtual bool isDLL() { return true; }
virtual void* get_pebliss() { assert(e); return (void*)e; }
virtual void* get_pebliss() { assert(e); return static_cast<void*>(e); }
private:
pe_bliss::pe_base* e;
......
#ifndef cmdstr_hpp
#define cmdstr_hpp
/*BINFMTCXX: -std=c++11 -Wall -Werror
*/
#include <spawn.h> // see manpages-posix-dev
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
static inline pair<string,int> command_to_string( const string& command)
{
auto ret=string();
int exit_code=0;
int cout_pipe[2];
int cerr_pipe[2];
posix_spawn_file_actions_t action;
if(pipe(cout_pipe) || pipe(cerr_pipe))
cout << "pipe returned an error.\n";
posix_spawn_file_actions_init(&action);
posix_spawn_file_actions_addclose(&action, cout_pipe[0]);
posix_spawn_file_actions_addclose(&action, cerr_pipe[0]);
posix_spawn_file_actions_adddup2(&action, cout_pipe[1], 1);
posix_spawn_file_actions_adddup2(&action, cerr_pipe[1], 2);
posix_spawn_file_actions_addclose(&action, cout_pipe[1]);
posix_spawn_file_actions_addclose(&action, cerr_pipe[1]);
// string command = "echo bla"; // example #1
// string command = "pgmcrater -width 64 -height 9 |pgmtopbm |pnmtoplainpnm";
vector<char> argsmem[] = {{'s', 'h', '\0'}, {'-', 'c', '\0'}}; // allows non-const access to literals
char *args[] = {&argsmem[0][0], &argsmem[1][0],const_cast<char*>(command.c_str()),nullptr};
pid_t pid;
if(posix_spawnp(&pid, args[0], &action, NULL, args, environ) != 0)
cout << "posix_spawnp failed with error: " << strerror(errno) << "\n";
close(cout_pipe[1]), close(cerr_pipe[1]); // close child-side of pipes
// Read from pipes
string buffer(1024,' ');
std::vector<pollfd> plist = { {cout_pipe[0],POLLIN}, {cerr_pipe[0],POLLIN} };
for ( int rval; (rval=poll(&plist[0],plist.size(),/*timeout*/-1))>0; )
{
if ( plist[0].revents&POLLIN) {
const auto bytes_read = read(cout_pipe[0], &buffer[0], buffer.length());
// cout << "read " << bytes_read << " bytes from stdout.\n";
// cout << buffer.substr(0, static_cast<size_t>(bytes_read)) << "\n";
ret += buffer.substr(0, static_cast<size_t>(bytes_read));
}
else if ( plist[1].revents&POLLIN ) {
const auto bytes_read = read(cerr_pipe[0], &buffer[0], buffer.length());
// cout << "read " << bytes_read << " bytes from stderr.\n";
// cout << buffer.substr(0, static_cast<size_t>(bytes_read)) << "\n";
ret += buffer.substr(0, static_cast<size_t>(bytes_read));
}
else
break; // nothing left to read
}
waitpid(pid,&exit_code,0);
cout << "exit code: " << exit_code << "\n";
posix_spawn_file_actions_destroy(&action);
return {ret,exit_code};
}
#endif
......@@ -32,6 +32,8 @@
#include <irdb-util>
#include <endian.h>
#include "cmdstr.hpp"
using namespace libIRDB;
using namespace std;
......@@ -44,26 +46,11 @@ using namespace std;
int command_to_stream(const string& command, ostream& stream)
{
auto redirect_command=command+" 2>&1 ";
auto buffer=array<char,128>();
std::cout << "Issuing subcommand: "<< command << std::endl;
auto pipe = popen(redirect_command.c_str(), "r");
if (!pipe)
{
stream << "Couldn't start command:"<< strerror(errno) << endl;
return 1;
}
while (fgets(buffer.data(), 128, pipe) != NULL)
{
stream<<buffer.data();
}
auto returnCode = pclose(pipe);
if(returnCode==-1)
stream << "Could not close pipe: "<< strerror(errno) << endl;
cout << "Issuing command: " << command << endl;
const auto res = command_to_string(command);
std::cout << "Return code = "<<returnCode << std::endl;
return returnCode;
stream << res.first << endl;
return res.second;
}
static void UpdateEntryPoints(
......
Subproject commit 40d475c2ea20ba07adfd138708e7e684c1adecb3
Subproject commit 2b640f5e65afd7c41df59ef6416fae46f46a929e
......@@ -73,11 +73,12 @@ class CreateFunctions_t
exit(1);
}
const auto cs_mode=
machine_type == mtArm32 ? CS_MODE_LITTLE_ENDIAN :
machine_type == mtAarch64 ? CS_MODE_LITTLE_ENDIAN :
file_class == ELF64 ? CS_MODE_64 :
file_class == ELF32 ? CS_MODE_32 :
const auto my_cs_mode =
machine_type == mtArm32 ? cs_mode(CS_MODE_LITTLE_ENDIAN) :
machine_type == mtAarch64 ? cs_mode(CS_MODE_LITTLE_ENDIAN) :
machine_type == mtMips32 ? cs_mode(CS_MODE_MIPS32 | CS_MODE_BIG_ENDIAN) :
file_class == ELF64 ? cs_mode(CS_MODE_64) :
file_class == ELF32 ? cs_mode(CS_MODE_32) :
throw std::runtime_error("Cannot handle ELF class");
const auto my_cs_arch =
......@@ -85,9 +86,10 @@ class CreateFunctions_t
machine_type == mtI386 ? CS_ARCH_X86 :
machine_type == mtArm32 ? CS_ARCH_ARM :
machine_type == mtAarch64 ? CS_ARCH_ARM64 :
machine_type == mtMips32 ? CS_ARCH_MIPS :
throw std::runtime_error("Cannot handle architecture");
if (cs_open(my_cs_arch, cs_mode , &cshandle) != CS_ERR_OK)
if (cs_open(my_cs_arch, my_cs_mode , &cshandle) != CS_ERR_OK)
{
cerr<<"Cannot initialize capstone"<<endl;
exit(1);
......
Subproject commit ef66c8c98ee8e67095e0f5f1566d9e89da5f49e0
Subproject commit ac13ebc803c4ca1fa32887500fe2fe4cb520f690