Files
SimpleRemoter/client/RegisterManager.cpp
T
yuanyuanxianganddeepseek-v4-pro 8bd6f3b60a Feature: Add list_registry MCP tool
Add a read-only list_registry MCP tool for querying a remote Windows
host's registry. An empty path returns the five root keys; a path such as
HKEY_LOCAL_MACHINE plus subkeys returns that key's immediate subkeys and
values (name, type, and formatted data).

Client side: enumerate with KEY_READ instead of KEY_ALL_ACCESS and map the
full value-type set (REG_SZ, REG_DWORD, REG_BINARY, REG_EXPAND_SZ,
REG_MULTI_SZ, REG_QWORD, REG_NONE) so unknown types are no longer
mis-reported as REG_SZ. The registry manager now always sends both the
TOKEN_REG_PATH and TOKEN_REG_KEY packets (an empty packet when a part is
empty), making the two-packet reply deterministic for the server.

Server side: add the three-phase flow (COMMAND_REGEDIT, COMMAND_REG_FIND,
then PATH plus KEY) with per-host pending state, parse the fixed-width
wire format with bounds checks, format value data for JSON, and guard
registry paths against exceeding MAX_PATH to protect the client stack.

Co-Authored-By: deepseek-v4-pro
2026-08-23 10:37:55 +02:00

83 lines
2.5 KiB
C++

// RegisterManager.cpp: implementation of the CRegisterManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RegisterManager.h"
#include "Common.h"
#include <IOSTREAM>
#if ENABLE_REGISTRY
// 与 RegisterOperation.cpp 的 REGMSG 同构(int count + DWORD size + DWORD valsize = 12 字节),
// 此处仅用于构造"空结果包"(count=0),无需跨文件共享完整定义。
struct REGMSG {
int count; //名字个数
DWORD size; //名字大小
DWORD valsize; //值大小
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CRegisterManager::CRegisterManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject)
{
BYTE bToken=TOKEN_REGEDIT;
HttpMask mask(DEFAULT_HOST, m_ClientObject->GetClientIPHeader());
m_ClientObject->Send2Server((char*)&bToken, 1, &mask);
}
CRegisterManager::~CRegisterManager()
{
Mprintf("CRegisterManager 析构\n");
}
VOID CRegisterManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
{
switch (szBuffer[0]) {
case COMMAND_REG_FIND: //查数据
if(ulLength>3) {
Find(szBuffer[1],(char*)(szBuffer+2));
} else {
Find(szBuffer[1],NULL); //Root数据
}
break;
default:
break;
}
}
VOID CRegisterManager::Find(char bToken, char *szPath)
{
RegisterOperation Opt(bToken);
if(szPath!=NULL) {
Opt.SetPath(szPath);
}
// 子键包(TOKEN_REG_PATH):无子键时也回传空包,保证服务端(含 MCP 无头查询)
// 能确定性收齐 PATH+KEY 两包,无需靠超时猜测是否有第二包。
char *szBuffer= Opt.FindPath();
if(szBuffer!=NULL) {
m_ClientObject->Send2Server((char*)szBuffer, LocalSize(szBuffer));
//目录下的目录
LocalFree(szBuffer);
} else {
char empty[1 + sizeof(REGMSG)] = { 0 };
empty[0] = TOKEN_REG_PATH;
m_ClientObject->Send2Server(empty, sizeof(empty));
}
// 值包(TOKEN_REG_KEY):同上,无值时也回传空包。
szBuffer = Opt.FindKey();
if(szBuffer!=NULL) {
//目录下的文件
m_ClientObject->Send2Server((char*)szBuffer, LocalSize(szBuffer));
LocalFree(szBuffer);
} else {
char empty[1 + sizeof(REGMSG)] = { 0 };
empty[0] = TOKEN_REG_KEY;
m_ClientObject->Send2Server(empty, sizeof(empty));
}
}
#endif