1
0
Fork 0

DBG+BRIDGE+GUI: basics of type display GUI working

This commit is contained in:
mrexodia 2016-11-26 20:03:37 +01:00
parent 457b4bd68b
commit f44c9fa705
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
10 changed files with 228 additions and 16 deletions

View File

@ -1057,6 +1057,7 @@ BRIDGE_IMPEXP void GuiUpdateAllViews()
GuiUpdateSEHChain();
GuiUpdateArgumentWidget();
GuiUpdateGraphView();
GuiUpdateTypeWidget();
}
BRIDGE_IMPEXP void GuiUpdateRegisterView()
@ -1523,6 +1524,21 @@ BRIDGE_IMPEXP void GuiProcessEvents()
_gui_sendmessage(GUI_PROCESS_EVENTS, nullptr, nullptr);
}
BRIDGE_IMPEXP void* GuiTypeAddNode(void* parent, const TYPEDESCRIPTOR* type)
{
return _gui_sendmessage(GUI_TYPE_ADDNODE, parent, (void*)type);
}
BRIDGE_IMPEXP bool GuiTypeClear()
{
return !!_gui_sendmessage(GUI_TYPE_CLEAR, nullptr, nullptr);
}
BRIDGE_IMPEXP void GuiUpdateTypeWidget()
{
_gui_sendmessage(GUI_UPDATE_TYPE_WIDGET, nullptr, nullptr);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
hInst = hinstDLL;

View File

@ -975,12 +975,18 @@ typedef enum
GUI_MENU_SET_ENTRY_CHECKED, // param1=int hEntry, param2=bool checked
GUI_ADD_INFO_LINE, // param1=const char* infoline, param2=unused
GUI_PROCESS_EVENTS, // param1=unused, param2=unused
GUI_TYPE_ADDNODE, // param1=void* parent, param2=TYPEDESCRIPTOR* type
GUI_TYPE_CLEAR, // param1=unused, param2=unused
GUI_UPDATE_TYPE_WIDGET, // param1=unused, param2=unused
} GUIMSG;
//GUI Typedefs
struct _TYPEDESCRIPTOR;
typedef void (*GUICALLBACK)();
typedef bool (*GUISCRIPTEXECUTE)(const char* text);
typedef void (*GUISCRIPTCOMPLETER)(const char* text, char** entries, int* entryCount);
typedef bool (*TYPETOSTRING)(const struct _TYPEDESCRIPTOR* type, char* dest, size_t* destCount); //don't change destCount for final failure
//GUI structures
typedef struct
@ -1018,6 +1024,17 @@ typedef struct
char className[MAX_STRING_SIZE];
} ACTIVEVIEW;
typedef struct _TYPEDESCRIPTOR
{
bool expanded; //is the type node expanded?
const char* name; //type name (int b)
duint addr; //virtual address
int id; //type id
int size; //sizeof(type)
TYPETOSTRING callback; //convert to string
void* userdata; //user data
} TYPEDESCRIPTOR;
//GUI functions
//code page is utf8
BRIDGE_IMPEXP const char* GuiTranslateText(const char* Source);
@ -1118,6 +1135,9 @@ BRIDGE_IMPEXP void GuiSelectInMemoryMap(duint addr);
BRIDGE_IMPEXP void GuiGetActiveView(ACTIVEVIEW* activeView);
BRIDGE_IMPEXP void GuiAddInfoLine(const char* infoLine);
BRIDGE_IMPEXP void GuiProcessEvents();
BRIDGE_IMPEXP void* GuiTypeAddNode(void* parent, const TYPEDESCRIPTOR* type);
BRIDGE_IMPEXP bool GuiTypeClear();
BRIDGE_IMPEXP void GuiUpdateTypeWidget();
#ifdef __cplusplus
}

View File

