Intro

At DefCon 23 I released a beta version of a project I was working on called Harness. Harness is remote access payload with the ability to provide a remote interactive PowerShell interface from a Windows system to virtually any TCP socket. The primary goal of the Harness Project is to provide a remote interface with the same capabilities and overall feel of the native PowerShell executable bundled with the Windows. At the time of release I did not have a good usage guide available so this article is intended to serve as an introduction and basic usage guide.

As of 25 September 2015 Harness 1.0 is available for download with added features and bug fixes.  I’ve been slowly adding much of this information to the github wiki where the project source code is located.

Goals

When I started the project I had two goals in mind:

  1. I wanted a fully interactive remote PowerShell console with the same capabilities as the native PowerShell.exe
  2. The ability to seamlessly import modules across the wire

Architecture

Server

Of course Harness follows the client-server model common across the Internet. For the purposes of this guide, and clarity, the Harness payload is the server and any TCP listener can be the client. For example, Harness will easily work with netcat; however, some of the more advanced features (e.g. ^import-module) built into Harness requires a companion handler that supports the built-in commands.

Native Client

The native Harness handler is contained within the PSHandler module. The PSHandler module implements the special command ^import-module that gives Harness the ability to import modules across the wire without staging PowerShell scripts on a web server. PSHandler is currently an experimental handler utilizing the Python asyncio library included in the Python 3.4 and above; however using asyncio is not necessarily required and implementing the ^import-module command in other handlers should be straight forward. See Development section of the wiki for more implementation details.

Installation

Installing Python 3.4

Many developers have not moved to Python 3.x, and believe me I get it. There were some major changes in Python 3, and people are resistant to change. So we continue to see more and more tools being pushed out written in Python 2.7. There’s nothing wrong with this in practice although new features will not be available for Python 2 by default. I wanted to limit the use of external libraries that users would have to install, so instead I opted to develop the framework in Python 3.4 to take advantage of new standard libraries like asyncio. Yes, I could have accomplished a solution in Python 2 also, but I didn’t. Luckily, it’s really easy to run Python 2 and Python 3 side-by-side. I’ve included a simple bash script to quickly download, build, and install Python 3.4 as an alternate install. To download and install Harness you can run the following commands on your Linux system:

 git clone https://github.com/Rich5/Harness.git  
 cd Harness/  
 chmod 755 python_install.sh  
 ./python_install.sh  

python_install.sh will run the following commands to download and install Python 3.4.

 wget http://python.org/ftp/python/3.4.3/Python-3.4.3.tar.xz  
 tar xf Python-3.4.3.tar.xz  
 cd Python-3.4.3  
 ./configure --prefix=/usr/local --enable-shared LDFLAGS="-Wl,-rpath /usr/local/lib"  
 make && make altinstall  

Once installed start the framework by running:

 Python3.4 harness.py  

 

harness_main

 

Client Framework

Harness is bundled in a small modular framework written in Python; however, the intent is for users to ultimately incorporate the server into their own toolsets if useful. With so many tools, frameworks, etc. there are far more refined security testing frameworks available.  Typing show modules will display the available modules:

harness_showmodules

 

Payloads

Generating payloads is fairly straight forward. To load a module type **_load _** to enter into the module sub-prompt. Then using the familiar **_show_** and **_set_** commands you can configure the payload. All modules are executed by typing **run** at the prompt.  Payload modules will then ask you to specify a location to save the file.

harness_load_module_x86exe

It’s up to the user to determine how to get the payload on the target. Executable payloads may be dropped to disk, and reflective payloads can be injected into a process using various techniques including Metasploit’s reflective dll inject module. In the future delivery modules will be included to take advantage of the usual attack vectors (staged payload, macro, PowerShell download, etc).

 

Starting the Listener

Loading the native handler is similar to any other module. Simply set the IP and PORT you want to listen on and type run.

harness_run_handler

As you can see the handler module is forced to run the background by design, and you now have a listener running on port 80. Multiple connections can be handled by the same handler. By default the handler is listening for SSL connections. This is not required, but should you want to use SSL you’ll need to generate your own self-signed certificates, and set the CERT_PATH and KEY_PATH variables accordingly.

On Linux a simple way to generate a self-signed certificate is with the following line:

 openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout server.key -out server.cert  

Shell

Currently the payload is a reverse shell, although there’s code for a bind shell already implemented in the source, and could easily be used if someone is motivated enough. Once the payload is executed a session is registered with the framework and is available with the session command.

harness_gaining_shell

Typing **_session _** will present you with the familiar PowerShell prompt. Harness is a completely custom host implemented in C# and C++. That means that all the features of the native PowerShell.exe had to be implemented by hand. Most of the host methods have been implemented in some capacity, but not all, and certainly not as well as the Microsoft developers did with the native executable. What this means is that most users will not notice much difference in their experience, but some of the more complex scripts may not function as expected. It’s impossible to test all the scripts that any given user may try. So if you come across a bug or strange behavior please submit a bug report on Github. As with all things I recommend testing thoroughly in the lab before trying out a technique on a target system.

Special Commands

Harness is intended to allow the user to utilize their own PowerShell scripts as a custom toolkit, but there some special commands that give Harness additional functionality. Commands prefixed with the ^ character indicate that special handling is required. The special commands can be handled on the client side, server side, or both. For example, the ^import-module function requires handling on both the client and server while the ^enable-format command is only handled on the server side.

^Import-Module

Allows the user to seamlessly import any PowerShell module remotely without requiring staging.

Usage: ^import-module

harness_import_module

The framework will take care of base64 encoding the file and sending it across the wire. In the event there is file corruption, during transfer, the Harness payload will usually alert you that there is a parse error and to try again. Once a module has been imported you may call the functions as usual. The example below show calling Invoke-AllChecks from PowerUp.

harness_run_PowerUp

^End and Multiline Input

One of the nice features of the native PowerShell.exe in that users can enter multi-line input. This makes it easy to construct simple functions or more complex command sequences on the fly. Harness implements multi-line input using a simple accumulator loop in conjunction with a PowerShell syntax parser. Every command sent to the server is checked for syntax errors. If parse errors are found the server sets a flag, changes the prompt (e.g. ») to indicate multi-line input, and starts accumulating input until the script is complete. To break out of multi-line input use the ^end special command rather than attempt CTRL-C.

Usage: ^end

harness_multiline_input

In the example below I have a typo that caused a parse error. Since I’m not able to complete the script the accumulator will never return out of the sub-prompt loop. Rather than kill the shell the ^end command allows you to break out of the loop cleanly without terminating the shell.

harness_end_command

^sleep

The ^sleep command allows the user to suspend the shell and schedule a call back at a specified time.  You may use a specific time or simply enter an offset from the current time.  NOTE: time is relative to the time on the target machine. This will be simplified by normalizing all time to UTC in future releases.

Usage: ^sleep [+Xd|h|m|s] | [dd/mm/yyyy hh:mm ]

harness_sleep

 

^enable-format and ^disable-format

All commands sent to the Harness payload are piped to the Out-String cmdlet to format output. If for some reason you do not want this behavior you can disable this feature with the ^disable-format command. Likewise ^enable-format should be self-explanatory.

Usage: ^enable-format

               ^disable-format

harness_formating

 

Conclusion

Overall Harness is a fun project, and I learned a lot things along the way. I’ll be adding updates and features as time allows. This is just one more tool to add to your toolbox. Use what works best for the situation at hand.

Download Harness here: https://github.com/Rich5/Harness