1
0
Fork 0

DBG: changes in controlflowanalysis

This commit is contained in:
Mr. eXoDia 2015-07-13 01:59:43 +02:00
parent 38683dae38
commit 8ac9f90eeb
5 changed files with 177 additions and 25 deletions

View File

@ -9,7 +9,7 @@ class Analysis
public:
explicit Analysis(uint base, uint size);
Analysis(const Analysis & that) = delete;
~Analysis();
virtual ~Analysis();
virtual void Analyse() = 0;
virtual void SetMarkers() = 0;

View File

@ -11,9 +11,17 @@ void ControlFlowAnalysis::Analyse()
DWORD ticks = GetTickCount();
BasicBlockStarts();
BasicBlocks();
dprintf("Basic block starts in %ums!\n", GetTickCount() - ticks);
ticks = GetTickCount();
dprintf("Analysis finished in %ums!\n", GetTickCount() - ticks);
BasicBlocks();
dprintf("Basick blocks in %ums!\n", GetTickCount() - ticks);
ticks = GetTickCount();
Functions();
dprintf("Functions in %ums!\n", GetTickCount() - ticks);
dprintf("Analysis finished!\n");
}
void ControlFlowAnalysis::SetMarkers()
@ -21,14 +29,16 @@ void ControlFlowAnalysis::SetMarkers()
dprintf("digraph ControlFlow {\n");
int i = 0;
std::map<uint, int> nodeMap;
for(auto block : _blocks)
for(const auto & it : _blocks)
{
const auto & block = it.second;
nodeMap.insert({ block.start, i });
dprintf(" node%u [label=\"start=%p, end=%p\"];\n", i, block.start, block.end);
dprintf(" node%u [label=\"s=%p, e=%p, f=%p\"];\n", i, block.start, block.end, block.function);
i++;
}
for(auto block : _blocks)
for(auto it : _blocks)
{
const auto & block = it.second;
int startNode = nodeMap[block.start];
if(block.left)
{
@ -65,26 +75,26 @@ void ControlFlowAnalysis::BasicBlockStarts()
uint addr = _base + i;
if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER))
{
if(bSkipFilling) //handle filling skip mode
if(bSkipFilling) //handle filling skip mode
{
if(!_cp.IsFilling()) //do nothing until the filling stopped
if(!_cp.IsFilling()) //do nothing until the filling stopped
{
bSkipFilling = false;
_blockStarts.insert(addr);
}
}
else if(_cp.InGroup(CS_GRP_RET) || _cp.InGroup(CS_GRP_INT)) //RET/INT break control flow
else if(_cp.InGroup(CS_GRP_RET) || _cp.InGroup(CS_GRP_INT)) //RET/INT break control flow
{
bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow)
}
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) //branches
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) //branches
{
uint dest1 = GetBranchOperand();
uint dest2 = 0;
if(_cp.GetId() != X86_INS_JMP) //unconditional jump
if(_cp.GetId() != X86_INS_JMP) //unconditional jump
dest2 = addr + _cp.Size();
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted)
bSkipFilling = true;
if(dest1)
_blockStarts.insert(dest1);
@ -128,29 +138,153 @@ void ControlFlowAnalysis::BasicBlocks()
{
if(_cp.InGroup(CS_GRP_RET))
{
_blocks.push_back(BasicBlock(start, addr, 0, 0)); //leaf block
insertBlock(BasicBlock(start, addr, 0, 0)); //leaf block
break;
}
else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop())
{
uint dest1 = GetBranchOperand();
uint dest2 = _cp.GetId() != X86_INS_JMP ? addr + _cp.Size() : 0;
_blocks.push_back(BasicBlock(start, addr, dest1, dest2));
insertBlock(BasicBlock(start, addr, dest1, dest2));
insertParent(dest1, start);
insertParent(dest2, start);
break;
}
addr += _cp.Size();
}
else
addr++;
if(addr == nextStart) //special case handling overlapping blocks
if(addr == nextStart) //special case handling overlapping blocks
{
_blocks.push_back(BasicBlock(start, prevaddr, 0, nextStart));
insertBlock(BasicBlock(start, prevaddr, 0, nextStart));
insertParent(nextStart, start);
break;
}
}
}
}
void ControlFlowAnalysis::Functions()
{
typedef std::pair<BasicBlock*, UintSet*> DelayedBlock;
std::vector<DelayedBlock> delayedBlocks;
for(auto & it : _blocks)
{
BasicBlock* block = &it.second;
UintSet* parents = findParents(block->start);
if(!block->function)
{
if(!parents) //no parents = function start
{
uint functionStart = block->start;
block->function = functionStart;
UintSet functionBlocks;
functionBlocks.insert(functionStart);
_functions[functionStart] = functionBlocks;
}
else //in function
{
uint function = findFunctionStart(block, parents);
if(!function) //this happens with loops sometimes
delayedBlocks.push_back(DelayedBlock(block, parents));
else
block->function = function;
}
}
else
DebugBreak(); //this should not happen
}
dprintf("%u/%u delayed blocks...\n", delayedBlocks.size(), _blocks.size());
for(auto & delayedBlock : delayedBlocks)
{
BasicBlock* block = delayedBlock.first;
UintSet* parents = delayedBlock.second;
uint function = findFunctionStart(block, parents);
if(!function)
{
dprintf("unresolved block %s\n", blockToString(block).c_str());
if(parents)
{
dprintf("parents:\n");
for(auto parent : *parents)
dprintf(" %s\n", blockToString(findBlock(parent)).c_str());
}
else
dprintf("parents: null");
dprintf("left: %s\n", blockToString(findBlock(block->left)).c_str());
dprintf("right: %s\n", blockToString(findBlock(block->right)).c_str());
return;
}
block->function = function;
}
}
void ControlFlowAnalysis::insertBlock(BasicBlock block)
{
if(_blocks.find(block.start) != _blocks.end())
DebugBreak();
_blocks[block.start] = block;
}
ControlFlowAnalysis::BasicBlock* ControlFlowAnalysis::findBlock(uint start)
{
if(!start)
return nullptr;
auto found = _blocks.find(start);
return found != _blocks.end() ? &found->second : nullptr;
}
void ControlFlowAnalysis::insertParent(uint child, uint parent)
{
if(!child || !parent)
return;
auto found = _parentMap.find(child);
if(found == _parentMap.end())
{
UintSet parents;
parents.insert(parent);
_parentMap[child] = parents;
}
else
found->second.insert(parent);
}
ControlFlowAnalysis::UintSet* ControlFlowAnalysis::findParents(uint child)
{
if(!child)
return nullptr;
auto found = _parentMap.find(child);
return found != _parentMap.end() ? &found->second : nullptr;
}
uint ControlFlowAnalysis::findFunctionStart(BasicBlock* block, ControlFlowAnalysis::UintSet* parents)
{
if(!block)
return 0;
if(block->function)
return block->function;
BasicBlock* left = findBlock(block->left);
if(left && left->function)
return left->function;
BasicBlock* right = findBlock(block->right);
if(right && right->function)
return right->function;
for(auto start : *parents)
{
BasicBlock* parent = findBlock(start);
if(parent->function)
return parent->function;
}
return 0;
}
String ControlFlowAnalysis::blockToString(BasicBlock* block)
{
if(!block)
return String("null");
return block->toString();
}
uint ControlFlowAnalysis::GetBranchOperand()
{
for(int i = 0; i < _cp.x86().op_count; i++)

View File

@ -2,15 +2,15 @@
#define _CONTROLFLOWANALYSIS_H
#include "_global.h"
#include "capstone_wrapper.h"
#include "analysis.h"
#include "addrinfo.h"
class ControlFlowAnalysis : public Analysis
{
public:
explicit ControlFlowAnalysis(uint base, uint size);
void Analyse();
void SetMarkers();
void Analyse() override;
void SetMarkers() override;
private:
struct BasicBlock
@ -19,6 +19,7 @@ private:
uint end;
uint left;
uint right;
uint function;
BasicBlock()
{
@ -26,6 +27,7 @@ private:
this->end = 0;
this->left = 0;
this->right = 0;
this->function = 0;
}
BasicBlock(uint start, uint end, uint left, uint right)
@ -34,14 +36,31 @@ private:
this->end = end;
this->left = min(left, right);
this->right = max(left, right);
this->function = 0;
}
String toString()
{
return StringUtils::sprintf("start:%p,end:%p,left:%p,right:%p,func:%p", start, end, left, right, function);
}
};
std::set<uint> _blockStarts;
std::vector<BasicBlock> _blocks;
typedef std::set<uint> UintSet;
UintSet _blockStarts;
std::map<uint, BasicBlock> _blocks; //start of block -> block
std::map<uint, UintSet> _parentMap; //start child -> parents
std::map<uint, UintSet> _functions; //function start -> function block starts
void BasicBlockStarts();
void BasicBlocks();
void Functions();
void insertBlock(BasicBlock block);
BasicBlock* findBlock(uint start);
void insertParent(uint child, uint parent);
UintSet* findParents(uint child);
uint findFunctionStart(BasicBlock* block, UintSet* parents);
String blockToString(BasicBlock* block);
uint GetBranchOperand();
};

View File

@ -2,15 +2,14 @@
#define _FUNCTIONANALYSIS_H
#include "_global.h"
#include "capstone_wrapper.h"
#include "analysis.h"
class FunctionAnalysis : public Analysis
{
public:
explicit FunctionAnalysis(uint base, uint size);
void Analyse();
void SetMarkers();
void Analyse() override;
void SetMarkers() override;
private:
struct FunctionInfo

View File

@ -1930,7 +1930,7 @@ CMDRESULT cbInstrCfanalyse(int argc, char* argv[])
uint base = MemFindBaseAddr(sel.start, &size);
ControlFlowAnalysis anal(base, size);
anal.Analyse();
anal.SetMarkers();
//anal.SetMarkers();
GuiUpdateAllViews();
return STATUS_CONTINUE;
}