Files
SimpleRemoter/client/RegisterManager.cpp
yuanyuanxiang 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++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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