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
This commit is contained in:
@@ -21,10 +21,13 @@ enum MYKEY {
|
||||
|
||||
|
||||
enum KEYVALUE {
|
||||
MREG_SZ,
|
||||
MREG_DWORD,
|
||||
MREG_BINARY,
|
||||
MREG_EXPAND_SZ
|
||||
MREG_SZ, // REG_SZ
|
||||
MREG_DWORD, // REG_DWORD
|
||||
MREG_BINARY, // REG_BINARY
|
||||
MREG_EXPAND_SZ, // REG_EXPAND_SZ
|
||||
MREG_MULTI_SZ, // REG_MULTI_SZ
|
||||
MREG_QWORD, // REG_QWORD
|
||||
MREG_NONE // REG_NONE / 未知类型
|
||||
};
|
||||
|
||||
struct REGMSG {
|
||||
@@ -70,7 +73,7 @@ char* RegisterOperation::FindPath()
|
||||
char *szBuffer=NULL;
|
||||
HKEY hKey; //注册表返回句柄
|
||||
/*打开注册表 User kdjfjkf\kdjfkdjf\ */
|
||||
if(RegOpenKeyEx(MKEY,KeyPath,0,KEY_ALL_ACCESS,&hKey)==ERROR_SUCCESS) { //打开
|
||||
if(RegOpenKeyEx(MKEY,KeyPath,0,KEY_READ,&hKey)==ERROR_SUCCESS) { //打开
|
||||
DWORD dwIndex=0,NameCount,NameMaxLen;
|
||||
DWORD KeySize,KeyCount,KeyMaxLen,MaxDataLen;
|
||||
//这就是枚举了
|
||||
@@ -93,7 +96,7 @@ char* RegisterOperation::FindPath()
|
||||
REGMSG msg; //数据头
|
||||
msg.size=KeySize;
|
||||
msg.count=KeyCount;
|
||||
memcpy(szBuffer+1,(void*)&msg,Size);
|
||||
memcpy(szBuffer+1,(void*)&msg,sizeof(REGMSG));
|
||||
|
||||
char * szTemp=new char[KeySize];
|
||||
for(dwIndex=0; dwIndex<KeyCount; dwIndex++) { //枚举项
|
||||
@@ -124,7 +127,7 @@ char* RegisterOperation::FindKey()
|
||||
|
||||
char *szBuffer=NULL;
|
||||
HKEY hKey; //注册表返回句柄
|
||||
if(RegOpenKeyEx(MKEY,KeyPath,0,KEY_ALL_ACCESS,&hKey)==ERROR_SUCCESS) { //打开
|
||||
if(RegOpenKeyEx(MKEY,KeyPath,0,KEY_READ,&hKey)==ERROR_SUCCESS) { //打开
|
||||
DWORD dwIndex=0,NameSize,NameCount,NameMaxLen,Type;
|
||||
DWORD KeyCount,KeyMaxLen,DataSize,MaxDataLen;
|
||||
//这就是枚举了
|
||||
@@ -167,17 +170,17 @@ char* RegisterOperation::FindKey()
|
||||
RegEnumValue(hKey,dwIndex,szValueName,&NameSize,
|
||||
NULL,&Type,szValueData,&DataSize);//读取键值
|
||||
|
||||
if(Type==REG_SZ) {
|
||||
szTemp[0]=MREG_SZ;
|
||||
}
|
||||
if(Type==REG_DWORD) {
|
||||
szTemp[0]=MREG_DWORD;
|
||||
}
|
||||
if(Type==REG_BINARY) {
|
||||
szTemp[0]=MREG_BINARY;
|
||||
}
|
||||
if(Type==REG_EXPAND_SZ) {
|
||||
szTemp[0]=MREG_EXPAND_SZ;
|
||||
// 值类型映射:REG_SZ/DWORD/BINARY/EXPAND_SZ 之外补 MULTI_SZ/QWORD/NONE,
|
||||
// 未识别类型一律 MREG_NONE(避免误报为 REG_SZ)。
|
||||
switch (Type) {
|
||||
case REG_SZ: szTemp[0] = MREG_SZ; break;
|
||||
case REG_EXPAND_SZ: szTemp[0] = MREG_EXPAND_SZ; break;
|
||||
case REG_MULTI_SZ: szTemp[0] = MREG_MULTI_SZ; break;
|
||||
case REG_DWORD: szTemp[0] = MREG_DWORD; break;
|
||||
case REG_QWORD: szTemp[0] = MREG_QWORD; break;
|
||||
case REG_BINARY: szTemp[0] = MREG_BINARY; break;
|
||||
case REG_NONE: szTemp[0] = MREG_NONE; break;
|
||||
default: szTemp[0] = MREG_NONE; break;
|
||||
}
|
||||
szTemp+=sizeof(BYTE);
|
||||
strcpy(szTemp,szValueName);
|
||||
|
||||
Reference in New Issue
Block a user