Skip to content

Commit

Permalink
pull upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
c2biz committed Apr 4, 2024
2 parents a8edd44 + bf1466d commit a32aed9
Show file tree
Hide file tree
Showing 69 changed files with 5,256 additions and 2,847 deletions.
222 changes: 152 additions & 70 deletions CHEATSHEET.md

Large diffs are not rendered by default.

78 changes: 39 additions & 39 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
# Contributing

Add your own cmdlets by submitting a pull request.
## Aim
- Maintain .NET 2.0 compatibility in order to support the broadest range of operating systems
- In case for whatever reason .NET 2.0 compatibility is not possible, add the `#if` preprocessor directive to the class specifying the unsupported .NET versions (for examples check the `*-Archive` cmdlets)

## Instructions
Use the TemplateCommand.cs file in the Commands folder to construct new cmdlets. The TemplateCommand cmdlet is hidden from the list of available cmdlets, but can be called in order to understand its workings. This command looks as follows: `Get-TemplateCommand [-MyFlag] -MyInteger [Int32] -MyString [Value]` and is also accessible via alias `gtc`.

### Example usages
| Action | Command |
| - | - |
| Simply run with default values | `gtc` |
| Run with the -MyFlag parameter which executes the 'else' statement | `gtc -MyFlag` |
| Run with the -MyInteger parameter which changes the number of iterations from its default number of 5 iterations to whatever number is provided | `gtc -MyInteger 10` |
| Run with the -MyString parameter which changes the text that is printed from its default value of 'Hello World' to whatever string is provided | `gtc -MyString "Bye PowerShell"` |
| Combination of parameters | `gtc -MyInteger 10 -MyString "Bye PowerShell"` |
| Combination of parameters - Using fact that MyString is the only mandatory parameter for this command | `gtc -MyInteger 10 "Bye PowerShell"` |
| Command in combination with a couple of data manipulators in the pipe | `gtc "Bye PowerShell" -MyInteger 30 \| ? Attribute2 -Like Line1* \| select Attribute2 \| fl` |

Execute the following steps to implement your own cmdlet:
1. Download Visual Studio Community from https://visualstudio.microsoft.com/downloads/
* In the installer select the **.NET desktop development** component.
* From this component no optional modules are required for developing NoPowerShell modules.
2. Make sure to have the .NET 2 framework installed: `OptionalFeatures.exe` -> '.NET Framework 3.5 (includes .NET 2.0 and 3.0)'.
3. Clone this repository and create a copy of the **TemplateCommand.cs** file.
* In case you are implementing a native PowerShell command, place it in folder the corresponding to the _Source_ attribute when executing in PowerShell: `Get-Command My-Commandlet`.
* Moreover, use the name of the _Source_ attribute in the command's namespace.
* Example of a native command: `Get-Command Get-Process` -> Source: `Microsoft.PowerShell.Management` -> Place the .cs file in the **Management** subfolder and use `NoPowerShell.Commands.Management` namespace.
* In case it is a non-native command, place it in the **Additional** folder and use the `NoPowerShell.Commands.Additional` namespace.
4. Update the `TemplateCommand` classname and its constructor name.
5. Update the static **Aliases** variable to the command and aliases you want to use to call this cmdlet. For native PowerShell commands you can lookup the aliases using `Get-Alias | ? ResolvedCommandName -EQ My-Commandlet` to obtain the list of aliases. Always make sure the full command is the first "alias", for example: `Get-Alias | ? ResolvedCommandName -EQ Get-Process` -> Aliases are: `Get-Process`, `gps`, `ps`
6. Update the static **Synopsis** variable to a small text that describes the command. This will be shown in the help.
7. Update the arguments supported by the command by adding _StringArguments_, _BoolArguments_ and _IntegerArguments_ to the static **SupportedArguments** variable.
8. In the Execute function:
1. Fetch the values of the _StringArguments_, _BoolArguments_ and _IntegerArguments_ as shown in the examples;
2. Based on the parameters provided by the user, perform your actions;
3. Make sure all results are stored in the `_results` variable.
# Contributing

