GadgetToJScript

Back in April 2017, James Forshaw (hail) released a tool called DotNetToJScript which was capable of generating JScript, VBA and VBScript that could run an arbitrary .NET assembly (mostly) from memory. Although not its intended purpose, it was quickly picked up by tool developers, pentesters, red teamers, bad guys etc and used to deliver .NET-based payloads via methods such as HTA.

Microsoft and other AV vendors started writing signatures for DN2JS, and we all know how that makes James feel (Exhibits A and B). Microsoft even went as far as to make some under-the-hood changes from Windows 10 / 2K16 to mitigate the use of DN2JS payloads, as evidenced by these notes in Covenant:

These factors seem to have resulted in a decline in prevalence for these payloads, or at least, they’re not hyped about so much.

Enter GadgetToJScript by Mohamed El Azaar. This tool generates .NET serialized gadgets that can trigger assembly load/execution when deserialized via BinaryFormatter from JScript, VBScript or VBA. So it once again, allows for a similar tradecraft as was originally provided by DN2JS and it works on Windows 10.


Before picking up the tool I had a quick Google to find any articles regarding its use, but this example by Chirag Savla is the only one I could really find.

Since the ActivitySurrogateSelector portion of G2JS is based on the work in ysoserial.net, it’s no surprise that they seem to work in similar ways. The ysoserial.net usage example says ActivitySurrogateSelector (This gadget ignores the command parameter and executes the constructor of ExploitClass class.). The ExploitClass is here and is actually compiled into the binary.

G2JS also requires that we execute from the constructor of a class; the out-of-the-box payload is hardcoded into the G2JS binary (as a string no less) and any required Reference Assemblies are hardcoded.

To me, this isn’t a very friendly approach, as I don’t want to modify and recompile G2JS for each payload I want to generate. Chirag solved this issue by modifying the TestAssemblyLoader class to read the payload in from a text file (from the current working directory), but still has this limitation of hardcoding any reference assemblies required by the compiler.

To make the tool more usable for my needs, I have a forked version of G2JS that can accept an input file and reference assemblies on the command line. Let’s see how it works.


> GadgetToJScript.exe -h
Usage:
  -i, --input=VALUE          Input file, example:
                               C:\Users\userX\Desktop\payload.cs
  -r, --references=VALUE     Reference Assemblies, example: System.dll,Syste-
                               m.IO.Compression.dll
  -w, --scriptType=VALUE     js, vbs, vba or hta
  -e, --encodeType=VALUE     VBA gadgets encoding: b64 or hex (default set to
                               b64)
  -o, --output=VALUE         Generated payload output file, example:
                               C:\Users\userX\Desktop\output (Without extension)
  -f, --regfree              Registration-free activation of .NET based COM
                               components
  -h, -?, --help             Show Help

The two new options are seen here. -i for the input file and -r to provide any required references as a comma-separated list (-r was previously assigned to -regfree, which I’ve changed to -f).

System.dll is actually hardcoded, so there’s no need to specify it on the cmdline even though it’s in the usage example.

This test payload was written in a completely separate .NET Class Library project. We can see that it’s using System.Windows.Forms to display a MessageBox.

If we try to build this, it will fail because the G2JS compiler has no reference to the Forms namespace.

> GadgetToJScript.exe -i ..\..\..\TestPayload\TestClass.cs -w js -o D:\Tools\this-will-fail

Unhandled Exception: System.InvalidOperationException: Error (CS0234): The type or namespace name 'Forms' does not exist in the namespace 'System.Windows' (are you missing an assembly reference?): 1

   at GadgetToJScript.AssemblyLoader.Compile(String InputFile, String ReferenceAssemblies) in D:\Tools\GadgetToJScript\GadgetToJScript\AssemblyLoader.cs:line 44
   at GadgetToJScript.Program.Main(String[] args) in D:\Tools\GadgetToJScript\GadgetToJScript\Program.cs:line 133

To “fix” this, all we need to do is specify System.Windows.Forms.dll as a reference.

> GadgetToJScript.exe -i ..\..\..\TestPayload\TestClass.cs -r System.Windows.Forms.dll -w js -o D:\Tools\msgbox

I won’t bother going into more complex payloads, as Chirag already did a good job with that. Hopefully these modifications will make it a little easier and more practical for people to pick up and use GadgetToJScript.