Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
190 lines (130 sloc) 9.09 KB
Extending PoshC2
Any red-teamer worth their salt will get familiar with their tooling and customise or extend it to suit their needs and the environment.
In addition to being customisable through the configuration file, such as the UserAgent and HTTP Responses in use, PoshC2 can be easily altered to suit the given situation.
It is recommended to git commit changes locally to PoshC2 if you alter files in the installation directory, as this means that you can still update PoshC2 and have your changes merged on top of incoming changes.
For any changes that would be useful for others, please consider adding a pull request.
Adding Modules
To add a new module, simply place it in the **resources/modules** directory in the PoshC2 installation directory.
Any PowerShell script can be loaded by the PowerShell implant and executed in memory:
.. code-block:: powershell
loadmodule MyPowerShellScript.ps1
Or similarly for Python Implant
.. code-block:: powershell
The C# Implant also has the ability to load and execute modules in memory, but these modules are C#.NET executables.
These modules are invoked through .NET reflection and do not touch disk, and PoshC2 requires a few extra bits of information.
* The Namespace of the class containing the **Main** method
* The Class name of the class containing the **Main** method
* The Assembly name
.. code-block:: powershell
loadmodule MySharpStuff.exe
run-exe Namespace.Class Assembly <args>
For example, if the below code was compiled into an executable:
.. code-block:: C#
using System;
namespace ConsoleApp1
class MySuperProgram
static void Main(string[] args)
if (args.Length >= 1)
Then we can see the namespace is **ConsoleApp1**, and the class is **MySuperProgram**
The Assembly Name can be found in Visual Studio by right-clicking the project (not the solution) and choosing `Properties`
.. image:: ./assemblyname.png
:width: 867
:align: center
Alternatively it can be found in the Projects **.csproj** file:
.. image:: ./assemblyname2.png
:width: 1554
:align: center
In this case the Assembly Name is **PwnStuff**.
The command then to run the executable and print "PoshC2Rocks" would be:
.. code-block:: powershell
run-exe ConsoleApp1.MySuperProgram PwnStuff PoshC2Rocks
.. image:: ./run-exe.png
:width: 1023
:align: center
There is also a ``run-dll`` command which works exactly the same way as ``run-exe`` for C#.NET DLLs, however there is one additional argument which specifies the entry point (and the class and namespace must match that of this entrypoint):
.. code-block:: powershell
run-dll ConsoleApp1.MySuperProgram PwnStuff MyEntryMethod PoshC2Rocks
Adding Aliases
We fully appreciate that nobody wants to type ``run-exe ConsoleApp1.MySuperProgram PwnStuff PoshC2Rocks`` over and over, and that is why we added aliases in **poshc2/client/**.
Aliases can either replace full or part commands, depending on the preference:
.. code-block:: python
# C# Implant
cs_alias = [
["s", "get-screenshot"],
# Parts of commands to replace if command starts with the key
cs_replace = [
["safetydump", "run-exe SafetyDump.Program SafetyDump"],
["sharpup", "run-exe SharpUp.Program SharpUp"],
["seatbelt", "run-exe Seatbelt.Program Seatbelt"],
["rubeus", "run-exe Rubeus.Program Rubeus"],
["sharpview", "run-exe SharpView.Program SharpView"],
["sharphound", "run-exe Sharphound2.Sharphound Sharphound"],
["sharpweb", "run-exe SharpWeb.Program SharbWeb"],
["watson", "run-exe Watson.Program Watson"],
["pwnstuff", "run-exe ConsoleApp1.MySuperProgram PwnStuff"]
There are separate lists for each Implant type, and the ``_alias`` lists replace the full typed command with the value if the full typed command matches the alias.
For example, if the user types ``s``, that is replaced with ``get-screenshot``. If the user types ``sort``, that is not.
The ``*_replace`` lists replace the alias with the value if the typed command **starts with** the alias, allowing the command to take arguments.
For example, if the user types ``rubeus kerberoast``, it will be replaced with ``run-exe Rubeus.Program Rubeus kerberoast``. If the user types ``echo "rubeus"``, no substitution will take place.
Adding the ``pwnstuff`` alias then allows us to run ``pwnstuff PoshC2Rocks`` instead of ``run-exe ConsoleApp1.MySuperProgram PwnStuff PoshC2Rocks``.
Adding Autoloads
PoshC2 allows certain modules to be loaded automatically when a command is run.
This is useful for loading a frequently used module without requiring the user to load it manually first, but has the risk of loading modules into memory by mistake if the user runs the wrong command at the wrong time.
To add an autoload, edit **poshc2/server/** and add a line for your command for the Implant type. For example, we can load PwnStuff.exe automatically when the user runs a ``pwnstuff ...`` command.
.. code-block:: python
def run_autoloads_sharp(command, randomuri, user):
command = command.lower().strip()
if command.startswith("run-exe seatbelt"): check_module_loaded("Seatbelt.exe", randomuri, user)
elif command.startswith("run-exe sharpup"): check_module_loaded("SharpUp.exe", randomuri, user)
elif command.startswith("run-exe safetydump"): check_module_loaded("SafetyDump.exe", randomuri, user)
elif command.startswith("run-exe rubeus"): check_module_loaded("Rubeus.exe", randomuri, user)
elif command.startswith("run-exe sharpview"): check_module_loaded("SharpView.exe", randomuri, user)
elif command.startswith("run-exe watson"): check_module_loaded("Watson.exe", randomuri, user)
elif command.startswith("run-exe sharphound"): check_module_loaded("SharpHound.exe", randomuri, user)
elif command.startswith("run-exe internalmonologue"): check_module_loaded("InternalMonologue.exe", randomuri, user)
elif command.startswith("run-exe sharpsocks"): check_module_loaded("SharpSocks.exe", randomuri, user)
elif command.startswith("run-exe sharpweb"): check_module_loaded("SharpWeb.exe", randomuri, user)
elif command.startswith("run-exe wmiexec.program"): check_module_loaded("WExec.exe", randomuri, user)
elif command.startswith("run-exe smbexec.program"): check_module_loaded("SExec.exe", randomuri, user)
elif command.startswith("run-exe invoke_dcom.program"): check_module_loaded("DCOM.exe", randomuri, user)
elif command.startswith("sharpsocks"): check_module_loaded("SharpSocks.exe", randomuri, user)
elif command.startswith("safetykatz"): check_module_loaded("SafetyKatz.exe", randomuri, user)
elif command.startswith("pwnstuff"): check_module_loaded("PwnStuff.exe", randomuri, user)
Adding Auto-completion
If you want to add an entry in the autocompletion prompt for your module, or add it to the ``help`` command, then you can add it to **poshc2/client/**.
Simply add it to the relevant lists for the different prompt contexts (C# Implant, PS Implant etc) for the autocompletion or to the relevant help text block and restart the Implant-Handler.
These commands can include aliases.
.. code-block:: python
SHARPCOMMANDS = ["get-userinfo", "stop-keystrokes", "get-keystrokes", "delete", "move", "label-implant", "upload-file", "quit",
"download-file", "get-content", "ls-recurse", "turtle", "cred-popper", "resolveip", "resolvednsname", "testadcredential",
"testlocalcredential", "get-screenshot", "modulesloaded", "get-serviceperms", "unhide-implant", "arpscan", "ls", "pwd", "dir",
"inject-shellcode", "start-process", "run-exe", "run-dll", "hide-implant", "help", "searchhelp", "listmodules", "loadmodule",
"loadmoduleforce", "back", "ps", "beacon", "setbeacon", "kill-implant", "get-screenshotmulti", "safetydump", "seatbelt", "sharpup",
"sharphound", "rubeus", "sharpview", "watson", "get-hash", "migrate", "sharpsocks", "safetykatz", "get-computerinfo", "get-dodgyprocesses", "sharpweb", "pwnstuff"
Adding Payloads
Payloads are generated when the C2 Server first starts for a new project, or when a new payload is created from the Implant-Handler through **create\*payload** commands, such as ``createnewpayload`` and ``createdaisypayload``.
The generation of these payloads can be altered by editing the templates in the **resources/payload-templates** directory of the installation directory and/or editing **poshc2/server/**, which is responsible for the generation of the payloads.
Operation Security is important, and so to prevent operators from running potentially dangerous commands, anything listed in `poshc2/client/` will require accepting an additional prompt when the command is run.
You can’t perform that action at this time.