Add your own cmdlets by submitting a pull request.
## Aim
- Maintain .NET 2.0 compatibility in order to support the broadest range of operating systems
- In case for whatever reason .NET 2.0 compatibility is not possible, add the `#if` preprocessor directive to the class specifying the unsupported .NET versions (for examples check the `*-Archive` cmdlets)

## Instructions
Use the TemplateCommand.cs file in the Commands folder to construct new cmdlets. The TemplateCommand cmdlet is hidden from the list of available cmdlets, but can be called in order to understand its workings. This command looks as follows: `Get-TemplateCommand [-MyFlag] -MyInteger [Int32] -MyString [Value]` and is also accessible via alias `gtc`.

### Example usages
| Action | Command |
| - | - |
| Simply run with default values | `gtc` |
| Run with the -MyFlag parameter which executes the 'else' statement | `gtc -MyFlag` |
| Run with the -MyInteger parameter which changes the number of iterations from its default number of 5 iterations to whatever number is provided | `gtc -MyInteger 10` |
| Run with the -MyString parameter which changes the text that is printed from its default value of 'Hello World' to whatever string is provided | `gtc -MyString "Bye PowerShell"` |
| Combination of parameters | `gtc -MyInteger 10 -MyString "Bye PowerShell"` |
| Combination of parameters - Using fact that MyString is the only mandatory parameter for this command | `gtc -MyInteger 10 "Bye PowerShell"` |
| Command in combination with a couple of data manipulators in the pipe | `gtc "Bye PowerShell" -MyInteger 30 \| ? Attribute2 -Like Line1* \| select Attribute2 \| fl` |

Execute the following steps to implement your own cmdlet:
1. Download Visual Studio Community from https://visualstudio.microsoft.com/downloads/
* In the installer select the **.NET desktop development** component.
* From this component no optional modules are required for developing NoPowerShell modules.
2. Make sure to have the .NET 2 framework installed: `OptionalFeatures.exe` -> '.NET Framework 3.5 (includes .NET 2.0 and 3.0)'.
3. Clone this repository and create a copy of the **TemplateCommand.cs** file.
* In case you are implementing a native PowerShell command, place it in folder the corresponding to the _Source_ attribute when executing in PowerShell: `Get-Command My-Commandlet`.
* Moreover, use the name of the _Source_ attribute in the command's namespace.
* Example of a native command: `Get-Command Get-Process` -> Source: `Microsoft.PowerShell.Management` -> Place the .cs file in the **Management** subfolder and use `NoPowerShell.Commands.Management` namespace.
* In case it is a non-native command, place it in the **Additional** folder and use the `NoPowerShell.Commands.Additional` namespace.
4. Update the `TemplateCommand` classname and its constructor name.
5. Update the static **Aliases** variable to the command and aliases you want to use to call this cmdlet. For native PowerShell commands you can lookup the aliases using `Get-Alias | ? ResolvedCommandName -EQ My-Commandlet` to obtain the list of aliases. Always make sure the full command is the first "alias", for example: `Get-Alias | ? ResolvedCommandName -EQ Get-Process` -> Aliases are: `Get-Process`, `gps`, `ps`
6. Update the static **Synopsis** variable to a small text that describes the command. This will be shown in the help.
7. Update the arguments supported by the command by adding _StringArguments_, _BoolArguments_ and _IntegerArguments_ to the static **SupportedArguments** variable.
8. In the Execute function:
1. Fetch the values of the _StringArguments_, _BoolArguments_ and _IntegerArguments_ as shown in the examples;
2. Based on the parameters provided by the user, perform your actions;
3. Make sure all results are stored in the `_results` variable.
9. Remove all of the template sample code and comments from the file to keep the source tidy.
2 changes: 1 addition & 1 deletion NoPowerShell.cna
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# https://github.com/bitsadmin
#

