#include "extractfunction.hpp" #include "leparseutil.hpp" #include "output.hpp" #include #include #include #include void extract_function(std::string file_path, binparse::Value32 object_id, binparse::Offset32 function_offset) { std::stringstream ss; ss << "f_" << function_offset << ".a"; std::string o_file = ss.str(); if(boost::filesystem::exists(o_file)) { return; } std::ofstream output(o_file); std::ifstream ifs(file_path, std::ios::binary); ifs.unsetf(std::ios::skipws); auto file = parse_file(ifs); _DInst decinst; _DecodeType dt = Decode32Bits; unsigned int decodedInstructionsCount = 0; std::vector code_buf = read_object(ifs, file, object_id); binparse::Offset32 base_reloc_offset = file.object_table.entries[object_id].reloc_base_address; binparse::Offset32 buffer_offset = binparse::Offset32(function_offset - base_reloc_offset); _CodeInfo ci; ci.code = code_buf.data() + buffer_offset; ci.codeLen = code_buf.size() - buffer_offset; ci.codeOffset = base_reloc_offset + buffer_offset; ci.dt = dt; ci.features = DF_RETURN_FC_ONLY | DF_STOP_ON_FLOW_CONTROL; binparse::Offset32 furthestjmp; bool done = false; while(!done) { distorm_decompose64(&ci, &decinst, 1, &decodedInstructionsCount); if(decinst.flags == FLAG_NOT_DECODABLE) { throw std::runtime_error("Could not decode the next instruction"); } switch(META_GET_FC(decinst.meta)) { case FC_CALL: { binparse::Offset32 target = binparse::Offset32(INSTRUCTION_GET_TARGET(&decinst)); std::cout << binparse::Offset32(ci.codeOffset) << " " << target << std::endl; extract_function(file_path, object_id, target); break; } case FC_CMOV: { //std::cout << "CMOV /care:\t"; break; } case FC_CND_BRANCH: { binparse::Offset32 target = binparse::Offset32(INSTRUCTION_GET_TARGET(&decinst)); if(target > furthestjmp) { furthestjmp = target; } //std::cout << "CJMP:\t"; break; } case FC_INT: { //std::cout << "Int:\t"; break; } case FC_RET: { if(binparse::Offset32(ci.nextOffset) > furthestjmp) { done = true; } //std::cout << "Return:\t"; break; } case FC_SYS: { //std::cout << "SYS?!?:\t"; break; } case FC_UNC_BRANCH: { binparse::Offset32 target = binparse::Offset32(INSTRUCTION_GET_TARGET(&decinst)); if(target > furthestjmp) { furthestjmp = target; } //std::cout << "JMP:\t"; break; } case FC_NONE: default: { throw std::runtime_error("This should never happen."); } } /* _DecodedInst inst; distorm_format64(&ci, &decinst, &inst); std::cout << std::hex << std::setw(8) << std::setfill('0') << inst.offset << ":\t" << inst.mnemonic.p << " " << inst.operands.p << std::endl; */ if(!done) { auto distance = ci.nextOffset - ci.codeOffset; ci.code += distance; ci.codeLen -= distance; ci.codeOffset += distance; } } std::cout << "Function starts at: " << function_offset << std::endl; std::cout << "Function ends at: " << binparse::Offset32(ci.nextOffset) << std::endl; auto end = ci.nextOffset; ci.code = code_buf.data() + buffer_offset; ci.nextOffset = 0; ci.codeLen = code_buf.size() - buffer_offset; ci.codeOffset = base_reloc_offset + buffer_offset; ci.dt = dt; ci.features = DF_NONE; while(ci.nextOffset < end) { distorm_decompose(&ci, &decinst, 1, &decodedInstructionsCount); _DecodedInst inst; distorm_format64(&ci, &decinst, &inst); std::cout << std::hex << std::setw(8) << std::setfill('0') << inst.offset << ":\t" << inst.mnemonic.p << " " << inst.operands.p << std::endl; output << inst.mnemonic.p << " " << inst.operands.p << std::endl; auto distance = ci.nextOffset - ci.codeOffset; ci.code += distance; ci.codeLen -= distance; ci.codeOffset += distance; } }