WingHexDisasm/winghexdisasm.cpp

291 lines
8.0 KiB
C++

#include "winghexdisasm.h"
#include <QApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QMessageBox>
#include <QMetaEnum>
#include <QSettings>
#include <QVBoxLayout>
Q_DECLARE_METATYPE(cs_arch)
Q_DECLARE_METATYPE(cs_mode)
#define ICONRES(name) QIcon(":/WingHexDisasm/img/" name ".png")
#define HOSTICONRES(name) QIcon(HOSTRESPIMG(name))
WingHexDisasm::WingHexDisasm(QObject *parent) { Q_UNUSED(parent); }
bool WingHexDisasm::init(QList<WingPluginInfo> loadedplugin) {
Q_UNUSED(loadedplugin);
if (SDKVERSION < 8) {
QMessageBox::critical(nullptr, "Error",
"UnSupported Plugin System Version!",
QMessageBox::Ok);
return false;
}
auto translator = new QTranslator(this);
auto s = GETPLUGINQM("WingHexDisasm.qm");
if (!translator->load(s) || !QApplication::installTranslator(translator)) {
QMessageBox::critical(nullptr, "Error", "Error Loading Translation File!",
QMessageBox::Ok);
return false;
}
w = new QWidget;
auto vlayout = new QVBoxLayout(w);
auto hlayout = new QHBoxLayout;
hlayout->addWidget(new QLabel(tr("Arch :"), w));
hlayout->addSpacing(10);
// 默认 x86_64 64 位指令
arch = new QComboBox(w);
QStringList archs({"ARM", "ARM64", "MIPS", "X86_64", "PPC", "SPARC", "SYSZ",
"XCORE", "M68K", "TMS320C64X", "M680X", "EVM", "MOS65XX",
"WASM", "BPF", "RISCV"});
arch->addItems(archs);
arch->setCurrentIndex(3);
void (QComboBox::*indexChanged)(int index) = &QComboBox::currentIndexChanged;
connect(arch, indexChanged, [=](int index) {
switch (index) {
case 0:
carch = cs_arch::CS_ARCH_ARM;
break;
case 1:
carch = cs_arch::CS_ARCH_ARM64;
break;
case 2:
carch = cs_arch::CS_ARCH_MIPS;
break;
case 3:
carch = cs_arch::CS_ARCH_X86;
break;
case 4:
carch = cs_arch::CS_ARCH_PPC;
break;
case 5:
carch = cs_arch::CS_ARCH_SPARC;
break;
case 6:
carch = cs_arch::CS_ARCH_SYSZ;
break;
case 7:
carch = cs_arch::CS_ARCH_XCORE;
break;
case 8:
carch = cs_arch::CS_ARCH_M68K;
break;
case 9:
carch = cs_arch::CS_ARCH_TMS320C64X;
break;
case 10:
carch = cs_arch::CS_ARCH_M680X;
break;
case 11:
carch = cs_arch::CS_ARCH_EVM;
break;
case 12:
carch = cs_arch::CS_ARCH_MOS65XX;
break;
case 13:
carch = cs_arch::CS_ARCH_WASM;
break;
case 14:
carch = cs_arch::CS_ARCH_BPF;
break;
case 15:
carch = cs_arch::CS_ARCH_RISCV;
break;
}
});
hlayout->addWidget(arch);
hlayout->addSpacing(30);
hlayout->addWidget(new QLabel(tr("Mode :"), w));
hlayout->addSpacing(10);
mode = new QComboBox(w);
QStringList modes({"x16", "x32", "x64", "THUMB", "MIPS32", "MIPS64"});
mode->addItems(modes);
mode->setCurrentIndex(2);
connect(mode, indexChanged, [=](int index) {
switch (index) {
case 0:
cmode = cs_mode::CS_MODE_16;
break;
case 1:
cmode = cs_mode::CS_MODE_32;
break;
case 2:
cmode = cs_mode::CS_MODE_64;
break;
case 3:
cmode = cs_mode::CS_MODE_THUMB;
break;
case 4:
cmode = cs_mode::CS_MODE_MIPS32;
break;
case 5:
cmode = cs_mode::CS_MODE_MIPS64;
break;
}
});
hlayout->addWidget(mode);
hlayout->addSpacing(10);
cbintel = new QCheckBox("Intel", w);
cbintel->setChecked(true);
connect(cbintel, &QCheckBox::toggled, [=] { this->disasm(tmpbuf); });
hlayout->addWidget(cbintel);
vlayout->addSpacing(10);
txtAsm = new QTextBrowser(w);
txtAsm->setUndoRedoEnabled(false);
vlayout->addItem(hlayout);
vlayout->addWidget(txtAsm);
PluginDockWidgetInit(dw, w, tr("DisasmWindow"), "DisasmWindow");
PluginMenuInitBegin(menu, tr("WingHexDisasm")) {
menu->setIcon(ICONRES("icon"));
PluginMenuAddItemIconAction(menu, tr("Disasm"), ICONRES("analyse"),
WingHexDisasm::on_disasm);
PluginMenuAddItemIconAction(menu, tr("Clear"), HOSTICONRES("clearhis"),
WingHexDisasm::on_clear);
menu->addSeparator();
PluginMenuAddItemIconLamba(menu, tr("Author"), HOSTICONRES("author"), [=] {
auto authord =
newAboutDialog(QPixmap(), {":/WingHexDisasm", ":/WingHexDisasm/img"});
authord->exec();
delete authord;
});
PluginMenuAddItemIconLamba(menu, tr("Sponsor"), HOSTICONRES("sponsor"),
[=] {
auto sponsor = newSponsorDialog();
sponsor->exec();
delete sponsor;
});
}
PluginMenuInitEnd();
QMenu *tmenu;
PluginMenuInitBegin(tmenu, "") {
PluginMenuAddItemIconAction(tmenu, tr("Disasm"), ICONRES("analyse"),
WingHexDisasm::on_disasm);
PluginMenuAddItemIconAction(tmenu, tr("Clear"), HOSTICONRES("clearhis"),
WingHexDisasm::on_clear);
}
PluginMenuInitEnd();
PluginToolButtonInit(tbtn, tmenu, ICONRES("icon"));
loadSetting();
return true;
}
WingHexDisasm::~WingHexDisasm() {}
void WingHexDisasm::unload() { saveSetting(); }
int WingHexDisasm::sdkVersion() { return SDKVERSION; }
QMenu *WingHexDisasm::registerMenu() { return menu; }
QToolButton *WingHexDisasm::registerToolButton() { return tbtn; }
void WingHexDisasm::registerDockWidget(
QHash<QDockWidget *, Qt::DockWidgetArea> &rdw) {
rdw.insert(dw, Qt::DockWidgetArea::NoDockWidgetArea);
}
const QString WingHexDisasm::pluginName() { return tr("WingHexDisasm"); }
const QString WingHexDisasm::pluginAuthor() { return WINGSUMMER; }
uint WingHexDisasm::pluginVersion() { return 1; }
const QString WingHexDisasm::signature() { return WINGSUMMER; }
const QString WingHexDisasm::pluginComment() {
return tr("A small disassembly plugin for WingHexExplorer.");
}
void WingHexDisasm::plugin2MessagePipe(WingPluginMessage type,
QList<QVariant> msg) {
Q_UNUSED(type);
Q_UNUSED(msg);
}
void WingHexDisasm::disasm(QByteArray code) {
csh handle;
cs_err err = cs_open(carch, cmode, &handle);
if (err != CS_ERR_OK) {
txtAsm->setText(tr("Error: Failed capstone initialization"));
} else if (code.length()) {
size_t count;
cs_insn *insn;
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
if (cbintel->isChecked()) {
cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
} else {
cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
}
auto *t = code.data();
count = cs_disasm(handle, reinterpret_cast<uint8_t *>(t),
size_t(code.size()), 0, 0, &insn);
if (count > 0) {
txtAsm->clear();
size_t j;
QStringList asms;
for (j = 0; j < count; j++) {
asms << (QString("%1 %2;").arg(insn[j].mnemonic).arg(insn[j].op_str));
}
txtAsm->setText(asms.join('\n'));
cs_free(insn, count);
} else {
txtAsm->setText(tr("Error: Failed to disassemble given op codes"));
}
cs_close(&handle);
tmpbuf.swap(code);
}
}
void WingHexDisasm::on_disasm() {
if (reader.currentDoc() < 0) {
this->toast(ICONRES("icon"), tr("No Document Opened"));
return;
}
if (reader.selectLength()) {
this->disasm(reader.selectedBytes());
} else {
this->toast(ICONRES("icon"), tr("No Selection Bytes"));
}
}
void WingHexDisasm::on_clear() { txtAsm->clear(); }
void WingHexDisasm::saveSetting() {
QSettings settings("wingsummer", "WingHexDisasm");
settings.setValue("arch", carch);
settings.setValue("mode", cmode);
}
void WingHexDisasm::loadSetting() {
QSettings settings("wingsummer", "WingHexDisasm");
carch = settings.value("arch", cs_arch::CS_ARCH_X86).value<cs_arch>();
cmode = settings.value("mode", cs_mode::CS_MODE_64).value<cs_mode>();
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(WingHexDisasm, GenericPlugin)
#endif // QT_VERSION < 0x050000