Add AutomatedPlanner skeleton class
This commit is contained in:
parent
29353111ac
commit
c8fd3a01df
@ -97,6 +97,8 @@ set(dcc_LIB_SOURCES
|
|||||||
src/Loaders.h
|
src/Loaders.h
|
||||||
src/FollowControlFlow.cpp
|
src/FollowControlFlow.cpp
|
||||||
src/FollowControlFlow.h
|
src/FollowControlFlow.h
|
||||||
|
|
||||||
|
src/AutomatedPlanner
|
||||||
)
|
)
|
||||||
set(dcc_UI_SOURCES
|
set(dcc_UI_SOURCES
|
||||||
src/ui/DccMainWindow.ui
|
src/ui/DccMainWindow.ui
|
||||||
|
|||||||
@ -151,7 +151,7 @@ enum DecompilationStep : uint32_t {
|
|||||||
//eStackTracing, // tracing stack depth across function calls
|
//eStackTracing, // tracing stack depth across function calls
|
||||||
|
|
||||||
};
|
};
|
||||||
struct Function : public std::enable_shared_from_this<Function>
|
class Function : public std::enable_shared_from_this<Function>
|
||||||
{
|
{
|
||||||
typedef llvm::iplist<BB> BasicBlockListType;
|
typedef llvm::iplist<BB> BasicBlockListType;
|
||||||
// BasicBlock iterators...
|
// BasicBlock iterators...
|
||||||
@ -216,6 +216,7 @@ public:
|
|||||||
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
// bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;}
|
||||||
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
|
bool hasRegArgs() const { return (flg & REG_ARGS)!=0;}
|
||||||
void markDoNotDecompile() { flg |= PROC_ISLIB; }
|
void markDoNotDecompile() { flg |= PROC_ISLIB; }
|
||||||
|
bool doNotDecompile() const { return isLibrary(); }
|
||||||
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
|
bool isLibrary() const { return (flg & PROC_ISLIB)!=0;}
|
||||||
void compoundCond();
|
void compoundCond();
|
||||||
void writeProcComments();
|
void writeProcComments();
|
||||||
|
|||||||
45
src/AutomatedPlanner.cpp
Normal file
45
src/AutomatedPlanner.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "AutomatedPlanner.h"
|
||||||
|
|
||||||
|
#include "project.h"
|
||||||
|
#include "FollowControlFlow.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class AutomatedPlanner
|
||||||
|
* @brief Class responsible for building command lists
|
||||||
|
*
|
||||||
|
* The goal for top level [Project] plan is to build a fully decompiled representation of source binaries
|
||||||
|
*/
|
||||||
|
|
||||||
|
AutomatedPlanner::AutomatedPlanner()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Given a state of a project, add actions that will advance the decompilation
|
||||||
|
* @param project
|
||||||
|
*/
|
||||||
|
void AutomatedPlanner::planFor(Project &project) {
|
||||||
|
// TODO: For now this logic is sprinkled all over the place, should move it here
|
||||||
|
// IF NO BINARY IMAGE LOADED - > add SelectImage/SelectProject command
|
||||||
|
// IF NO LOADER SELECTED -> add SelectLoader command
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutomatedPlanner::planFor(Function & func) {
|
||||||
|
if(func.doNotDecompile())
|
||||||
|
return; // for functions marked as non-decompileable we don't add any commands
|
||||||
|
switch(func.nStep) {
|
||||||
|
case eNotDecoded:
|
||||||
|
addAction(func,new FollowControlFlow(func.state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutomatedPlanner::addAction(Function & func, Command * cmd)
|
||||||
|
{
|
||||||
|
Project::get()->addCommand(func.shared_from_this(),cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutomatedPlanner::addAction(Project & func, Command * cmd)
|
||||||
|
{
|
||||||
|
func.addCommand(cmd);
|
||||||
|
}
|
||||||
20
src/AutomatedPlanner.h
Normal file
20
src/AutomatedPlanner.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef AUTOMATEDPLANNER_H
|
||||||
|
#define AUTOMATEDPLANNER_H
|
||||||
|
|
||||||
|
class Project;
|
||||||
|
class Function;
|
||||||
|
class Command;
|
||||||
|
|
||||||
|
class AutomatedPlanner
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AutomatedPlanner();
|
||||||
|
|
||||||
|
void planFor(Project & project);
|
||||||
|
void planFor(Function & func);
|
||||||
|
protected:
|
||||||
|
void addAction(Function &func,Command *cmd);
|
||||||
|
void addAction(Project &func,Command *cmd);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AUTOMATEDPLANNER_H
|
||||||
@ -25,7 +25,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Project *m_project;
|
Project *m_project;
|
||||||
PtrFunction *m_func;
|
PtrFunction m_func;
|
||||||
QVector<QPair<Command *,QString>> m_failures;
|
QVector<QPair<Command *,QString>> m_failures;
|
||||||
void reset();
|
void reset();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
#include "FollowControlFlow.h"
|
#include "FollowControlFlow.h"
|
||||||
|
|
||||||
|
#include "project.h"
|
||||||
|
|
||||||
QString FollowControlFlow::instanceDescription() const
|
QString FollowControlFlow::instanceDescription() const
|
||||||
{
|
{
|
||||||
return name() + " @ 0x"+QString::number(m_address,16);
|
return name() + " @ 0x"+QString::number(m_start_state.IP,16);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FollowControlFlow::execute(CommandContext *ctx)
|
bool FollowControlFlow::execute(CommandContext *ctx)
|
||||||
{
|
{
|
||||||
|
Project &proj(*ctx->m_project);
|
||||||
|
PtrFunction scanned_func(ctx->m_func);
|
||||||
|
scanned_func->FollowCtrl(proj.callGraph, &m_start_state);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,11 +3,13 @@
|
|||||||
|
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
class FollowControlFlow : public Command
|
class FollowControlFlow : public Command
|
||||||
{
|
{
|
||||||
uint32_t m_address;
|
STATE m_start_state;
|
||||||
public:
|
public:
|
||||||
FollowControlFlow(uint32_t addr) : Command("Follow control flow",eFunction),m_address(addr) {}
|
FollowControlFlow(STATE addr) : Command("Follow control flow",eFunction),m_start_state(addr) {}
|
||||||
|
|
||||||
// Command interface
|
// Command interface
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "CallGraph.h"
|
#include "CallGraph.h"
|
||||||
#include "msvc_fixes.h"
|
#include "msvc_fixes.h"
|
||||||
#include "chklib.h"
|
#include "chklib.h"
|
||||||
|
#include "FollowControlFlow.h"
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -116,6 +117,7 @@ ICODE *Function::translate_XCHG(LLInst *ll,ICODE &_Icode)
|
|||||||
* using a depth first search. */
|
* using a depth first search. */
|
||||||
void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
||||||
{
|
{
|
||||||
|
Project *project(Project::get());
|
||||||
PROG &prog(Project::get()->prog);
|
PROG &prog(Project::get()->prog);
|
||||||
ICODE _Icode, *pIcode; /* This gets copied to pProc->Icode[] later */
|
ICODE _Icode, *pIcode; /* This gets copied to pProc->Icode[] later */
|
||||||
SYM * psym;
|
SYM * psym;
|
||||||
@ -187,8 +189,8 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
|||||||
pstate->JCond.regi = 0;
|
pstate->JCond.regi = 0;
|
||||||
|
|
||||||
/* This sets up range check for indexed JMPs hopefully
|
/* This sets up range check for indexed JMPs hopefully
|
||||||
* Handles JA/JAE for fall through and JB/JBE on branch
|
* Handles JA/JAE for fall through and JB/JBE on branch
|
||||||
*/
|
*/
|
||||||
if (ip > 0 and prev.ll()->getOpcode() == iCMP and (prev.ll()->testFlags(I)))
|
if (ip > 0 and prev.ll()->getOpcode() == iCMP and (prev.ll()->testFlags(I)))
|
||||||
{
|
{
|
||||||
pstate->JCond.immed = (int16_t)prev.ll()->src().getImm2();
|
pstate->JCond.immed = (int16_t)prev.ll()->src().getImm2();
|
||||||
@ -201,7 +203,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
|
|||||||
StCopy = *pstate;
|
StCopy = *pstate;
|
||||||
|
|
||||||
/* Straight line code */
|
/* Straight line code */
|
||||||
this->FollowCtrl (pcallGraph, &StCopy); // recurrent ?
|
project->addCommand(shared_from_this(),new FollowControlFlow(StCopy)); // recurrent ?
|
||||||
|
|
||||||
if (fBranch) /* Do branching code */
|
if (fBranch) /* Do branching code */
|
||||||
{
|
{
|
||||||
@ -359,7 +361,7 @@ bool Function::followAllTableEntries(JumpTable &table, uint32_t cs, ICODE& pIcod
|
|||||||
StCopy.IP = cs + LH(&prog.image()[i]);
|
StCopy.IP = cs + LH(&prog.image()[i]);
|
||||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||||
|
|
||||||
FollowCtrl (pcallGraph, &StCopy);
|
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
||||||
|
|
||||||
++last_current_insn; // incremented here because FollowCtrl might have adde more instructions after the Jmp
|
++last_current_insn; // incremented here because FollowCtrl might have adde more instructions after the Jmp
|
||||||
last_current_insn->ll()->caseEntry = k++;
|
last_current_insn->ll()->caseEntry = k++;
|
||||||
@ -446,7 +448,7 @@ bool Function::decodeIndirectJMP(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pca
|
|||||||
uint32_t jump_target_location = table_addr + num_cases*2 + i*2;
|
uint32_t jump_target_location = table_addr + num_cases*2 + i*2;
|
||||||
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
||||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||||
FollowCtrl (pcallGraph, &StCopy);
|
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
||||||
++last_current_insn;
|
++last_current_insn;
|
||||||
last_current_insn->ll()->caseEntry = i;
|
last_current_insn->ll()->caseEntry = i;
|
||||||
last_current_insn->ll()->setFlags(CASE);
|
last_current_insn->ll()->setFlags(CASE);
|
||||||
@ -532,7 +534,7 @@ bool Function::decodeIndirectJMP2(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pc
|
|||||||
uint32_t jump_target_location = table_addr + num_cases*4 + i*2;
|
uint32_t jump_target_location = table_addr + num_cases*4 + i*2;
|
||||||
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
||||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||||
FollowCtrl (pcallGraph, &StCopy);
|
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
||||||
++last_current_insn;
|
++last_current_insn;
|
||||||
last_current_insn->ll()->caseEntry = i;
|
last_current_insn->ll()->caseEntry = i;
|
||||||
last_current_insn->ll()->setFlags(CASE);
|
last_current_insn->ll()->setFlags(CASE);
|
||||||
@ -637,7 +639,8 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
|||||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
iICODE last_current_insn = (++Icode.rbegin()).base();
|
||||||
//ip = Icode.size();
|
//ip = Icode.size();
|
||||||
|
|
||||||
FollowCtrl (pcallGraph, &StCopy);
|
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
||||||
|
|
||||||
++last_current_insn;
|
++last_current_insn;
|
||||||
last_current_insn->ll()->caseEntry = k++;
|
last_current_insn->ll()->caseEntry = k++;
|
||||||
last_current_insn->ll()->setFlags(CASE);
|
last_current_insn->ll()->setFlags(CASE);
|
||||||
@ -658,6 +661,7 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
|||||||
|
|
||||||
flg |= PROC_IJMP;
|
flg |= PROC_IJMP;
|
||||||
flg &= ~TERMINATES;
|
flg &= ~TERMINATES;
|
||||||
|
// TODO: consider adding a new user-interactive command ResolveControlFlowFailure ?
|
||||||
interactDis(shared_from_this(), Icode.size()-1);
|
interactDis(shared_from_this(), Icode.size()-1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -777,7 +781,7 @@ bool Function::process_CALL(ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *psta
|
|||||||
pcallGraph->insertCallGraph (this->shared_from_this(), iter);
|
pcallGraph->insertCallGraph (this->shared_from_this(), iter);
|
||||||
|
|
||||||
/* Process new procedure */
|
/* Process new procedure */
|
||||||
x.FollowCtrl (pcallGraph, pstate);
|
Project::get()->addCommand(iter,new FollowControlFlow(*pstate));
|
||||||
|
|
||||||
/* Restore segment registers & IP from localState */
|
/* Restore segment registers & IP from localState */
|
||||||
pstate->IP = localState.IP;
|
pstate->IP = localState.IP;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "CommandQueueView.h"
|
#include "CommandQueueView.h"
|
||||||
|
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
|
#include "../AutomatedPlanner.h"
|
||||||
|
|
||||||
#include "ui_CommandQueueView.h"
|
#include "ui_CommandQueueView.h"
|
||||||
|
|
||||||
@ -43,3 +44,10 @@ void CommandQueueView::on_btnStep_clicked()
|
|||||||
Project &project(*Project::get());
|
Project &project(*Project::get());
|
||||||
project.processCommands(1);
|
project.processCommands(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandQueueView::on_btnPlan_clicked()
|
||||||
|
{
|
||||||
|
AutomatedPlanner planner;
|
||||||
|
// TODO: Use some kind of UI context to retrieve currently selected function
|
||||||
|
//planner.planFor(func);
|
||||||
|
}
|
||||||
|
|||||||
@ -24,6 +24,8 @@ protected:
|
|||||||
private slots:
|
private slots:
|
||||||
void on_btnStep_clicked();
|
void on_btnStep_clicked();
|
||||||
|
|
||||||
|
void on_btnPlan_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::CommandQueueView *ui;
|
Ui::CommandQueueView *ui;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,16 +15,40 @@
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="dockWidgetContents">
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Planned actions:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListWidget" name="lstQueuedCommands"/>
|
<widget class="QListWidget" name="lstQueuedCommands"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnPlan">
|
||||||
|
<property name="text">
|
||||||
|
<string>Plan</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnStep">
|
<widget class="QPushButton" name="btnStep">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Step</string>
|
<string>Execute</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Completed actions:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="lstCompletedCommands"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
|||||||
@ -11,12 +11,12 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>DockWidget</string>
|
<string>Doc&kWidget</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="dockWidgetContents">
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTableView" name="m_func_list_view">
|
<widget class="QTreeView" name="m_func_list_view">
|
||||||
<property name="editTriggers">
|
<property name="editTriggers">
|
||||||
<set>QAbstractItemView::NoEditTriggers</set>
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
</property>
|
</property>
|
||||||
@ -32,40 +32,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections/>
|
||||||
<connection>
|
|
||||||
<sender>m_func_list_view</sender>
|
|
||||||
<signal>activated(QModelIndex)</signal>
|
|
||||||
<receiver>FunctionListDockWidget</receiver>
|
|
||||||
<slot>displayRequest(QModelIndex)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>199</x>
|
|
||||||
<y>161</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>199</x>
|
|
||||||
<y>149</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>m_func_list_view</sender>
|
|
||||||
<signal>clicked(QModelIndex)</signal>
|
|
||||||
<receiver>FunctionListDockWidget</receiver>
|
|
||||||
<slot>functionSelected(QModelIndex)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>199</x>
|
|
||||||
<y>161</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>199</x>
|
|
||||||
<y>149</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
<slots>
|
<slots>
|
||||||
<signal>displayRequested()</signal>
|
<signal>displayRequested()</signal>
|
||||||
<slot>displayRequest(QModelIndex)</slot>
|
<slot>displayRequest(QModelIndex)</slot>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user