From fa2db577990a9436c9e44b63daa0b3ee74a039a9 Mon Sep 17 00:00:00 2001 From: "Mr. eXoDia" Date: Wed, 22 Jun 2016 17:28:54 +0200 Subject: [PATCH] DBG: AStyle --- src/dbg/advancedanalysis.cpp | 746 +++++++++++++++---------------- src/dbg/advancedanalysis.h | 302 ++++++------- src/dbg/datainst_helper.cpp | 618 +++++++++++++------------- src/dbg/datainst_helper.h | 22 +- src/dbg/debugger_commands.cpp | 4 +- src/dbg/encodemap.cpp | 762 ++++++++++++++++---------------- src/dbg/encodemap.h | 50 +-- src/dbg/module.cpp | 6 +- src/dbg/x64_dbg.cpp | 2 +- src/gui/Src/Utils/EncodeMap.cpp | 408 ++++++++--------- src/gui/Src/Utils/EncodeMap.h | 64 +-- 11 files changed, 1492 insertions(+), 1492 deletions(-) diff --git a/src/dbg/advancedanalysis.cpp b/src/dbg/advancedanalysis.cpp index 0317b0d4..604003ee 100644 --- a/src/dbg/advancedanalysis.cpp +++ b/src/dbg/advancedanalysis.cpp @@ -1,373 +1,373 @@ -#include "advancedanalysis.h" -#include -#include "console.h" -#include "filehelper.h" -#include "function.h" -#include "xrefs.h" -#include "encodemap.h" - -AdvancedAnalysis::AdvancedAnalysis(duint base, duint size, bool dump) - : Analysis(base, size), - mDump(dump) -{ - mEncMap = new byte[size]; - memset(mEncMap, 0, size); -} - -void AdvancedAnalysis::Analyse() -{ - linearXrefPass(); - findEntryPoints(); - analyzeCandidateFunctions(true); - findFuzzyEntryPoints(); - analyzeCandidateFunctions(true); - findInvalidXrefs(); - writeDataXrefs(); -} - -void AdvancedAnalysis::SetMarkers() -{ - if(mDump) - for(const auto & function : mFunctions) - FileHelper::WriteAllText(StringUtils::sprintf("cfgraph_" fhex ".dot", function.entryPoint), function.ToDot()); - - byte* buffer = (byte*)EncodeMapGetBuffer(mBase, true); - memcpy(buffer, mEncMap, mSize); - EncodeMapReleaseBuffer(buffer); - - XrefDelRange(mBase, mBase + mSize - 1); - for(const auto & vec : mXrefs) - { - for(const auto & xref : vec.second) - { - if(xref.valid) - XrefAdd(xref.addr, xref.from); - } - } - - FunctionClear(); - for(const auto & function : mFunctions) - { - duint start = ~0; - duint end = 0; - duint icount = 0; - for(const auto & node : function.nodes) - { - icount += node.second.icount; - start = min(node.second.start, start); - end = max(node.second.end, end); - } - if(!FunctionAdd(start, end, false, icount)) - { - FunctionDelete(start); - FunctionDelete(end); - FunctionAdd(start, end, false, icount); - } - } - GuiUpdateAllViews(); -} - -void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata) -{ - //BFS through the disassembly starting at entryPoint - CFGraph graph(entryPoint); - UintSet visited; - std::queue queue; - mEntryPoints.insert(entryPoint); - queue.push(graph.entryPoint); - while(!queue.empty()) - { - auto start = queue.front(); - queue.pop(); - if(visited.count(start) || !inRange(start)) //already visited or out of range - continue; - visited.insert(start); - - CFNode node(graph.entryPoint, start, start); - while(true) - { - node.icount++; - if(!mCp.Disassemble(node.end, translateAddr(node.end))) - { - if(writedata) - mEncMap[node.end - mBase] = (byte)enc_byte; - node.end++; - continue; - } - if(writedata) - { - mEncMap[node.end - mBase] = (byte)enc_code; - for(int i = 1; i < mCp.Size(); i++) - mEncMap[node.end - mBase + i] = (byte)enc_middle; - } - if(mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop()) //jump - { - //set the branch destinations - node.brtrue = mCp.BranchDestination(); - if(mCp.GetId() != X86_INS_JMP) //unconditional jumps dont have a brfalse - node.brfalse = node.end + mCp.Size(); - - //add node to the function graph - graph.AddNode(node); - - //enqueue branch destinations - if(node.brtrue) - queue.push(node.brtrue); - if(node.brfalse) - queue.push(node.brfalse); - - break; - } - if(mCp.InGroup(CS_GRP_CALL)) //call - { - //TODO: handle no return - duint target = mCp.BranchDestination(); - if(inRange(target) && mEntryPoints.find(target) == mEntryPoints.end()) - mCandidateEPs.insert(target); - } - if(mCp.InGroup(CS_GRP_RET)) //return - { - node.terminal = true; - graph.AddNode(node); - break; - } - node.end += mCp.Size(); - } - } - mFunctions.push_back(graph); -} - - -void AdvancedAnalysis::linearXrefPass() -{ - dputs("Starting xref analysis..."); - auto ticks = GetTickCount(); - - for(auto addr = mBase; addr < mBase + mSize;) - { - if(!mCp.Disassemble(addr, translateAddr(addr))) - { - addr++; - continue; - } - addr += mCp.Size(); - - XREF xref; - xref.valid = true; - xref.addr = 0; - xref.from = mCp.Address(); - for(auto i = 0; i < mCp.OpCount(); i++) - { - duint dest = mCp.ResolveOpValue(i, [](x86_reg)->size_t - { - return 0; - }); - if(inRange(dest)) - { - xref.addr = dest; - break; - } - } - if(xref.addr) - { - if(mCp.InGroup(CS_GRP_CALL)) - xref.type = XREF_CALL; - else if(mCp.InGroup(CS_GRP_JUMP)) - xref.type = XREF_JMP; - else - xref.type = XREF_DATA; - - auto found = mXrefs.find(xref.addr); - if(found == mXrefs.end()) - { - std::vector vec; - vec.push_back(xref); - mXrefs[xref.addr] = vec; - } - else - { - found->second.push_back(xref); - } - } - } - - dprintf("%u xrefs found in %ums!\n", mXrefs.size(), GetTickCount() - ticks); -} - -void AdvancedAnalysis::findInvalidXrefs() -{ - for(auto & vec : mXrefs) - { - duint jmps = 0, calls = 0; - duint addr = vec.first; - byte desttype = mEncMap[vec.first - mBase]; - for(auto & xref : vec.second) - { - byte type = mEncMap[xref.from - mBase]; - if(desttype == enc_code && type != enc_unknown && type != enc_code) - xref.valid = false; - else if(desttype == enc_middle) - xref.valid = false; - } - } -} - -bool isFloatInstruction(x86_insn opcode) -{ - switch(opcode) - { - case X86_INS_FLD: - case X86_INS_FST: - case X86_INS_FSTP: - case X86_INS_FADD: - case X86_INS_FSUB: - case X86_INS_FSUBR: - case X86_INS_FMUL: - case X86_INS_FDIV: - case X86_INS_FDIVR: - case X86_INS_FCOM: - case X86_INS_FCOMP: - - return true; - default: - return false; - } -} - -void AdvancedAnalysis::writeDataXrefs() -{ - for(auto & vec : mXrefs) - { - for(auto & xref : vec.second) - { - if(xref.type == XREF_DATA && xref.valid) - { - if(!mCp.Disassemble(xref.from, translateAddr(xref.from))) - { - xref.valid = false; - continue; - } - auto opcode = mCp.GetId(); - bool isfloat = isFloatInstruction(opcode); - for(auto i = 0; i < mCp.OpCount(); i++) - { - auto & op = mCp[i]; - ENCODETYPE type = enc_unknown; - - //Todo: Analyze op type and set correct type - if(op.type == X86_OP_MEM) - { - duint datasize = op.size; - duint size = datasize; - duint offset = xref.addr - mBase; - switch(op.size) - { - case 1: - type = enc_byte; - break; - case 2: - type = enc_word; - break; - case 4: - type = isfloat ? enc_real4 : enc_dword; - break; - case 6: - type = enc_fword; - break; - case 8: - type = isfloat ? enc_real8 : enc_qword; - break; - case 10: - type = isfloat ? enc_real10 : enc_tbyte; - break; - case 16: - type = enc_oword; - break; - case 32: - type = enc_ymmword; - break; - //case 64: type = enc_zmmword; break; - } - if(datasize == 1) - { - memset(mEncMap + offset, (byte)type, size); - } - else - { - memset(mEncMap + offset, (byte)enc_middle, size); - for(duint i = offset; i < offset + size; i += datasize) - mEncMap[i] = (byte)type; - } - } - } - } - } - } -} - -void AdvancedAnalysis::findFuzzyEntryPoints() -{ - for(const auto & entryPoint : mFuzzyEPs) - { - mCandidateEPs.insert(entryPoint); - } -} - -void AdvancedAnalysis::findEntryPoints() -{ - duint modbase = ModBaseFromAddr(mBase); - if(modbase) - { - apienumexports(modbase, [&](duint Base, const char* Module, const char* Name, duint Address) - { - // If within limits... - if(inRange(Address)) - { - mCandidateEPs.insert(Address); - } - }); - } - - - for(const auto & vec : mXrefs) - { - duint jmps = 0, calls = 0; - duint addr = vec.first; - for(const auto & xref : vec.second) - { - if(xref.type == XREF_CALL) - calls++; - else if(xref.type == XREF_JMP) - jmps++; - } - if(calls >= 1 && jmps + calls > 1) - mCandidateEPs.insert(addr); - else if(calls >= 1) - mFuzzyEPs.insert(addr); - } -} - -void AdvancedAnalysis::analyzeCandidateFunctions(bool writedata) -{ - std::unordered_set pendingEPs; - while(true) - { - pendingEPs.clear(); - if(mCandidateEPs.size() == 0) - return; - for(const auto & entryPoint : mCandidateEPs) - { - pendingEPs.insert(entryPoint); - } - mCandidateEPs.clear(); - - for(const auto & entryPoint : pendingEPs) - { - if(mEntryPoints.find(entryPoint) == mEntryPoints.end()) - { - analyzeFunction(entryPoint, true); - } - } - } - -} +#include "advancedanalysis.h" +#include +#include "console.h" +#include "filehelper.h" +#include "function.h" +#include "xrefs.h" +#include "encodemap.h" + +AdvancedAnalysis::AdvancedAnalysis(duint base, duint size, bool dump) + : Analysis(base, size), + mDump(dump) +{ + mEncMap = new byte[size]; + memset(mEncMap, 0, size); +} + +void AdvancedAnalysis::Analyse() +{ + linearXrefPass(); + findEntryPoints(); + analyzeCandidateFunctions(true); + findFuzzyEntryPoints(); + analyzeCandidateFunctions(true); + findInvalidXrefs(); + writeDataXrefs(); +} + +void AdvancedAnalysis::SetMarkers() +{ + if(mDump) + for(const auto & function : mFunctions) + FileHelper::WriteAllText(StringUtils::sprintf("cfgraph_" fhex ".dot", function.entryPoint), function.ToDot()); + + byte* buffer = (byte*)EncodeMapGetBuffer(mBase, true); + memcpy(buffer, mEncMap, mSize); + EncodeMapReleaseBuffer(buffer); + + XrefDelRange(mBase, mBase + mSize - 1); + for(const auto & vec : mXrefs) + { + for(const auto & xref : vec.second) + { + if(xref.valid) + XrefAdd(xref.addr, xref.from); + } + } + + FunctionClear(); + for(const auto & function : mFunctions) + { + duint start = ~0; + duint end = 0; + duint icount = 0; + for(const auto & node : function.nodes) + { + icount += node.second.icount; + start = min(node.second.start, start); + end = max(node.second.end, end); + } + if(!FunctionAdd(start, end, false, icount)) + { + FunctionDelete(start); + FunctionDelete(end); + FunctionAdd(start, end, false, icount); + } + } + GuiUpdateAllViews(); +} + +void AdvancedAnalysis::analyzeFunction(duint entryPoint, bool writedata) +{ + //BFS through the disassembly starting at entryPoint + CFGraph graph(entryPoint); + UintSet visited; + std::queue queue; + mEntryPoints.insert(entryPoint); + queue.push(graph.entryPoint); + while(!queue.empty()) + { + auto start = queue.front(); + queue.pop(); + if(visited.count(start) || !inRange(start)) //already visited or out of range + continue; + visited.insert(start); + + CFNode node(graph.entryPoint, start, start); + while(true) + { + node.icount++; + if(!mCp.Disassemble(node.end, translateAddr(node.end))) + { + if(writedata) + mEncMap[node.end - mBase] = (byte)enc_byte; + node.end++; + continue; + } + if(writedata) + { + mEncMap[node.end - mBase] = (byte)enc_code; + for(int i = 1; i < mCp.Size(); i++) + mEncMap[node.end - mBase + i] = (byte)enc_middle; + } + if(mCp.InGroup(CS_GRP_JUMP) || mCp.IsLoop()) //jump + { + //set the branch destinations + node.brtrue = mCp.BranchDestination(); + if(mCp.GetId() != X86_INS_JMP) //unconditional jumps dont have a brfalse + node.brfalse = node.end + mCp.Size(); + + //add node to the function graph + graph.AddNode(node); + + //enqueue branch destinations + if(node.brtrue) + queue.push(node.brtrue); + if(node.brfalse) + queue.push(node.brfalse); + + break; + } + if(mCp.InGroup(CS_GRP_CALL)) //call + { + //TODO: handle no return + duint target = mCp.BranchDestination(); + if(inRange(target) && mEntryPoints.find(target) == mEntryPoints.end()) + mCandidateEPs.insert(target); + } + if(mCp.InGroup(CS_GRP_RET)) //return + { + node.terminal = true; + graph.AddNode(node); + break; + } + node.end += mCp.Size(); + } + } + mFunctions.push_back(graph); +} + + +void AdvancedAnalysis::linearXrefPass() +{ + dputs("Starting xref analysis..."); + auto ticks = GetTickCount(); + + for(auto addr = mBase; addr < mBase + mSize;) + { + if(!mCp.Disassemble(addr, translateAddr(addr))) + { + addr++; + continue; + } + addr += mCp.Size(); + + XREF xref; + xref.valid = true; + xref.addr = 0; + xref.from = mCp.Address(); + for(auto i = 0; i < mCp.OpCount(); i++) + { + duint dest = mCp.ResolveOpValue(i, [](x86_reg)->size_t + { + return 0; + }); + if(inRange(dest)) + { + xref.addr = dest; + break; + } + } + if(xref.addr) + { + if(mCp.InGroup(CS_GRP_CALL)) + xref.type = XREF_CALL; + else if(mCp.InGroup(CS_GRP_JUMP)) + xref.type = XREF_JMP; + else + xref.type = XREF_DATA; + + auto found = mXrefs.find(xref.addr); + if(found == mXrefs.end()) + { + std::vector vec; + vec.push_back(xref); + mXrefs[xref.addr] = vec; + } + else + { + found->second.push_back(xref); + } + } + } + + dprintf("%u xrefs found in %ums!\n", mXrefs.size(), GetTickCount() - ticks); +} + +void AdvancedAnalysis::findInvalidXrefs() +{ + for(auto & vec : mXrefs) + { + duint jmps = 0, calls = 0; + duint addr = vec.first; + byte desttype = mEncMap[vec.first - mBase]; + for(auto & xref : vec.second) + { + byte type = mEncMap[xref.from - mBase]; + if(desttype == enc_code && type != enc_unknown && type != enc_code) + xref.valid = false; + else if(desttype == enc_middle) + xref.valid = false; + } + } +} + +bool isFloatInstruction(x86_insn opcode) +{ + switch(opcode) + { + case X86_INS_FLD: + case X86_INS_FST: + case X86_INS_FSTP: + case X86_INS_FADD: + case X86_INS_FSUB: + case X86_INS_FSUBR: + case X86_INS_FMUL: + case X86_INS_FDIV: + case X86_INS_FDIVR: + case X86_INS_FCOM: + case X86_INS_FCOMP: + + return true; + default: + return false; + } +} + +void AdvancedAnalysis::writeDataXrefs() +{ + for(auto & vec : mXrefs) + { + for(auto & xref : vec.second) + { + if(xref.type == XREF_DATA && xref.valid) + { + if(!mCp.Disassemble(xref.from, translateAddr(xref.from))) + { + xref.valid = false; + continue; + } + auto opcode = mCp.GetId(); + bool isfloat = isFloatInstruction(opcode); + for(auto i = 0; i < mCp.OpCount(); i++) + { + auto & op = mCp[i]; + ENCODETYPE type = enc_unknown; + + //Todo: Analyze op type and set correct type + if(op.type == X86_OP_MEM) + { + duint datasize = op.size; + duint size = datasize; + duint offset = xref.addr - mBase; + switch(op.size) + { + case 1: + type = enc_byte; + break; + case 2: + type = enc_word; + break; + case 4: + type = isfloat ? enc_real4 : enc_dword; + break; + case 6: + type = enc_fword; + break; + case 8: + type = isfloat ? enc_real8 : enc_qword; + break; + case 10: + type = isfloat ? enc_real10 : enc_tbyte; + break; + case 16: + type = enc_oword; + break; + case 32: + type = enc_ymmword; + break; + //case 64: type = enc_zmmword; break; + } + if(datasize == 1) + { + memset(mEncMap + offset, (byte)type, size); + } + else + { + memset(mEncMap + offset, (byte)enc_middle, size); + for(duint i = offset; i < offset + size; i += datasize) + mEncMap[i] = (byte)type; + } + } + } + } + } + } +} + +void AdvancedAnalysis::findFuzzyEntryPoints() +{ + for(const auto & entryPoint : mFuzzyEPs) + { + mCandidateEPs.insert(entryPoint); + } +} + +void AdvancedAnalysis::findEntryPoints() +{ + duint modbase = ModBaseFromAddr(mBase); + if(modbase) + { + apienumexports(modbase, [&](duint Base, const char* Module, const char* Name, duint Address) + { + // If within limits... + if(inRange(Address)) + { + mCandidateEPs.insert(Address); + } + }); + } + + + for(const auto & vec : mXrefs) + { + duint jmps = 0, calls = 0; + duint addr = vec.first; + for(const auto & xref : vec.second) + { + if(xref.type == XREF_CALL) + calls++; + else if(xref.type == XREF_JMP) + jmps++; + } + if(calls >= 1 && jmps + calls > 1) + mCandidateEPs.insert(addr); + else if(calls >= 1) + mFuzzyEPs.insert(addr); + } +} + +void AdvancedAnalysis::analyzeCandidateFunctions(bool writedata) +{ + std::unordered_set pendingEPs; + while(true) + { + pendingEPs.clear(); + if(mCandidateEPs.size() == 0) + return; + for(const auto & entryPoint : mCandidateEPs) + { + pendingEPs.insert(entryPoint); + } + mCandidateEPs.clear(); + + for(const auto & entryPoint : pendingEPs) + { + if(mEntryPoints.find(entryPoint) == mEntryPoints.end()) + { + analyzeFunction(entryPoint, true); + } + } + } + +} diff --git a/src/dbg/advancedanalysis.h b/src/dbg/advancedanalysis.h index ce1c79a4..b341be17 100644 --- a/src/dbg/advancedanalysis.h +++ b/src/dbg/advancedanalysis.h @@ -1,152 +1,152 @@ -#pragma once - -#include "analysis.h" - -class AdvancedAnalysis : public Analysis -{ -public: - explicit AdvancedAnalysis(duint base, duint size, bool dump = false); - void Analyse() override; - void SetMarkers() override; - - using UintSet = std::unordered_set; - - template - using UintMap = std::unordered_map; - - struct CFNode - { - duint parentGraph; //function of which this node is a part - duint start; //start of the block - duint end; //end of the block (inclusive) - duint brtrue; //destination if condition is true - duint brfalse; //destination if condition is false - duint icount; //number of instructions in node - bool terminal; //node is a RET - - explicit CFNode(duint parentGraph, duint start, duint end) - : parentGraph(parentGraph), - start(start), - end(end), - brtrue(0), - brfalse(0), - icount(0), - terminal(false) - { - } - - explicit CFNode() - : CFNode(0, 0, 0) - { - } - - String ToString() const - { - return StringUtils::sprintf("start: " fhex "\nend: " fhex "\nfunction: " fhex, start, end, parentGraph); - } - }; - - struct CFGraph - { - duint entryPoint; //graph entry point - UintMap nodes; //CFNode.start -> CFNode - UintMap parents; //CFNode.start -> parents - - explicit CFGraph(duint entryPoint) - : entryPoint(entryPoint) - { - } - - void AddNode(const CFNode & node) - { - nodes[node.start] = node; - AddParent(node.start, node.brtrue); - AddParent(node.start, node.brfalse); - } - - void AddParent(duint child, duint parent) - { - if(!child || !parent) - return; - auto found = parents.find(child); - if(found == parents.end()) - { - UintSet p; - p.insert(parent); - parents[child] = p; - } - else - found->second.insert(parent); - } - - const char* GetNodeColor(const CFNode & node) const - { - if(node.terminal) - return "firebrick"; - if(node.start == entryPoint) - return "forestgreen"; - return "lightblue"; - } - - String ToDot() const - { - String result = "digraph CFGraph {\n"; - for(const auto & node : nodes) - result += StringUtils::sprintf(" n" fhex "[label=\"%s\" style=filled fillcolor=%s shape=box]\n", - node.second.start, - node.second.ToString().c_str(), - GetNodeColor(node.second)); - result += "\n"; - for(const auto & node : nodes) - { - if(node.second.brtrue) - result += StringUtils::sprintf(" n" fhex "-> n" fhex " [color=green]\n", - node.second.start, - node.second.brtrue); - if(node.second.brfalse) - result += StringUtils::sprintf(" n" fhex "-> n" fhex " [color=red]\n", - node.second.start, - node.second.brfalse); - } - result += "\n"; - - for(const auto & parent : parents) - { - for(const auto & node : parent.second) - result += StringUtils::sprintf(" n" fhex "-> n" fhex " [style=dotted color=grey]\n", - node, - parent.first); - } - result += "}"; - return result; - } - }; - -protected: - struct XREF - { - duint addr; - duint from; - XREFTYPE type; - bool valid; - }; - - std::unordered_set mEntryPoints; - std::unordered_set mCandidateEPs; - std::unordered_set mFuzzyEPs; - std::vector mFunctions; - std::unordered_map> mXrefs; - byte* mEncMap; -private: - - duint mMaxDepth; - bool mDump; - void linearXrefPass(); - void findInvalidXrefs(); - void writeDataXrefs(); - - void findFuzzyEntryPoints(); - void findEntryPoints(); - void analyzeCandidateFunctions(bool writedata); - void analyzeFunction(duint entryPoint, bool writedata); +#pragma once + +#include "analysis.h" + +class AdvancedAnalysis : public Analysis +{ +public: + explicit AdvancedAnalysis(duint base, duint size, bool dump = false); + void Analyse() override; + void SetMarkers() override; + + using UintSet = std::unordered_set; + + template + using UintMap = std::unordered_map; + + struct CFNode + { + duint parentGraph; //function of which this node is a part + duint start; //start of the block + duint end; //end of the block (inclusive) + duint brtrue; //destination if condition is true + duint brfalse; //destination if condition is false + duint icount; //number of instructions in node + bool terminal; //node is a RET + + explicit CFNode(duint parentGraph, duint start, duint end) + : parentGraph(parentGraph), + start(start), + end(end), + brtrue(0), + brfalse(0), + icount(0), + terminal(false) + { + } + + explicit CFNode() + : CFNode(0, 0, 0) + { + } + + String ToString() const + { + return StringUtils::sprintf("start: " fhex "\nend: " fhex "\nfunction: " fhex, start, end, parentGraph); + } + }; + + struct CFGraph + { + duint entryPoint; //graph entry point + UintMap nodes; //CFNode.start -> CFNode + UintMap parents; //CFNode.start -> parents + + explicit CFGraph(duint entryPoint) + : entryPoint(entryPoint) + { + } + + void AddNode(const CFNode & node) + { + nodes[node.start] = node; + AddParent(node.start, node.brtrue); + AddParent(node.start, node.brfalse); + } + + void AddParent(duint child, duint parent) + { + if(!child || !parent) + return; + auto found = parents.find(child); + if(found == parents.end()) + { + UintSet p; + p.insert(parent); + parents[child] = p; + } + else + found->second.insert(parent); + } + + const char* GetNodeColor(const CFNode & node) const + { + if(node.terminal) + return "firebrick"; + if(node.start == entryPoint) + return "forestgreen"; + return "lightblue"; + } + + String ToDot() const + { + String result = "digraph CFGraph {\n"; + for(const auto & node : nodes) + result += StringUtils::sprintf(" n" fhex "[label=\"%s\" style=filled fillcolor=%s shape=box]\n", + node.second.start, + node.second.ToString().c_str(), + GetNodeColor(node.second)); + result += "\n"; + for(const auto & node : nodes) + { + if(node.second.brtrue) + result += StringUtils::sprintf(" n" fhex "-> n" fhex " [color=green]\n", + node.second.start, + node.second.brtrue); + if(node.second.brfalse) + result += StringUtils::sprintf(" n" fhex "-> n" fhex " [color=red]\n", + node.second.start, + node.second.brfalse); + } + result += "\n"; + + for(const auto & parent : parents) + { + for(const auto & node : parent.second) + result += StringUtils::sprintf(" n" fhex "-> n" fhex " [style=dotted color=grey]\n", + node, + parent.first); + } + result += "}"; + return result; + } + }; + +protected: + struct XREF + { + duint addr; + duint from; + XREFTYPE type; + bool valid; + }; + + std::unordered_set mEntryPoints; + std::unordered_set mCandidateEPs; + std::unordered_set mFuzzyEPs; + std::vector mFunctions; + std::unordered_map> mXrefs; + byte* mEncMap; +private: + + duint mMaxDepth; + bool mDump; + void linearXrefPass(); + void findInvalidXrefs(); + void writeDataXrefs(); + + void findFuzzyEntryPoints(); + void findEntryPoints(); + void analyzeCandidateFunctions(bool writedata); + void analyzeFunction(duint entryPoint, bool writedata); }; \ No newline at end of file diff --git a/src/dbg/datainst_helper.cpp b/src/dbg/datainst_helper.cpp index 52918478..d7591a0c 100644 --- a/src/dbg/datainst_helper.cpp +++ b/src/dbg/datainst_helper.cpp @@ -1,309 +1,309 @@ -#include "datainst_helper.h" -#include "encodemap.h" -#include "stringutils.h" -#include - -std::unordered_map disasmMap; - -std::unordered_map assembleMap; - -void initDataInstMap() -{ - disasmMap.clear(); - assembleMap.clear(); -#define INSTRUCTION_MAP(type, desc) disasmMap[type] = desc; \ - assembleMap[desc] = type; - - INSTRUCTION_MAP(enc_byte, "byte") - INSTRUCTION_MAP(enc_word, "word") - INSTRUCTION_MAP(enc_dword, "dword") - INSTRUCTION_MAP(enc_fword, "fword") - INSTRUCTION_MAP(enc_qword, "qword") - INSTRUCTION_MAP(enc_tbyte, "tbyte") - INSTRUCTION_MAP(enc_oword, "oword") - INSTRUCTION_MAP(enc_real4, "real4") - INSTRUCTION_MAP(enc_real8, "real8") - INSTRUCTION_MAP(enc_real10, "real10") - INSTRUCTION_MAP(enc_mmword, "mmword") - INSTRUCTION_MAP(enc_xmmword, "xmmword") - INSTRUCTION_MAP(enc_ymmword, "ymmword") - INSTRUCTION_MAP(enc_ascii, "ascii") - INSTRUCTION_MAP(enc_unicode, "unicode") - -#undef INSTRUCTION_MAP - -#define INSTRUCTION_ASSEMBLE_MAP(type, desc) assembleMap[desc] = type; - INSTRUCTION_ASSEMBLE_MAP(enc_byte, "db") - INSTRUCTION_ASSEMBLE_MAP(enc_word, "dw") - INSTRUCTION_ASSEMBLE_MAP(enc_dword, "dd") - INSTRUCTION_ASSEMBLE_MAP(enc_qword, "dq") - -#undef INSTRUCTION_ASSEMBLE_MAP - -} - - - - -String GetDataTypeString(void* buffer, duint size, ENCODETYPE type) -{ - - switch(type) - { - case enc_byte: - return StringUtils::ToIntegralString(buffer); - case enc_word: - return StringUtils::ToIntegralString(buffer); - case enc_dword: - return StringUtils::ToIntegralString(buffer); - case enc_fword: - return StringUtils::ToHex((char*)buffer, 6, true); - case enc_qword: - return StringUtils::ToIntegralString(buffer); - case enc_tbyte: - return StringUtils::ToHex((char*)buffer, 10, true); - case enc_oword: - return StringUtils::ToHex((char*)buffer, 16, true); - case enc_mmword: - case enc_xmmword: - case enc_ymmword: - return StringUtils::ToHex((char*)buffer, size, false); - case enc_real4: - return StringUtils::ToFloatingString(buffer); - case enc_real8: - return StringUtils::ToFloatingString(buffer); - case enc_real10: - return StringUtils::ToHex((char*)buffer, 10, true); - //return ToLongDoubleString(buffer); - case enc_ascii: - return String((const char*)buffer, size); - case enc_unicode: - return StringUtils::Utf16ToUtf8(WString((const wchar_t*)buffer, size / sizeof(wchar_t))); - default: - return StringUtils::ToIntegralString(buffer); - } -} - -String GetDataInstMnemonic(ENCODETYPE type) -{ - if(disasmMap.find(type) == disasmMap.end()) - type == enc_byte; - if(disasmMap.find(type) == disasmMap.end()) - return "???"; - return disasmMap[type]; -} - -String GetDataInstString(void* buffer, duint size, ENCODETYPE type) -{ - return GetDataInstMnemonic(type) + " " + GetDataTypeString(buffer, size, type); -} -duint decodesimpledata(const unsigned char* buffer, ENCODETYPE type) -{ - switch(type) - { - case enc_byte: - return *((unsigned char*)buffer); - case enc_word: - return *((unsigned short*)buffer); - case enc_dword: - return *((unsigned int*)buffer); -#ifdef _WIN64 - case enc_qword: - return *((unsigned long long int*)buffer); -#endif // _WIN64 - } - return 0; -} - -struct DataInstruction -{ - ENCODETYPE type; - String oprand; -}; - -bool parsedatainstruction(const char* instruction, DataInstruction & di) -{ - di.type = enc_unknown; - di.oprand = ""; - String instStr = StringUtils::Trim(String(instruction)); - size_t pos = instStr.find_first_of(" \t"); - String opcode = instStr.substr(0, pos); - std::transform(opcode.begin(), opcode.end(), opcode.begin(), ::tolower); - if(assembleMap.find(opcode) == assembleMap.end()) - return false; - di.type = assembleMap[opcode]; - pos = instStr.find_first_not_of(" \t", pos); - if(pos == String::npos) - return false; - di.oprand = instStr.substr(pos); -} - -bool isdatainstruction(const char* instruction) -{ - DataInstruction di; - parsedatainstruction(instruction, di); - - return di.type != enc_unknown; -} - -bool tryassembledata(duint addr, unsigned char* dest, int destsize, int* size, const char* instruction, char* error) -{ - DataInstruction di; - if(!parsedatainstruction(instruction, di)) - { - if(di.oprand == "") - strcpy_s(error, MAX_ERROR_SIZE, "Missing oprand"); - return false; - } - - duint retsize = 0; - String buffer; - try - { - switch(di.type) - { - case enc_byte: - case enc_word: - case enc_dword: - case enc_fword: - case enc_qword: - case enc_tbyte: - case enc_oword: - { - retsize = GetEncodeTypeSize(di.type); - buffer = StringUtils::FromHex(di.oprand, retsize, true); - break; - } - case enc_mmword: - case enc_xmmword: - case enc_ymmword: - { - retsize = GetEncodeTypeSize(di.type); - if(retsize > destsize) - { - strcpy_s(error, MAX_ERROR_SIZE, "insufficient buffer"); - if(size) - { - *size = retsize; //return correct size - return dest == nullptr; - } - return false; - } - else - { - - buffer = StringUtils::FromHex(di.oprand, retsize, false); - } - break; - } - case enc_real4: - { - retsize = 4; - float f = std::stof(di.oprand); - buffer = String((char*)&f, 4); - break; - } - - case enc_real8: - { - retsize = 8; - double d = std::stod(di.oprand); - buffer = String((char*)&d, 8); - break; - } - - case enc_real10: - strcpy_s(error, MAX_ERROR_SIZE, "80bit extended float is not supported"); - return false; //80 bit float is not supported in MSVC, need to add other library - case enc_ascii: - { - if(di.oprand.size() > destsize) - { - strcpy_s(error, MAX_ERROR_SIZE, "string too long"); - if(size) - { - *size = di.oprand.size(); //return correct size - return dest == nullptr; - } - return false; - } - else - { - retsize = di.oprand.size(); - buffer = di.oprand; - } - break; - } - - case enc_unicode: - { - WString unicode = StringUtils::Utf8ToUtf16(di.oprand); - - if(unicode.size()*sizeof(wchar_t) > destsize) - { - strcpy_s(error, MAX_ERROR_SIZE, "string too long"); - if(size) - { - retsize = unicode.size() * 2; //return correct size - return dest == nullptr; - } - - return false; - } - else - { - retsize = unicode.size() * 2; - buffer = String((char*)unicode.c_str(), retsize); - } - break; - } - default: - return false; - } - } - catch(const std::exception & e) - { - strcpy_s(error, MAX_ERROR_SIZE, e.what()); - return false; - } - if(size) - *size = retsize; - - if(dest) - memcpy_s((char*)dest, retsize, buffer.c_str(), retsize); - return true; -} - -bool trydisasm(const unsigned char* buffer, duint addr, DISASM_INSTR* instr, duint codesize) -{ - ENCODETYPE type = EncodeMapGetType(addr, codesize); - duint size = EncodeMapGetSize(addr, codesize); - if(type == enc_unknown || type == enc_code) - return false; - memset(instr, 0, sizeof(DISASM_INSTR)); - instr->argcount = 1; - instr->type = instr_normal; - instr->arg[0].type = arg_normal; - instr->arg[0].value = decodesimpledata(buffer, type); - strcpy_s(instr->arg[0].mnemonic, GetDataTypeString((void*)buffer, size, type).c_str()); - instr->instr_size = size; - String str = GetDataInstString((void*)buffer, MAX_DISASM_BUFFER, type); - strcpy_s(instr->instruction, str.c_str()); - return true; -} - -bool trydisasmfast(const unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* basicinfo, duint codesize) -{ - ENCODETYPE type = EncodeMapGetType(addr, codesize); - duint size = EncodeMapGetSize(addr, codesize); - if(type == enc_unknown || type == enc_code) - return false; - memset(basicinfo, 0, sizeof(BASIC_INSTRUCTION_INFO)); - basicinfo->type = TYPE_VALUE; - basicinfo->size = size; - String str = GetDataInstString((void*)data, MAX_DISASM_BUFFER, type); - strcpy_s(basicinfo->instruction, str.c_str()); - basicinfo->value.size = VALUE_SIZE(size); - basicinfo->value.value = decodesimpledata(data, type); - return true; -} +#include "datainst_helper.h" +#include "encodemap.h" +#include "stringutils.h" +#include + +std::unordered_map disasmMap; + +std::unordered_map assembleMap; + +void initDataInstMap() +{ + disasmMap.clear(); + assembleMap.clear(); +#define INSTRUCTION_MAP(type, desc) disasmMap[type] = desc; \ + assembleMap[desc] = type; + + INSTRUCTION_MAP(enc_byte, "byte") + INSTRUCTION_MAP(enc_word, "word") + INSTRUCTION_MAP(enc_dword, "dword") + INSTRUCTION_MAP(enc_fword, "fword") + INSTRUCTION_MAP(enc_qword, "qword") + INSTRUCTION_MAP(enc_tbyte, "tbyte") + INSTRUCTION_MAP(enc_oword, "oword") + INSTRUCTION_MAP(enc_real4, "real4") + INSTRUCTION_MAP(enc_real8, "real8") + INSTRUCTION_MAP(enc_real10, "real10") + INSTRUCTION_MAP(enc_mmword, "mmword") + INSTRUCTION_MAP(enc_xmmword, "xmmword") + INSTRUCTION_MAP(enc_ymmword, "ymmword") + INSTRUCTION_MAP(enc_ascii, "ascii") + INSTRUCTION_MAP(enc_unicode, "unicode") + +#undef INSTRUCTION_MAP + +#define INSTRUCTION_ASSEMBLE_MAP(type, desc) assembleMap[desc] = type; + INSTRUCTION_ASSEMBLE_MAP(enc_byte, "db") + INSTRUCTION_ASSEMBLE_MAP(enc_word, "dw") + INSTRUCTION_ASSEMBLE_MAP(enc_dword, "dd") + INSTRUCTION_ASSEMBLE_MAP(enc_qword, "dq") + +#undef INSTRUCTION_ASSEMBLE_MAP + +} + + + + +String GetDataTypeString(void* buffer, duint size, ENCODETYPE type) +{ + + switch(type) + { + case enc_byte: + return StringUtils::ToIntegralString(buffer); + case enc_word: + return StringUtils::ToIntegralString(buffer); + case enc_dword: + return StringUtils::ToIntegralString(buffer); + case enc_fword: + return StringUtils::ToHex((char*)buffer, 6, true); + case enc_qword: + return StringUtils::ToIntegralString(buffer); + case enc_tbyte: + return StringUtils::ToHex((char*)buffer, 10, true); + case enc_oword: + return StringUtils::ToHex((char*)buffer, 16, true); + case enc_mmword: + case enc_xmmword: + case enc_ymmword: + return StringUtils::ToHex((char*)buffer, size, false); + case enc_real4: + return StringUtils::ToFloatingString(buffer); + case enc_real8: + return StringUtils::ToFloatingString(buffer); + case enc_real10: + return StringUtils::ToHex((char*)buffer, 10, true); + //return ToLongDoubleString(buffer); + case enc_ascii: + return String((const char*)buffer, size); + case enc_unicode: + return StringUtils::Utf16ToUtf8(WString((const wchar_t*)buffer, size / sizeof(wchar_t))); + default: + return StringUtils::ToIntegralString(buffer); + } +} + +String GetDataInstMnemonic(ENCODETYPE type) +{ + if(disasmMap.find(type) == disasmMap.end()) + type == enc_byte; + if(disasmMap.find(type) == disasmMap.end()) + return "???"; + return disasmMap[type]; +} + +String GetDataInstString(void* buffer, duint size, ENCODETYPE type) +{ + return GetDataInstMnemonic(type) + " " + GetDataTypeString(buffer, size, type); +} +duint decodesimpledata(const unsigned char* buffer, ENCODETYPE type) +{ + switch(type) + { + case enc_byte: + return *((unsigned char*)buffer); + case enc_word: + return *((unsigned short*)buffer); + case enc_dword: + return *((unsigned int*)buffer); +#ifdef _WIN64 + case enc_qword: + return *((unsigned long long int*)buffer); +#endif // _WIN64 + } + return 0; +} + +struct DataInstruction +{ + ENCODETYPE type; + String oprand; +}; + +bool parsedatainstruction(const char* instruction, DataInstruction & di) +{ + di.type = enc_unknown; + di.oprand = ""; + String instStr = StringUtils::Trim(String(instruction)); + size_t pos = instStr.find_first_of(" \t"); + String opcode = instStr.substr(0, pos); + std::transform(opcode.begin(), opcode.end(), opcode.begin(), ::tolower); + if(assembleMap.find(opcode) == assembleMap.end()) + return false; + di.type = assembleMap[opcode]; + pos = instStr.find_first_not_of(" \t", pos); + if(pos == String::npos) + return false; + di.oprand = instStr.substr(pos); +} + +bool isdatainstruction(const char* instruction) +{ + DataInstruction di; + parsedatainstruction(instruction, di); + + return di.type != enc_unknown; +} + +bool tryassembledata(duint addr, unsigned char* dest, int destsize, int* size, const char* instruction, char* error) +{ + DataInstruction di; + if(!parsedatainstruction(instruction, di)) + { + if(di.oprand == "") + strcpy_s(error, MAX_ERROR_SIZE, "Missing oprand"); + return false; + } + + duint retsize = 0; + String buffer; + try + { + switch(di.type) + { + case enc_byte: + case enc_word: + case enc_dword: + case enc_fword: + case enc_qword: + case enc_tbyte: + case enc_oword: + { + retsize = GetEncodeTypeSize(di.type); + buffer = StringUtils::FromHex(di.oprand, retsize, true); + break; + } + case enc_mmword: + case enc_xmmword: + case enc_ymmword: + { + retsize = GetEncodeTypeSize(di.type); + if(retsize > destsize) + { + strcpy_s(error, MAX_ERROR_SIZE, "insufficient buffer"); + if(size) + { + *size = retsize; //return correct size + return dest == nullptr; + } + return false; + } + else + { + + buffer = StringUtils::FromHex(di.oprand, retsize, false); + } + break; + } + case enc_real4: + { + retsize = 4; + float f = std::stof(di.oprand); + buffer = String((char*)&f, 4); + break; + } + + case enc_real8: + { + retsize = 8; + double d = std::stod(di.oprand); + buffer = String((char*)&d, 8); + break; + } + + case enc_real10: + strcpy_s(error, MAX_ERROR_SIZE, "80bit extended float is not supported"); + return false; //80 bit float is not supported in MSVC, need to add other library + case enc_ascii: + { + if(di.oprand.size() > destsize) + { + strcpy_s(error, MAX_ERROR_SIZE, "string too long"); + if(size) + { + *size = di.oprand.size(); //return correct size + return dest == nullptr; + } + return false; + } + else + { + retsize = di.oprand.size(); + buffer = di.oprand; + } + break; + } + + case enc_unicode: + { + WString unicode = StringUtils::Utf8ToUtf16(di.oprand); + + if(unicode.size()*sizeof(wchar_t) > destsize) + { + strcpy_s(error, MAX_ERROR_SIZE, "string too long"); + if(size) + { + retsize = unicode.size() * 2; //return correct size + return dest == nullptr; + } + + return false; + } + else + { + retsize = unicode.size() * 2; + buffer = String((char*)unicode.c_str(), retsize); + } + break; + } + default: + return false; + } + } + catch(const std::exception & e) + { + strcpy_s(error, MAX_ERROR_SIZE, e.what()); + return false; + } + if(size) + *size = retsize; + + if(dest) + memcpy_s((char*)dest, retsize, buffer.c_str(), retsize); + return true; +} + +bool trydisasm(const unsigned char* buffer, duint addr, DISASM_INSTR* instr, duint codesize) +{ + ENCODETYPE type = EncodeMapGetType(addr, codesize); + duint size = EncodeMapGetSize(addr, codesize); + if(type == enc_unknown || type == enc_code) + return false; + memset(instr, 0, sizeof(DISASM_INSTR)); + instr->argcount = 1; + instr->type = instr_normal; + instr->arg[0].type = arg_normal; + instr->arg[0].value = decodesimpledata(buffer, type); + strcpy_s(instr->arg[0].mnemonic, GetDataTypeString((void*)buffer, size, type).c_str()); + instr->instr_size = size; + String str = GetDataInstString((void*)buffer, MAX_DISASM_BUFFER, type); + strcpy_s(instr->instruction, str.c_str()); + return true; +} + +bool trydisasmfast(const unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* basicinfo, duint codesize) +{ + ENCODETYPE type = EncodeMapGetType(addr, codesize); + duint size = EncodeMapGetSize(addr, codesize); + if(type == enc_unknown || type == enc_code) + return false; + memset(basicinfo, 0, sizeof(BASIC_INSTRUCTION_INFO)); + basicinfo->type = TYPE_VALUE; + basicinfo->size = size; + String str = GetDataInstString((void*)data, MAX_DISASM_BUFFER, type); + strcpy_s(basicinfo->instruction, str.c_str()); + basicinfo->value.size = VALUE_SIZE(size); + basicinfo->value.value = decodesimpledata(data, type); + return true; +} diff --git a/src/dbg/datainst_helper.h b/src/dbg/datainst_helper.h index a9d90f53..f1751303 100644 --- a/src/dbg/datainst_helper.h +++ b/src/dbg/datainst_helper.h @@ -1,12 +1,12 @@ -#pragma once -#include "_global.h" - -void initDataInstMap(); - -bool isdatainstruction(const char* instruction); - -bool tryassembledata(duint addr, unsigned char* dest, int destsize, int* size, const char* instruction, char* error); - -bool trydisasm(const unsigned char* buffer, duint addr, DISASM_INSTR* instr, duint codesize); - +#pragma once +#include "_global.h" + +void initDataInstMap(); + +bool isdatainstruction(const char* instruction); + +bool tryassembledata(duint addr, unsigned char* dest, int destsize, int* size, const char* instruction, char* error); + +bool trydisasm(const unsigned char* buffer, duint addr, DISASM_INSTR* instr, duint codesize); + bool trydisasmfast(const unsigned char* buffer, duint addr, BASIC_INSTRUCTION_INFO* basicinfo, duint codesize); \ No newline at end of file diff --git a/src/dbg/debugger_commands.cpp b/src/dbg/debugger_commands.cpp index 79372e86..30b2452d 100644 --- a/src/dbg/debugger_commands.cpp +++ b/src/dbg/debugger_commands.cpp @@ -702,7 +702,7 @@ CMDRESULT cbDebugGetBPXMemoryHitCount(int argc, char* argv[]) CMDRESULT cbDebugSetBPGoto(int argc, char* argv[]) { - if (argc != 3) + if(argc != 3) { dputs("argument count mismatch!\n"); return STATUS_ERROR; @@ -1297,7 +1297,7 @@ CMDRESULT cbDebugRunToParty(int argc, char* argv[]) for(auto j : i.sections) { BREAKPOINT bp; - if (!BpGet(j.addr, BPMEMORY, nullptr, &bp)) + if(!BpGet(j.addr, BPMEMORY, nullptr, &bp)) { RunToUserCodeBreakpoints.push_back(std::make_pair(j.addr, j.size)); SetMemoryBPXEx(j.addr, j.size, UE_MEMORY_EXECUTE, false, (void*)cbRunToUserCodeBreakpoint); diff --git a/src/dbg/encodemap.cpp b/src/dbg/encodemap.cpp index ce422ceb..c827b848 100644 --- a/src/dbg/encodemap.cpp +++ b/src/dbg/encodemap.cpp @@ -1,381 +1,381 @@ -#include "encodemap.h" -#include -#include "addrinfo.h" -#include -#include - -struct ENCODEMAP : AddrInfo -{ - duint size; - byte* data; -}; - - -std::unordered_map referenceCount; - - -void IncreaseReferenceCount(void* buffer, bool lock = true) -{ - if(lock) - { - EXCLUSIVE_ACQUIRE(LockEncodeMaps); - } - auto iter = referenceCount.find((duint)buffer); - if(iter == referenceCount.end()) - referenceCount[(duint)buffer] = 1; - else - referenceCount[(duint)buffer]++; -} - -duint DecreaseReferenceCount(void* buffer, bool lock = true) -{ - if(lock) - { - EXCLUSIVE_ACQUIRE(LockEncodeMaps); - } - auto iter = referenceCount.find((duint)buffer); - if(iter == referenceCount.end()) - return -1; - if(iter->second == 1) - { - referenceCount.erase(iter->first); - return 0; - } - else - referenceCount[iter->first]--; - return iter->second; -} - - - -struct EncodeMapSerializer : AddrInfoSerializer -{ - bool Save(const ENCODEMAP & value) override - { - - AddrInfoSerializer::Save(value); - set("data", json_stringn((const char*)value.data, value.size)); - return true; - } - - bool Load(ENCODEMAP & value) override - { - if(!AddrInfoSerializer::Load(value)) - return false; - auto data = get("data"); - value.size = json_string_length(data); - value.data = (byte*)VirtualAlloc(NULL, value.size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if(value.data == NULL) return false; - memcpy(value.data, (byte*)json_string_value(data), value.size); - IncreaseReferenceCount(value.data, false); - return true; - } -}; - -struct EncodeMap : AddrInfoHashMap -{ - const char* jsonKey() const override - { - return "encodemaps"; - } -}; - -static EncodeMap encmaps; - -bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map) -{ - duint base, segsize; - - base = MemFindBaseAddr(addr, &segsize); - if(!base) - return false; - - duint key = EncodeMap::VaKey(base); - if(!encmaps.Contains(key)) - { - map.size = segsize; - map.data = (byte*)VirtualAlloc(NULL, segsize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if(map.data == NULL) return false; - IncreaseReferenceCount(map.data); - encmaps.PrepareValue(map, base, false); - encmaps.Add(map); - } - else - { - if(!encmaps.Get(key, map)) - return false; - } - return true; -} - - - -void* EncodeMapGetBuffer(duint addr, bool create) -{ - duint base, size; - - if(!MemIsValidReadPtr(addr)) - return nullptr; - base = MemFindBaseAddr(addr, &size); - - ENCODEMAP map; - bool result = create ? EncodeMapGetorCreate(addr, map) : encmaps.Get(EncodeMap::VaKey(base), map); - if(result) - { - duint offset = addr - base; - if(offset >= map.size) - return nullptr; - IncreaseReferenceCount(map.data); - return map.data; - } - return nullptr; -} - - -void EncodeMapReleaseBuffer(void* buffer, bool lock) -{ - if(DecreaseReferenceCount(buffer, lock) == 0) - VirtualFree(buffer, 0, MEM_RELEASE); -} - -void EncodeMapReleaseBuffer(void* buffer) -{ - EncodeMapReleaseBuffer(buffer, true); -} - - - -bool IsRangeConflict(byte* typebuffer, duint size, duint codesize) -{ - if(codesize > size) - return true; - size = min(size, codesize); - if(size <= 0) - return false; - ENCODETYPE type = (ENCODETYPE)typebuffer[0]; - if(type == enc_middle) - return true; - for(int i = 1; i < size; i++) - { - if((ENCODETYPE)typebuffer[i] != enc_unknown && (ENCODETYPE)typebuffer[i] != enc_middle) - return true; - } - - return false; -} - -duint GetEncodeTypeSize(ENCODETYPE type) -{ - switch(type) - { - case enc_byte: - return 1; - case enc_word: - return 2; - case enc_dword: - return 4; - case enc_fword: - return 6; - case enc_qword: - return 8; - case enc_tbyte: - return 10; - case enc_oword: - return 16; - case enc_mmword: - return 8; - case enc_xmmword: - return 16; - case enc_ymmword: - return 32; - case enc_real4: - return 4; - case enc_real8: - return 8; - case enc_real10: - return 10; - case enc_ascii: - return 1; - case enc_unicode: - return 2; - default: - return 1; - } -} - -bool IsCodeType(ENCODETYPE type) -{ - return type == enc_code || type == enc_junk; -} - -ENCODETYPE EncodeMapGetType(duint addr, duint codesize) -{ - duint base, size; - - base = MemFindBaseAddr(addr, &size); - if(!base) - return ENCODETYPE::enc_unknown; - - ENCODEMAP map; - if(encmaps.Get(EncodeMap::VaKey(base), map)) - { - duint offset = addr - base; - if(offset >= map.size) - return ENCODETYPE::enc_unknown; - ENCODETYPE type = (ENCODETYPE)map.data[offset]; - - if((type == enc_unknown || type == enc_middle) && IsRangeConflict(map.data + offset, size - offset, codesize)) - return enc_byte; - else - return type; - } - - return ENCODETYPE::enc_unknown; -} - -duint EncodeMapGetSize(duint addr, duint codesize) -{ - duint base; - - base = MemFindBaseAddr(addr, 0); - if(!base) - return codesize; - - ENCODEMAP map; - if(encmaps.Get(EncodeMap::VaKey(base), map)) - { - duint offset = addr - base; - if(offset >= map.size) - return 1; - ENCODETYPE type = (ENCODETYPE)map.data[offset]; - - duint datasize = GetEncodeTypeSize(type); - if(type == enc_unknown || type == enc_code || type == enc_junk) - { - if(IsRangeConflict(map.data + offset, map.size - offset, codesize) || codesize == 0) - return datasize; - else - return codesize; - } - else if(type == enc_ascii || type == enc_unicode) - { - duint totalsize = 0; - for(int i = offset; i < map.size; i += datasize) - { - if(map.data[i] == type) - totalsize += datasize; - else - break; - } - return totalsize; - } - else - return datasize; - } - - return codesize; -} - -bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type) -{ - duint base; - - base = MemFindBaseAddr(addr, 0); - if(!base) - return false; - - - ENCODEMAP map; - if(!EncodeMapGetorCreate(base, map)) - return false; - duint offset = addr - base; - size = min(map.size - offset, size); - duint datasize = GetEncodeTypeSize(type); - if(datasize == 1 && !IsCodeType(type)) - { - memset(map.data + offset, (byte)type, size); - } - else - { - memset(map.data + offset, (byte)enc_middle, size); - if(IsCodeType(type) && size > 1) - { - Capstone cp; - unsigned char* buffer = new unsigned char[size]; - if(!MemRead(addr, buffer, size)) - { - delete[] buffer; - return false; - - } - int buffersize = size, bufferoffset = 0, cmdsize; - for(int i = offset; i < offset + size;) - { - map.data[i] = (byte)type; - cp.Disassemble(base + i, buffer + bufferoffset, buffersize); - cmdsize = cp.Success() ? cp.Size() : 1; - i += cmdsize; - bufferoffset += cmdsize; - buffersize -= cmdsize; - } - - } - else - { - for(int i = offset; i < offset + size; i += datasize) - map.data[i] = (byte)type; - } - - } - - for(int i = offset + size + 1; i < map.size; i++) - { - if(map.data[i] == enc_middle) - map.data[i] = (byte)enc_unknown; - else - break; - } - return true; -} - -void EncodeMapDelSegment(duint Start) -{ - duint base = MemFindBaseAddr(Start, 0); - if(!base) - return; - duint key = EncodeMap::VaKey(base); - ENCODEMAP map; - if(encmaps.Contains(key)) - { - encmaps.Get(key, map); - EncodeMapReleaseBuffer(map.data); - } - encmaps.Delete(key); -} - -void EncodeMapDelRange(duint Start, duint End) -{ - EncodeMapSetType(Start, End - Start + 1, enc_unknown); -} - -void EncodeMapCacheSave(JSON Root) -{ - encmaps.CacheSave(Root); -} - -void EncodeMapCacheLoad(JSON Root) -{ - encmaps.CacheLoad(Root); -} - -void EncodeMapClear() -{ - EXCLUSIVE_ACQUIRE(LockEncodeMaps); - for(auto & encmap : encmaps.GetDataUnsafe()) - { - EncodeMapReleaseBuffer(encmap.second.data, false); - - } - EXCLUSIVE_RELEASE(LockEncodeMaps); - encmaps.Clear(); -} +#include "encodemap.h" +#include +#include "addrinfo.h" +#include +#include + +struct ENCODEMAP : AddrInfo +{ + duint size; + byte* data; +}; + + +std::unordered_map referenceCount; + + +void IncreaseReferenceCount(void* buffer, bool lock = true) +{ + if(lock) + { + EXCLUSIVE_ACQUIRE(LockEncodeMaps); + } + auto iter = referenceCount.find((duint)buffer); + if(iter == referenceCount.end()) + referenceCount[(duint)buffer] = 1; + else + referenceCount[(duint)buffer]++; +} + +duint DecreaseReferenceCount(void* buffer, bool lock = true) +{ + if(lock) + { + EXCLUSIVE_ACQUIRE(LockEncodeMaps); + } + auto iter = referenceCount.find((duint)buffer); + if(iter == referenceCount.end()) + return -1; + if(iter->second == 1) + { + referenceCount.erase(iter->first); + return 0; + } + else + referenceCount[iter->first]--; + return iter->second; +} + + + +struct EncodeMapSerializer : AddrInfoSerializer +{ + bool Save(const ENCODEMAP & value) override + { + + AddrInfoSerializer::Save(value); + set("data", json_stringn((const char*)value.data, value.size)); + return true; + } + + bool Load(ENCODEMAP & value) override + { + if(!AddrInfoSerializer::Load(value)) + return false; + auto data = get("data"); + value.size = json_string_length(data); + value.data = (byte*)VirtualAlloc(NULL, value.size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if(value.data == NULL) return false; + memcpy(value.data, (byte*)json_string_value(data), value.size); + IncreaseReferenceCount(value.data, false); + return true; + } +}; + +struct EncodeMap : AddrInfoHashMap +{ + const char* jsonKey() const override + { + return "encodemaps"; + } +}; + +static EncodeMap encmaps; + +bool EncodeMapGetorCreate(duint addr, ENCODEMAP & map) +{ + duint base, segsize; + + base = MemFindBaseAddr(addr, &segsize); + if(!base) + return false; + + duint key = EncodeMap::VaKey(base); + if(!encmaps.Contains(key)) + { + map.size = segsize; + map.data = (byte*)VirtualAlloc(NULL, segsize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if(map.data == NULL) return false; + IncreaseReferenceCount(map.data); + encmaps.PrepareValue(map, base, false); + encmaps.Add(map); + } + else + { + if(!encmaps.Get(key, map)) + return false; + } + return true; +} + + + +void* EncodeMapGetBuffer(duint addr, bool create) +{ + duint base, size; + + if(!MemIsValidReadPtr(addr)) + return nullptr; + base = MemFindBaseAddr(addr, &size); + + ENCODEMAP map; + bool result = create ? EncodeMapGetorCreate(addr, map) : encmaps.Get(EncodeMap::VaKey(base), map); + if(result) + { + duint offset = addr - base; + if(offset >= map.size) + return nullptr; + IncreaseReferenceCount(map.data); + return map.data; + } + return nullptr; +} + + +void EncodeMapReleaseBuffer(void* buffer, bool lock) +{ + if(DecreaseReferenceCount(buffer, lock) == 0) + VirtualFree(buffer, 0, MEM_RELEASE); +} + +void EncodeMapReleaseBuffer(void* buffer) +{ + EncodeMapReleaseBuffer(buffer, true); +} + + + +bool IsRangeConflict(byte* typebuffer, duint size, duint codesize) +{ + if(codesize > size) + return true; + size = min(size, codesize); + if(size <= 0) + return false; + ENCODETYPE type = (ENCODETYPE)typebuffer[0]; + if(type == enc_middle) + return true; + for(int i = 1; i < size; i++) + { + if((ENCODETYPE)typebuffer[i] != enc_unknown && (ENCODETYPE)typebuffer[i] != enc_middle) + return true; + } + + return false; +} + +duint GetEncodeTypeSize(ENCODETYPE type) +{ + switch(type) + { + case enc_byte: + return 1; + case enc_word: + return 2; + case enc_dword: + return 4; + case enc_fword: + return 6; + case enc_qword: + return 8; + case enc_tbyte: + return 10; + case enc_oword: + return 16; + case enc_mmword: + return 8; + case enc_xmmword: + return 16; + case enc_ymmword: + return 32; + case enc_real4: + return 4; + case enc_real8: + return 8; + case enc_real10: + return 10; + case enc_ascii: + return 1; + case enc_unicode: + return 2; + default: + return 1; + } +} + +bool IsCodeType(ENCODETYPE type) +{ + return type == enc_code || type == enc_junk; +} + +ENCODETYPE EncodeMapGetType(duint addr, duint codesize) +{ + duint base, size; + + base = MemFindBaseAddr(addr, &size); + if(!base) + return ENCODETYPE::enc_unknown; + + ENCODEMAP map; + if(encmaps.Get(EncodeMap::VaKey(base), map)) + { + duint offset = addr - base; + if(offset >= map.size) + return ENCODETYPE::enc_unknown; + ENCODETYPE type = (ENCODETYPE)map.data[offset]; + + if((type == enc_unknown || type == enc_middle) && IsRangeConflict(map.data + offset, size - offset, codesize)) + return enc_byte; + else + return type; + } + + return ENCODETYPE::enc_unknown; +} + +duint EncodeMapGetSize(duint addr, duint codesize) +{ + duint base; + + base = MemFindBaseAddr(addr, 0); + if(!base) + return codesize; + + ENCODEMAP map; + if(encmaps.Get(EncodeMap::VaKey(base), map)) + { + duint offset = addr - base; + if(offset >= map.size) + return 1; + ENCODETYPE type = (ENCODETYPE)map.data[offset]; + + duint datasize = GetEncodeTypeSize(type); + if(type == enc_unknown || type == enc_code || type == enc_junk) + { + if(IsRangeConflict(map.data + offset, map.size - offset, codesize) || codesize == 0) + return datasize; + else + return codesize; + } + else if(type == enc_ascii || type == enc_unicode) + { + duint totalsize = 0; + for(int i = offset; i < map.size; i += datasize) + { + if(map.data[i] == type) + totalsize += datasize; + else + break; + } + return totalsize; + } + else + return datasize; + } + + return codesize; +} + +bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type) +{ + duint base; + + base = MemFindBaseAddr(addr, 0); + if(!base) + return false; + + + ENCODEMAP map; + if(!EncodeMapGetorCreate(base, map)) + return false; + duint offset = addr - base; + size = min(map.size - offset, size); + duint datasize = GetEncodeTypeSize(type); + if(datasize == 1 && !IsCodeType(type)) + { + memset(map.data + offset, (byte)type, size); + } + else + { + memset(map.data + offset, (byte)enc_middle, size); + if(IsCodeType(type) && size > 1) + { + Capstone cp; + unsigned char* buffer = new unsigned char[size]; + if(!MemRead(addr, buffer, size)) + { + delete[] buffer; + return false; + + } + int buffersize = size, bufferoffset = 0, cmdsize; + for(int i = offset; i < offset + size;) + { + map.data[i] = (byte)type; + cp.Disassemble(base + i, buffer + bufferoffset, buffersize); + cmdsize = cp.Success() ? cp.Size() : 1; + i += cmdsize; + bufferoffset += cmdsize; + buffersize -= cmdsize; + } + + } + else + { + for(int i = offset; i < offset + size; i += datasize) + map.data[i] = (byte)type; + } + + } + + for(int i = offset + size + 1; i < map.size; i++) + { + if(map.data[i] == enc_middle) + map.data[i] = (byte)enc_unknown; + else + break; + } + return true; +} + +void EncodeMapDelSegment(duint Start) +{ + duint base = MemFindBaseAddr(Start, 0); + if(!base) + return; + duint key = EncodeMap::VaKey(base); + ENCODEMAP map; + if(encmaps.Contains(key)) + { + encmaps.Get(key, map); + EncodeMapReleaseBuffer(map.data); + } + encmaps.Delete(key); +} + +void EncodeMapDelRange(duint Start, duint End) +{ + EncodeMapSetType(Start, End - Start + 1, enc_unknown); +} + +void EncodeMapCacheSave(JSON Root) +{ + encmaps.CacheSave(Root); +} + +void EncodeMapCacheLoad(JSON Root) +{ + encmaps.CacheLoad(Root); +} + +void EncodeMapClear() +{ + EXCLUSIVE_ACQUIRE(LockEncodeMaps); + for(auto & encmap : encmaps.GetDataUnsafe()) + { + EncodeMapReleaseBuffer(encmap.second.data, false); + + } + EXCLUSIVE_RELEASE(LockEncodeMaps); + encmaps.Clear(); +} diff --git a/src/dbg/encodemap.h b/src/dbg/encodemap.h index 2b724bfb..b1a9260b 100644 --- a/src/dbg/encodemap.h +++ b/src/dbg/encodemap.h @@ -1,26 +1,26 @@ -#pragma once -#include "_global.h" - -void* EncodeMapGetBuffer(duint addr, bool create = false); - -void EncodeMapReleaseBuffer(void* buffer); - -ENCODETYPE EncodeMapGetType(duint addr, duint codesize); - -duint EncodeMapGetSize(duint addr, duint codesize); - -void EncodeMapDelSegment(duint addr); - -void EncodeMapDelRange(duint addr, duint size); - -bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type); - -void EncodeMapDelRange(duint Start, duint End); - -void EncodeMapCacheSave(JSON Root); - -void EncodeMapCacheLoad(JSON Root); - -void EncodeMapClear(); - +#pragma once +#include "_global.h" + +void* EncodeMapGetBuffer(duint addr, bool create = false); + +void EncodeMapReleaseBuffer(void* buffer); + +ENCODETYPE EncodeMapGetType(duint addr, duint codesize); + +duint EncodeMapGetSize(duint addr, duint codesize); + +void EncodeMapDelSegment(duint addr); + +void EncodeMapDelRange(duint addr, duint size); + +bool EncodeMapSetType(duint addr, duint size, ENCODETYPE type); + +void EncodeMapDelRange(duint Start, duint End); + +void EncodeMapCacheSave(JSON Root); + +void EncodeMapCacheLoad(JSON Root); + +void EncodeMapClear(); + duint GetEncodeTypeSize(ENCODETYPE type); \ No newline at end of file diff --git a/src/dbg/module.cpp b/src/dbg/module.cpp index 613f3503..2d5179d0 100644 --- a/src/dbg/module.cpp +++ b/src/dbg/module.cpp @@ -110,7 +110,7 @@ bool ModLoad(duint Base, duint Size, const char* FullPath) GetEnvironmentVariableW(L"windir", sysdir, sizeof(sysdir)); String Utf8Sysdir = StringUtils::Utf16ToUtf8(sysdir); Utf8Sysdir.append("\\"); - if (_memicmp(Utf8Sysdir.c_str(), FullPath, Utf8Sysdir.size()) == 0) + if(_memicmp(Utf8Sysdir.c_str(), FullPath, Utf8Sysdir.size()) == 0) { info.party = 1; } @@ -423,7 +423,7 @@ int ModGetParty(duint Address) auto module = ModInfoFromAddr(Address); // If the module is not found, it is an user module - if (!module) + if(!module) return 0; return module->party; @@ -436,7 +436,7 @@ void ModSetParty(duint Address, int Party) auto module = ModInfoFromAddr(Address); // If the module is not found, it is an user module - if (!module) + if(!module) return; module->party = Party; diff --git a/src/dbg/x64_dbg.cpp b/src/dbg/x64_dbg.cpp index 11986ec8..96e7cf9e 100644 --- a/src/dbg/x64_dbg.cpp +++ b/src/dbg/x64_dbg.cpp @@ -159,7 +159,7 @@ static void registercommands() dbgcmdnew("SetMemoryBreakpointFastResume", cbDebugSetBPXMemoryFastResume, true); //set breakpoint fast resume dbgcmdnew("SetMemoryGetBreakpointHitCount", cbDebugGetBPXMemoryHitCount, true); //get breakpoint hit count dbgcmdnew("ResetMemoryBreakpointHitCount", cbDebugResetBPXMemoryHitCount, true); //reset breakpoint hit count - + dbgcmdnew("bpgoto", cbDebugSetBPGoto, true); //variables diff --git a/src/gui/Src/Utils/EncodeMap.cpp b/src/gui/Src/Utils/EncodeMap.cpp index 5fc84eec..44e0694b 100644 --- a/src/gui/Src/Utils/EncodeMap.cpp +++ b/src/gui/Src/Utils/EncodeMap.cpp @@ -1,204 +1,204 @@ -#include "EncodeMap.h" - -EncodeMap::EncodeMap(QObject* parent) : QObject(parent), mBase(0), mSize(0), mBuffer(nullptr) -{ -} - -EncodeMap::~EncodeMap() -{ - if(mBuffer) - DbgReleaseEncodeTypeBuffer(mBuffer); -} - - -void EncodeMap::setMemoryRegion(duint addr) -{ - - mBase = DbgMemFindBaseAddr(addr, &mSize); - if(!mBase) - return; - - if(mBuffer) - DbgReleaseEncodeTypeBuffer(mBuffer); - mBuffer = (byte*)DbgGetEncodeTypeBuffer(addr); -} - - - -bool EncodeMap::isRangeConflict(duint offset, duint size, duint codesize, duint tmpcodecount, duint* tmpcodelist) -{ - if(codesize > size) - return true; - size = std::min(size, codesize); - if(size <= 0) - return false; - ENCODETYPE type = (ENCODETYPE)mBuffer[offset]; - if(type == enc_middle) - return true; - for(int i = 0; i < tmpcodecount; i++) - { - if(tmpcodelist[i] > offset + mBase && tmpcodelist[i] < offset + size + mBase) - return true; - } - - for(int i = 1 + offset; i < size + offset; i++) - { - if((ENCODETYPE)mBuffer[i] != enc_unknown && (ENCODETYPE)mBuffer[i] != enc_middle) - return true; - } - - return false; -} - -void EncodeMap::setDataType(duint va, ENCODETYPE type) -{ - setDataType(va, getEncodeTypeSize(type), type); -} - -void EncodeMap::setDataType(duint va, duint size, ENCODETYPE type) -{ - DbgSetEncodeType(va, size, type); - if(!mBuffer && va >= mBase && va < mBase + mSize) - setMemoryRegion(va); -} - -void EncodeMap::delRange(duint start, duint size) -{ - DbgDelEncodeTypeRange(start, size); -} - -void EncodeMap::delSegment(duint va) -{ - DbgDelEncodeTypeSegment(va); - if(mBuffer && va >= mBase && va < mBase + mSize) - { - mBuffer = nullptr; - DbgReleaseEncodeTypeBuffer(mBuffer); - } -} - -duint EncodeMap::getEncodeTypeSize(ENCODETYPE type) -{ - switch(type) - { - case enc_byte: - return 1; - case enc_word: - return 2; - case enc_dword: - return 4; - case enc_fword: - return 6; - case enc_qword: - return 8; - case enc_tbyte: - return 10; - case enc_oword: - return 16; - case enc_mmword: - return 8; - case enc_xmmword: - return 16; - case enc_ymmword: - return 32; - case enc_real4: - return 4; - case enc_real8: - return 8; - case enc_real10: - return 10; - case enc_ascii: - return 1; - case enc_unicode: - return 2; - default: - return 1; - } -} - -bool EncodeMap::isDataType(ENCODETYPE type) -{ - switch(type) - { - case enc_unknown: - case enc_code: - case enc_middle: - case enc_junk: - return false; - default: - return true; - } -} - - -ENCODETYPE EncodeMap::getDataType(duint addr, duint codesize, duint tmpcodecount, duint* tmpcodelist) -{ - if(addr - mBase >= mSize) - return ENCODETYPE::enc_unknown; - for(int i = 0; i < tmpcodecount; i++) - { - if(addr == tmpcodelist[i]) - return enc_code; - else if(addr < tmpcodelist[i] && addr + codesize > tmpcodelist[i] && !mBuffer) - return enc_byte; - } - - if(!mBuffer) - return ENCODETYPE::enc_unknown; - - duint offset = addr - mBase; - ENCODETYPE type = (ENCODETYPE)mBuffer[offset]; - bool conflict = isRangeConflict(offset, mSize - offset, codesize, tmpcodecount, tmpcodelist); - if(conflict) - return enc_byte; - else - return type; -} - -duint EncodeMap::getDataSize(duint addr, duint codesize, duint tmpcodecount, duint* tmpcodelist) -{ - - if(addr - mBase >= mSize) - return codesize; - for(int i = 0; i < tmpcodecount; i++) - { - if(addr == tmpcodelist[i]) - return codesize; - else if(addr < tmpcodelist[i] && addr + codesize > tmpcodelist[i] && !mBuffer) - return 1; - } - - if(!mBuffer) - return codesize; - - duint offset = addr - mBase; - - ENCODETYPE type = (ENCODETYPE)mBuffer[offset]; - - duint datasize = getEncodeTypeSize(type); - if(type == enc_unknown || type == enc_code || type == enc_junk) - { - if(isRangeConflict(offset, mSize - offset, codesize, tmpcodecount, tmpcodelist) || codesize == 0) - { - return datasize; - } - else - return codesize; - } - else if(type == enc_ascii || type == enc_unicode) - { - duint totalsize = 0; - for(int i = offset; i < mSize; i += datasize) - { - if(mBuffer[i] == type) - totalsize += datasize; - else - break; - } - return totalsize; - } - else - return datasize; - - return codesize; -} +#include "EncodeMap.h" + +EncodeMap::EncodeMap(QObject* parent) : QObject(parent), mBase(0), mSize(0), mBuffer(nullptr) +{ +} + +EncodeMap::~EncodeMap() +{ + if(mBuffer) + DbgReleaseEncodeTypeBuffer(mBuffer); +} + + +void EncodeMap::setMemoryRegion(duint addr) +{ + + mBase = DbgMemFindBaseAddr(addr, &mSize); + if(!mBase) + return; + + if(mBuffer) + DbgReleaseEncodeTypeBuffer(mBuffer); + mBuffer = (byte*)DbgGetEncodeTypeBuffer(addr); +} + + + +bool EncodeMap::isRangeConflict(duint offset, duint size, duint codesize, duint tmpcodecount, duint* tmpcodelist) +{ + if(codesize > size) + return true; + size = std::min(size, codesize); + if(size <= 0) + return false; + ENCODETYPE type = (ENCODETYPE)mBuffer[offset]; + if(type == enc_middle) + return true; + for(int i = 0; i < tmpcodecount; i++) + { + if(tmpcodelist[i] > offset + mBase && tmpcodelist[i] < offset + size + mBase) + return true; + } + + for(int i = 1 + offset; i < size + offset; i++) + { + if((ENCODETYPE)mBuffer[i] != enc_unknown && (ENCODETYPE)mBuffer[i] != enc_middle) + return true; + } + + return false; +} + +void EncodeMap::setDataType(duint va, ENCODETYPE type) +{ + setDataType(va, getEncodeTypeSize(type), type); +} + +void EncodeMap::setDataType(duint va, duint size, ENCODETYPE type) +{ + DbgSetEncodeType(va, size, type); + if(!mBuffer && va >= mBase && va < mBase + mSize) + setMemoryRegion(va); +} + +void EncodeMap::delRange(duint start, duint size) +{ + DbgDelEncodeTypeRange(start, size); +} + +void EncodeMap::delSegment(duint va) +{ + DbgDelEncodeTypeSegment(va); + if(mBuffer && va >= mBase && va < mBase + mSize) + { + mBuffer = nullptr; + DbgReleaseEncodeTypeBuffer(mBuffer); + } +} + +duint EncodeMap::getEncodeTypeSize(ENCODETYPE type) +{ + switch(type) + { + case enc_byte: + return 1; + case enc_word: + return 2; + case enc_dword: + return 4; + case enc_fword: + return 6; + case enc_qword: + return 8; + case enc_tbyte: + return 10; + case enc_oword: + return 16; + case enc_mmword: + return 8; + case enc_xmmword: + return 16; + case enc_ymmword: + return 32; + case enc_real4: + return 4; + case enc_real8: + return 8; + case enc_real10: + return 10; + case enc_ascii: + return 1; + case enc_unicode: + return 2; + default: + return 1; + } +} + +bool EncodeMap::isDataType(ENCODETYPE type) +{ + switch(type) + { + case enc_unknown: + case enc_code: + case enc_middle: + case enc_junk: + return false; + default: + return true; + } +} + + +ENCODETYPE EncodeMap::getDataType(duint addr, duint codesize, duint tmpcodecount, duint* tmpcodelist) +{ + if(addr - mBase >= mSize) + return ENCODETYPE::enc_unknown; + for(int i = 0; i < tmpcodecount; i++) + { + if(addr == tmpcodelist[i]) + return enc_code; + else if(addr < tmpcodelist[i] && addr + codesize > tmpcodelist[i] && !mBuffer) + return enc_byte; + } + + if(!mBuffer) + return ENCODETYPE::enc_unknown; + + duint offset = addr - mBase; + ENCODETYPE type = (ENCODETYPE)mBuffer[offset]; + bool conflict = isRangeConflict(offset, mSize - offset, codesize, tmpcodecount, tmpcodelist); + if(conflict) + return enc_byte; + else + return type; +} + +duint EncodeMap::getDataSize(duint addr, duint codesize, duint tmpcodecount, duint* tmpcodelist) +{ + + if(addr - mBase >= mSize) + return codesize; + for(int i = 0; i < tmpcodecount; i++) + { + if(addr == tmpcodelist[i]) + return codesize; + else if(addr < tmpcodelist[i] && addr + codesize > tmpcodelist[i] && !mBuffer) + return 1; + } + + if(!mBuffer) + return codesize; + + duint offset = addr - mBase; + + ENCODETYPE type = (ENCODETYPE)mBuffer[offset]; + + duint datasize = getEncodeTypeSize(type); + if(type == enc_unknown || type == enc_code || type == enc_junk) + { + if(isRangeConflict(offset, mSize - offset, codesize, tmpcodecount, tmpcodelist) || codesize == 0) + { + return datasize; + } + else + return codesize; + } + else if(type == enc_ascii || type == enc_unicode) + { + duint totalsize = 0; + for(int i = offset; i < mSize; i += datasize) + { + if(mBuffer[i] == type) + totalsize += datasize; + else + break; + } + return totalsize; + } + else + return datasize; + + return codesize; +} diff --git a/src/gui/Src/Utils/EncodeMap.h b/src/gui/Src/Utils/EncodeMap.h index 886c9e02..b5329e36 100644 --- a/src/gui/Src/Utils/EncodeMap.h +++ b/src/gui/Src/Utils/EncodeMap.h @@ -1,32 +1,32 @@ -#ifndef ENCODEMAP_H -#define ENCODEMAP_H - -#include -#include "bridge/bridgemain.h" - -class EncodeMap : public QObject -{ - Q_OBJECT -public: - explicit EncodeMap(QObject* parent = 0); - ~EncodeMap(); - - void setMemoryRegion(duint va); - duint getDataSize(duint va, duint codesize, duint tmpcodecount = 0, duint* tmpcodelist = nullptr); - ENCODETYPE getDataType(duint addr, duint codesize, duint tmpcodecount = 0, duint* tmpcodelist = nullptr); - void setDataType(duint va, ENCODETYPE type); - void setDataType(duint va, duint size, ENCODETYPE type); - void delRange(duint start, duint size); - void delSegment(duint va); - bool isRangeConflict(duint offset, duint size, duint codesize, duint tmpcodecount = 0, duint* tmpcodelist = nullptr); - bool isDataType(ENCODETYPE type); - duint getEncodeTypeSize(ENCODETYPE type); - bool isCode(ENCODETYPE type) {return type == enc_unknown || type == enc_code; } - -protected: - duint mBase; - duint mSize; - byte* mBuffer; -}; - -#endif // ENCODEMAP_H +#ifndef ENCODEMAP_H +#define ENCODEMAP_H + +#include +#include "bridge/bridgemain.h" + +class EncodeMap : public QObject +{ + Q_OBJECT +public: + explicit EncodeMap(QObject* parent = 0); + ~EncodeMap(); + + void setMemoryRegion(duint va); + duint getDataSize(duint va, duint codesize, duint tmpcodecount = 0, duint* tmpcodelist = nullptr); + ENCODETYPE getDataType(duint addr, duint codesize, duint tmpcodecount = 0, duint* tmpcodelist = nullptr); + void setDataType(duint va, ENCODETYPE type); + void setDataType(duint va, duint size, ENCODETYPE type); + void delRange(duint start, duint size); + void delSegment(duint va); + bool isRangeConflict(duint offset, duint size, duint codesize, duint tmpcodecount = 0, duint* tmpcodelist = nullptr); + bool isDataType(ENCODETYPE type); + duint getEncodeTypeSize(ENCODETYPE type); + bool isCode(ENCODETYPE type) {return type == enc_unknown || type == enc_code; } + +protected: + duint mBase; + duint mSize; + byte* mBuffer; +}; + +#endif // ENCODEMAP_H