1
0
Fork 0

DBG: AStyle

This commit is contained in:
Mr. eXoDia 2016-06-22 17:28:54 +02:00
parent 5fc4d90d8b
commit fa2db57799
11 changed files with 1492 additions and 1492 deletions

View File

@ -1,373 +1,373 @@
#include "advancedanalysis.h"
#include <queue>
#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<duint> 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<XREF> 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<duint> 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 <queue>
#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<duint> 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<XREF> 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<duint> 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);
}
}
}
}

View File

@ -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<duint>;
template<class T>
using UintMap = std::unordered_map<duint, T>;
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<CFNode> nodes; //CFNode.start -> CFNode
UintMap<UintSet> 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<duint> mEntryPoints;
std::unordered_set<duint> mCandidateEPs;
std::unordered_set<duint> mFuzzyEPs;
std::vector<CFGraph> mFunctions;
std::unordered_map<duint, std::vector<XREF>> 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<duint>;
template<class T>
using UintMap = std::unordered_map<duint, T>;
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<CFNode> nodes; //CFNode.start -> CFNode
UintMap<UintSet> 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<duint> mEntryPoints;
std::unordered_set<duint> mCandidateEPs;
std::unordered_set<duint> mFuzzyEPs;
std::vector<CFGraph> mFunctions;
std::unordered_map<duint, std::vector<XREF>> 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);
};

View File

@ -1,309 +1,309 @@
#include "datainst_helper.h"
#include "encodemap.h"
#include "stringutils.h"
#include <capstone_wrapper.h>
std::unordered_map<ENCODETYPE, std::string> disasmMap;
std::unordered_map<std::string, ENCODETYPE> 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<unsigned char>(buffer);
case enc_word:
return StringUtils::ToIntegralString<unsigned short>(buffer);
case enc_dword:
return StringUtils::ToIntegralString<unsigned int>(buffer);
case enc_fword:
return StringUtils::ToHex((char*)buffer, 6, true);
case enc_qword:
return StringUtils::ToIntegralString<unsigned long long int>(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<float>(buffer);
case enc_real8:
return StringUtils::ToFloatingString<double>(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<unsigned char>(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 <capstone_wrapper.h>
std::unordered_map<ENCODETYPE, std::string> disasmMap;
std::unordered_map<std::string, ENCODETYPE> 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<unsigned char>(buffer);
case enc_word:
return StringUtils::ToIntegralString<unsigned short>(buffer);
case enc_dword:
return StringUtils::ToIntegralString<unsigned int>(buffer);
case enc_fword:
return StringUtils::ToHex((char*)buffer, 6, true);
case enc_qword:
return StringUtils::ToIntegralString<unsigned long long int>(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<float>(buffer);
case enc_real8:
return StringUtils::ToFloatingString<double>(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<unsigned char>(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;
}

View File

@ -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);

View File

@ -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);

View File

@ -1,381 +1,381 @@
#include "encodemap.h"
#include <unordered_map>
#include "addrinfo.h"
#include <algorithm>
#include <capstone_wrapper.h>
struct ENCODEMAP : AddrInfo
{
duint size;
byte* data;
};
std::unordered_map<duint, duint> 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<ENCODEMAP>
{
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<LockEncodeMaps, ENCODEMAP, EncodeMapSerializer>
{
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 <unordered_map>
#include "addrinfo.h"
#include <algorithm>
#include <capstone_wrapper.h>
struct ENCODEMAP : AddrInfo
{
duint size;
byte* data;
};
std::unordered_map<duint, duint> 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<ENCODEMAP>
{
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<LockEncodeMaps, ENCODEMAP, EncodeMapSerializer>
{
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();
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -1,32 +1,32 @@
#ifndef ENCODEMAP_H
#define ENCODEMAP_H
#include <QObject>
#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 <QObject>
#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