@ -8,6 +8,7 @@ namespace Types
{
enum Primitive
{
Unknown,
Int8,
Uint8,
Int16,

View File

@ -360,6 +360,82 @@ static void registercommands()
dbgcmdnew("EnumTypes", cbInstrEnumTypes, false); //EnumTypes
dbgcmdnew("LoadTypes", cbInstrLoadTypes, false); //LoadTypes
dbgcmdnew("ParseTypes", cbInstrParseTypes, false); //ParseTypes
dbgcmdnew("TestTypeGui", [](int argc, char* argv[])
{
TYPEDESCRIPTOR type;
type.expanded = true;
type.name = "struct TEST";
type.addr = 0;
type.id = 0;
type.size = 19;
type.callback = [](const TYPEDESCRIPTOR * type, char* dest, size_t* destCount)
{
if(type->id == -1)
{
*dest = '\0';
return true;
}
auto value = StringUtils::sprintf("0x%X, %d (size: %d)", type->userdata, type->userdata, type->size);
if(*destCount <= value.size())
{
*destCount = value.size() + 1;
return false;
}
strcpy_s(dest, *destCount, value.c_str());
return true;
};
type.userdata = 0;
auto t = GuiTypeAddNode(nullptr, &type);
type.id = 1;
type.addr = 0;
type.size = 4;
type.name = "int a";
type.userdata = (void*)0xA;
GuiTypeAddNode(t, &type);
type.addr = 4;
type.size = 1;
type.name = "char b";
type.userdata = (void*)0xB;
GuiTypeAddNode(t, &type);
type.id = 0;
type.addr = 5;
type.size = 10;
type.name = "struct BLUB";
type.userdata = 0;
auto e = GuiTypeAddNode(t, &type);
type.id = 1;
type.size = 2;
type.name = "short c";
type.userdata = (void*)0xC;
GuiTypeAddNode(e, &type);
type.id = 0;
type.addr = 7;
type.size = 8;
type.name = "int[2]";
type.userdata = 0;
type.expanded = false;
auto d = GuiTypeAddNode(e, &type);
type.id = 1;
type.size = 4;
type.name = "int d[0]";
type.userdata = (void*)0xD0;
GuiTypeAddNode(d, &type);
type.addr = 11;
type.size = 4;
type.name = "int d[1]";
type.userdata = (void*)0xD1;
GuiTypeAddNode(d, &type);
type.addr = 15;
type.size = 4;
type.name = "int f";
type.userdata = (void*)0xF;
type.expanded = true;
GuiTypeAddNode(t, &type);
GuiUpdateAllViews();
return true;
}, false);
//plugins
dbgcmdnew("StartScylla\1scylla\1imprec", cbDebugStartScylla, false); //start scylla

View File

@ -696,6 +696,28 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2)
QCoreApplication::processEvents();
}
break;
case GUI_TYPE_ADDNODE:
{
BridgeResult result;
emit typeAddNode(param1, (const TYPEDESCRIPTOR*)param2);
return (void*)result.Wait();
}
break;
case GUI_TYPE_CLEAR:
{
BridgeResult result;
emit typeClear();
result.Wait();
}
break;
case GUI_UPDATE_TYPE_WIDGET:
{
emit typeUpdateWidget();
}
break;
}
return nullptr;

View File

@ -141,6 +141,9 @@ signals:
void selectInMemoryMap(duint addr);
void getActiveView(ACTIVEVIEW* activeView);
void addInfoLine(const QString & text);
void typeAddNode(void* parent, const TYPEDESCRIPTOR* type);
void typeClear();
void typeUpdateWidget();
private:
QMutex* mBridgeMutex;

View File

