feat: kernel memory plugin + unified source menu + driver improvements

- KernelMemory plugin: kernel-mode process/physical memory R/W via IOCTL driver
- rcxdrv.sys: MmCopyMemory for reads, MDL mapping with correct cache types
  (MmCached for RAM, MmNonCached for MMIO only — fixes cache corruption BSOD)
- Driver reconnect: ensureDriverLoaded tries device handle first, no auto
  stop+delete cycle. Manual unload closes handle only, service stays running.
- Unified source menu: ProviderRegistry::populateSourceMenu() shared by both
  main window Data Source menu and RcxEditor inline picker (icons + dll names)
- IProviderPlugin::populatePluginMenu() for conditional plugin actions
  (e.g. "Unload Kernel Driver" only when loaded)
- Physical memory mode removed from selectTarget (access via context menu only)
- requestOpenProviderTab sets base address from provider after template load
- Address parser: vtop(), cr3(), physRead() callbacks for kernel paging expressions
This commit is contained in:
IChooseYou
2026-03-13 14:46:22 -06:00
committed by IChooseYou
parent 7f7bbdcc45
commit b08736245b
22 changed files with 2671 additions and 120 deletions

View File

@@ -1,5 +1,8 @@
#include "providerregistry.h"
#include <QDebug>
#include <QMenu>
#include <QIcon>
#include <QHash>
ProviderRegistry& ProviderRegistry::instance() {
static ProviderRegistry s_instance;
@@ -56,3 +59,57 @@ const ProviderRegistry::ProviderInfo* ProviderRegistry::findProvider(const QStri
void ProviderRegistry::clear() {
m_providers.clear();
}
void ProviderRegistry::populateSourceMenu(QMenu* menu,
const QVector<SavedSourceDisplay>& savedSources)
{
static const QHash<QString, QString> s_providerIcons = {
{QStringLiteral("processmemory"), QStringLiteral(":/vsicons/server-process.svg")},
{QStringLiteral("remoteprocessmemory"), QStringLiteral(":/vsicons/remote.svg")},
{QStringLiteral("windbgmemory"), QStringLiteral(":/vsicons/debug.svg")},
{QStringLiteral("reclass.netcompatlayer"), QStringLiteral(":/vsicons/plug.svg")},
};
// File source
auto* fileAct = menu->addAction(QIcon(QStringLiteral(":/vsicons/file-binary.svg")),
QStringLiteral("File"));
fileAct->setIconVisibleInMenu(true);
fileAct->setData(QStringLiteral("File"));
// Registered providers
const auto& providers = instance().providers();
for (const auto& prov : providers) {
auto it = s_providerIcons.constFind(prov.identifier);
QIcon icon(it != s_providerIcons.constEnd() ? *it
: QStringLiteral(":/vsicons/extensions.svg"));
QString label = prov.dllFileName.isEmpty()
? prov.name
: QStringLiteral("%1 (%2)").arg(prov.name, prov.dllFileName);
auto* act = menu->addAction(icon, label);
act->setIconVisibleInMenu(true);
act->setData(prov.name); // routing key for selectSource()
// Plugin-specific actions (e.g. "Unload Driver" when loaded)
if (prov.plugin)
prov.plugin->populatePluginMenu(menu);
}
// Saved sources
if (!savedSources.isEmpty()) {
menu->addSeparator();
for (int i = 0; i < savedSources.size(); i++) {
auto* act = menu->addAction(savedSources[i].text);
act->setCheckable(true);
act->setChecked(savedSources[i].active);
act->setData(QStringLiteral("#saved:%1").arg(i));
}
menu->addSeparator();
auto* clearAct = menu->addAction(
QIcon(QStringLiteral(":/vsicons/clear-all.svg")),
QStringLiteral("Clear All"));
clearAct->setIconVisibleInMenu(true);
clearAct->setData(QStringLiteral("#clear"));
}
}