#include "extractfunction.hpp" #include "le_parse_util.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 << ".asm"; 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); _DecodeType dt = Decode32Bits; unsigned int decodedInstructionsCount = 0; std::vector code_buf = load_binary(file); _CodeInfo ci; ci.code = code_buf.data() + function_offset; ci.codeLen = code_buf.size() - function_offset; ci.codeOffset = function_offset; ci.dt = dt; ci.features = DF_RETURN_FC_ONLY | DF_STOP_ON_FLOW_CONTROL; binparse::Offset32 furthestjmp; bool done = false; std::cout << "Scanning function: " << function_offset << std::endl; while(!done) { _DInst decinst; 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)); _DecodedInst inst; distorm_format64(&ci, &decinst, &inst); //std::cout << inst.mnemonic.p << " " << inst.operands.p << std::endl; //std::cout << "target: " << target << std::endl; if(decinst.ops[0].type == O_PC || decinst.ops[0].type == O_PTR || decinst.ops[0].type == O_DISP) { //extract_function(file_path, object_id, target); } else if (decinst.ops[0].type == O_SMEM) { std::cout << "unhandled case: " << inst.mnemonic.p << " " << inst.operands.p << std::endl; } else { std::cout << "unrecognized case: " << inst.mnemonic.p << " " << inst.operands.p << std::endl; } 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 << "syscall:\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 << binparse::Offset32(ci.codeOffset) << " " << 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() + function_offset; ci.nextOffset = 0; ci.codeLen = code_buf.size() - function_offset; ci.codeOffset = function_offset; ci.dt = dt; ci.features = DF_NONE; while(ci.nextOffset < end) { _DInst decinst; 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 << binparse::Offset32(inst.offset) << " " << inst.mnemonic.p << " " << inst.operands.p << std::endl; auto distance = ci.nextOffset - ci.codeOffset; ci.code += distance; ci.codeLen -= distance; ci.codeOffset += distance; } }