@ -1,13 +1,23 @@
#include "StructWidget.h"
#include "ui_StructWidget.h"
struct TypeDescriptor
{
TYPEDESCRIPTOR type;
QString name;
};
Q_DECLARE_METATYPE(TypeDescriptor)
StructWidget::StructWidget(QWidget* parent) :
QWidget(parent),
ui(new Ui::StructWidget)
{
ui->setupUi(this);
ui->treeWidget->setStyleSheet("QTreeWidget { color: #000000; background-color: #FFF8F0; alternate-background-color: #DCD9CF; }");
showTree();
connect(Bridge::getBridge(), SIGNAL(typeAddNode(void*, const TYPEDESCRIPTOR*)), this, SLOT(typeAddNode(void*, const TYPEDESCRIPTOR*)));
connect(Bridge::getBridge(), SIGNAL(typeClear()), this, SLOT(typeClear()));
connect(Bridge::getBridge(), SIGNAL(typeUpdateWidget()), this, SLOT(typeUpdateWidget()));
setupColumns();
}
StructWidget::~StructWidget()
@ -15,18 +25,68 @@ StructWidget::~StructWidget()
delete ui;
}
void StructWidget::showTree()
void StructWidget::typeAddNode(void* parent, const TYPEDESCRIPTOR* type)
{
TypeDescriptor dtype;
dtype.type = *type;
dtype.name = QString(dtype.type.name);
dtype.type.name = nullptr;
auto text = QStringList() << dtype.name << ToPtrString(dtype.type.addr) << "0x" + ToHexString(dtype.type.size);
QTreeWidgetItem* item = parent ? new QTreeWidgetItem((QTreeWidgetItem*)parent, text) : new QTreeWidgetItem(ui->treeWidget, text);
item->setExpanded(dtype.type.expanded);
QVariant var;
var.setValue(dtype);
item->setData(0, Qt::UserRole, var);
Bridge::getBridge()->setResult(dsint(item));
}
void StructWidget::typeClear()
{
ui->treeWidget->clear();
QTreeWidgetItem* t = new QTreeWidgetItem(ui->treeWidget, QStringList() << "struct TEST");
new QTreeWidgetItem(t, QStringList() << "int a" << "00000000" << "0xA");
new QTreeWidgetItem(t, QStringList() << "char b" << "00000004" << "0xB");
QTreeWidgetItem* e = new QTreeWidgetItem(t, QStringList() << "struct BLUB");
new QTreeWidgetItem(e, QStringList() << "short c" << "00000005" << "0xC");
QTreeWidgetItem* d = new QTreeWidgetItem(e, QStringList() << "int[2]");
new QTreeWidgetItem(d, QStringList() << "int d[0]" << "00000007" << "0xD0");
new QTreeWidgetItem(d, QStringList() << "int d[1]" << "00000011" << "0xD1");
new QTreeWidgetItem(t, QStringList() << "int f" << "00000015" << "0xF");
ui->treeWidget->setColumnWidth(0, 200);
ui->treeWidget->setColumnWidth(1, 80);
Bridge::getBridge()->setResult();
}
void StructWidget::typeUpdateWidget()
{
QTreeWidgetItemIterator it(ui->treeWidget);
while(*it)
{
QString valueStr;
QTreeWidgetItem* item = *it;
auto type = item->data(0, Qt::UserRole).value<TypeDescriptor>();
if(type.type.callback) //use the provided callback
{
char value[128] = "";
size_t valueCount = _countof(value);
if(!type.type.callback(&type.type, value, &valueCount) && valueCount && valueCount != _countof(value))
{
auto dest = new char[valueCount];
if(type.type.callback(&type.type, dest, &valueCount))
valueStr = value;
else
valueStr = "???";
delete[] dest;
}
else
valueStr = value;
}
else if(!item->childCount() && type.type.size > 0 && type.type.size <= sizeof(uint64_t)) //attempt to display small, non-parent values
{
uint64_t data;
if(DbgMemRead(type.type.addr, &data, type.type.size))
valueStr = QString().sprintf("0x%llX, %llu", data, data, data);
else if(type.type.addr)
valueStr = "???";
}
item->setText(3, valueStr);
++it;
}
}
void StructWidget::setupColumns()
{
ui->treeWidget->setColumnWidth(0, 200); //Name
ui->treeWidget->setColumnWidth(1, 80); //Address
ui->treeWidget->setColumnWidth(2, 80); //Size
//ui->treeWidget->setColumnWidth(3, 80); //Value
}

View File

@ -2,6 +2,7 @@
#define STRUCTWIDGET_H
#include <QWidget>
#include "Bridge.h"
namespace Ui
{
@ -16,10 +17,15 @@ public:
explicit StructWidget(QWidget* parent = 0);
~StructWidget();
public slots:
void typeAddNode(void* parent, const TYPEDESCRIPTOR* type);
void typeClear();
void typeUpdateWidget();
private:
Ui::StructWidget* ui;
void showTree();
void setupColumns();
};
#endif // STRUCTWIDGET_H

View File

@ -55,6 +55,11 @@
<string>Address</string>
</property>
</column>
<column>
<property name="text">
<string>Size</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>

View File

@ -211,7 +211,8 @@ SOURCES += \
dbg/commands/cmd-watch-control.cpp \
gui/Src/Gui/CustomizeMenuDialog.cpp \
gui/Src/Utils/MenuBuilder.cpp \
gui/Src/Gui/SimpleTraceDialog.cpp
gui/Src/Gui/SimpleTraceDialog.cpp \
gui/Src/Gui/StructWidget.cpp
HEADERS += \
gui/Src/Exports.h \
@ -282,6 +283,7 @@ HEADERS += \
gui/Src/Gui/YaraRuleSelectionDialog.h \
gui/Src/Disassembler/capstone_gui.h \
gui/Src/Disassembler/QBeaEngine.h \
gui/Src/Gui/StructWidget.h \
dbg/_dbgfunctions.h \
dbg/_exports.h \
dbg/_global.h \
@ -471,7 +473,8 @@ FORMS += \
gui/Src/Gui/XrefBrowseDialog.ui \
gui/Src/Gui/YaraRuleSelectionDialog.ui \
gui/Src/Gui/CustomizeMenuDialog.ui \
gui/Src/Gui/SimpleTraceDialog.ui
gui/Src/Gui/SimpleTraceDialog.ui \
gui/Src/Gui/StructWidget.ui
TRANSLATIONS += \
gui/Translations/x64dbg.ts