From fe4db7071730714efee05efcce1ac9f10bb9d106 Mon Sep 17 00:00:00 2001 From: mrexodia Date: Tue, 14 Mar 2017 08:13:39 +0100 Subject: [PATCH] DBG+BRIDGE+GUI: highlight indirect calls in the graph + fixed shadow in certain situations --- src/bridge/bridgegraph.h | 5 ++++ src/dbg/analysis/recursiveanalysis.cpp | 22 +++++++++++++++--- src/gui/Src/Gui/AppearanceDialog.cpp | 1 + src/gui/Src/Gui/DisassemblerGraphView.cpp | 28 +++++++++++++++-------- src/gui/Src/Gui/DisassemblerGraphView.h | 2 ++ src/gui/Src/Utils/Configuration.cpp | 1 + 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/bridge/bridgegraph.h b/src/bridge/bridgegraph.h index 1249625a..ef35ad1f 100644 --- a/src/bridge/bridgegraph.h +++ b/src/bridge/bridgegraph.h @@ -17,6 +17,7 @@ typedef struct duint icount; //number of instructions in node bool terminal; //node is a RET bool split; //node is a split (brtrue points to the next node) + bool indirectcall; //node contains indirect calls (call reg, call [reg+X]) void* userdata; //user data ListInfo exits; //exits (including brtrue and brfalse, duint) ListInfo instrs; //block instructions @@ -47,6 +48,7 @@ struct BridgeCFNode duint icount; //number of instructions in node bool terminal; //node is a RET bool split; //node is a split (brtrue points to the next node) + bool indirectcall; //node contains indirect calls (call reg, call [reg+X]) void* userdata; //user data std::vector exits; //exits (including brtrue and brfalse) std::vector instrs; //block instructions @@ -70,6 +72,7 @@ struct BridgeCFNode brfalse = nodeList->brfalse; icount = nodeList->icount; terminal = nodeList->terminal; + indirectcall = nodeList->indirectcall; split = nodeList->split; userdata = nodeList->userdata; if(!BridgeList::ToVector(&nodeList->exits, exits, freedata)) @@ -86,6 +89,7 @@ struct BridgeCFNode brfalse(0), icount(0), terminal(false), + indirectcall(false), split(false), userdata(nullptr) { @@ -114,6 +118,7 @@ struct BridgeCFNode out.brfalse = brfalse; out.icount = icount; out.terminal = terminal; + out.indirectcall = indirectcall; out.split = split; out.userdata = userdata; BridgeList::CopyData(&out.exits, exits); diff --git a/src/dbg/analysis/recursiveanalysis.cpp b/src/dbg/analysis/recursiveanalysis.cpp index 94c9977d..f1679fba 100644 --- a/src/dbg/analysis/recursiveanalysis.cpp +++ b/src/dbg/analysis/recursiveanalysis.cpp @@ -138,11 +138,11 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint) break; } - if(mCp.InGroup(CS_GRP_CALL)) //call + if(mCp.InGroup(CS_GRP_CALL)) //call { //TODO: add this to a queue to be analyzed later } - if(mCp.InGroup(CS_GRP_RET)) //return + if(mCp.InGroup(CS_GRP_RET)) //return { node.terminal = true; graph.AddNode(node); @@ -191,9 +191,25 @@ void RecursiveAnalysis::analyzeFunction(duint entryPoint) continue; node.instrs.reserve(node.icount); auto addr = node.start; - while(addr <= node.end) + while(addr <= node.end) //disassemble all instructions { auto size = mCp.Disassemble(addr, translateAddr(addr)) ? mCp.Size() : 1; + if(mCp.InGroup(CS_GRP_CALL) && mCp.OpCount()) //call reg / call [reg+X] + { + auto & op = mCp[0]; + switch(op.type) + { + case X86_OP_REG: + node.indirectcall = true; + break; + case X86_OP_MEM: + node.indirectcall |= op.mem.base != X86_REG_RIP && + (op.mem.base != X86_REG_INVALID || op.mem.index != X86_REG_INVALID); + break; + default: + break; + } + } BridgeCFInstruction instr; instr.addr = addr; for(int i = 0; i < size; i++) diff --git a/src/gui/Src/Gui/AppearanceDialog.cpp b/src/gui/Src/Gui/AppearanceDialog.cpp index ed3de534..dd4288f5 100644 --- a/src/gui/Src/Gui/AppearanceDialog.cpp +++ b/src/gui/Src/Gui/AppearanceDialog.cpp @@ -550,6 +550,7 @@ void AppearanceDialog::colorInfoListInit() colorInfoListAppend(tr("Background"), "GraphBackgroundColor", ""); colorInfoListAppend(tr("Node"), "GraphNodeColor", "GraphNodeBackgroundColor"); colorInfoListAppend(tr("Terminal node shadow"), "GraphRetShadowColor", ""); + colorInfoListAppend(tr("Indirect call shadow"), "GraphIndirectcallShadowColor", ""); colorInfoListAppend(tr("Unconditional branch line"), "GraphJmpColor", ""); colorInfoListAppend(tr("True branch line"), "GraphBrtrueColor", ""); colorInfoListAppend(tr("False branch line"), "GraphBrfalseColor", ""); diff --git a/src/gui/Src/Gui/DisassemblerGraphView.cpp b/src/gui/Src/Gui/DisassemblerGraphView.cpp index 0667ab9b..61325b5d 100644 --- a/src/gui/Src/Gui/DisassemblerGraphView.cpp +++ b/src/gui/Src/Gui/DisassemblerGraphView.cpp @@ -192,6 +192,8 @@ void DisassemblerGraphView::paintNormal(QPainter & p, QRect & viewportRect, int p.setPen(QColor(0, 0, 0, 0)); if(block.block.terminal) p.setBrush(retShadowColor); + else if(block.block.indirectcall) + p.setBrush(indirectcallShadowColor); else p.setBrush(QColor(0, 0, 0, 128)); p.drawRect(block.x + this->charWidth + 4, block.y + this->charWidth + 4, @@ -199,7 +201,7 @@ void DisassemblerGraphView::paintNormal(QPainter & p, QRect & viewportRect, int //Render node background p.setPen(graphNodeColor); - p.setBrush(QBrush(disassemblyBackgroundColor)); + p.setBrush(disassemblyBackgroundColor); p.drawRect(block.x + this->charWidth, block.y + this->charWidth, block.width - (4 + 2 * this->charWidth), block.height - (4 + 2 * this->charWidth)); @@ -340,9 +342,11 @@ void DisassemblerGraphView::paintOverview(QPainter & p, QRect & viewportRect, in //Render shadow p.setPen(QColor(0, 0, 0, 0)); - if(traceCount && block.block.terminal) + if((isCip || traceCount) && block.block.terminal) p.setBrush(retShadowColor); - else if(block.block.terminal || isCip) + else if((isCip || traceCount) && block.block.indirectcall) + p.setBrush(indirectcallShadowColor); + else if(isCip) p.setBrush(QColor(0, 0, 0, 0)); else p.setBrush(QColor(0, 0, 0, 128)); @@ -353,7 +357,7 @@ void DisassemblerGraphView::paintOverview(QPainter & p, QRect & viewportRect, in pen.setColor(graphNodeColor); p.setPen(pen); if(isCip) - p.setBrush(QBrush(mCipBackgroundColor)); + p.setBrush(mCipBackgroundColor); else if(traceCount) { // Color depending on how often a sequence of code is executed @@ -366,14 +370,16 @@ void DisassemblerGraphView::paintOverview(QPainter & p, QRect & viewportRect, in if(disassemblyTracedColor.blue() > 160) colorDiff *= -1; - p.setBrush(QBrush(QColor(disassemblyTracedColor.red(), - disassemblyTracedColor.green(), - std::max(0, std::min(256, disassemblyTracedColor.blue() + colorDiff))))); + p.setBrush(QColor(disassemblyTracedColor.red(), + disassemblyTracedColor.green(), + std::max(0, std::min(256, disassemblyTracedColor.blue() + colorDiff)))); } else if(block.block.terminal) - p.setBrush(QBrush(retShadowColor)); + p.setBrush(retShadowColor); + else if(block.block.indirectcall) + p.setBrush(indirectcallShadowColor); else - p.setBrush(QBrush(disassemblyBackgroundColor)); + p.setBrush(disassemblyBackgroundColor); p.drawRect(block.x + this->charWidth, block.y + this->charWidth, block.width - (4 + 2 * this->charWidth), block.height - (4 + 2 * this->charWidth)); } @@ -400,7 +406,7 @@ void DisassemblerGraphView::paintEvent(QPaintEvent* event) //Render background QRect viewportRect(this->viewport()->rect().topLeft(), this->viewport()->rect().bottomRight() - QPoint(1, 1)); - p.setBrush(QBrush(backgroundColor)); + p.setBrush(backgroundColor); p.drawRect(viewportRect); p.setBrush(Qt::black); @@ -1498,6 +1504,7 @@ void DisassemblerGraphView::loadCurrentGraph() block.false_path = node.brfalse; block.true_path = node.brtrue; block.terminal = node.terminal; + block.indirectcall = node.indirectcall; block.header_text = Text(getSymbolicName(block.entry), mLabelColor, mLabelBackgroundColor); { Instr instr; @@ -1676,6 +1683,7 @@ void DisassemblerGraphView::colorsUpdatedSlot() brtrueColor = ConfigColor("GraphBrtrueColor"); brfalseColor = ConfigColor("GraphBrfalseColor"); retShadowColor = ConfigColor("GraphRetShadowColor"); + indirectcallShadowColor = ConfigColor("GraphIndirectcallShadowColor"); backgroundColor = ConfigColor("GraphBackgroundColor"); if(!backgroundColor.alpha()) backgroundColor = disassemblySelectionColor; diff --git a/src/gui/Src/Gui/DisassemblerGraphView.h b/src/gui/Src/Gui/DisassemblerGraphView.h index f1f0e6ab..950234ef 100644 --- a/src/gui/Src/Gui/DisassemblerGraphView.h +++ b/src/gui/Src/Gui/DisassemblerGraphView.h @@ -143,6 +143,7 @@ public: duint true_path = 0; duint false_path = 0; bool terminal = false; + bool indirectcall = false; }; struct DisassemblerBlock @@ -320,6 +321,7 @@ private: QColor brtrueColor; QColor brfalseColor; QColor retShadowColor; + QColor indirectcallShadowColor; QColor backgroundColor; QColor mAutoCommentColor; QColor mAutoCommentBackgroundColor; diff --git a/src/gui/Src/Utils/Configuration.cpp b/src/gui/Src/Utils/Configuration.cpp index bdccfe38..a056adec 100644 --- a/src/gui/Src/Utils/Configuration.cpp +++ b/src/gui/Src/Utils/Configuration.cpp @@ -204,6 +204,7 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false) defaultColors.insert("GraphBrtrueColor", QColor("#387804")); defaultColors.insert("GraphBrfalseColor", QColor("#ED4630")); defaultColors.insert("GraphRetShadowColor", QColor("#900000")); + defaultColors.insert("GraphIndirectcallShadowColor", QColor("#008080")); defaultColors.insert("GraphBackgroundColor", Qt::transparent); defaultColors.insert("GraphNodeColor", QColor("#000000")); defaultColors.insert("GraphNodeBackgroundColor", Qt::transparent);