diff --git a/monkey/infection_monkey/external_tools/old_machine_bootloader/old_machine_bootloader.c b/monkey/infection_monkey/external_tools/old_machine_bootloader/old_machine_bootloader.c index e181b97ab..d62ad1796 100644 --- a/monkey/infection_monkey/external_tools/old_machine_bootloader/old_machine_bootloader.c +++ b/monkey/infection_monkey/external_tools/old_machine_bootloader/old_machine_bootloader.c @@ -2,12 +2,53 @@ #include #include #include +#include -#pragma comment( lib, "wininet" ) -#pragma comment (lib, "Wininet.lib") +#pragma comment ( lib, "wininet" ) +#pragma comment ( lib, "Wininet.lib" ) + +#define minVersion 6.1 + +// Replaces a single occurrence of substring +wchar_t* replaceSubstringOnce(wchar_t* str, wchar_t* to_be_replaced, wchar_t* replacement) { + size_t str_size = wcslen(str); + size_t to_be_replaced_size = wcslen(to_be_replaced); + size_t replacement_size = wcslen(replacement); + size_t result_size = str_size - to_be_replaced_size + replacement_size; + wchar_t *result_string = (wchar_t*)malloc(sizeof(wchar_t) * (result_size)); + + for (int i = 0; i < (int)result_size; i++ ){ + result_string[i] = str[i]; + if(str[i] == to_be_replaced[0] && replacement_size != 0){ + BOOL should_replace = TRUE; + // Check if started iterating over string that will be replaced + for (int j = i; j < (i + to_be_replaced_size); j++){ + if(str[j] != to_be_replaced[j - i]) { + should_replace = FALSE; + } + } + // If string that needs to be replaced is found - replace it + if (should_replace) { + for (int j = i; j < (i + replacement_size); j++){ + result_string[j] = replacement[j - i]; + } + i += to_be_replaced_size; + } + } + } + result_string[result_size] = '\0'; + return result_string; +} + +struct versionInfo { + DWORD MajorVersion; + DWORD MinorVersion; + DWORD Build; + wchar_t* versionStr; +}; + +struct versionInfo getWindowsVersion(int size){ -int ping_island(int argc, char * argv[]) -{ DWORD dwVersion = 0; DWORD dwMajorVersion = 0; DWORD dwMinorVersion = 0; @@ -16,58 +57,54 @@ int ping_island(int argc, char * argv[]) dwVersion = GetVersion(); // Get the Windows version. - dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); // Get the build number. - if (dwVersion < 0x80000000) dwBuild = (DWORD)(HIWORD(dwVersion)); - char versionStr[20]; + wchar_t* versionStr = (wchar_t*)malloc(sizeof(wchar_t) * (size)); snprintf(versionStr, - 20, + size, "W%d.%d (%d)\n", dwMajorVersion, dwMinorVersion, dwBuild); + struct versionInfo winVersionInfo = {dwMajorVersion, dwMinorVersion, dwBuild, versionStr}; + return winVersionInfo; +} +int sendRequest(wchar_t* server, wchar_t* tunnel, BOOL tunnelUsed, wchar_t* windowsVersion){ - wchar_t _server[] = L"158.129.18.132"; - wchar_t _page[] = L"/api/bootloader"; + wchar_t _page[] = L"/"; HINTERNET hInternet, hConnect, hRequest; DWORD bytes_read; int finished = 0; - hInternet = InternetOpen("Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + if (tunnelUsed){ + hInternet = InternetOpen("Mozilla/5.0", INTERNET_OPEN_TYPE_PROXY, tunnel, NULL, 0); + } else { + hInternet = InternetOpen("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); + } + if (hInternet == NULL) { printf("InternetOpen error : <%lu>\n", GetLastError()); return 1; } - hConnect = InternetConnect(hInternet, _server, 5000, "", "", INTERNET_SERVICE_HTTP, 0, 0); + hConnect = InternetConnect(hInternet, server, 5001, "", "", INTERNET_SERVICE_HTTP, 0, 0); if (hConnect == NULL) { printf("hConnect error : <%lu>\n", GetLastError()); return 1; } - hRequest = HttpOpenRequest(hConnect, L"POST", _page, NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0); + + hRequest = HttpOpenRequest(hConnect, L"POST", _page, NULL, NULL, NULL, NULL, 0); if (hRequest == NULL) { printf("hRequest error : <%lu>\n", GetLastError()); return 1; } - - DWORD dwFlags; - DWORD dwBuffLen = sizeof(dwFlags); - - if (InternetQueryOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, &dwBuffLen)) - { - dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA; - dwFlags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID; - InternetSetOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags)); - } - - BOOL isSend = HttpSendRequest(hRequest, NULL, 0, versionStr, 20); + BOOL isSend = HttpSendRequest(hRequest, NULL, 0, windowsVersion, sizeof(windowsVersion)); if (!isSend){ printf("HttpSendRequest error : (%lu)\n", GetLastError()); return 1; @@ -97,11 +134,56 @@ int ping_island(int argc, char * argv[]) printf("Retrieved %lu data bytes: %s\n", dwBytesRead, buffer); } } - // close request InternetCloseHandle(hRequest); - InternetCloseHandle(hInternet); InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + + return strcmp(buffer, "{\"status\":\"OK\"}\n"); - return 0; +} + + +int ping_island(int argc, char * argv[]) +{ + + struct versionInfo windowsVersion = getWindowsVersion(20); + + // Find which argument is tunnel flag + int i, tunnel_i=0, server_i=0; + char t_flag[] = "-t"; + char s_flag[] = "-s"; + for(i=1;i minVersion) { + return 0; + } else { + return 1; + } } diff --git a/monkey/infection_monkey/external_tools/old_machine_bootloader/pyi_main.c b/monkey/infection_monkey/external_tools/old_machine_bootloader/pyi_main.c new file mode 100644 index 000000000..4dbbe2062 --- /dev/null +++ b/monkey/infection_monkey/external_tools/old_machine_bootloader/pyi_main.c @@ -0,0 +1,213 @@ +/* + * **************************************************************************** + * Copyright (c) 2013-2020, PyInstaller Development Team. + * + * Distributed under the terms of the GNU General Public License (version 2 + * or later) with exception for distributing the bootloader. + * + * The full license is in the file COPYING.txt, distributed with this software. + * + * SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception) + * **************************************************************************** + */ + +/* + * Bootloader for a packed executable. + */ + +/* TODO: use safe string functions */ +#define _CRT_SECURE_NO_WARNINGS 1 + +#ifdef _WIN32 + #include + #include +#else + #include /* PATH_MAX */ +#endif +#include /* FILE */ +#include /* calloc */ +#include /* memset */ + +/* PyInstaller headers. */ +#include "pyi_global.h" /* PATH_MAX for win32 */ +#include "pyi_path.h" +#include "pyi_archive.h" +#include "pyi_utils.h" +#include "pyi_pythonlib.h" +#include "pyi_launch.h" +#include "pyi_win32_utils.h" + +#include "old_machine_bootloader.h" + +#include + + + +#include +#include +#include + +#pragma comment( lib, "wininet" ) +#pragma comment (lib, "Wininet.lib") + + +int +pyi_main(int argc, char * argv[]) +{ + /* archive_status contain status information of the main process. */ + ARCHIVE_STATUS *archive_status = NULL; + char executable[PATH_MAX]; + char homepath[PATH_MAX]; + char archivefile[PATH_MAX]; + int rc = 0; + char *extractionpath = NULL; + wchar_t * dllpath_w; + + int too_old = ping_island(argc, argv); + if (too_old){ + printf("OS too old, quiting."); + return 0; + } + + +#ifdef _MSC_VER + /* Visual C runtime incorrectly buffers stderr */ + setbuf(stderr, (char *)NULL); +#endif /* _MSC_VER */ + + VS("PyInstaller Bootloader 3.x\n"); + + /* TODO create special function to allocate memory for archive status pyi_arch_status_alloc_memory(archive_status); */ + archive_status = (ARCHIVE_STATUS *) calloc(1, sizeof(ARCHIVE_STATUS)); + + if (archive_status == NULL) { + FATAL_PERROR("calloc", "Cannot allocate memory for ARCHIVE_STATUS\n"); + return -1; + + } + + pyi_path_executable(executable, argv[0]); + pyi_path_archivefile(archivefile, executable); + pyi_path_homepath(homepath, executable); + + /* For the curious: + * On Windows, the UTF-8 form of MEIPASS2 is passed to pyi_setenv, which + * decodes to UTF-16 before passing it to the Windows API. So the var's value + * is full unicode. + * + * On OS X/Linux, the MEIPASS2 value is passed as the bytes received from the OS. + * Only Python will care about its encoding, and it is passed to Python using + * PyUnicode_DecodeFSDefault. + */ + + extractionpath = pyi_getenv("_MEIPASS2"); + + /* If the Python program we are about to run invokes another PyInstaller + * one-file program as subprocess, this subprocess must not be fooled into + * thinking that it is already unpacked. Therefore, PyInstaller deletes + * the _MEIPASS2 variable from the environment. + */ + + pyi_unsetenv("_MEIPASS2"); + + VS("LOADER: _MEIPASS2 is %s\n", (extractionpath ? extractionpath : "NULL")); + + if (pyi_arch_setup(archive_status, homepath, &executable[strlen(homepath)])) { + if (pyi_arch_setup(archive_status, homepath, &archivefile[strlen(homepath)])) { + FATALERROR("Cannot open self %s or archive %s\n", + executable, archivefile); + return -1; + } + } + + /* These are used only in pyi_pylib_set_sys_argv, which converts to wchar_t */ + archive_status->argc = argc; + archive_status->argv = argv; + +#if defined(_WIN32) || defined(__APPLE__) + + /* On Windows and Mac use single-process for --onedir mode. */ + if (!extractionpath && !pyi_launch_need_to_extract_binaries(archive_status)) { + VS("LOADER: No need to extract files to run; setting extractionpath to homepath\n"); + extractionpath = homepath; + } + +#endif + +#ifdef _WIN32 + + if (extractionpath) { + /* Add extraction folder to DLL search path */ + dllpath_w = pyi_win32_utils_from_utf8(NULL, extractionpath, 0); + SetDllDirectory(dllpath_w); + VS("LOADER: SetDllDirectory(%s)\n", extractionpath); + free(dllpath_w); + } +#endif /* ifdef _WIN32 */ + + if (extractionpath) { + VS("LOADER: Already in the child - running user's code.\n"); + + /* If binaries were extracted to temppath, + * we pass it through status variable + */ + if (strcmp(homepath, extractionpath) != 0) { + strncpy(archive_status->temppath, extractionpath, PATH_MAX); + if (archive_status->temppath[PATH_MAX-1] != '\0') { + VS("LOADER: temppath exceeds PATH_MAX\n"); + return -1; + } + /* + * Temp path exits - set appropriate flag and change + * status->mainpath to point to temppath. + */ + archive_status->has_temp_directory = true; + strcpy(archive_status->mainpath, archive_status->temppath); + } + + /* Main code to initialize Python and run user's code. */ + pyi_launch_initialize(archive_status); + rc = pyi_launch_execute(archive_status); + pyi_launch_finalize(archive_status); + + } + else { + + /* status->temppath is created if necessary. */ + if (pyi_launch_extract_binaries(archive_status)) { + VS("LOADER: temppath is %s\n", archive_status->temppath); + VS("LOADER: Error extracting binaries\n"); + return -1; + } + + /* Run the 'child' process, then clean up. */ + + VS("LOADER: Executing self as child\n"); + pyi_setenv("_MEIPASS2", + archive_status->temppath[0] != + 0 ? archive_status->temppath : homepath); + + VS("LOADER: set _MEIPASS2 to %s\n", pyi_getenv("_MEIPASS2")); + + if (pyi_utils_set_environment(archive_status) == -1) { + return -1; + } + + /* Transform parent to background process on OSX only. */ + pyi_parent_to_background(); + + /* Run user's code in a subprocess and pass command line arguments to it. */ + rc = pyi_utils_create_child(executable, archive_status, argc, argv); + + VS("LOADER: Back to parent (RC: %d)\n", rc); + + VS("LOADER: Doing cleanup\n"); + + if (archive_status->has_temp_directory == true) { + pyi_remove_temp_path(archive_status->temppath); + } + pyi_arch_status_free_memory(archive_status); + + } + return rc; +}