diff --git a/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp b/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp index c3639772..e10b625b 100644 --- a/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp +++ b/x64_dbg_gui/Project/Src/Gui/CPUDump.cpp @@ -6,6 +6,7 @@ #include "LineEditDialog.h" #include "HexEditDialog.h" #include "YaraRuleSelectionDialog.h" +#include "DataCopyDialog.h" CPUDump::CPUDump(QWidget* parent) : HexDump(parent) { @@ -239,6 +240,10 @@ void CPUDump::setupContextMenu() this->addAction(mYaraAction); connect(mYaraAction, SIGNAL(triggered()), this, SLOT(yaraSlot())); + //Data copy + mDataCopyAction = new QAction(QIcon(":/icons/images/data-copy.png"), "Data copy...", this); + connect(mDataCopyAction, SIGNAL(triggered()), this, SLOT(dataCopySlot())); + //Find References mFindReferencesAction = new QAction("Find &References", this); mFindReferencesAction->setShortcutContext(Qt::WidgetShortcut); @@ -473,6 +478,7 @@ void CPUDump::contextMenuEvent(QContextMenuEvent* event) wMenu->addMenu(mBreakpointMenu); wMenu->addAction(mFindPatternAction); wMenu->addAction(mYaraAction); + wMenu->addAction(mDataCopyAction); wMenu->addMenu(mGotoMenu); wMenu->addSeparator(); wMenu->addMenu(mHexMenu); @@ -1346,3 +1352,14 @@ void CPUDump::yaraSlot() emit displayReferencesWidget(); } } + +void CPUDump::dataCopySlot() +{ + int_t selStart = getSelectionStart(); + int_t selSize = getSelectionEnd() - selStart + 1; + QVector data; + data.resize(selSize); + mMemPage->read(data.data(), selStart, selSize); + DataCopyDialog dataDialog(&data, this); + dataDialog.exec(); +} diff --git a/x64_dbg_gui/Project/Src/Gui/CPUDump.h b/x64_dbg_gui/Project/Src/Gui/CPUDump.h index dc8a837c..cb4240d4 100644 --- a/x64_dbg_gui/Project/Src/Gui/CPUDump.h +++ b/x64_dbg_gui/Project/Src/Gui/CPUDump.h @@ -79,6 +79,7 @@ public slots: void selectionUpdatedSlot(); void yaraSlot(); + void dataCopySlot(); private: QMenu* mBreakpointMenu; @@ -160,6 +161,7 @@ private: QAction* mFindPatternAction; QAction* mFindReferencesAction; QAction* mYaraAction; + QAction* mDataCopyAction; QAction* mUndoSelection; QMenu* mSpecialMenu; diff --git a/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.cpp b/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.cpp new file mode 100644 index 00000000..c74676cb --- /dev/null +++ b/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.cpp @@ -0,0 +1,175 @@ +#include "DataCopyDialog.h" +#include "ui_DataCopyDialog.h" +#include "Bridge.h" + +DataCopyDialog::DataCopyDialog(const QVector* data, QWidget* parent) : QDialog(parent), ui(new Ui::DataCopyDialog) +{ + ui->setupUi(this); +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + setWindowFlags(Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint); +#endif + setFixedSize(this->size()); //fixed size + mData = data; + + ui->comboType->addItem("C-Style BYTE (Hex)"); + ui->comboType->addItem("C-Style WORD (Hex)"); + ui->comboType->addItem("C-Style DWORD (Hex)"); + ui->comboType->addItem("C-Style String"); + ui->comboType->addItem("C-Style Unicode String"); + + ui->comboType->setCurrentIndex(DataCByte); + + printData((DataType)ui->comboType->currentIndex()); +} + +QString DataCopyDialog::printEscapedString(bool & bPrevWasHex, int ch, const char* hexFormat) +{ + QString data=""; + switch(ch) //escaping + { + case '\t': + data = "\\t"; + bPrevWasHex = false; + break; + case '\f': + data = "\\f"; + bPrevWasHex = false; + break; + case '\v': + data = "\\v"; + bPrevWasHex = false; + break; + case '\n': + data = "\\n"; + bPrevWasHex = false; + break; + case '\r': + data = "\\r"; + bPrevWasHex = false; + break; + case '\\': + data = "\\\\"; + bPrevWasHex = false; + break; + case '\"': + data = "\\\""; + bPrevWasHex = false; + break; + default: + if(ch>=' ' && ch<='~') + { + if(bPrevWasHex && isxdigit(ch)) + data = QString().sprintf("\"\"%c", ch); + else + data = QString().sprintf("%c", ch); + bPrevWasHex = false; + } + else + { + bPrevWasHex=true; + data = QString().sprintf(hexFormat, ch); + } + break; + } + return data; +} + +void DataCopyDialog::printData(DataType type) +{ + ui->editCode->clear(); + QString data; + switch(type) + { + case DataCByte: + { + data += "{"; + for(int i = 0; i < mData->size(); i++) + { + if(i) + data += ", "; + data += QString().sprintf("0x%02X", mData->at(i)); + } + data += "};"; + } + break; + + case DataCWord: + { + int numwords = mData->size() / sizeof(unsigned short); + data += "{"; + for(int i = 0; i < numwords; i++) + { + if(i) + data += ", "; + data += QString().sprintf("0x%04X", ((unsigned short*)mData->constData())[i]); + } + data += "};"; + } + break; + + case DataCDword: + { + int numdwords = mData->size() / sizeof(unsigned int); + data += "{"; + for(int i = 0; i < numdwords; i++) + { + if(i) + data += ", "; + data += QString().sprintf("0x%08X", ((unsigned int*)mData->constData())[i]); + } + data += "};"; + } + break; + + case DataCString: + { + data += "\""; + bool bPrevWasHex=false; + for(int i = 0; i < mData->size(); i++) + { + byte_t ch = mData->at(i); + data += printEscapedString(bPrevWasHex, ch, "\\x%02X"); + } + data += "\""; + } + break; + + case DataCUnicodeString: //extended ASCII + hex escaped only + { + data += "L\""; + int numwchars = mData->size() / sizeof(unsigned short); + bool bPrevWasHex = false; + for(int i = 0; i < numwchars; i++) + { + unsigned short ch = ((unsigned short*)mData->constData())[i]; + if((ch & 0xFF00) == 0) //extended ASCII + { + data += printEscapedString(bPrevWasHex, ch, "\\x%04X"); + } + else //full unicode character + { + bPrevWasHex=true; + data += QString().sprintf("\\x%04X", ch); + } + } + data += "\""; + } + break; + } + ui->editCode->setPlainText(data); +} + +DataCopyDialog::~DataCopyDialog() +{ + delete ui; +} + +void DataCopyDialog::on_comboType_currentIndexChanged(int index) +{ + printData((DataType)index); +} + +void DataCopyDialog::on_buttonCopy_clicked() +{ + Bridge::CopyToClipboard(ui->editCode->toPlainText()); +} diff --git a/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.h b/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.h new file mode 100644 index 00000000..7e61735e --- /dev/null +++ b/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.h @@ -0,0 +1,42 @@ +#ifndef DATACOPYDIALOG_H +#define DATACOPYDIALOG_H + +#include +#include +#include "NewTypes.h" + +namespace Ui +{ +class DataCopyDialog; +} + +class DataCopyDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DataCopyDialog(const QVector* data, QWidget* parent = 0); + ~DataCopyDialog(); + +private slots: + void on_comboType_currentIndexChanged(int index); + void on_buttonCopy_clicked(); + +private: + Ui::DataCopyDialog* ui; + const QVector* mData; + + enum DataType + { + DataCByte = 0, + DataCWord, + DataCDword, + DataCString, + DataCUnicodeString, + }; + + void printData(DataType type); + QString printEscapedString(bool & bPrevWasHex, int ch, const char* hexFormat); +}; + +#endif // DATACOPYDIALOG_H diff --git a/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.ui b/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.ui new file mode 100644 index 00000000..d94c78a3 --- /dev/null +++ b/x64_dbg_gui/Project/Src/Gui/DataCopyDialog.ui @@ -0,0 +1,63 @@ + + + DataCopyDialog + + + + 0 + 0 + 400 + 242 + + + + Data Copy + + + + :/icons/images/data-copy.png:/icons/images/data-copy.png + + + + + 10 + 10 + 381 + 225 + + + + + + + + Courier New + + + + + + + + + + + + + Copy + + + + + + + + + + + + + + + + diff --git a/x64_dbg_gui/Project/images/data-copy.png b/x64_dbg_gui/Project/images/data-copy.png new file mode 100644 index 00000000..76add6a0 Binary files /dev/null and b/x64_dbg_gui/Project/images/data-copy.png differ diff --git a/x64_dbg_gui/Project/resource.qrc b/x64_dbg_gui/Project/resource.qrc index 7357e1d8..c1ca6b83 100644 --- a/x64_dbg_gui/Project/resource.qrc +++ b/x64_dbg_gui/Project/resource.qrc @@ -52,5 +52,6 @@ images/close-all-tabs.png images/bug-report.png images/yara.png + images/data-copy.png diff --git a/x64_dbg_gui/Project/x64_dbg.pro b/x64_dbg_gui/Project/x64_dbg.pro index e80fa89f..45bc39b5 100644 --- a/x64_dbg_gui/Project/x64_dbg.pro +++ b/x64_dbg_gui/Project/x64_dbg.pro @@ -87,7 +87,8 @@ SOURCES += \ Src/Gui/SelectFields.cpp \ Src/Gui/ReferenceManager.cpp \ Src/Bridge/BridgeResult.cpp \ - Src/Gui/YaraRuleSelectionDialog.cpp + Src/Gui/YaraRuleSelectionDialog.cpp \ + Src/Gui/DataCopyDialog.cpp HEADERS += \ @@ -153,7 +154,8 @@ HEADERS += \ Src/Gui/SelectFields.h \ Src/Gui/ReferenceManager.h \ Src/Bridge/BridgeResult.h \ - Src/Gui/YaraRuleSelectionDialog.h + Src/Gui/YaraRuleSelectionDialog.h \ + Src/Gui/DataCopyDialog.h INCLUDEPATH += \ @@ -189,7 +191,8 @@ FORMS += \ Src/Gui/AttachDialog.ui \ Src/Gui/PageMemoryRights.ui \ Src/Gui/SelectFields.ui \ - Src/Gui/YaraRuleSelectionDialog.ui + Src/Gui/YaraRuleSelectionDialog.ui \ + Src/Gui/DataCopyDialog.ui INCLUDEPATH += $$PWD/Src/Bridge