summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-09-10 19:44:33 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-09-10 19:44:33 +0200
commitf69d884353a23986ee40b108997ba155235d7529 (patch)
tree8c98b26445a9e54fbf30095d653cb6b94c92dbdb
parent4f65043e40dbaf8e4cc290327e34270645dedce3 (diff)
downloadopenwar-f69d884353a23986ee40b108997ba155235d7529.tar.gz
openwar-f69d884353a23986ee40b108997ba155235d7529.tar.bz2
openwar-f69d884353a23986ee40b108997ba155235d7529.zip
Working function extract, ugly but it works.
-rw-r--r--disasm/extractfunction.cpp94
1 files changed, 87 insertions, 7 deletions
diff --git a/disasm/extractfunction.cpp b/disasm/extractfunction.cpp
index 4fb675c..1af481e 100644
--- a/disasm/extractfunction.cpp
+++ b/disasm/extractfunction.cpp
@@ -2,6 +2,8 @@
#include "leparseutil.hpp"
+#include "output.hpp"
+
#include <distorm.h>
#include <iomanip>
@@ -28,22 +30,100 @@ void extract_function(std::string file_path, binparse::Value32 object_id, binpar
ci.codeLen = code_buf.size() - buffer_offset;
ci.codeOffset = base_reloc_offset + buffer_offset;
ci.dt = dt;
- ci.features = DF_NONE;
+ ci.features = DF_RETURN_FC_ONLY | DF_STOP_ON_FLOW_CONTROL;
+
+ std::cout << "Function starts at: " << function_offset << std::endl;
- while(true) {
+ binparse::Offset32 furthestjmp;
+
+ bool done = false;
+ while(!done) {
distorm_decompose64(&ci, &decinst, 1, &decodedInstructionsCount);
if(decinst.flags == FLAG_NOT_DECODABLE) {
- break;
+ throw std::runtime_error("Could not decode the next instruction");
}
-
+
+ switch(META_GET_FC(decinst.meta)) {
+ case FC_CALL: {
+ //std::cout << "Call:\t";
+ 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 += decinst.size;
- ci.codeLen -= decinst.size;
- ci.codeOffset += decinst.size;
+ ci.code += distance;
+ ci.codeLen -= distance;
+ ci.codeOffset += distance;
+ }
+ }
+ std::cout << "Function ends at: " << binparse::Offset32(ci.nextOffset) << std::endl;
+
+ std::vector<_DecodedInst> instructions;
+ instructions.resize(100000);
+ unsigned int read_inst;
+
+ auto result = distorm_decode64(
+ file.object_table.entries[object_id].reloc_base_address + buffer_offset,
+ code_buf.data() + buffer_offset,
+ ci.nextOffset - function_offset,
+ Decode32Bits,
+ instructions.data(),
+ instructions.size(),
+ &read_inst
+ );
+
+ instructions.resize(read_inst);
+ instructions.shrink_to_fit();
+
+ for(auto&& inst : instructions) {
+ std::cout << std::hex << std::setw(8) << std::setfill('0') << inst.offset << ":\t" << inst.mnemonic.p << " " << inst.operands.p << std::endl;
}
}