$binary = "scripts/NoPowerShell.exe";
$binary = "NoPowerShell.exe";
$help = "Execute a command via the reflective NoPowerShell commandline";
beacon_command_register("nps", $help, "Use: nps [command]\n\n$help");

Expand Down
102 changes: 66 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# NoPowerShell
NoPowerShell is a tool implemented in C# which supports executing PowerShell-like commands while remaining invisible to any PowerShell logging mechanisms. This .NET Framework 2 compatible binary can be loaded in Cobalt Strike to execute commands in-memory. No `System.Management.Automation.dll` is used; only native .NET libraries. An alternative usecase for NoPowerShell is to launch it as a DLL via rundll32.exe: `rundll32 NoPowerShell.dll,main`.
NoPowerShell is a tool implemented in C# which supports executing PowerShell-like commands while remaining invisible to any PowerShell logging mechanisms. This .NET Framework 2 compatible binary can be loaded in Cobalt Strike to execute commands in-memory. No `System.Management.Automation.dll` is used; only native .NET libraries. An alternative usecase for NoPowerShell is to launch it as a DLL via rundll32.exe in a restricted environment: `rundll32 NoPowerShell.dll,main`.

This project makes it easy for everyone to extend its functionality using only a few lines of C# code. For more info, see [CONTRIBUTING.md](https://github.com/bitsadmin/nopowershell/blob/master/CONTRIBUTING.md).

