summaryrefslogtreecommitdiff
path: root/examples/triage/imports.cpp
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2019-04-02 15:30:45 -0400
committerRusty Wagner <rusty@vector35.com>2019-04-02 15:36:40 -0400
commit73a9399f5d1d86c7e291498b7fe836550f2f76ab (patch)
treee7c7cfe9a2f27a93ddac41cf600e7bc1fc638a83 /examples/triage/imports.cpp
parentc17af471c48ea092434917c803f9c88fe91022a6 (diff)
Add a C++ version of the triage plugin (no Makefile yet)
Diffstat (limited to 'examples/triage/imports.cpp')
-rw-r--r--examples/triage/imports.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/examples/triage/imports.cpp b/examples/triage/imports.cpp
new file mode 100644
index 00000000..89683878
--- /dev/null
+++ b/examples/triage/imports.cpp
@@ -0,0 +1,306 @@
+#include <string.h>
+#include <algorithm>
+#include "imports.h"
+#include "view.h"
+#include "fontsettings.h"
+
+
+GenericImportsModel::GenericImportsModel(BinaryViewRef data)
+{
+ m_nameCol = 1;
+ m_moduleCol = -1;
+ m_ordinalCol = -1;
+ m_totalCols = 2;
+ m_sortCol = 0;
+ m_sortOrder = Qt::AscendingOrder;
+ m_allEntries = data->GetSymbolsOfType(ImportAddressSymbol);
+ for (auto& sym: m_allEntries)
+ {
+ if ((sym->GetNameSpace().size() != 1) || (sym->GetNameSpace()[0] != "BNINTERNALNAMESPACE"))
+ {
+ m_hasModules = true;
+ break;
+ }
+ }
+ if (m_hasModules)
+ {
+ m_nameCol = 3;
+ m_moduleCol = 1;
+ m_ordinalCol = 2;
+ m_totalCols = 4;
+ }
+ m_entries = m_allEntries;
+}
+
+
+int GenericImportsModel::columnCount(const QModelIndex&) const
+{
+ return m_totalCols;
+}
+
+
+int GenericImportsModel::rowCount(const QModelIndex& parent) const
+{
+ if (parent.isValid())
+ return 0;
+ return (int)m_entries.size();
+}
+
+
+QVariant GenericImportsModel::data(const QModelIndex& index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ if (index.row() >= (int)m_entries.size())
+ return QVariant();
+ if (index.column() == 0)
+ return QString("0x") + QString::number(m_entries[index.row()]->GetAddress(), 16);
+ if (index.column() == m_nameCol)
+ {
+ QString name = QString::fromStdString(m_entries[index.row()]->GetFullName());
+ if (name.endsWith("@GOT"))
+ name = name.mid(0, name.size() - strlen("@GOT"));
+ else if (name.endsWith("@PLT"))
+ name = name.mid(0, name.size() - strlen("@PLT"));
+ else if (name.endsWith("@IAT"))
+ name = name.mid(0, name.size() - strlen("@IAT"));
+ return name;
+ }
+ if (index.column() == m_moduleCol)
+ return getNamespace(m_entries[index.row()]);
+ if (index.column() == m_ordinalCol)
+ return QString::number(m_entries[index.row()]->GetOrdinal());
+ return QVariant();
+}
+
+
+QVariant GenericImportsModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Vertical)
+ return QVariant();
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ if (section == 0)
+ return QString("Entry");
+ if (section == m_nameCol)
+ return QString("Name");
+ if (section == m_moduleCol)
+ return QString("Module");
+ if (section == m_ordinalCol)
+ return QString("Ordinal");
+ return QVariant();
+}
+
+
+QModelIndex GenericImportsModel::index(int row, int col, const QModelIndex& parent) const
+{
+ if (parent.isValid())
+ return QModelIndex();
+ if (row >= (int)m_entries.size())
+ return QModelIndex();
+ if (col >= m_totalCols)
+ return QModelIndex();
+ return createIndex(row, col);
+}
+
+
+QModelIndex GenericImportsModel::parent(const QModelIndex&) const
+{
+ return QModelIndex();
+}
+
+
+SymbolRef GenericImportsModel::getSymbol(const QModelIndex& index)
+{
+ if (index.row() >= (int)m_entries.size())
+ return nullptr;
+ return m_entries[index.row()];
+}
+
+
+QString GenericImportsModel::getNamespace(SymbolRef sym) const
+{
+ QString name = QString::fromStdString(sym->GetNameSpace().GetString());
+ if (name == "BNINTERNALNAMESPACE")
+ return "";
+ return name;
+}
+
+
+void GenericImportsModel::performSort(int col, Qt::SortOrder order)
+{
+ std::sort(m_entries.begin(), m_entries.end(), [&](SymbolRef a, SymbolRef b) {
+ if (col == 0)
+ {
+ if (order == Qt::AscendingOrder)
+ return a->GetAddress() < b->GetAddress();
+ else
+ return a->GetAddress() > b->GetAddress();
+ }
+ else if (col == m_nameCol)
+ {
+ if (order == Qt::AscendingOrder)
+ return a->GetFullName() < b->GetFullName();
+ else
+ return a->GetFullName() > b->GetFullName();
+ }
+ else if (col == m_moduleCol)
+ {
+ if (order == Qt::AscendingOrder)
+ return getNamespace(a) < getNamespace(b);
+ else
+ return getNamespace(a) > getNamespace(b);
+ }
+ else if (col == m_ordinalCol)
+ {
+ if (order == Qt::AscendingOrder)
+ return a->GetOrdinal() < b->GetOrdinal();
+ else
+ return a->GetOrdinal() > b->GetOrdinal();
+ }
+ return false;
+ });
+}
+
+
+void GenericImportsModel::sort(int col, Qt::SortOrder order)
+{
+ beginResetModel();
+ m_sortCol = col;
+ m_sortOrder = order;
+ performSort(col, order);
+ endResetModel();
+}
+
+
+void GenericImportsModel::setFilter(const std::string& filterText)
+{
+ beginResetModel();
+ m_entries.clear();
+ for (auto& entry: m_allEntries)
+ {
+ if (FilteredView::match(entry->GetFullName(), filterText))
+ m_entries.push_back(entry);
+ else if (FilteredView::match(getNamespace(entry).toStdString(), filterText))
+ m_entries.push_back(entry);
+ }
+ performSort(m_sortCol, m_sortOrder);
+ endResetModel();
+}
+
+
+ImportsTreeView::ImportsTreeView(ImportsWidget* parent, TriageView* view, BinaryViewRef data): QTreeView(parent)
+{
+ m_data = data;
+ m_parent = parent;
+ m_view = view;
+
+ // Allow view-specific shortcuts when imports are focused
+ m_actionHandler.setupActionHandler(this);
+ m_actionHandler.setActionContext([=]() { return m_view->actionContext(); });
+
+ m_model = new GenericImportsModel(m_data);
+ setModel(m_model);
+ setRootIsDecorated(false);
+ setUniformRowHeights(true);
+ setSortingEnabled(true);
+ sortByColumn(0, Qt::AscendingOrder);
+ if (m_model->HasOrdinalCol())
+ setColumnWidth(m_model->GetOrdinalCol(), 55);
+
+ setFont(getMonospaceFont(this));
+
+ connect(selectionModel(), &QItemSelectionModel::currentChanged, this, &ImportsTreeView::importSelected);
+ connect(this, &QTreeView::doubleClicked, this, &ImportsTreeView::importDoubleClicked);
+}
+
+
+void ImportsTreeView::importSelected(const QModelIndex& cur, const QModelIndex&)
+{
+ SymbolRef sym = m_model->getSymbol(cur);
+ if (sym)
+ m_view->setCurrentOffset(sym->GetAddress());
+}
+
+
+void ImportsTreeView::importDoubleClicked(const QModelIndex& cur)
+{
+ SymbolRef sym = m_model->getSymbol(cur);
+ if (sym)
+ {
+ ViewFrame* viewFrame = ViewFrame::viewFrameForWidget(this);
+ if (viewFrame)
+ viewFrame->navigate("Linear:" + viewFrame->getCurrentDataType(), sym->GetAddress());
+ }
+}
+
+
+void ImportsTreeView::setFilter(const std::string& filterText)
+{
+ m_model->setFilter(filterText);
+}
+
+
+void ImportsTreeView::scrollToFirstItem()
+{
+ scrollToTop();
+}
+
+
+void ImportsTreeView::scrollToCurrentItem()
+{
+ scrollTo(currentIndex());
+}
+
+
+void ImportsTreeView::selectFirstItem()
+{
+ setCurrentIndex(m_model->index(0, 0, QModelIndex()));
+}
+
+
+void ImportsTreeView::activateFirstItem()
+{
+ importDoubleClicked(m_model->index(0, 0, QModelIndex()));
+}
+
+
+void ImportsTreeView::closeFilter()
+{
+ setFocus(Qt::OtherFocusReason);
+}
+
+
+void ImportsTreeView::keyPressEvent(QKeyEvent* event)
+{
+ if ((event->text().size() == 1) && (event->text()[0] > ' ') && (event->text()[0] < 127))
+ {
+ m_parent->showFilter(event->text());
+ event->accept();
+ }
+ else if ((event->key() == Qt::Key_Return) || (event->key() == Qt::Key_Enter))
+ {
+ QList<QModelIndex> sel = selectionModel()->selectedIndexes();
+ if (sel.size() != 0)
+ importDoubleClicked(sel[0]);
+ }
+ QTreeView::keyPressEvent(event);
+}
+
+
+ImportsWidget::ImportsWidget(QWidget* parent, TriageView* view, BinaryViewRef data): QWidget(parent)
+{
+ QVBoxLayout* layout = new QVBoxLayout();
+ layout->setContentsMargins(0, 0, 0, 0);
+ ImportsTreeView* imports = new ImportsTreeView(this, view, data);
+ m_filter = new FilteredView(this, imports, imports);
+ layout->addWidget(m_filter, 1);
+ setLayout(layout);
+ setMinimumSize(UIContext::getScaledWindowSize(100, 196));
+}
+
+
+void ImportsWidget::showFilter(const QString& filter)
+{
+ m_filter->showFilter(filter);
+}