Expand All @@ -14,23 +14,35 @@ Latest binaries available from the [Releases](https://github.com/bitsadmin/nopow
![NoPowerShellDll via rundll32](https://raw.githubusercontent.com/bitsadmin/nopowershell/master/Pictures/NoPowerShellDll.png "NoPowerShellDll via rundll32")

# Why NoPowerShell
NoPowerShell is developed to be used with the `execute-assembly` command of Cobalt Strike.
NoPowerShell is developed to be used with the `execute-assembly` command of Cobalt Strike or in a restricted environment using `rundll32`.
Reasons to use NoPowerShell:
- Executes pretty stealthy
- Powerful functionality
- Provides the cmdlets you are already familiar with in PowerShell, so no need to learn yet another tool
- If you are not yet very familiar with PowerShell, the cmd.exe aliases are available as well (i.e. `ping` instead of `Test-NetConnection`)
- In case via `powerpick` or `powershell` cmdlets are not available, they _are_ available in `nps` (i.e. cmdlets from the ActiveDirectory module)
- If you are not yet very familiar with PowerShell, the cmd.exe aliases are available as well (e.g. `ping` instead of `Test-NetConnection`)
- In case via `powerpick` or `powershell` cmdlets are not available, they _are_ available in `nps` (e.g. cmdlets from the ActiveDirectory module)
- Easily extensible with only a few lines of C#

# Usage
## Examples
See [CHEATSHEET.md](https://github.com/bitsadmin/nopowershell/blob/master/CHEATSHEET.md).

## Install in Cobalt Strike
1. Copy both `NoPowerShell.exe` and `NoPowerShell.cna` to the **scripts** subfolder of Cobalt Strike
2. Launch Cobalt Strike and load the `NoPowerShell.cna` script in the Script Manager
3. Interact with a beacon and execute commands using the `nps` command
## Use in Cobalt Strike via execute-assembly
Use Cobalt Strike's `execute-assembly` command to launch the `NoPowerShell.exe`. For example `execute-assembly /path/to/NoPowerShell.exe Get-Command`.
Optionally `NoPowerShell.cna` can be used to add the `nps` alias to Cobalt Strike.

## Use in Cobalt Strike via BOF.NET
1. Install the BOF.NET BOF from https://github.com/CCob/BOF.NET
2. Load the BOF.NET runtime: `bofnet_init`
3. Load the NoPowerShell module: `bofnet_load /path/to/NoPowerShell.dll`
4. Execute NoPowerShell cmdlets: `bofnet_execute NoPowerShell.Program Get-Command`

## Use in Cobalt Strike using @williamknows fork of BOF.NET
This fork allows running regular .NET executables
1. Obtain and compile @williamknows' fork of the BOF.NET from https://github.com/CCob/BOF.NET
2. Load the BOF.NET runtime: `bofnet_init`
3. Load the NoPowerShell module: `bofnet_load /path/to/NoPowerShell.exe`
4. Execute NoPowerShell cmdlets: `bofnet_executeassembly NoPowerShell Get-Command`

## Launch via rundll32
1. Create a new shortcut to `NoPowerShell.dll` file (drag using right click -> Create shortcuts here)
Expand All @@ -39,32 +51,32 @@ See [CHEATSHEET.md](https://github.com/bitsadmin/nopowershell/blob/master/CHEATS
4. Double click the shortcut

## Note
When using NoPowerShell from cmd.exe or PowerShell, you need to escape the pipe character (`|`) with respectively a caret (`^`) or a backtick (`` ` ``), i.e.:
When using NoPowerShell from cmd.exe or PowerShell, you need to escape the pipe character (`|`) with respectively a caret (`^`) or a backtick (`` ` ``), e.g.:

- cmd.exe: `ls ^| select Name`
- PowerShell: ```ls `| select Name```

# Known issues
- Pipeline characters need to surrounded by spaces
- Pipeline characters need to be surrounded by spaces
- TLS 1.1+ is not supported by .NET Framework 2, so any site enforcing it will result in a connection error

# Improvements
- Fix above issues
- Improve stability by adding exception handling
- Support for parameter groups
- Add support for ArrayArgument parameter
- Add support for .NET code in commandline, i.e.: `[System.Security.Principal.WindowsIdentity]::GetCurrent().Name`
- Add support for .NET code in commandline, e.g.: `[System.Security.Principal.WindowsIdentity]::GetCurrent().Name`

# Requested NoPowerShell cmdlets
| Cmdlet | Description |
| - | - |
| Get-ADTrusts | Unofficial command showing equivalent of `nltest /domain_trusts /all_trusts /v` |
| Get-QWinsta | Unofficial command showing equivalent of `qwinsta` / `query session` |
| Invoke-Command | Using PSRemoting execute a command on a remote machine (which in that case will of course be logged) |
| Get-Service | Include option to also show service paths like in `sc qc` |
| * | Sysinternals utilities like `pipelist` and `sdelete` |
| * | More \*-Item\* commands |
| Search-ADAccount | |
| Get-ADPrincipalGroupMembership | |
| Get-ADOrganizationalUnits | |
| * | More commands from the `ActiveDirectory` PowerShell module |
| * | Sysinternals utilities like `pipelist` and `sdelete` |

# Contributed NoPowerShell cmdlets
Authors of additional NoPowerShell cmdlets are added to the table below. Moreover, the table lists commands that are requested by the community to add. Together we can develop a powerful NoPowerShell toolkit!
Expand All @@ -74,45 +86,60 @@ Authors of additional NoPowerShell cmdlets are added to the table below. Moreove
| | | | | |

# Included NoPowerShell cmdlets
| Cmdlet | Category | Notes |
| Cmdlet | Module | Notes |
| - | - | - |
| Get-ADGroup | ActiveDirectory | |
| Get-ADGroupMember | ActiveDirectory | |
| Get-ADUser | ActiveDirectory | |
| Get-ADComputer | ActiveDirectory | |
| Compress-Archive | Archive | Requires .NET 4.5+ |
| Expand-Archive | Archive | Requires .NET 4.5+ |
| Get-Whoami | Additional | whoami.exe /ALL is not implemented yet |
| Get-ADObject | ActiveDirectory | |
| Get-ADUser | ActiveDirectory | |
| Get-ADTrust | ActiveDirectory | |
| Get-WinStation | Additional | |
| Get-RemoteSmbShare | Additional | |
| Get-Command | Core | |
| Get-Help | Core | |
| Get-Whoami | Additional | whoami.exe /ALL is not implemented yet |
| Expand-Archive | Archive | Requires .NET 4.5+ |
| Compress-Archive | Archive | Requires .NET 4.5+ |
| Where-Object | Core | |
| Get-Help | Core | |
| Get-Command | Core | |
| Resolve-DnsName | DnsClient | |
| Get-LocalGroup | LocalAccounts | |
| Get-LocalGroupMember | LocalAccounts | |
| Get-LocalUser | LocalAccounts | |
| Get-ItemProperty | Management | |
| Invoke-WmiMethod | Management | |
| Remove-Item | Management | |
| Copy-Item | Management | |
| Get-ChildItem | Management | |
| Get-Content | Management | |
| Get-ItemProperty | Management | |
| Get-ChildItem | Management | |
| Get-WmiObject | Management | |
| Get-Process | Management | |
| Stop-Process | Management | |
| Get-HotFix | Management | |
| Get-PSDrive | Management | |
| Get-WmiObject | Management | |
| Get-HotFix| Management | |
| Invoke-WmiMethod | Management | Quick & dirty implementation |
| Remove-Item | Management | |
| Get-ComputerInfo | Management | Few fields still need to be added to mimic systeminfo.exe |
| Get-NetIPAddress | NetTCPIP | |
| Get-ItemPropertyValue | Management | |
| Set-Clipboard | Management | |
| Get-DnsClientCache | Management | |
| Get-ComputerInfo | Management | |
| Get-Clipboard | Management | |
| Get-NetRoute | NetTCPIP | |
| Test-NetConnection | NetTCPIP | |
| Get-NetIPAddress | NetTCPIP | |
| Get-NetNeighbor | NetTCPIP | No support for IPv6 yet |
| Test-NetConnection | NetTCPIP | |
| Get-GetNetTCPConnection | NetTCPIP | |
| Get-SmbShare | SmbShare | |
| Get-SmbMapping | SmbShare | |
| Format-List | Utility | |
| Format-Table | Utility | |
| Invoke-WebRequest | Utility |
| Measure-Object | Utility |
| Select-Object | Utility |
| Sort-Object | Utility | |
| Export-Csv | Utility | |
| Format-List | Utility | |
| Select-Object | Utility | |
| Out-File | Utility | |
| Write-Output | Utility | |
| Invoke-WebRequest | Utility | |
| Measure-Object | Utility | |

Also make sure to check out the [Cheatsheet](https://github.com/bitsadmin/nopowershell/blob/master/CHEATSHEET.md) for examples on how to use these cmdlets.

# Acknowledgements
Various NoPowerShell cmdlets and NoPowerShell DLL include code created by other developers.
Expand All @@ -123,6 +150,9 @@ Various NoPowerShell cmdlets and NoPowerShell DLL include code created by other
| Michael Conrad | https://github.com/MichaCo/ | Parts of the Resolve-Dns cmdlet are based on the code of the DnsClient.Net project |
| Rex Logan | https://stackoverflow.com/a/1148861 | Most code of the Get-NetNeighbor cmdlet originates from his StackOverflow post |
| PowerShell developers | https://github.com/PowerShell/ | Code of NoPowerShell DLL is largely based on the code handling the console input of PowerShell |

| Benjamin Delpy | https://github.com/gentilkiwi/ | Code of Get-WinStation is inspired by the code of Mimikatz' ts::sessions command |
| Dan Ports | https://github.com/danports/ | Marshalling code of Get-Winstation is partially copied from the Cassia project |
| Mazdak | https://www.codeproject.com/Articles/2937/Getting-local-groups-and-member-names-in-C | Native function calls for the Get-LocalGroupMember cmdlet |
| Rex Logan | https://stackoverflow.com/a/1148861 | Code of Get-NetNeighbor cmdlet |

**Authored by Arris Huijgen ([@bitsadmin](https://twitter.com/bitsadmin/) - https://github.com/bitsadmin/)**
Loading

0 comments on commit a32aed9

Please sign in to comment.