├── Out-CompressedCommand.ps1 ├── Out-EncodedBXORCommand.ps1 ├── Out-EncodedHexCommand.ps1 ├── Out-PowerShellLauncher.ps1 ├── Out-EncodedAsciiCommand.ps1 ├── Out-EncodedBinaryCommand.ps1 ├── Out-EncodedOctalCommand.ps1 ├── Out-SecureStringCommand.ps1 ├── Out-ObfuscatedStringCommand.ps1 ├── Out-ObfuscatedTokenCommand.ps1 ├── Out-EncodedWhitespaceCommand.ps1 ├── Out-EncodedSpecialCharOnlyCommand.ps1 ├── Invoke-Obfuscation.psd1 ├── Invoke-Obfuscation.psm1 ├── README.md ├── LICENSE └── Invoke-Obfuscation.ps1 /Out-CompressedCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-CompressedCommand.ps1 -------------------------------------------------------------------------------- /Out-EncodedBXORCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-EncodedBXORCommand.ps1 -------------------------------------------------------------------------------- /Out-EncodedHexCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-EncodedHexCommand.ps1 -------------------------------------------------------------------------------- /Out-PowerShellLauncher.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-PowerShellLauncher.ps1 -------------------------------------------------------------------------------- /Out-EncodedAsciiCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-EncodedAsciiCommand.ps1 -------------------------------------------------------------------------------- /Out-EncodedBinaryCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-EncodedBinaryCommand.ps1 -------------------------------------------------------------------------------- /Out-EncodedOctalCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-EncodedOctalCommand.ps1 -------------------------------------------------------------------------------- /Out-SecureStringCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-SecureStringCommand.ps1 -------------------------------------------------------------------------------- /Out-ObfuscatedStringCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-ObfuscatedStringCommand.ps1 -------------------------------------------------------------------------------- /Out-ObfuscatedTokenCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-ObfuscatedTokenCommand.ps1 -------------------------------------------------------------------------------- /Out-EncodedWhitespaceCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-EncodedWhitespaceCommand.ps1 -------------------------------------------------------------------------------- /Out-EncodedSpecialCharOnlyCommand.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/e1abrador/Invoke-Obfuscation/master/Out-EncodedSpecialCharOnlyCommand.ps1 -------------------------------------------------------------------------------- /Invoke-Obfuscation.psd1: -------------------------------------------------------------------------------- 1 | # This file is part of Invoke-Obfuscation. 2 | # 3 | # Copyright 2017 Daniel Bohannon <@danielhbohannon> 4 | # while at Mandiant 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | 19 | 20 | # 21 | # Module manifest for module 'Invoke-Obfuscation' 22 | # 23 | # Generated by: Daniel Bohannon (@danielhbohannon) 24 | # 25 | # Generated on: 2017-01-19 26 | # 27 | 28 | 29 | 30 | @{ 31 | 32 | # Version number of this module. 33 | ModuleVersion = '1.1' 34 | 35 | # ID used to uniquely identify this module 36 | GUID = 'd0a9150d-b6a4-4b17-a325-e3a24fed0aa9' 37 | 38 | # Author of this module 39 | Author = 'Daniel Bohannon (@danielhbohannon)' 40 | 41 | # Copyright statement for this module 42 | Copyright = 'Apache License, Version 2.0' 43 | 44 | # Description of the functionality provided by this module 45 | Description = 'PowerShell module file for importing all required modules for the Invoke-Obfuscation framework.' 46 | 47 | # Minimum version of the Windows PowerShell engine required by this module 48 | PowerShellVersion = '2.0' 49 | 50 | # Minimum version of the Windows PowerShell host required by this module 51 | PowerShellHostVersion = '2.0' 52 | 53 | # Script files (.ps1) that are run in the caller's environment prior to importing this module 54 | ScriptsToProcess = @('Out-ObfuscatedTokenCommand.ps1','Out-ObfuscatedAst.ps1','Out-ObfuscatedStringCommand.ps1','Out-EncodedAsciiCommand.ps1','Out-EncodedHexCommand.ps1','Out-EncodedOctalCommand.ps1','Out-EncodedBinaryCommand.ps1','Out-SecureStringCommand.ps1','Out-EncodedBXORCommand.ps1','Out-EncodedSpecialCharOnlyCommand.ps1','Out-EncodedWhitespaceCommand.ps1','Out-CompressedCommand.ps1','Out-PowerShellLauncher.ps1','Invoke-Obfuscation.ps1') 55 | 56 | # Functions to export from this module 57 | FunctionsToExport = '*' 58 | 59 | # HelpInfo URI of this module 60 | # HelpInfoURI = '' 61 | 62 | } -------------------------------------------------------------------------------- /Invoke-Obfuscation.psm1: -------------------------------------------------------------------------------- 1 | # This file is part of Invoke-Obfuscation. 2 | # 3 | # Copyright 2017 Daniel Bohannon <@danielhbohannon> 4 | # while at Mandiant 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | 19 | 20 | # Get location of this script no matter what the current directory is for the process executing this script. 21 | $ScriptDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition) 22 | 23 | Write-Host "`n[*] Invoke-Obfuscation.psm1 has been decomissioned." -ForegroundColor Red 24 | Write-Host "[*] Please run" -NoNewLine -ForegroundColor Red 25 | Write-Host " Import-Module $ScriptDir\Invoke-Obfuscation.psd1 " -NoNewLine -ForegroundColor Yellow 26 | Write-Host "instead." -ForegroundColor Red 27 | 28 | 29 | 30 | <# 31 | .SYNOPSIS 32 | 33 | PowerShell module file for importing all required modules for the Invoke-Obfuscation framework. 34 | 35 | Invoke-Obfuscation Module Loader 36 | Author: Daniel Bohannon (@danielhbohannon) 37 | License: Apache License, Version 2.0 38 | Required Dependencies: None 39 | Optional Dependencies: None 40 | 41 | .DESCRIPTION 42 | 43 | PowerShell module file for importing all required modules for the Invoke-Obfuscation framework. 44 | 45 | .EXAMPLE 46 | 47 | C:\PS> Import-Module .\Invoke-Obfuscation.psm1 48 | 49 | .NOTES 50 | 51 | PowerShell module file for importing all required modules for the Invoke-Obfuscation framework. 52 | This is a personal project developed by Daniel Bohannon while an employee at MANDIANT, A FireEye Company. 53 | 54 | .LINK 55 | 56 | http://www.danielbohannon.com 57 | #> 58 | <# 59 | # Confirm all necessary commands are loaded and import appropriate .ps1 files in current directory if necessary. 60 | Write-Host "`n[*] Validating necessary commands are loaded into current PowerShell session.`n" 61 | 62 | $RequiredFunctions = @() 63 | $RequiredFunctions += 'Out-ObfuscatedTokenCommand' 64 | $RequiredFunctions += 'Out-ObfuscatedStringCommand' 65 | $RequiredFunctions += 'Out-EncodedAsciiCommand' 66 | $RequiredFunctions += 'Out-EncodedHexCommand' 67 | $RequiredFunctions += 'Out-EncodedOctalCommand' 68 | $RequiredFunctions += 'Out-EncodedBinaryCommand' 69 | $RequiredFunctions += 'Out-SecureStringCommand' 70 | $RequiredFunctions += 'Out-EncodedBXORCommand' 71 | $RequiredFunctions += 'Out-PowerShellLauncher' 72 | $RequiredFunctions += 'Invoke-Obfuscation' 73 | 74 | # Get location of this script no matter what the current directory is for the process executing this script. 75 | $ScriptDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition) 76 | 77 | $UnloadedFunctionExists = $FALSE 78 | ForEach($Function in $RequiredFunctions) 79 | { 80 | # Check if $Function is loaded. 81 | If(!(Get-Command * | Where-Object {$_.Name -like $Function})) 82 | { 83 | # Validate that appropriate .ps1 file exists. 84 | If(Test-Path $ScriptDir\$Function.ps1) 85 | { 86 | # Import module. 87 | Import-Module $ScriptDir\$Function.ps1 88 | 89 | # Re-check if $Function is loaded. 90 | If((Get-Command * | Where-Object {$_.Name -like $Function}).Name) 91 | { 92 | Write-Host "[*] Function Loaded :: $Function" -ForegroundColor Green 93 | } 94 | Else 95 | { 96 | Write-Host "[*] Function Not Loaded :: $Function (After running Import-Module $ScriptDir\$Function.ps1)" -ForegroundColor Red 97 | $UnloadedFunctionExists = $TRUE 98 | } 99 | } 100 | Else { 101 | Write-Host "[*] Function Not Loaded :: $Function (Cannot locate $ScriptDir\$Function.ps1)" -ForegroundColor Red 102 | $UnloadedFunctionExists = $TRUE 103 | } 104 | } 105 | Else { 106 | Write-Host "[*] Function Already Loaded :: $Function" -ForegroundColor Green 107 | } 108 | } 109 | 110 | # Show error and warning if any functions were not properly loaded. 111 | If($UnloadedFunctionExists) 112 | { 113 | Write-Host "`n[*] One or more above functions are not loaded." -ForegroundColor Red 114 | Write-Host " Ensure Invoke-Obfuscation.psm1 is in the same directory as above scripts.`n" -ForegroundColor Red 115 | } 116 | Else 117 | { 118 | Write-Host "`n[*] All modules loaded and ready to run " -NoNewLine 119 | 120 | # Write output below string in interactive format. 121 | ForEach($Char in [Char[]]'Invoke-Obfuscation') 122 | { 123 | Write-Host $Char -NoNewline -ForegroundColor Green 124 | Start-Sleep -Milliseconds (Get-Random -Input @(25..200)) 125 | } 126 | Start-Sleep -Milliseconds 500 127 | Write-Host "`n" 128 | } 129 | #> -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Invoke-Obfuscation v1.8 2 | =============== 3 | 4 | ![Invoke-Obfuscation Screenshot](https://github.com/danielbohannon/danielbohannon.github.io/blob/master/Invoke-Obfuscation%20Screenshot.png) 5 | 6 | Introduction 7 | ------------ 8 | Invoke-Obfuscation is a PowerShell v2.0+ compatible PowerShell command 9 | and script obfuscator. 10 | 11 | Background 12 | ---------- 13 | In the Fall of 2015 I decided to begin researching the flexibility of 14 | PowerShell's language and began cataloguing the various ways to 15 | accomplish a handful of common techniques that most attackers use on a 16 | regular basis. 17 | 18 | Initially focusing on encoded command and remote download cradle syntaxes, 19 | I discovered that various escape characters that did not hinder the 20 | execution of the command persisted in the command line arguments, both in 21 | the running process as well as what is logged in Security EID 4688 and 22 | Sysmon EID 1 event logs. This led me to systematically explore ways of 23 | obfuscating each kind of "token" found in any PowerShell command or script. 24 | 25 | I then explored more obscure ways to perform string-level obfuscation, 26 | various encoding/encrypting techniques (like ASCII/hex/octal/binary and even 27 | SecureString), and finally PowerShell launch techniques to abstract the 28 | command line arguments from powershell.exe and to push it back to the parent 29 | and even grandparent process. 30 | 31 | Purpose 32 | ------- 33 | Attackers and commodity malware have started using extremely basic 34 | obfuscation techniques to hide the majority of the command from the command 35 | line arguments of powershell.exe. I developed this tool to aid the Blue Team 36 | in simulating obfuscated commands based on what I currently know to be 37 | syntactically possible in PowerShell 2.0-5.0 so that they can test their 38 | detection capabilities of these techniques. 39 | 40 | The tool's sole purpose is to break any assumptions that we as defenders may 41 | have concerning how PowerShell commands can appear on the command line. My 42 | hope is that it will encourage the Blue Team to shift to looking for 43 | Indicators of Obfuscation on the command line in addition to updating 44 | PowerShell logging to include Module, ScriptBlock and Transcription logging 45 | as these sources simplify most aspects of the obfuscation techniques 46 | generated by this tool. 47 | 48 | Usage 49 | ----- 50 | While all of the layers of obfuscation have been built out into separate 51 | scripts, most users will find the `Invoke-Obfuscation` function to be the 52 | easiest way to explorer and visualize the obfuscation techniques that this 53 | framework currently supports. 54 | 55 | Installation 56 | ------------ 57 | The source code for Invoke-Obfuscation is hosted at Github, and you may 58 | download, fork and review it from this repository 59 | (https://github.com/danielbohannon/Invoke-Obfuscation). Please report issues 60 | or feature requests through Github's bug tracker associated with this project. 61 | 62 | To install: 63 | 64 | Import-Module ./Invoke-Obfuscation.psd1 65 | Invoke-Obfuscation 66 | 67 | License 68 | ------- 69 | Invoke-Obfuscation is released under the Apache 2.0 license. 70 | 71 | Release Notes 72 | ------------- 73 | v1.0 - 2016-09-25 DerbyCon 6.0 (Louisville, Kentucky USA): PUBLIC Release of Invoke-Obfuscation. 74 | 75 | v1.1 - 2016-10-09 SANS DFIR Summit (Prague, Czech Republic): Added -f format operator re-ordering 76 | functionality to all applicable TOKEN obfuscation functions. Also added additional 77 | syntax options for setting variable values. 78 | 79 | v1.2 - 2016-10-20 CODE BLUE (Tokyo, Japan): Added Type TOKEN obfuscation (direct type 80 | casting with string obfuscation options for type name). 81 | 82 | v1.3 - 2016-10-22 Hacktivity (Budapest, Hungary): Added two new LAUNCHERs: CLIP+ and CLIP++. 83 | Also added additional (and simpler) array char conversion syntax for all ENCODING 84 | functions that does not require For-EachObject/%. 85 | 86 | v1.4 - 2016-10-28 BruCON (Ghent, Belgium): Added new BXOR ENCODING function. Also enhanced 87 | randomized case for all components of all ENCODING functions as well as for 88 | PowerShell execution flags for all LAUNCHERs. Finally, added -EP shorthand option 89 | for -ExecutionPolicy to all LAUNCHERs as well as the optional integer representation 90 | of the -WindowStyle PowerShell execution flag: Normal (0), Hidden (1), Minimized (2), 91 | Maximized (3). 92 | 93 | v1.5 - 2016-11-04 Blue Hat (Redmond, Washington USA): Added WMIC LAUNCHER with some 94 | randomization of WMIC command line arguments. 95 | 96 | v1.6 - 2017-01-24 Blue Hat IL (Tel Aviv, Israel): 97 | - Added CLI functionality: 98 | E.g., Invoke-Obfuscation -ScriptBlock {Write-Host 'CLI FTW!'} -Command 'Token\All\1, 99 | Encoding\1,Launcher\Stdin++\234,Clip' -Quiet -NoExit 100 | - Added UNDO functionality to remove one layer of obfuscation at a time. 101 | - Removed Whitespace obfuscation from Token\All\1 to speed up large script obfuscation. 102 | - Added Process Argument Tree output for all launchers to aid defenders. 103 | - Added base menu auto-detect functionality to avoid needing to use BACK or HOME: 104 | E.g., if you ran TOKEN then ALL then 1, then just type LAUNCHER and you will get to 105 | the LAUNCHER menu without needing to type HOME or BACK to get back to the home menu. 106 | - Added multi-command syntax utilized by CLI and interactive mode: 107 | E.g., Token\All\1,String\3,Encoding\5,Launcher\Ps\234,Clip 108 | - Added regex capability to all menu and obfuscation commands: 109 | E.g., Token\*\*,String\[13],Encoding\(1|6),Launcher\.*[+]{2}\234,Clip 110 | - Added OUT FILEPATH single command functionality. 111 | - Added decoding if powershell -enc syntax is entered as a SCRIPTBLOCK value. 112 | - Added alias ForEach to ForEach-Object/% randomized syntax options in all ENCODING 113 | functions. 114 | - Added -Key -Ke -K KEY substring syntax options to Out-SecureStringCommand.ps1. 115 | - Added more thorough case randomization to all \Home\String obfuscation functions. 116 | - Added -ST/-STA (Single-Threaded Apartment) flags to CLIP+ and CLIP++ launcher 117 | functions since they are required if running on PowerShell 2.0. 118 | - Added Get-Item/GI/Item syntax everywhere where Get-ChildItem is used to get 119 | variable values. 120 | - Added Set-Item variable instantiation syntax to TYPE obfuscation function. 121 | - Added additional Invoke-Expression/IEX syntax using PowerShell automatic variables 122 | and environment variable value concatenations in Out-ObfuscatedStringCommand.ps1's 123 | Out-EncapsulatedInvokeExpression function and copied to all launchers, STRING and 124 | ENCODING functions to add numerous command-line syntaxes for IEX. 125 | - Added two new JOIN syntaxes for String\Reverse and all ENCODING obfuscation options: 126 | 1) Added [String]::Join('',$string) JOIN syntax 127 | 2) Added OFS-variable JOIN syntax (Output Field Separator automatic variable) 128 | - Added two more SecureString syntaxes to Encoding\5: 129 | 1) PtrToStringAnsi / SecureStringToGlobalAllocAnsi 130 | 2) PtrToStringBSTR / SecureStringToBSTR 131 | - Added six GetMember alternate syntaxes for several SecureString members: 132 | 1) PtrToStringAuto, ([Runtime.InteropServices.Marshal].GetMembers()[3].Name).Invoke 133 | 2) PtrToStringAuto, ([Runtime.InteropServices.Marshal].GetMembers()[5].Name).Invoke 134 | 3) PtrToStringUni , ([Runtime.InteropServices.Marshal].GetMembers()[2].Name).Invoke 135 | 4) PtrToStringUni , ([Runtime.InteropServices.Marshal].GetMembers()[4].Name).Invoke 136 | 5) PtrToStringAnsi, ([Runtime.InteropServices.Marshal].GetMembers()[0].Name).Invoke 137 | 6) PtrToStringAnsi, ([Runtime.InteropServices.Marshal].GetMembers()[1].Name).Invoke 138 | - Updated Out-ObfuscatedTokenCommand.ps1 so that VARIABLE obfuscation won't 139 | encapsulate variables in ${} if they are already encapsulated (so ${${var}} won't 140 | happen as this causes errors). 141 | - Replaced Invoke-Obfuscation.psm1 with Invoke-Obfuscation.psd1 (thanks @Carlos_Perez). 142 | - Fixed several TOKEN-level obfuscation bugs reported by @cobbr_io and @IISResetMe. 143 | 144 | v1.7 - 2017-03-03 nullcon (Goa, India): 145 | - Added 3 new LAUNCHERs: RUNDLL, RUNDLL++ and MSHTA++ 146 | - Added additional ExecutionContext wildcard variable strings 147 | 148 | v1.8 - 2017-07-27 Black Hat (Las Vegas, Nevada USA): 149 | - Added 2 new ENCODING options: Special Characters and Whitespace 150 | 151 | v1.8.1 - 2017-12-19: 152 | - Added COMPRESS function for easier conversion of multi-line scripts to a one-liner 153 | command while drastically reducing the command length for cmd.exe command line length 154 | limitation purposes. 155 | 156 | v1.8.2 - 2018-01-04: 157 | - Added AST obfuscation functions, which obfuscates by manipulating the structure of 158 | the AbstractSyntaxTree without using many special characters. 159 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017 Daniel Bohannon 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Invoke-Obfuscation.ps1: -------------------------------------------------------------------------------- 1 | # This file is part of Invoke-Obfuscation. 2 | # 3 | # Copyright 2017 Daniel Bohannon <@danielhbohannon> 4 | # while at Mandiant 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | 19 | 20 | Function Invoke-Obfuscation 21 | { 22 | <# 23 | .SYNOPSIS 24 | 25 | Master function that orchestrates the application of all obfuscation functions to provided PowerShell script block or script path contents. Interactive mode enables one to explore all available obfuscation functions and apply them incrementally to input PowerShell script block or script path contents. 26 | 27 | Invoke-Obfuscation Function: Invoke-Obfuscation 28 | Author: Daniel Bohannon (@danielhbohannon) 29 | License: Apache License, Version 2.0 30 | Required Dependencies: Show-AsciiArt, Show-HelpMenu, Show-Menu, Show-OptionsMenu, Show-Tutorial and Out-ScriptContents (all located in Invoke-Obfuscation.ps1) 31 | Optional Dependencies: None 32 | 33 | .DESCRIPTION 34 | 35 | Invoke-Obfuscation orchestrates the application of all obfuscation functions to provided PowerShell script block or script path contents to evade detection by simple IOCs and process execution monitoring relying solely on command-line arguments and common parent-child process relationships. 36 | 37 | .PARAMETER ScriptBlock 38 | 39 | Specifies a scriptblock containing your payload. 40 | 41 | .PARAMETER ScriptPath 42 | 43 | Specifies the path to your payload (can be local file, UNC-path, or remote URI). 44 | 45 | .PARAMETER Command 46 | 47 | Specifies the obfuscation commands to run against the input ScriptBlock or ScriptPath parameter. 48 | 49 | .PARAMETER NoExit 50 | 51 | (Optional - only works if Command is specified) Outputs the option to not exit after running obfuscation commands defined in Command parameter. 52 | 53 | .PARAMETER Quiet 54 | 55 | (Optional - only works if Command is specified) Outputs the option to output only the final obfuscated result via stdout. 56 | 57 | .EXAMPLE 58 | 59 | C:\PS> Import-Module .\Invoke-Obfuscation.psd1; Invoke-Obfuscation 60 | 61 | C:\PS> Import-Module .\Invoke-Obfuscation.psd1; Invoke-Obfuscation -ScriptBlock {Write-Host 'Hello World!' -ForegroundColor Green; Write-Host 'Obfuscation Rocks!' -ForegroundColor Green} 62 | 63 | C:\PS> Import-Module .\Invoke-Obfuscation.psd1; Invoke-Obfuscation -ScriptBlock {Write-Host 'Hello World!' -ForegroundColor Green; Write-Host 'Obfuscation Rocks!' -ForegroundColor Green} -Command 'TOKEN\ALL\1,1,TEST,LAUNCHER\STDIN++\2347,CLIP' 64 | 65 | C:\PS> Import-Module .\Invoke-Obfuscation.psd1; Invoke-Obfuscation -ScriptBlock {Write-Host 'Hello World!' -ForegroundColor Green; Write-Host 'Obfuscation Rocks!' -ForegroundColor Green} -Command 'TOKEN\ALL\1,1,TEST,LAUNCHER\STDIN++\2347,CLIP' -NoExit 66 | 67 | C:\PS> Import-Module .\Invoke-Obfuscation.psd1; Invoke-Obfuscation -ScriptBlock {Write-Host 'Hello World!' -ForegroundColor Green; Write-Host 'Obfuscation Rocks!' -ForegroundColor Green} -Command 'TOKEN\ALL\1,1,TEST,LAUNCHER\STDIN++\2347,CLIP' -Quiet 68 | 69 | C:\PS> Import-Module .\Invoke-Obfuscation.psd1; Invoke-Obfuscation -ScriptBlock {Write-Host 'Hello World!' -ForegroundColor Green; Write-Host 'Obfuscation Rocks!' -ForegroundColor Green} -Command 'TOKEN\ALL\1,1,TEST,LAUNCHER\STDIN++\2347,CLIP' -NoExit -Quiet 70 | 71 | .NOTES 72 | 73 | Invoke-Obfuscation orchestrates the application of all obfuscation functions to provided PowerShell script block or script path contents to evade detection by simple IOCs and process execution monitoring relying solely on command-line arguments. 74 | This is a personal project developed by Daniel Bohannon while an employee at MANDIANT, A FireEye Company. 75 | 76 | .LINK 77 | 78 | http://www.danielbohannon.com 79 | #> 80 | 81 | [CmdletBinding(DefaultParameterSetName = 'ScriptBlock')] Param ( 82 | [Parameter(Position = 0, ValueFromPipeline = $True, ParameterSetName = 'ScriptBlock')] 83 | [ValidateNotNullOrEmpty()] 84 | [ScriptBlock] 85 | $ScriptBlock, 86 | 87 | [Parameter(Position = 0, ParameterSetName = 'ScriptPath')] 88 | [ValidateNotNullOrEmpty()] 89 | [String] 90 | $ScriptPath, 91 | 92 | [String] 93 | $Command, 94 | 95 | [Switch] 96 | $NoExit, 97 | 98 | [Switch] 99 | $Quiet 100 | ) 101 | 102 | # Define variables for CLI functionality. 103 | $Script:CliCommands = @() 104 | $Script:CompoundCommand = @() 105 | $Script:QuietWasSpecified = $FALSE 106 | $CliWasSpecified = $FALSE 107 | $NoExitWasSpecified = $FALSE 108 | 109 | # Either convert ScriptBlock to a String or convert script at $Path to a String. 110 | If($PSBoundParameters['ScriptBlock']) 111 | { 112 | $Script:CliCommands += ('set scriptblock ' + [String]$ScriptBlock) 113 | } 114 | If($PSBoundParameters['ScriptPath']) 115 | { 116 | $Script:CliCommands += ('set scriptpath ' + $ScriptPath) 117 | } 118 | 119 | # Append Command to CliCommands if specified by user input. 120 | If($PSBoundParameters['Command']) 121 | { 122 | $Script:CliCommands += $Command.Split(',') 123 | $CliWasSpecified = $TRUE 124 | 125 | If($PSBoundParameters['NoExit']) 126 | { 127 | $NoExitWasSpecified = $TRUE 128 | } 129 | 130 | If($PSBoundParameters['Quiet']) 131 | { 132 | # Create empty Write-Host and Start-Sleep proxy functions to cause any Write-Host or Start-Sleep invocations to not do anything until non-interactive -Command values are finished being processed. 133 | Function Write-Host {} 134 | Function Start-Sleep {} 135 | $Script:QuietWasSpecified = $TRUE 136 | } 137 | } 138 | 139 | ######################################## 140 | ## Script-wide variable instantiation ## 141 | ######################################## 142 | 143 | # Script-level array of Show Options menu, set as SCRIPT-level so it can be set from within any of the functions. 144 | # Build out menu for Show Options selection from user in Show-OptionsMenu menu. 145 | $Script:ScriptPath = '' 146 | $Script:ScriptBlock = '' 147 | $Script:CliSyntax = @() 148 | $Script:ExecutionCommands = @() 149 | $Script:ObfuscatedCommand = '' 150 | $Script:ObfuscatedCommandHistory = @() 151 | $Script:ObfuscationLength = '' 152 | $Script:OptionsMenu = @() 153 | $Script:OptionsMenu += , @('ScriptPath ' , $Script:ScriptPath , $TRUE) 154 | $Script:OptionsMenu += , @('ScriptBlock' , $Script:ScriptBlock , $TRUE) 155 | $Script:OptionsMenu += , @('CommandLineSyntax' , $Script:CliSyntax , $FALSE) 156 | $Script:OptionsMenu += , @('ExecutionCommands' , $Script:ExecutionCommands, $FALSE) 157 | $Script:OptionsMenu += , @('ObfuscatedCommand' , $Script:ObfuscatedCommand, $FALSE) 158 | $Script:OptionsMenu += , @('ObfuscationLength' , $Script:ObfuscatedCommand, $FALSE) 159 | # Build out $SetInputOptions from above items set as $TRUE (as settable). 160 | $SettableInputOptions = @() 161 | ForEach($Option in $Script:OptionsMenu) 162 | { 163 | If($Option[2]) {$SettableInputOptions += ([String]$Option[0]).ToLower().Trim()} 164 | } 165 | 166 | # Script-level variable for whether LAUNCHER has been applied to current ObfuscatedToken. 167 | $Script:LauncherApplied = $FALSE 168 | 169 | # Ensure Invoke-Obfuscation module was properly imported before continuing. 170 | If(!(Get-Module Invoke-Obfuscation | Where-Object {$_.ModuleType -eq 'Manifest'})) 171 | { 172 | $PathTopsd1 = "$ScriptDir\Invoke-Obfuscation.psd1" 173 | If($PathTopsd1.Contains(' ')) {$PathTopsd1 = '"' + $PathTopsd1 + '"'} 174 | Write-Host "`n`nERROR: Invoke-Obfuscation module is not loaded. You must run:" -ForegroundColor Red 175 | Write-Host " Import-Module $PathTopsd1`n`n" -ForegroundColor Yellow 176 | Start-Sleep -Seconds 3 177 | Exit 178 | } 179 | 180 | # Maximum size for cmd.exe and clipboard. 181 | $CmdMaxLength = 8190 182 | 183 | # Build interactive menus. 184 | $LineSpacing = '[*] ' 185 | 186 | # Main Menu. 187 | $MenuLevel = @() 188 | $MenuLevel+= , @($LineSpacing, 'TOKEN' , 'Obfuscate PowerShell command ') 189 | $MenuLevel+= , @($LineSpacing, 'AST' , "`tObfuscate PowerShell nodes <(PS3.0+)>") 190 | $MenuLevel+= , @($LineSpacing, 'STRING' , 'Obfuscate entire command as a ') 191 | $MenuLevel+= , @($LineSpacing, 'ENCODING' , 'Obfuscate entire command via ') 192 | $MenuLevel+= , @($LineSpacing, 'COMPRESS' , 'Convert entire command to one-liner and ') 193 | $MenuLevel+= , @($LineSpacing, 'LAUNCHER' , 'Obfuscate command args w/ techniques (run once at end)') 194 | 195 | # Main\Token Menu. 196 | $MenuLevel_Token = @() 197 | $MenuLevel_Token += , @($LineSpacing, 'STRING' , 'Obfuscate tokens (suggested to run first)') 198 | $MenuLevel_Token += , @($LineSpacing, 'COMMAND' , 'Obfuscate tokens') 199 | $MenuLevel_Token += , @($LineSpacing, 'ARGUMENT' , 'Obfuscate tokens') 200 | $MenuLevel_Token += , @($LineSpacing, 'MEMBER' , 'Obfuscate tokens') 201 | $MenuLevel_Token += , @($LineSpacing, 'VARIABLE' , 'Obfuscate tokens') 202 | $MenuLevel_Token += , @($LineSpacing, 'TYPE ' , 'Obfuscate tokens') 203 | $MenuLevel_Token += , @($LineSpacing, 'COMMENT' , 'Remove all tokens') 204 | $MenuLevel_Token += , @($LineSpacing, 'WHITESPACE' , 'Insert random (suggested to run last)') 205 | $MenuLevel_Token += , @($LineSpacing, 'ALL ' , 'Select choices from above (random order)') 206 | 207 | $MenuLevel_Token_String = @() 208 | $MenuLevel_Token_String += , @($LineSpacing, '1' , "Concatenate --> e.g. <('co'+'ffe'+'e')>" , @('Out-ObfuscatedTokenCommand', 'String', 1)) 209 | $MenuLevel_Token_String += , @($LineSpacing, '2' , "Reorder --> e.g. <('{1}{0}'-f'ffee','co')>" , @('Out-ObfuscatedTokenCommand', 'String', 2)) 210 | 211 | $MenuLevel_Token_Command = @() 212 | $MenuLevel_Token_Command += , @($LineSpacing, '1' , 'Ticks --> e.g. ' , @('Out-ObfuscatedTokenCommand', 'Command', 1)) 213 | $MenuLevel_Token_Command += , @($LineSpacing, '2' , "Splatting + Concatenate --> e.g. <&('Ne'+'w-Ob'+'ject')>" , @('Out-ObfuscatedTokenCommand', 'Command', 2)) 214 | $MenuLevel_Token_Command += , @($LineSpacing, '3' , "Splatting + Reorder --> e.g. <&('{1}{0}'-f'bject','New-O')>" , @('Out-ObfuscatedTokenCommand', 'Command', 3)) 215 | 216 | $MenuLevel_Token_Argument = @() 217 | $MenuLevel_Token_Argument += , @($LineSpacing, '1' , 'Random Case --> e.g. ' , @('Out-ObfuscatedTokenCommand', 'CommandArgument', 1)) 218 | $MenuLevel_Token_Argument += , @($LineSpacing, '2' , 'Ticks --> e.g. ' , @('Out-ObfuscatedTokenCommand', 'CommandArgument', 2)) 219 | $MenuLevel_Token_Argument += , @($LineSpacing, '3' , "Concatenate --> e.g. <('Ne'+'t.We'+'bClient')>" , @('Out-ObfuscatedTokenCommand', 'CommandArgument', 3)) 220 | $MenuLevel_Token_Argument += , @($LineSpacing, '4' , "Reorder --> e.g. <('{1}{0}'-f'bClient','Net.We')>" , @('Out-ObfuscatedTokenCommand', 'CommandArgument', 4)) 221 | 222 | $MenuLevel_Token_Member = @() 223 | $MenuLevel_Token_Member += , @($LineSpacing, '1' , 'Random Case --> e.g. ' , @('Out-ObfuscatedTokenCommand', 'Member', 1)) 224 | $MenuLevel_Token_Member += , @($LineSpacing, '2' , 'Ticks --> e.g. ' , @('Out-ObfuscatedTokenCommand', 'Member', 2)) 225 | $MenuLevel_Token_Member += , @($LineSpacing, '3' , "Concatenate --> e.g. <('dOwnLo'+'AdsT'+'Ring').Invoke()>" , @('Out-ObfuscatedTokenCommand', 'Member', 3)) 226 | $MenuLevel_Token_Member += , @($LineSpacing, '4' , "Reorder --> e.g. <('{1}{0}'-f'dString','Downloa').Invoke()>" , @('Out-ObfuscatedTokenCommand', 'Member', 4)) 227 | 228 | $MenuLevel_Token_Variable = @() 229 | $MenuLevel_Token_Variable += , @($LineSpacing, '1' , 'Random Case + {} + Ticks --> e.g. <${c`hEm`eX}>' , @('Out-ObfuscatedTokenCommand', 'Variable', 1)) 230 | 231 | $MenuLevel_Token_Type = @() 232 | $MenuLevel_Token_Type += , @($LineSpacing, '1' , "Type Cast + Concatenate --> e.g. <[Type]('Con'+'sole')>" , @('Out-ObfuscatedTokenCommand', 'Type', 1)) 233 | $MenuLevel_Token_Type += , @($LineSpacing, '2' , "Type Cast + Reordered --> e.g. <[Type]('{1}{0}'-f'sole','Con')>" , @('Out-ObfuscatedTokenCommand', 'Type', 2)) 234 | 235 | $MenuLevel_Token_Whitespace = @() 236 | $MenuLevel_Token_Whitespace += , @($LineSpacing, '1' , "`tRandom Whitespace --> e.g. <.( 'Ne' +'w-Ob' + 'ject')>" , @('Out-ObfuscatedTokenCommand', 'RandomWhitespace', 1)) 237 | 238 | $MenuLevel_Token_Comment = @() 239 | $MenuLevel_Token_Comment += , @($LineSpacing, '1' , "Remove Comments --> e.g. self-explanatory" , @('Out-ObfuscatedTokenCommand', 'Comment', 1)) 240 | 241 | $MenuLevel_Token_All = @() 242 | $MenuLevel_Token_All += , @($LineSpacing, '1' , "`tExecute Token obfuscation techniques (random order)" , @('Out-ObfuscatedTokenCommandAll', '', '')) 243 | 244 | # Main\Token Menu. 245 | $MenuLevel_Ast = @() 246 | $MenuLevel_Ast += , @($LineSpacing, 'NamedAttributeArgumentAst' , 'Obfuscate nodes') 247 | $MenuLevel_Ast += , @($LineSpacing, 'ParamBlockAst' , "`t`tObfuscate nodes") 248 | $MenuLevel_Ast += , @($LineSpacing, 'ScriptBlockAst' , "`t`tObfuscate nodes") 249 | $MenuLevel_Ast += , @($LineSpacing, 'AttributeAst' , "`t`tObfuscate nodes") 250 | $MenuLevel_Ast += , @($LineSpacing, 'BinaryExpressionAst' , "`tObfuscate nodes") 251 | $MenuLevel_Ast += , @($LineSpacing, 'HashtableAst' , "`t`tObfuscate nodes") 252 | $MenuLevel_Ast += , @($LineSpacing, 'CommandAst' , "`t`tObfuscate nodes") 253 | $MenuLevel_Ast += , @($LineSpacing, 'AssignmentStatementAst' , "`tObfuscate nodes") 254 | $MenuLevel_Ast += , @($LineSpacing, 'TypeExpressionAst' , "`tObfuscate nodes") 255 | $MenuLevel_Ast += , @($LineSpacing, 'TypeConstraintAst' , "`tObfuscate nodes") 256 | $MenuLevel_Ast += , @($LineSpacing, 'ALL' , "`t`t`tSelect choices from above") 257 | 258 | $MenuLevel_Ast_NamedAttributeArgumentAst = @() 259 | $MenuLevel_Ast_NamedAttributeArgumentAst += , @($LineSpacing, '1' , 'Reorder e.g. <[Parameter(Mandatory, ValueFromPipeline = $True)]> --> <[Parameter(Mandatory = $True, ValueFromPipeline)]>' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.NamedAttributeArgumentAst'), 1)) 260 | 261 | $MenuLevel_Ast_ParamBlockAst = @() 262 | $MenuLevel_Ast_ParamBlockAst += , @($LineSpacing, '1' , 'Reorder e.g. --> ' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.ParamBlockAst'), 1)) 263 | 264 | $MenuLevel_Ast_ScriptBlockAst = @() 265 | $MenuLevel_Ast_ScriptBlockAst += , @($LineSpacing, '1' , 'Reorder e.g. <{ Begin {} Process {} End {} }> --> <{ End {} Begin {} Process {} }>' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.ScriptBlockAst'), 1)) 266 | 267 | $MenuLevel_Ast_AttributeAst = @() 268 | $MenuLevel_Ast_AttributeAst += , @($LineSpacing, '1' , 'Reorder e.g. <[Parameter(Position = 0, Mandatory)]> --> <[Parameter(Mandatory, Position = 0)]>' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.AttributeAst'), 1)) 269 | 270 | $MenuLevel_Ast_BinaryExpressionAst = @() 271 | $MenuLevel_Ast_BinaryExpressionAst += , @($LineSpacing, '1' , 'Reorder e.g. <(2 + 3) * 4> --> <4 * (3 + 2)>' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.BinaryExpressionAst'), 1)) 272 | 273 | $MenuLevel_Ast_HashtableAst = @() 274 | $MenuLevel_Ast_HashtableAst += , @($LineSpacing, '1' , "Reorder e.g. <@{ProviderName = 'Microsoft-Windows-PowerShell'; Id = 4104}> --> <@{Id = 4104; ProviderName = 'Microsoft-Windows-PowerShell'}>" , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.HashtableAst'), 1)) 275 | 276 | $MenuLevel_Ast_CommandAst = @() 277 | $MenuLevel_Ast_CommandAst += , @($LineSpacing, '1' , 'Reorder e.g. --> ' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.CommandAst'), 1)) 278 | 279 | $MenuLevel_Ast_AssignmentStatementAst = @() 280 | $MenuLevel_Ast_AssignmentStatementAst += , @($LineSpacing, '1' , 'Rename e.g. <$Example = "Example"> --> ' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.AssignmentStatementAst'), 1)) 281 | 282 | $MenuLevel_Ast_TypeExpressionAst = @() 283 | $MenuLevel_Ast_TypeExpressionAst += , @($LineSpacing, '1' , 'Rename e.g. <[ScriptBlock]> --> <[Management.Automation.ScriptBlock]>' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.TypeExpressionAst'), 1)) 284 | 285 | $MenuLevel_Ast_TypeConstraintAst = @() 286 | $MenuLevel_Ast_TypeConstraintAst += , @($LineSpacing, '1' , 'Rename e.g. <[Int] $Integer = 1> --> <[System.Int32] $Integer = 1>' , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.TypeConstraintAst'), 1)) 287 | 288 | $MenuLevel_Ast_All = @() 289 | $MenuLevel_Ast_All += , @($LineSpacing, '1' , "`tExecute Ast obfuscation techniques" , @('Out-ObfuscatedAst', @('System.Management.Automation.Language.NamedAttributeArgumentAst', 'System.Management.Automation.Language.ParamBlockAst', 'System.Management.Automation.Language.ScriptBlockAst', 'System.Management.Automation.Language.AttributeAst', 'System.Management.Automation.Language.BinaryExpressionAst', 'System.Management.Automation.Language.HashtableAst', 'System.Management.Automation.Language.CommandAst', 'System.Management.Automation.Language.AssignmentStatementAst', 'System.Management.Automation.Language.TypeExpressionAst', 'System.Management.Automation.Language.TypeConstraintAst'), '')) 290 | 291 | # Main\String Menu. 292 | $MenuLevel_String = @() 293 | $MenuLevel_String += , @($LineSpacing, '1' , ' entire command' , @('Out-ObfuscatedStringCommand', '', 1)) 294 | $MenuLevel_String += , @($LineSpacing, '2' , ' entire command after concatenating' , @('Out-ObfuscatedStringCommand', '', 2)) 295 | $MenuLevel_String += , @($LineSpacing, '3' , ' entire command after concatenating' , @('Out-ObfuscatedStringCommand', '', 3)) 296 | 297 | # Main\Encoding Menu. 298 | $MenuLevel_Encoding = @() 299 | $MenuLevel_Encoding += , @($LineSpacing, '1' , "`tEncode entire command as " , @('Out-EncodedAsciiCommand' , '', '')) 300 | $MenuLevel_Encoding += , @($LineSpacing, '2' , "`tEncode entire command as " , @('Out-EncodedHexCommand' , '', '')) 301 | $MenuLevel_Encoding += , @($LineSpacing, '3' , "`tEncode entire command as " , @('Out-EncodedOctalCommand' , '', '')) 302 | $MenuLevel_Encoding += , @($LineSpacing, '4' , "`tEncode entire command as " , @('Out-EncodedBinaryCommand' , '', '')) 303 | $MenuLevel_Encoding += , @($LineSpacing, '5' , "`tEncrypt entire command as (AES)" , @('Out-SecureStringCommand' , '', '')) 304 | $MenuLevel_Encoding += , @($LineSpacing, '6' , "`tEncode entire command as " , @('Out-EncodedBXORCommand' , '', '')) 305 | $MenuLevel_Encoding += , @($LineSpacing, '7' , "`tEncode entire command as " , @('Out-EncodedSpecialCharOnlyCommand' , '', '')) 306 | $MenuLevel_Encoding += , @($LineSpacing, '8' , "`tEncode entire command as " , @('Out-EncodedWhitespaceCommand' , '', '')) 307 | 308 | # Main\Compress Menu. 309 | $MenuLevel_Compress = @() 310 | $MenuLevel_Compress += , @($LineSpacing, '1' , "Convert entire command to one-liner and " , @('Out-CompressedCommand' , '', '')) 311 | 312 | # Main\Launcher Menu. 313 | $MenuLevel_Launcher = @() 314 | $MenuLevel_Launcher += , @($LineSpacing, 'PS' , "`t") 315 | $MenuLevel_Launcher += , @($LineSpacing, 'CMD' , ' + PowerShell') 316 | $MenuLevel_Launcher += , @($LineSpacing, 'WMIC' , ' + PowerShell') 317 | $MenuLevel_Launcher += , @($LineSpacing, 'RUNDLL' , ' + PowerShell') 318 | $MenuLevel_Launcher += , @($LineSpacing, 'VAR+' , 'Cmd + set && PowerShell iex ') 319 | $MenuLevel_Launcher += , @($LineSpacing, 'STDIN+' , 'Cmd + | PowerShell - (stdin)') 320 | $MenuLevel_Launcher += , @($LineSpacing, 'CLIP+' , 'Cmd + | Clip && PowerShell iex ') 321 | $MenuLevel_Launcher += , @($LineSpacing, 'VAR++' , 'Cmd + set && Cmd && PowerShell iex ') 322 | $MenuLevel_Launcher += , @($LineSpacing, 'STDIN++' , 'Cmd + set && Cmd | PowerShell - (stdin)') 323 | $MenuLevel_Launcher += , @($LineSpacing, 'CLIP++' , 'Cmd + | Clip && Cmd && PowerShell iex ') 324 | $MenuLevel_Launcher += , @($LineSpacing, 'RUNDLL++' , 'Cmd + set Var && && PowerShell iex Var') 325 | $MenuLevel_Launcher += , @($LineSpacing, 'MSHTA++' , 'Cmd + set Var && && PowerShell iex Var') 326 | 327 | $MenuLevel_Launcher_PS = @() 328 | $MenuLevel_Launcher_PS += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 329 | $MenuLevel_Launcher_PS += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '1')) 330 | $MenuLevel_Launcher_PS += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '1')) 331 | $MenuLevel_Launcher_PS += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '1')) 332 | $MenuLevel_Launcher_PS += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '1')) 333 | $MenuLevel_Launcher_PS += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '1')) 334 | $MenuLevel_Launcher_PS += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '1')) 335 | $MenuLevel_Launcher_PS += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '1')) 336 | $MenuLevel_Launcher_PS += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '1')) 337 | $MenuLevel_Launcher_PS += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '1')) 338 | 339 | $MenuLevel_Launcher_CMD = @() 340 | $MenuLevel_Launcher_CMD += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 341 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '2')) 342 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '2')) 343 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '2')) 344 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '2')) 345 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '2')) 346 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '2')) 347 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '2')) 348 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '2')) 349 | $MenuLevel_Launcher_CMD += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '2')) 350 | 351 | $MenuLevel_Launcher_WMIC = @() 352 | $MenuLevel_Launcher_WMIC += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 353 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '3')) 354 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '3')) 355 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '3')) 356 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '3')) 357 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '3')) 358 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '3')) 359 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '3')) 360 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '3')) 361 | $MenuLevel_Launcher_WMIC += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '3')) 362 | 363 | $MenuLevel_Launcher_RUNDLL = @() 364 | $MenuLevel_Launcher_RUNDLL += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 365 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '4')) 366 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '4')) 367 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '4')) 368 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '4')) 369 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '4')) 370 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '4')) 371 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '4')) 372 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '4')) 373 | $MenuLevel_Launcher_RUNDLL += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '4')) 374 | 375 | ${MenuLevel_Launcher_VAR+} = @() 376 | ${MenuLevel_Launcher_VAR+} += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 377 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '5')) 378 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '5')) 379 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '5')) 380 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '5')) 381 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '5')) 382 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '5')) 383 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '5')) 384 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '5')) 385 | ${MenuLevel_Launcher_VAR+} += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '5')) 386 | 387 | ${MenuLevel_Launcher_STDIN+} = @() 388 | ${MenuLevel_Launcher_STDIN+} += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 389 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '6')) 390 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '6')) 391 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '6')) 392 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '6')) 393 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '6')) 394 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '6')) 395 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '6')) 396 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '6')) 397 | ${MenuLevel_Launcher_STDIN+} += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '6')) 398 | 399 | ${MenuLevel_Launcher_CLIP+} = @() 400 | ${MenuLevel_Launcher_CLIP+} += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 401 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '7')) 402 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '7')) 403 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '7')) 404 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '7')) 405 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '7')) 406 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '7')) 407 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '7')) 408 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '7')) 409 | ${MenuLevel_Launcher_CLIP+} += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '7')) 410 | 411 | ${MenuLevel_Launcher_VAR++} = @() 412 | ${MenuLevel_Launcher_VAR++} += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 413 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '8')) 414 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '8')) 415 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '8')) 416 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '8')) 417 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '8')) 418 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '8')) 419 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '8')) 420 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '8')) 421 | ${MenuLevel_Launcher_VAR++} += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '8')) 422 | 423 | ${MenuLevel_Launcher_STDIN++} = @() 424 | ${MenuLevel_Launcher_STDIN++} += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 425 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '0' , "`tNO EXECUTION FLAGS" , @('Out-PowerShellLauncher', '', '9')) 426 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '1' , "`t-NoExit" , @('Out-PowerShellLauncher', '', '9')) 427 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '2' , "`t-NonInteractive" , @('Out-PowerShellLauncher', '', '9')) 428 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '3' , "`t-NoLogo" , @('Out-PowerShellLauncher', '', '9')) 429 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '4' , "`t-NoProfile" , @('Out-PowerShellLauncher', '', '9')) 430 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '5' , "`t-Command" , @('Out-PowerShellLauncher', '', '9')) 431 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '6' , "`t-WindowStyle Hidden" , @('Out-PowerShellLauncher', '', '9')) 432 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '7' , "`t-ExecutionPolicy Bypass" , @('Out-PowerShellLauncher', '', '9')) 433 | ${MenuLevel_Launcher_STDIN++} += , @($LineSpacing, '8' , "`t-Wow64 (to path 32-bit powershell.exe)" , @('Out-PowerShellLauncher', '', '9')) 434 | 435 | ${MenuLevel_Launcher_CLIP++} = @() 436 | ${MenuLevel_Launcher_CLIP++} += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 437 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '10')) 438 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '10')) 439 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '10')) 440 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '10')) 441 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '10')) 442 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '10')) 443 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '10')) 444 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '10')) 445 | ${MenuLevel_Launcher_CLIP++} += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '10')) 446 | 447 | ${MenuLevel_Launcher_RUNDLL++} = @() 448 | ${MenuLevel_Launcher_RUNDLL++} += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 449 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '11')) 450 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '11')) 451 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '11')) 452 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '11')) 453 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '11')) 454 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '11')) 455 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '11')) 456 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '11')) 457 | ${MenuLevel_Launcher_RUNDLL++} += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '11')) 458 | 459 | ${MenuLevel_Launcher_MSHTA++} = @() 460 | ${MenuLevel_Launcher_MSHTA++} += , @("Enter string of numbers with all desired flags to pass to function. (e.g. 23459)`n", '' , '' , @('', '', '')) 461 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '0' , 'NO EXECUTION FLAGS' , @('Out-PowerShellLauncher', '', '12')) 462 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '1' , '-NoExit' , @('Out-PowerShellLauncher', '', '12')) 463 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '2' , '-NonInteractive' , @('Out-PowerShellLauncher', '', '12')) 464 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '3' , '-NoLogo' , @('Out-PowerShellLauncher', '', '12')) 465 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '4' , '-NoProfile' , @('Out-PowerShellLauncher', '', '12')) 466 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '5' , '-Command' , @('Out-PowerShellLauncher', '', '12')) 467 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '6' , '-WindowStyle Hidden' , @('Out-PowerShellLauncher', '', '12')) 468 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '7' , '-ExecutionPolicy Bypass' , @('Out-PowerShellLauncher', '', '12')) 469 | ${MenuLevel_Launcher_MSHTA++} += , @($LineSpacing, '8' , '-Wow64 (to path 32-bit powershell.exe)' , @('Out-PowerShellLauncher', '', '12')) 470 | 471 | # Input options to display non-interactive menus or perform actions. 472 | $TutorialInputOptions = @(@('tutorial') , " of how to use this tool `t " ) 473 | $MenuInputOptionsShowHelp = @(@('help','get-help','?','-?','/?','menu'), "Show this Menu `t " ) 474 | $MenuInputOptionsShowOptions = @(@('show options','show','options') , " for payload to obfuscate `t " ) 475 | $ClearScreenInputOptions = @(@('clear','clear-host','cls') , " screen `t " ) 476 | $CopyToClipboardInputOptions = @(@('copy','clip','clipboard') , " ObfuscatedCommand to clipboard `t " ) 477 | $OutputToDiskInputOptions = @(@('out') , "Write ObfuscatedCommand to disk `t " ) 478 | $ExecutionInputOptions = @(@('exec','execute','test','run') , " ObfuscatedCommand locally `t " ) 479 | $ResetObfuscationInputOptions = @(@('reset') , " ALL obfuscation for ObfuscatedCommand ") 480 | $UndoObfuscationInputOptions = @(@('undo') , " LAST obfuscation for ObfuscatedCommand ") 481 | $BackCommandInputOptions = @(@('back','cd ..') , "Go to previous obfuscation menu `t " ) 482 | $ExitCommandInputOptions = @(@('quit','exit') , " Invoke-Obfuscation `t " ) 483 | $HomeMenuInputOptions = @(@('home','main') , "Return to Menu `t " ) 484 | # For Version 1.0 ASCII art is not necessary. 485 | #$ShowAsciiArtInputOptions = @(@('ascii') , "Display random art for the lulz :)`t") 486 | 487 | # Add all above input options lists to be displayed in SHOW OPTIONS menu. 488 | $AllAvailableInputOptionsLists = @() 489 | $AllAvailableInputOptionsLists += , $TutorialInputOptions 490 | $AllAvailableInputOptionsLists += , $MenuInputOptionsShowHelp 491 | $AllAvailableInputOptionsLists += , $MenuInputOptionsShowOptions 492 | $AllAvailableInputOptionsLists += , $ClearScreenInputOptions 493 | $AllAvailableInputOptionsLists += , $ExecutionInputOptions 494 | $AllAvailableInputOptionsLists += , $CopyToClipboardInputOptions 495 | $AllAvailableInputOptionsLists += , $OutputToDiskInputOptions 496 | $AllAvailableInputOptionsLists += , $ResetObfuscationInputOptions 497 | $AllAvailableInputOptionsLists += , $UndoObfuscationInputOptions 498 | $AllAvailableInputOptionsLists += , $BackCommandInputOptions 499 | $AllAvailableInputOptionsLists += , $ExitCommandInputOptions 500 | $AllAvailableInputOptionsLists += , $HomeMenuInputOptions 501 | # For Version 1.0 ASCII art is not necessary. 502 | #$AllAvailableInputOptionsLists += , $ShowAsciiArtInputOptions 503 | 504 | # Input options to change interactive menus. 505 | $ExitInputOptions = $ExitCommandInputOptions[0] 506 | $MenuInputOptions = $BackCommandInputOptions[0] 507 | 508 | # Obligatory ASCII Art. 509 | Show-AsciiArt 510 | Start-Sleep -Seconds 2 511 | 512 | # Show Help Menu once at beginning of script. 513 | Show-HelpMenu 514 | 515 | # Main loop for user interaction. Show-Menu function displays current function along with acceptable input options (defined in arrays instantiated above). 516 | # User input and validation is handled within Show-Menu. 517 | $UserResponse = '' 518 | While($ExitInputOptions -NotContains ([String]$UserResponse).ToLower()) 519 | { 520 | $UserResponse = ([String]$UserResponse).Trim() 521 | 522 | If($HomeMenuInputOptions[0] -Contains ([String]$UserResponse).ToLower()) 523 | { 524 | $UserResponse = '' 525 | } 526 | 527 | # Display menu if it is defined in a menu variable with $UserResponse in the variable name. 528 | If(Test-Path ('Variable:' + "MenuLevel$UserResponse")) 529 | { 530 | $UserResponse = Show-Menu (Get-Variable "MenuLevel$UserResponse").Value $UserResponse $Script:OptionsMenu 531 | } 532 | Else 533 | { 534 | Write-Error "The variable MenuLevel$UserResponse does not exist." 535 | $UserResponse = 'quit' 536 | } 537 | 538 | If(($UserResponse -eq 'quit') -AND $CliWasSpecified -AND !$NoExitWasSpecified) 539 | { 540 | Write-Output $Script:ObfuscatedCommand.Trim("`n") 541 | $UserInput = 'quit' 542 | } 543 | } 544 | } 545 | 546 | 547 | # Get location of this script no matter what the current directory is for the process executing this script. 548 | $ScriptDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition) 549 | 550 | 551 | Function Show-Menu 552 | { 553 | <# 554 | .SYNOPSIS 555 | 556 | HELPER FUNCTION :: Displays current menu with obfuscation navigation and application options for Invoke-Obfuscation. 557 | 558 | Invoke-Obfuscation Function: Show-Menu 559 | Author: Daniel Bohannon (@danielhbohannon) 560 | License: Apache License, Version 2.0 561 | Required Dependencies: None 562 | Optional Dependencies: None 563 | 564 | .DESCRIPTION 565 | 566 | Show-Menu displays current menu with obfuscation navigation and application options for Invoke-Obfuscation. 567 | 568 | .PARAMETER Menu 569 | 570 | Specifies the menu options to display, with acceptable input options parsed out of this array. 571 | 572 | .PARAMETER MenuName 573 | 574 | Specifies the menu header display and the breadcrumb used in the interactive prompt display. 575 | 576 | .PARAMETER Script:OptionsMenu 577 | 578 | Specifies the script-wide variable containing additional acceptable input in addition to each menu's specific acceptable input (e.g. EXIT, QUIT, BACK, HOME, MAIN, etc.). 579 | 580 | .EXAMPLE 581 | 582 | C:\PS> Show-Menu 583 | 584 | .NOTES 585 | 586 | This is a personal project developed by Daniel Bohannon while an employee at MANDIANT, A FireEye Company. 587 | 588 | .LINK 589 | 590 | http://www.danielbohannon.com 591 | #> 592 | 593 | Param( 594 | [Parameter(ValueFromPipeline = $true)] 595 | [ValidateNotNullOrEmpty()] 596 | [Object[]] 597 | $Menu, 598 | 599 | [String] 600 | $MenuName, 601 | 602 | [Object[]] 603 | $Script:OptionsMenu 604 | ) 605 | 606 | # Extract all acceptable values from $Menu. 607 | $AcceptableInput = @() 608 | $SelectionContainsCommand = $FALSE 609 | ForEach($Line in $Menu) 610 | { 611 | # If there are 4 items in each $Line in $Menu then the fourth item is a command to exec if selected. 612 | If($Line.Count -eq 4) 613 | { 614 | $SelectionContainsCommand = $TRUE 615 | } 616 | $AcceptableInput += ($Line[1]).Trim(' ') 617 | } 618 | 619 | $UserInput = $NULL 620 | 621 | While($AcceptableInput -NotContains $UserInput) 622 | { 623 | # Format custom breadcrumb prompt. 624 | Write-Host "`n" 625 | $BreadCrumb = $MenuName.Trim('_') 626 | If($BreadCrumb.Length -gt 1) 627 | { 628 | If($BreadCrumb.ToLower() -eq 'show options') 629 | { 630 | $BreadCrumb = 'Show Options' 631 | } 632 | If($MenuName -ne '') 633 | { 634 | # Handle specific case substitutions from what is ALL CAPS in interactive menu and then correct casing we want to appear in the Breadcrumb. 635 | $BreadCrumbOCD = @() 636 | $BreadCrumbOCD += , @('ps' ,'PS') 637 | $BreadCrumbOCD += , @('cmd' ,'Cmd') 638 | $BreadCrumbOCD += , @('wmic' ,'Wmic') 639 | $BreadCrumbOCD += , @('rundll' ,'RunDll') 640 | $BreadCrumbOCD += , @('var+' ,'Var+') 641 | $BreadCrumbOCD += , @('stdin+' ,'StdIn+') 642 | $BreadCrumbOCD += , @('clip+' ,'Clip+') 643 | $BreadCrumbOCD += , @('var++' ,'Var++') 644 | $BreadCrumbOCD += , @('stdin++' ,'StdIn++') 645 | $BreadCrumbOCD += , @('clip++' ,'Clip++') 646 | $BreadCrumbOCD += , @('rundll++','RunDll++') 647 | $BreadCrumbOCD += , @('mshta++' ,'Mshta++') 648 | $BreadCrumbOCD += , @('ast', 'AST') 649 | 650 | $BreadCrumbArray = @() 651 | ForEach($Crumb in $BreadCrumb.Split('_')) 652 | { 653 | # Perform casing substitutions for any matches in $BreadCrumbOCD array. 654 | $StillLookingForSubstitution = $TRUE 655 | ForEach($Substitution in $BreadCrumbOCD) 656 | { 657 | If($Crumb.ToLower() -eq $Substitution[0]) 658 | { 659 | $BreadCrumbArray += $Substitution[1] 660 | $StillLookingForSubstitution = $FALSE 661 | } 662 | } 663 | 664 | # If no substitution occurred above then simply upper-case the first character and lower-case all the remaining characters. 665 | If($StillLookingForSubstitution) 666 | { 667 | $BreadCrumbArray += $Crumb.SubString(0,1).ToUpper() + $Crumb.SubString(1).ToLower() 668 | 669 | # If no substitution was found for the 3rd or later BreadCrumb element (only for Launcher BreadCrumb) then throw a warning so we can add this substitution pair to $BreadCrumbOCD. 670 | If(($BreadCrumb.Split('_').Count -eq 2) -AND ($BreadCrumb.StartsWith('Launcher_')) -AND ($Crumb -ne 'Launcher')) 671 | { 672 | Write-Warning "No substituion pair was found for `$Crumb=$Crumb in `$BreadCrumb=$BreadCrumb. Add this `$Crumb substitution pair to `$BreadCrumbOCD array in Invoke-Obfuscation." 673 | } 674 | } 675 | } 676 | $BreadCrumb = $BreadCrumbArray -Join '\' 677 | } 678 | $BreadCrumb = '\' + $BreadCrumb 679 | } 680 | 681 | # Output menu heading. 682 | $FirstLine = "Choose one of the below " 683 | If($BreadCrumb -ne '') 684 | { 685 | $FirstLine = $FirstLine + $BreadCrumb.Trim('\') + ' ' 686 | } 687 | Write-Host "$FirstLine" -NoNewLine 688 | 689 | # Change color and verbiage if selection will execute command. 690 | If($SelectionContainsCommand) 691 | { 692 | Write-Host "options" -NoNewLine -ForegroundColor Green 693 | Write-Host " to" -NoNewLine 694 | Write-Host " APPLY" -NoNewLine -ForegroundColor Green 695 | Write-Host " to current payload" -NoNewLine 696 | } 697 | Else 698 | { 699 | Write-Host "options" -NoNewLine -ForegroundColor Yellow 700 | } 701 | Write-Host ":`n" 702 | 703 | ForEach($Line in $Menu) 704 | { 705 | $LineSpace = $Line[0] 706 | $LineOption = $Line[1] 707 | $LineValue = $Line[2] 708 | Write-Host $LineSpace -NoNewLine 709 | 710 | # If not empty then include breadcrumb in $LineOption output (is not colored and won't affect user input syntax). 711 | If(($BreadCrumb -ne '') -AND ($LineSpace.StartsWith('['))) 712 | { 713 | Write-Host ($BreadCrumb.ToUpper().Trim('\') + '\') -NoNewLine 714 | } 715 | 716 | # Change color if selection will execute command. 717 | If($SelectionContainsCommand) 718 | { 719 | Write-Host $LineOption -NoNewLine -ForegroundColor Green 720 | } 721 | Else 722 | { 723 | Write-Host $LineOption -NoNewLine -ForegroundColor Yellow 724 | } 725 | 726 | # Add additional coloring to string encapsulated by <> if it exists in $LineValue. 727 | If($LineValue.Contains('<') -AND $LineValue.Contains('>')) 728 | { 729 | $FirstPart = $LineValue.SubString(0,$LineValue.IndexOf('<')) 730 | $MiddlePart = $LineValue.SubString($FirstPart.Length+1) 731 | $MiddlePart = $MiddlePart.SubString(0,$MiddlePart.IndexOf('>')) 732 | $LastPart = $LineValue.SubString($FirstPart.Length+$MiddlePart.Length+2) 733 | Write-Host "`t$FirstPart" -NoNewLine 734 | Write-Host $MiddlePart -NoNewLine -ForegroundColor Cyan 735 | 736 | # Handle if more than one term needs to be output in different color. 737 | If($LastPart.Contains('<') -AND $LastPart.Contains('>')) 738 | { 739 | $LineValue = $LastPart 740 | $FirstPart = $LineValue.SubString(0,$LineValue.IndexOf('<')) 741 | $MiddlePart = $LineValue.SubString($FirstPart.Length+1) 742 | $MiddlePart = $MiddlePart.SubString(0,$MiddlePart.IndexOf('>')) 743 | $LastPart = $LineValue.SubString($FirstPart.Length+$MiddlePart.Length+2) 744 | Write-Host "$FirstPart" -NoNewLine 745 | If($MiddlePart.EndsWith("(PS3.0+)")) 746 | { 747 | Write-Host $MiddlePart -NoNewline -ForegroundColor Red 748 | } 749 | Else 750 | { 751 | Write-Host $MiddlePart -NoNewLine -ForegroundColor Cyan 752 | } 753 | } 754 | 755 | Write-Host $LastPart 756 | } 757 | Else 758 | { 759 | Write-Host "`t$LineValue" 760 | } 761 | } 762 | 763 | # Prompt for user input with custom breadcrumb prompt. 764 | Write-Host '' 765 | If($UserInput -ne '') {Write-Host ''} 766 | $UserInput = '' 767 | 768 | While(($UserInput -eq '') -AND ($Script:CompoundCommand.Count -eq 0)) 769 | { 770 | # Output custom prompt. 771 | Write-Host "Invoke-Obfuscation$BreadCrumb> " -NoNewLine -ForegroundColor Magenta 772 | 773 | # Get interactive user input if CliCommands input variable was not specified by user. 774 | If(($Script:CliCommands.Count -gt 0) -OR ($Script:CliCommands -ne $NULL)) 775 | { 776 | If($Script:CliCommands.GetType().Name -eq 'String') 777 | { 778 | $NextCliCommand = $Script:CliCommands.Trim() 779 | $Script:CliCommands = @() 780 | } 781 | Else 782 | { 783 | $NextCliCommand = ([String]$Script:CliCommands[0]).Trim() 784 | $Script:CliCommands = For($i=1; $i -lt $Script:CliCommands.Count; $i++) {$Script:CliCommands[$i]} 785 | } 786 | 787 | $UserInput = $NextCliCommand 788 | } 789 | Else 790 | { 791 | # If Command was defined on command line and NoExit switch was not defined then output final ObfuscatedCommand to stdout and then quit. Otherwise continue with interactive Invoke-Obfuscation. 792 | If($CliWasSpecified -AND ($Script:CliCommands.Count -lt 1) -AND ($Script:CompoundCommand.Count -lt 1) -AND ($Script:QuietWasSpecified -OR !$NoExitWasSpecified)) 793 | { 794 | If($Script:QuietWasSpecified) 795 | { 796 | # Remove Write-Host and Start-Sleep proxy functions so that Write-Host and Start-Sleep cmdlets will be called during the remainder of the interactive Invoke-Obfuscation session. 797 | Remove-Item -Path Function:Write-Host 798 | Remove-Item -Path Function:Start-Sleep 799 | 800 | $Script:QuietWasSpecified = $FALSE 801 | 802 | # Automatically run 'Show Options' so the user has context of what has successfully been executed. 803 | $UserInput = 'show options' 804 | $BreadCrumb = 'Show Options' 805 | } 806 | # -NoExit wasn't specified and -Command was, so we will output the result back in the main While loop. 807 | If(!$NoExitWasSpecified) 808 | { 809 | $UserInput = 'quit' 810 | } 811 | } 812 | Else 813 | { 814 | $UserInput = (Read-Host).Trim() 815 | } 816 | 817 | # Process interactive UserInput using CLI syntax, so comma-delimited and slash-delimited commands can be processed interactively. 818 | If(($Script:CliCommands.Count -eq 0) -AND !$UserInput.ToLower().StartsWith('set ') -AND $UserInput.Contains(',')) 819 | { 820 | $Script:CliCommands = $UserInput.Split(',') 821 | 822 | # Reset $UserInput so current While loop will be traversed once more and process UserInput command as a CliCommand. 823 | $UserInput = '' 824 | } 825 | } 826 | } 827 | 828 | # Trim any leading trailing slashes so it doesn't misinterpret it as a compound command unnecessarily. 829 | $UserInput = $UserInput.Trim('/\') 830 | 831 | # Cause UserInput of base menu level directories to automatically work. 832 | # The only exception is STRING if the current MenuName is _token since it can be the base menu STRING or TOKEN/STRING. 833 | If((($MenuLevel | ForEach-Object {$_[1].Trim()}) -Contains $UserInput.Split('/\')[0]) -AND !(('string' -Contains $UserInput.Split('/\')[0]) -AND ($MenuName -eq '_token')) -AND ($MenuName -ne '')) 834 | { 835 | $UserInput = 'home/' + $UserInput.Trim() 836 | } 837 | 838 | # If current command contains \ or / and does not start with SET or OUT then we are dealing with a compound command. 839 | # Setting $Script:CompounCommand in below IF block. 840 | If(($Script:CompoundCommand.Count -eq 0) -AND !$UserInput.ToLower().StartsWith('set ') -AND !$UserInput.ToLower().StartsWith('out ') -AND ($UserInput.Contains('\') -OR $UserInput.Contains('/'))) 841 | { 842 | $Script:CompoundCommand = $UserInput.Split('/\') 843 | } 844 | 845 | # If current command contains \ or / and does not start with SET then we are dealing with a compound command. 846 | # Parsing out next command from $Script:CompounCommand in below IF block. 847 | If($Script:CompoundCommand.Count -gt 0) 848 | { 849 | $UserInput = '' 850 | While(($UserInput -eq '') -AND ($Script:CompoundCommand.Count -gt 0)) 851 | { 852 | # If last compound command then it will be a string. 853 | If($Script:CompoundCommand.GetType().Name -eq 'String') 854 | { 855 | $NextCompoundCommand = $Script:CompoundCommand.Trim() 856 | $Script:CompoundCommand = @() 857 | } 858 | Else 859 | { 860 | # If there are more commands left in compound command then it won't be a string (above IF block). 861 | # In this else block we get the next command from CompoundCommand array. 862 | $NextCompoundCommand = ([String]$Script:CompoundCommand[0]).Trim() 863 | 864 | # Set remaining commands back into CompoundCommand. 865 | $Temp = $Script:CompoundCommand 866 | $Script:CompoundCommand = @() 867 | For($i=1; $i -lt $Temp.Count; $i++) 868 | { 869 | $Script:CompoundCommand += $Temp[$i] 870 | } 871 | } 872 | $UserInput = $NextCompoundCommand 873 | } 874 | } 875 | 876 | # Handle new RegEx functionality. 877 | # Identify if there is any regex in current UserInput by removing all alphanumeric characters (and + or # which are found in launcher names). 878 | $TempUserInput = $UserInput.ToLower() 879 | @(97..122) | ForEach-Object {$TempUserInput = $TempUserInput.Replace([String]([Char]$_),'')} 880 | @(0..9) | ForEach-Object {$TempUserInput = $TempUserInput.Replace($_,'')} 881 | $TempUserInput = $TempUserInput.Replace(' ','').Replace('+','').Replace('#','').Replace('\','').Replace('/','').Replace('-','').Replace('?','') 882 | 883 | If(($TempUserInput.Length -gt 0) -AND !($UserInput.Trim().ToLower().StartsWith('set ')) -AND !($UserInput.Trim().ToLower().StartsWith('out '))) 884 | { 885 | # Replace any simple wildcard with .* syntax. 886 | $UserInput = $UserInput.Replace('.*','_____').Replace('*','.*').Replace('_____','.*') 887 | 888 | # Prepend UserInput with ^ and append with $ if not already there. 889 | If(!$UserInput.Trim().StartsWith('^') -AND !$UserInput.Trim().StartsWith('.*')) 890 | { 891 | $UserInput = '^' + $UserInput 892 | } 893 | If(!$UserInput.Trim().EndsWith('$') -AND !$UserInput.Trim().EndsWith('.*')) 894 | { 895 | $UserInput = $UserInput + '$' 896 | } 897 | 898 | # See if there are any filtered matches in the current menu. 899 | Try 900 | { 901 | $MenuFiltered = ($Menu | Where-Object {($_[1].Trim() -Match $UserInput) -AND ($_[1].Trim().Length -gt 0)} | ForEach-Object {$_[1].Trim()}) 902 | } 903 | Catch 904 | { 905 | # Output error message if Regular Expression causes error in above filtering step. 906 | # E.g. Using *+ instead of *[+] 907 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 908 | Write-Host ' The current Regular Expression caused the following error:' 909 | write-host " $_" -ForegroundColor Red 910 | } 911 | 912 | # If there are filtered matches in the current menu then randomly choose one for the UserInput value. 913 | If($MenuFiltered -ne $NULL) 914 | { 915 | # Randomly select UserInput from filtered options. 916 | $UserInput = (Get-Random -Input $MenuFiltered).Trim() 917 | 918 | # Output randomly chosen option (and filtered options selected from) if more than one option were returned from regex. 919 | If($MenuFiltered.Count -gt 1) 920 | { 921 | # Change color and verbiage if acceptable options will execute an obfuscation function. 922 | If($SelectionContainsCommand) 923 | { 924 | $ColorToOutput = 'Green' 925 | } 926 | Else 927 | { 928 | $ColorToOutput = 'Yellow' 929 | } 930 | 931 | Write-Host "`n`nRandomly selected " -NoNewline 932 | Write-Host $UserInput -NoNewline -ForegroundColor $ColorToOutput 933 | write-host " from the following filtered options: " -NoNewline 934 | 935 | For($i=0; $i -lt $MenuFiltered.Count-1; $i++) 936 | { 937 | Write-Host $MenuFiltered[$i].Trim() -NoNewLine -ForegroundColor $ColorToOutput 938 | Write-Host ', ' -NoNewLine 939 | } 940 | Write-Host $MenuFiltered[$MenuFiltered.Count-1].Trim() -NoNewLine -ForegroundColor $ColorToOutput 941 | } 942 | } 943 | } 944 | 945 | # If $UserInput is all numbers and is in a menu in $MenusWithMultiSelectNumbers 946 | $OverrideAcceptableInput = $FALSE 947 | $MenusWithMultiSelectNumbers = @('\Launcher') 948 | If(($UserInput.Trim(' 0123456789').Length -eq 0) -AND $BreadCrumb.Contains('\') -AND ($MenusWithMultiSelectNumbers -Contains $BreadCrumb.SubString(0,$BreadCrumb.LastIndexOf('\')))) 949 | { 950 | $OverrideAcceptableInput = $TRUE 951 | } 952 | 953 | If($ExitInputOptions -Contains $UserInput.ToLower()) 954 | { 955 | Return $ExitInputOptions[0] 956 | } 957 | ElseIf($MenuInputOptions -Contains $UserInput.ToLower()) 958 | { 959 | # Commands like 'back' that will return user to previous interactive menu. 960 | If($BreadCrumb.Contains('\')) {$UserInput = $BreadCrumb.SubString(0,$BreadCrumb.LastIndexOf('\')).Replace('\','_')} 961 | Else {$UserInput = ''} 962 | 963 | Return $UserInput.ToLower() 964 | } 965 | ElseIf($HomeMenuInputOptions[0] -Contains $UserInput.ToLower()) 966 | { 967 | Return $UserInput.ToLower() 968 | } 969 | ElseIf($UserInput.ToLower().StartsWith('set ')) 970 | { 971 | # Extract $UserInputOptionName and $UserInputOptionValue from $UserInput SET command. 972 | $UserInputOptionName = $NULL 973 | $UserInputOptionValue = $NULL 974 | $HasError = $FALSE 975 | 976 | $UserInputMinusSet = $UserInput.SubString(4).Trim() 977 | If($UserInputMinusSet.IndexOf(' ') -eq -1) 978 | { 979 | $HasError = $TRUE 980 | $UserInputOptionName = $UserInputMinusSet.Trim() 981 | } 982 | Else 983 | { 984 | $UserInputOptionName = $UserInputMinusSet.SubString(0,$UserInputMinusSet.IndexOf(' ')).Trim().ToLower() 985 | $UserInputOptionValue = $UserInputMinusSet.SubString($UserInputMinusSet.IndexOf(' ')).Trim() 986 | } 987 | 988 | # Validate that $UserInputOptionName is defined in $SettableInputOptions. 989 | If($SettableInputOptions -Contains $UserInputOptionName) 990 | { 991 | # Perform separate validation for $UserInputOptionValue before setting value. Set to 'emptyvalue' if no value was entered. 992 | If($UserInputOptionValue.Length -eq 0) {$UserInputOptionName = 'emptyvalue'} 993 | Switch($UserInputOptionName.ToLower()) 994 | { 995 | 'scriptpath' { 996 | If($UserInputOptionValue -AND ((Test-Path $UserInputOptionValue) -OR ($UserInputOptionValue -Match '(http|https)://'))) 997 | { 998 | # Reset ScriptBlock in case it contained a value. 999 | $Script:ScriptBlock = '' 1000 | 1001 | # Check if user-input ScriptPath is a URL or a directory. 1002 | If($UserInputOptionValue -Match '(http|https)://') 1003 | { 1004 | # ScriptPath is a URL. 1005 | 1006 | # Download content. 1007 | $Script:ScriptBlock = (New-Object Net.WebClient).DownloadString($UserInputOptionValue) 1008 | 1009 | # Set script-wide variables for future reference. 1010 | $Script:ScriptPath = $UserInputOptionValue 1011 | $Script:ObfuscatedCommand = $Script:ScriptBlock 1012 | $Script:ObfuscatedCommandHistory = @() 1013 | $Script:ObfuscatedCommandHistory += $Script:ScriptBlock 1014 | $Script:CliSyntax = @() 1015 | $Script:ExecutionCommands = @() 1016 | $Script:LauncherApplied = $FALSE 1017 | 1018 | Write-Host "`n`nSuccessfully set ScriptPath (as URL):" -ForegroundColor Cyan 1019 | Write-Host $Script:ScriptPath -ForegroundColor Magenta 1020 | } 1021 | ElseIf ((Get-Item $UserInputOptionValue) -is [System.IO.DirectoryInfo]) 1022 | { 1023 | # ScriptPath does not exist. 1024 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1025 | Write-Host ' Path is a directory instead of a file (' -NoNewLine 1026 | Write-Host "$UserInputOptionValue" -NoNewLine -ForegroundColor Cyan 1027 | Write-Host ").`n" -NoNewLine 1028 | } 1029 | Else 1030 | { 1031 | # Read contents from user-input ScriptPath value. 1032 | Get-ChildItem $UserInputOptionValue -ErrorAction Stop | Out-Null 1033 | $Script:ScriptBlock = [IO.File]::ReadAllText((Resolve-Path $UserInputOptionValue)) 1034 | 1035 | # Set script-wide variables for future reference. 1036 | $Script:ScriptPath = $UserInputOptionValue 1037 | $Script:ObfuscatedCommand = $Script:ScriptBlock 1038 | $Script:ObfuscatedCommandHistory = @() 1039 | $Script:ObfuscatedCommandHistory += $Script:ScriptBlock 1040 | $Script:CliSyntax = @() 1041 | $Script:ExecutionCommands = @() 1042 | $Script:LauncherApplied = $FALSE 1043 | 1044 | Write-Host "`n`nSuccessfully set ScriptPath:" -ForegroundColor Cyan 1045 | Write-Host $Script:ScriptPath -ForegroundColor Magenta 1046 | } 1047 | } 1048 | Else 1049 | { 1050 | # ScriptPath not found (failed Test-Path). 1051 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1052 | Write-Host ' Path not found (' -NoNewLine 1053 | Write-Host "$UserInputOptionValue" -NoNewLine -ForegroundColor Cyan 1054 | Write-Host ").`n" -NoNewLine 1055 | } 1056 | } 1057 | 'scriptblock' { 1058 | # Remove evenly paired {} '' or "" if user includes it around their scriptblock input. 1059 | ForEach($Char in @(@('{','}'),@('"','"'),@("'","'"))) 1060 | { 1061 | While($UserInputOptionValue.StartsWith($Char[0]) -AND $UserInputOptionValue.EndsWith($Char[1])) 1062 | { 1063 | $UserInputOptionValue = $UserInputOptionValue.SubString(1,$UserInputOptionValue.Length-2).Trim() 1064 | } 1065 | } 1066 | 1067 | # Check if input is PowerShell encoded command syntax so we can decode for scriptblock. 1068 | If($UserInputOptionValue -Match 'powershell(.exe | )\s*-(e |ec |en |enc |enco |encod |encode)\s*["'']*[a-z=]') 1069 | { 1070 | # Extract encoded command. 1071 | $EncodedCommand = $UserInputOptionValue.SubString($UserInputOptionValue.ToLower().IndexOf(' -e')+3) 1072 | $EncodedCommand = $EncodedCommand.SubString($EncodedCommand.IndexOf(' ')).Trim(" '`"") 1073 | 1074 | # Decode Unicode-encoded $EncodedCommand 1075 | $UserInputOptionValue = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($EncodedCommand)) 1076 | } 1077 | 1078 | # Set script-wide variables for future reference. 1079 | $Script:ScriptPath = 'N/A' 1080 | $Script:ScriptBlock = $UserInputOptionValue 1081 | $Script:ObfuscatedCommand = $UserInputOptionValue 1082 | $Script:ObfuscatedCommandHistory = @() 1083 | $Script:ObfuscatedCommandHistory += $UserInputOptionValue 1084 | $Script:CliSyntax = @() 1085 | $Script:ExecutionCommands = @() 1086 | $Script:LauncherApplied = $FALSE 1087 | 1088 | Write-Host "`n`nSuccessfully set ScriptBlock:" -ForegroundColor Cyan 1089 | Write-Host $Script:ScriptBlock -ForegroundColor Magenta 1090 | } 1091 | 'emptyvalue' { 1092 | # No OPTIONVALUE was entered after OPTIONNAME. 1093 | $HasError = $TRUE 1094 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1095 | Write-Host ' No value was entered after' -NoNewLine 1096 | Write-Host ' SCRIPTBLOCK/SCRIPTPATH' -NoNewLine -ForegroundColor Cyan 1097 | Write-Host '.' -NoNewLine 1098 | } 1099 | default {Write-Error "An invalid OPTIONNAME ($UserInputOptionName) was passed to switch block."; Exit} 1100 | } 1101 | } 1102 | Else 1103 | { 1104 | $HasError = $TRUE 1105 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1106 | Write-Host ' OPTIONNAME' -NoNewLine 1107 | Write-Host " $UserInputOptionName" -NoNewLine -ForegroundColor Cyan 1108 | Write-Host " is not a settable option." -NoNewLine 1109 | } 1110 | 1111 | If($HasError) 1112 | { 1113 | Write-Host "`n Correct syntax is" -NoNewLine 1114 | Write-Host ' SET OPTIONNAME VALUE' -NoNewLine -ForegroundColor Green 1115 | Write-Host '.' -NoNewLine 1116 | 1117 | Write-Host "`n Enter" -NoNewLine 1118 | Write-Host ' SHOW OPTIONS' -NoNewLine -ForegroundColor Yellow 1119 | Write-Host ' for more details.' 1120 | } 1121 | } 1122 | ElseIf(($AcceptableInput -Contains $UserInput) -OR ($OverrideAcceptableInput)) 1123 | { 1124 | # User input matches $AcceptableInput extracted from the current $Menu, so decide if: 1125 | # 1) an obfuscation function needs to be called and remain in current interactive prompt, or 1126 | # 2) return value to enter into a new interactive prompt. 1127 | 1128 | # Format breadcrumb trail to successfully retrieve the next interactive prompt. 1129 | $UserInput = $BreadCrumb.Trim('\').Replace('\','_') + '_' + $UserInput 1130 | If($BreadCrumb.StartsWith('\')) {$UserInput = '_' + $UserInput} 1131 | 1132 | # If the current selection contains a command to execute then continue. Otherwise return to go to another menu. 1133 | If($SelectionContainsCommand) 1134 | { 1135 | # Make sure user has entered command or path to script. 1136 | If($Script:ObfuscatedCommand -ne $NULL) 1137 | { 1138 | # Iterate through lines in $Menu to extract command for the current selection in $UserInput. 1139 | ForEach($Line in $Menu) 1140 | { 1141 | If($Line[1].Trim(' ') -eq $UserInput.SubString($UserInput.LastIndexOf('_')+1)) {$CommandToExec = $Line[3]; Continue} 1142 | } 1143 | 1144 | If(!$OverrideAcceptableInput) 1145 | { 1146 | # Extract arguments from $CommandToExec. 1147 | $Function = $CommandToExec[0] 1148 | $Token = $CommandToExec[1] 1149 | $ObfLevel = $CommandToExec[2] 1150 | } 1151 | Else 1152 | { 1153 | # Overload above arguments if $OverrideAcceptableInput is $TRUE, and extract $Function from $BreadCrumb 1154 | Switch($BreadCrumb.ToLower()) 1155 | { 1156 | '\launcher\ps' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 1} 1157 | '\launcher\cmd' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 2} 1158 | '\launcher\wmic' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 3} 1159 | '\launcher\rundll' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 4} 1160 | '\launcher\var+' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 5} 1161 | '\launcher\stdin+' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 6} 1162 | '\launcher\clip+' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 7} 1163 | '\launcher\var++' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 8} 1164 | '\launcher\stdin++' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 9} 1165 | '\launcher\clip++' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 10} 1166 | '\launcher\rundll++' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 11} 1167 | '\launcher\mshta++' {$Function = 'Out-PowerShellLauncher'; $ObfLevel = 12} 1168 | default {Write-Error "An invalid value ($($BreadCrumb.ToLower())) was passed to switch block for setting `$Function when `$OverrideAcceptableInput -eq `$TRUE."; Exit} 1169 | } 1170 | # Extract $ObfLevel from first element in array (in case 0th element is used for informational purposes), and extract $Token from $BreadCrumb. 1171 | $ObfLevel = $Menu[1][3][2] 1172 | $Token = $UserInput.SubString($UserInput.LastIndexOf('_')+1) 1173 | } 1174 | 1175 | # Convert ObfuscatedCommand (string) to ScriptBlock for next obfuscation function. 1176 | If(!($Script:LauncherApplied)) 1177 | { 1178 | $ObfCommandScriptBlock = $ExecutionContext.InvokeCommand.NewScriptBlock($Script:ObfuscatedCommand) 1179 | } 1180 | 1181 | # Validate that user has set SCRIPTPATH or SCRIPTBLOCK (by seeing if $Script:ObfuscatedCommand is empty). 1182 | If($Script:ObfuscatedCommand -eq '') 1183 | { 1184 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1185 | Write-Host " Cannot execute obfuscation commands without setting ScriptPath or ScriptBlock values in SHOW OPTIONS menu. Set these by executing" -NoNewLine 1186 | Write-Host ' SET SCRIPTBLOCK script_block_or_command' -NoNewLine -ForegroundColor Green 1187 | Write-Host ' or' -NoNewLine 1188 | Write-Host ' SET SCRIPTPATH path_to_script_or_URL' -NoNewLine -ForegroundColor Green 1189 | Write-Host '.' 1190 | Continue 1191 | } 1192 | 1193 | # Save current ObfuscatedCommand to see if obfuscation was successful (i.e. no warnings prevented obfuscation from occurring). 1194 | $ObfuscatedCommandBefore = $Script:ObfuscatedCommand 1195 | $CmdToPrint = $NULL 1196 | If($Function -eq 'Out-ObfuscatedAst' -AND $PSVersionTable.PSVersion.Major -lt 3) 1197 | { 1198 | $AstPS3ErrorMessage = "AST obfuscation can only be used with PS3.0+. Update to PS3.0 or higher to use AST obfuscation." 1199 | If ($Script:QuietWasSpecified) 1200 | { 1201 | Write-Error $AstPS3ErrorMessage 1202 | } 1203 | Else 1204 | { 1205 | Write-Host "`n`nERROR: " -NoNewLine -ForegroundColor Red 1206 | Write-Host $AstPS3ErrorMessage -NoNewLine 1207 | } 1208 | } 1209 | ElseIf($Script:LauncherApplied) 1210 | { 1211 | If($Function -eq 'Out-PowerShellLauncher') 1212 | { 1213 | $ErrorMessage = ' You have already applied a launcher to ObfuscatedCommand.' 1214 | } 1215 | Else 1216 | { 1217 | $ErrorMessage = ' You cannot obfuscate after applying a Launcher to ObfuscatedCommand.' 1218 | } 1219 | 1220 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1221 | Write-Host $ErrorMessage -NoNewLine 1222 | Write-Host "`n Enter" -NoNewLine 1223 | Write-Host ' UNDO' -NoNewLine -ForegroundColor Yellow 1224 | Write-Host " to remove the launcher from ObfuscatedCommand.`n" -NoNewLine 1225 | } 1226 | Else 1227 | { 1228 | # Switch block to route to the correct function. 1229 | Switch($Function) 1230 | { 1231 | 'Out-ObfuscatedTokenCommand' { 1232 | $Script:ObfuscatedCommand = Out-ObfuscatedTokenCommand -ScriptBlock $ObfCommandScriptBlock $Token $ObfLevel 1233 | $CmdToPrint = @("Out-ObfuscatedTokenCommand -ScriptBlock "," '$Token' $ObfLevel") 1234 | } 1235 | 'Out-ObfuscatedTokenCommandAll' { 1236 | $Script:ObfuscatedCommand = Out-ObfuscatedTokenCommand -ScriptBlock $ObfCommandScriptBlock 1237 | $CmdToPrint = @("Out-ObfuscatedTokenCommand -ScriptBlock ","") 1238 | } 1239 | 'Out-ObfuscatedAst' { 1240 | $Script:ObfuscatedCommand = Out-ObfuscatedAst -ScriptBlock $ObfCommandScriptBlock -AstTypesToObfuscate $Token 1241 | $CmdToPrint = @("Out-ObfuscatedAst -ScriptBlock ","") 1242 | } 1243 | 'Out-ObfuscatedStringCommand' { 1244 | $Script:ObfuscatedCommand = Out-ObfuscatedStringCommand -ScriptBlock $ObfCommandScriptBlock $ObfLevel 1245 | $CmdToPrint = @("Out-ObfuscatedStringCommand -ScriptBlock "," $ObfLevel") 1246 | } 1247 | 'Out-EncodedAsciiCommand' { 1248 | $Script:ObfuscatedCommand = Out-EncodedAsciiCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1249 | $CmdToPrint = @("Out-EncodedAsciiCommand -ScriptBlock "," -PassThru") 1250 | } 1251 | 'Out-EncodedHexCommand' { 1252 | $Script:ObfuscatedCommand = Out-EncodedHexCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1253 | $CmdToPrint = @("Out-EncodedHexCommand -ScriptBlock "," -PassThru") 1254 | } 1255 | 'Out-EncodedOctalCommand' { 1256 | $Script:ObfuscatedCommand = Out-EncodedOctalCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1257 | $CmdToPrint = @("Out-EncodedOctalCommand -ScriptBlock "," -PassThru") 1258 | } 1259 | 'Out-EncodedBinaryCommand' { 1260 | $Script:ObfuscatedCommand = Out-EncodedBinaryCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1261 | $CmdToPrint = @("Out-EncodedBinaryCommand -ScriptBlock "," -PassThru") 1262 | } 1263 | 'Out-SecureStringCommand' { 1264 | $Script:ObfuscatedCommand = Out-SecureStringCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1265 | $CmdToPrint = @("Out-SecureStringCommand -ScriptBlock "," -PassThru") 1266 | } 1267 | 'Out-EncodedBXORCommand' { 1268 | $Script:ObfuscatedCommand = Out-EncodedBXORCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1269 | $CmdToPrint = @("Out-EncodedBXORCommand -ScriptBlock "," -PassThru") 1270 | } 1271 | 'Out-EncodedSpecialCharOnlyCommand' { 1272 | $Script:ObfuscatedCommand = Out-EncodedSpecialCharOnlyCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1273 | $CmdToPrint = @("Out-EncodedSpecialCharOnlyCommand -ScriptBlock "," -PassThru") 1274 | } 1275 | 'Out-EncodedWhitespaceCommand' { 1276 | $Script:ObfuscatedCommand = Out-EncodedWhitespaceCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1277 | $CmdToPrint = @("Out-EncodedWhitespaceCommand -ScriptBlock "," -PassThru") 1278 | } 1279 | 'Out-CompressedCommand' { 1280 | $Script:ObfuscatedCommand = Out-CompressedCommand -ScriptBlock $ObfCommandScriptBlock -PassThru 1281 | $CmdToPrint = @("Out-CompressedCommand -ScriptBlock "," -PassThru") 1282 | } 1283 | 'Out-PowerShellLauncher' { 1284 | # Extract numbers from string so we can output proper flag syntax in ExecutionCommands history. 1285 | $SwitchesAsStringArray = [char[]]$Token | Sort-Object -Unique | Where-Object {$_ -ne ' '} 1286 | 1287 | If($SwitchesAsStringArray -Contains '0') 1288 | { 1289 | $CmdToPrint = @("Out-PowerShellLauncher -ScriptBlock "," $ObfLevel") 1290 | } 1291 | Else 1292 | { 1293 | $HasWindowStyle = $FALSE 1294 | $SwitchesToPrint = @() 1295 | ForEach($Value in $SwitchesAsStringArray) 1296 | { 1297 | Switch($Value) 1298 | { 1299 | 1 {$SwitchesToPrint += '-NoExit'} 1300 | 2 {$SwitchesToPrint += '-NonInteractive'} 1301 | 3 {$SwitchesToPrint += '-NoLogo'} 1302 | 4 {$SwitchesToPrint += '-NoProfile'} 1303 | 5 {$SwitchesToPrint += '-Command'} 1304 | 6 {If(!$HasWindowStyle) {$SwitchesToPrint += '-WindowStyle Hidden'; $HasWindowStyle = $TRUE}} 1305 | 7 {$SwitchesToPrint += '-ExecutionPolicy Bypass'} 1306 | 8 {$SwitchesToPrint += '-Wow64'} 1307 | default {Write-Error "An invalid `$SwitchesAsString value ($Value) was passed to switch block."; Exit;} 1308 | } 1309 | } 1310 | $SwitchesToPrint = $SwitchesToPrint -Join ' ' 1311 | $CmdToPrint = @("Out-PowerShellLauncher -ScriptBlock "," $SwitchesToPrint $ObfLevel") 1312 | } 1313 | 1314 | $Script:ObfuscatedCommand = Out-PowerShellLauncher -ScriptBlock $ObfCommandScriptBlock -SwitchesAsString $Token $ObfLevel 1315 | 1316 | # Only set LauncherApplied to true if before/after are different (i.e. no warnings prevented launcher from being applied). 1317 | If($ObfuscatedCommandBefore -ne $Script:ObfuscatedCommand) 1318 | { 1319 | $Script:LauncherApplied = $TRUE 1320 | } 1321 | } 1322 | default {Write-Error "An invalid `$Function value ($Function) was passed to switch block."; Exit;} 1323 | } 1324 | 1325 | If(($Script:ObfuscatedCommand -ceq $ObfuscatedCommandBefore) -AND ($MenuName.StartsWith('_Token_'))) 1326 | { 1327 | Write-Host "`nWARNING:" -NoNewLine -ForegroundColor Red 1328 | Write-Host " There were not any" -NoNewLine 1329 | If($BreadCrumb.SubString($BreadCrumb.LastIndexOf('\')+1).ToLower() -ne 'all') {Write-Host " $($BreadCrumb.SubString($BreadCrumb.LastIndexOf('\')+1))" -NoNewLine -ForegroundColor Yellow} 1330 | Write-Host " tokens to further obfuscate, so nothing changed." 1331 | } 1332 | Else 1333 | { 1334 | # Add to $Script:ObfuscatedCommandHistory if a change took place for the current ObfuscatedCommand. 1335 | $Script:ObfuscatedCommandHistory += , $Script:ObfuscatedCommand 1336 | 1337 | # Convert UserInput to CLI syntax to store in CliSyntax variable if obfuscation occurred. 1338 | $CliSyntaxCurrentCommand = $UserInput.Trim('_ ').Replace('_','\') 1339 | 1340 | # Add CLI command syntax to $Script:CliSyntax to maintain a history of commands to arrive at current obfuscated command for CLI syntax. 1341 | $Script:CliSyntax += $CliSyntaxCurrentCommand 1342 | 1343 | # Add execution syntax to $Script:ExecutionCommands to maintain a history of commands to arrive at current obfuscated command. 1344 | $Script:ExecutionCommands += ($CmdToPrint[0] + '$ScriptBlock' + $CmdToPrint[1]) 1345 | 1346 | # Output syntax of CLI syntax and full command we executed in above Switch block. 1347 | Write-Host "`nExecuted:`t" 1348 | Write-Host " CLI: " -NoNewline 1349 | Write-Host $CliSyntaxCurrentCommand -ForegroundColor Cyan 1350 | Write-Host " FULL: " -NoNewline 1351 | Write-Host $CmdToPrint[0] -NoNewLine -ForegroundColor Cyan 1352 | Write-Host '$ScriptBlock' -NoNewLine -ForegroundColor Magenta 1353 | Write-Host $CmdToPrint[1] -ForegroundColor Cyan 1354 | 1355 | # Output obfuscation result. 1356 | Write-Host "`nResult:`t" 1357 | Out-ScriptContents $Script:ObfuscatedCommand -PrintWarning 1358 | } 1359 | } 1360 | } 1361 | } 1362 | Else 1363 | { 1364 | Return $UserInput 1365 | } 1366 | } 1367 | Else 1368 | { 1369 | If ($MenuInputOptionsShowHelp[0] -Contains $UserInput) {Show-HelpMenu} 1370 | ElseIf($MenuInputOptionsShowOptions[0] -Contains $UserInput) {Show-OptionsMenu} 1371 | ElseIf($TutorialInputOptions[0] -Contains $UserInput) {Show-Tutorial} 1372 | ElseIf($ClearScreenInputOptions[0] -Contains $UserInput) {Clear-Host} 1373 | # For Version 1.0 ASCII art is not necessary. 1374 | #ElseIf($ShowAsciiArtInputOptions[0] -Contains $UserInput) {Show-AsciiArt -Random} 1375 | ElseIf($ResetObfuscationInputOptions[0] -Contains $UserInput) 1376 | { 1377 | If(($Script:ObfuscatedCommand -ne $NULL) -AND ($Script:ObfuscatedCommand.Length -eq 0)) 1378 | { 1379 | Write-Host "`n`nWARNING:" -NoNewLine -ForegroundColor Red 1380 | Write-Host " ObfuscatedCommand has not been set. There is nothing to reset." 1381 | } 1382 | ElseIf($Script:ObfuscatedCommand -ceq $Script:ScriptBlock) 1383 | { 1384 | Write-Host "`n`nWARNING:" -NoNewLine -ForegroundColor Red 1385 | Write-Host " No obfuscation has been applied to ObfuscatedCommand. There is nothing to reset." 1386 | } 1387 | Else 1388 | { 1389 | $Script:LauncherApplied = $FALSE 1390 | $Script:ObfuscatedCommand = $Script:ScriptBlock 1391 | $Script:ObfuscatedCommandHistory = @($Script:ScriptBlock) 1392 | $Script:CliSyntax = @() 1393 | $Script:ExecutionCommands = @() 1394 | 1395 | Write-Host "`n`nSuccessfully reset ObfuscatedCommand." -ForegroundColor Cyan 1396 | } 1397 | } 1398 | ElseIf($UndoObfuscationInputOptions[0] -Contains $UserInput) 1399 | { 1400 | If(($Script:ObfuscatedCommand -ne $NULL) -AND ($Script:ObfuscatedCommand.Length -eq 0)) 1401 | { 1402 | Write-Host "`n`nWARNING:" -NoNewLine -ForegroundColor Red 1403 | Write-Host " ObfuscatedCommand has not been set. There is nothing to undo." 1404 | } 1405 | ElseIf($Script:ObfuscatedCommand -ceq $Script:ScriptBlock) 1406 | { 1407 | Write-Host "`n`nWARNING:" -NoNewLine -ForegroundColor Red 1408 | Write-Host " No obfuscation has been applied to ObfuscatedCommand. There is nothing to undo." 1409 | } 1410 | Else 1411 | { 1412 | # Set ObfuscatedCommand to the last state in ObfuscatedCommandHistory. 1413 | $Script:ObfuscatedCommand = $Script:ObfuscatedCommandHistory[$Script:ObfuscatedCommandHistory.Count-2] 1414 | 1415 | # Remove the last state from ObfuscatedCommandHistory. 1416 | $Temp = $Script:ObfuscatedCommandHistory 1417 | $Script:ObfuscatedCommandHistory = @() 1418 | For($i=0; $i -lt $Temp.Count-1; $i++) 1419 | { 1420 | $Script:ObfuscatedCommandHistory += $Temp[$i] 1421 | } 1422 | 1423 | # Remove last command from CliSyntax. Trim all trailing OUT or CLIP commands until an obfuscation command is removed. 1424 | $CliSyntaxCount = $Script:CliSyntax.Count 1425 | While(($Script:CliSyntax[$CliSyntaxCount-1] -Match '^(clip|out )') -AND ($CliSyntaxCount -gt 0)) 1426 | { 1427 | $CliSyntaxCount-- 1428 | } 1429 | $Temp = $Script:CliSyntax 1430 | $Script:CliSyntax = @() 1431 | For($i=0; $i -lt $CliSyntaxCount-1; $i++) 1432 | { 1433 | $Script:CliSyntax += $Temp[$i] 1434 | } 1435 | 1436 | # Remove last command from ExecutionCommands. 1437 | $Temp = $Script:ExecutionCommands 1438 | $Script:ExecutionCommands = @() 1439 | For($i=0; $i -lt $Temp.Count-1; $i++) 1440 | { 1441 | $Script:ExecutionCommands += $Temp[$i] 1442 | } 1443 | 1444 | # If this is removing a launcher then we must change the launcher state so we can continue obfuscating. 1445 | If($Script:LauncherApplied) 1446 | { 1447 | $Script:LauncherApplied = $FALSE 1448 | Write-Host "`n`nSuccessfully removed launcher from ObfuscatedCommand." -ForegroundColor Cyan 1449 | } 1450 | Else 1451 | { 1452 | Write-Host "`n`nSuccessfully removed last obfuscation from ObfuscatedCommand." -ForegroundColor Cyan 1453 | } 1454 | } 1455 | } 1456 | ElseIf(($OutputToDiskInputOptions[0] -Contains $UserInput) -OR ($OutputToDiskInputOptions[0] -Contains $UserInput.Trim().Split(' ')[0])) 1457 | { 1458 | If(($Script:ObfuscatedCommand -ne '') -AND ($Script:ObfuscatedCommand -ceq $Script:ScriptBlock)) 1459 | { 1460 | Write-Host "`n`nWARNING:" -NoNewLine -ForegroundColor Red 1461 | Write-Host " You haven't applied any obfuscation.`n Just enter" -NoNewLine 1462 | Write-Host " SHOW OPTIONS" -NoNewLine -ForegroundColor Yellow 1463 | Write-Host " and look at ObfuscatedCommand." 1464 | } 1465 | ElseIf($Script:ObfuscatedCommand -ne '') 1466 | { 1467 | # Get file path information from compound user input (e.g. OUT C:\FILENAME.TXT). 1468 | If($UserInput.Trim().Split(' ').Count -gt 1) 1469 | { 1470 | # Get file path information from user input. 1471 | $UserInputOutputFilePath = $UserInput.Trim().SubString(4).Trim() 1472 | Write-Host '' 1473 | } 1474 | Else 1475 | { 1476 | # Get file path information from user interactively. 1477 | $UserInputOutputFilePath = Read-Host "`n`nEnter path for output file (or leave blank for default)" 1478 | } 1479 | # Decipher if user input a full file path, just a file name or nothing (default). 1480 | If($UserInputOutputFilePath.Trim() -eq '') 1481 | { 1482 | # User did not input anything so use default filename and current directory of this script. 1483 | $OutputFilePath = "$ScriptDir\Obfuscated_Command.txt" 1484 | } 1485 | ElseIf(!($UserInputOutputFilePath.Contains('\')) -AND !($UserInputOutputFilePath.Contains('/'))) 1486 | { 1487 | # User input is not a file path so treat it as a filename and use current directory of this script. 1488 | $OutputFilePath = "$ScriptDir\$($UserInputOutputFilePath.Trim())" 1489 | } 1490 | Else 1491 | { 1492 | # User input is a full file path. 1493 | $OutputFilePath = $UserInputOutputFilePath 1494 | } 1495 | 1496 | # Write ObfuscatedCommand out to disk. 1497 | $Script:ObfuscatedCommand | Out-File $OutputFilePath -Encoding ASCII 1498 | 1499 | If($Script:LauncherApplied -AND (Test-Path $OutputFilePath)) 1500 | { 1501 | $Script:CliSyntax += "out $OutputFilePath" 1502 | Write-Host "`nSuccessfully output ObfuscatedCommand to" -NoNewLine -ForegroundColor Cyan 1503 | Write-Host " $OutputFilePath" -NoNewLine -ForegroundColor Yellow 1504 | Write-Host ".`nA Launcher has been applied so this script cannot be run as a standalone .ps1 file." -ForegroundColor Cyan 1505 | If($Env:windir) { C:\Windows\Notepad.exe $OutputFilePath } 1506 | } 1507 | ElseIf(!$Script:LauncherApplied -AND (Test-Path $OutputFilePath)) 1508 | { 1509 | $Script:CliSyntax += "out $OutputFilePath" 1510 | Write-Host "`nSuccessfully output ObfuscatedCommand to" -NoNewLine -ForegroundColor Cyan 1511 | Write-Host " $OutputFilePath" -NoNewLine -ForegroundColor Yellow 1512 | Write-Host "." -ForegroundColor Cyan 1513 | If($Env:windir) { C:\Windows\Notepad.exe $OutputFilePath } 1514 | } 1515 | Else 1516 | { 1517 | Write-Host "`nERROR: Unable to write ObfuscatedCommand out to" -NoNewLine -ForegroundColor Red 1518 | Write-Host " $OutputFilePath" -NoNewLine -ForegroundColor Yellow 1519 | } 1520 | } 1521 | ElseIf($Script:ObfuscatedCommand -eq '') 1522 | { 1523 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1524 | Write-Host " There isn't anything to write out to disk.`n Just enter" -NoNewLine 1525 | Write-Host " SHOW OPTIONS" -NoNewLine -ForegroundColor Yellow 1526 | Write-Host " and look at ObfuscatedCommand." 1527 | } 1528 | } 1529 | ElseIf($CopyToClipboardInputOptions[0] -Contains $UserInput) 1530 | { 1531 | If(($Script:ObfuscatedCommand -ne '') -AND ($Script:ObfuscatedCommand -ceq $Script:ScriptBlock)) 1532 | { 1533 | Write-Host "`n`nWARNING:" -NoNewLine -ForegroundColor Red 1534 | Write-Host " You haven't applied any obfuscation.`n Just enter" -NoNewLine 1535 | Write-Host " SHOW OPTIONS" -NoNewLine -ForegroundColor Yellow 1536 | Write-Host " and look at ObfuscatedCommand." 1537 | } 1538 | ElseIf($Script:ObfuscatedCommand -ne '') 1539 | { 1540 | # Copy ObfuscatedCommand to clipboard. 1541 | # Try-Catch block introduced since PowerShell v2.0 without -STA defined will not be able to perform clipboard functionality. 1542 | Try 1543 | { 1544 | $Null = [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 1545 | [Windows.Forms.Clipboard]::SetText($Script:ObfuscatedCommand) 1546 | 1547 | If($Script:LauncherApplied) 1548 | { 1549 | Write-Host "`n`nSuccessfully copied ObfuscatedCommand to clipboard." -ForegroundColor Cyan 1550 | } 1551 | Else 1552 | { 1553 | Write-Host "`n`nSuccessfully copied ObfuscatedCommand to clipboard.`nNo Launcher has been applied, so command can only be pasted into powershell.exe." -ForegroundColor Cyan 1554 | } 1555 | } 1556 | Catch 1557 | { 1558 | $ErrorMessage = "Clipboard functionality will not work in PowerShell version $($PsVersionTable.PsVersion.Major) unless you add -STA (Single-Threaded Apartment) execution flag to powershell.exe." 1559 | 1560 | If((Get-Command Write-Host).CommandType -ne 'Cmdlet') 1561 | { 1562 | # Retrieving Write-Host and Start-Sleep Cmdlets to get around the current proxy functions of Write-Host and Start-Sleep that are overloaded if -Quiet flag was used. 1563 | . ((Get-Command Write-Host) | Where-Object {$_.CommandType -eq 'Cmdlet'}) "`n`nWARNING: " -NoNewLine -ForegroundColor Red 1564 | . ((Get-Command Write-Host) | Where-Object {$_.CommandType -eq 'Cmdlet'}) $ErrorMessage -NoNewLine 1565 | 1566 | . ((Get-Command Start-Sleep) | Where-Object {$_.CommandType -eq 'Cmdlet'}) 2 1567 | } 1568 | Else 1569 | { 1570 | Write-Host "`n`nWARNING: " -NoNewLine -ForegroundColor Red 1571 | Write-Host $ErrorMessage 1572 | 1573 | If($Script:CliSyntax -gt 0) {Start-Sleep 2} 1574 | } 1575 | } 1576 | 1577 | $Script:CliSyntax += 'clip' 1578 | } 1579 | ElseIf($Script:ObfuscatedCommand -eq '') 1580 | { 1581 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1582 | Write-Host " There isn't anything to copy to your clipboard.`n Just enter" -NoNewLine 1583 | Write-Host " SHOW OPTIONS" -NoNewLine -ForegroundColor Yellow 1584 | Write-Host " and look at ObfuscatedCommand." -NoNewLine 1585 | } 1586 | 1587 | } 1588 | ElseIf($ExecutionInputOptions[0] -Contains $UserInput) 1589 | { 1590 | If($Script:LauncherApplied) 1591 | { 1592 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1593 | Write-Host " Cannot execute because you have applied a Launcher.`n Enter" -NoNewLine 1594 | Write-Host " COPY" -NoNewLine -ForeGroundColor Yellow 1595 | Write-Host "/" -NoNewLine 1596 | Write-Host "CLIP" -NoNewLine -ForeGroundColor Yellow 1597 | Write-Host " and paste into cmd.exe.`n Or enter" -NoNewLine 1598 | Write-Host " UNDO" -NoNewLine -ForeGroundColor Yellow 1599 | Write-Host " to remove the Launcher from ObfuscatedCommand." 1600 | } 1601 | ElseIf($Script:ObfuscatedCommand -ne '') 1602 | { 1603 | If($Script:ObfuscatedCommand -ceq $Script:ScriptBlock) {Write-Host "`n`nInvoking (though you haven't obfuscated anything yet):"} 1604 | Else {Write-Host "`n`nInvoking:"} 1605 | 1606 | Out-ScriptContents $Script:ObfuscatedCommand 1607 | Write-Host '' 1608 | $null = Invoke-Expression $Script:ObfuscatedCommand 1609 | } 1610 | Else { 1611 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1612 | Write-Host " Cannot execute because you have not set ScriptPath or ScriptBlock.`n Enter" -NoNewline 1613 | Write-Host " SHOW OPTIONS" -NoNewLine -ForegroundColor Yellow 1614 | Write-Host " to set ScriptPath or ScriptBlock." 1615 | } 1616 | } 1617 | Else 1618 | { 1619 | Write-Host "`n`nERROR:" -NoNewLine -ForegroundColor Red 1620 | Write-Host " You entered an invalid option. Enter" -NoNewLine 1621 | Write-Host " HELP" -NoNewLine -ForegroundColor Yellow 1622 | Write-Host " for more information." 1623 | 1624 | # If the failed input was part of $Script:CompoundCommand then cancel out the rest of the compound command so it is not further processed. 1625 | If($Script:CompoundCommand.Count -gt 0) 1626 | { 1627 | $Script:CompoundCommand = @() 1628 | } 1629 | 1630 | # Output all available/acceptable options for current menu if invalid input was entered. 1631 | If($AcceptableInput.Count -gt 1) 1632 | { 1633 | $Message = 'Valid options for current menu include:' 1634 | } 1635 | Else 1636 | { 1637 | $Message = 'Valid option for current menu includes:' 1638 | } 1639 | Write-Host " $Message " -NoNewLine 1640 | 1641 | $Counter=0 1642 | ForEach($AcceptableOption in $AcceptableInput) 1643 | { 1644 | $Counter++ 1645 | 1646 | # Change color and verbiage if acceptable options will execute an obfuscation function. 1647 | If($SelectionContainsCommand) 1648 | { 1649 | $ColorToOutput = 'Green' 1650 | } 1651 | Else 1652 | { 1653 | $ColorToOutput = 'Yellow' 1654 | } 1655 | 1656 | Write-Host $AcceptableOption -NoNewLine -ForegroundColor $ColorToOutput 1657 | If(($Counter -lt $AcceptableInput.Length) -AND ($AcceptableOption.Length -gt 0)) 1658 | { 1659 | Write-Host ', ' -NoNewLine 1660 | } 1661 | } 1662 | Write-Host '' 1663 | } 1664 | } 1665 | } 1666 | 1667 | Return $UserInput.ToLower() 1668 | } 1669 | 1670 | 1671 | Function Show-OptionsMenu 1672 | { 1673 | <# 1674 | .SYNOPSIS 1675 | 1676 | HELPER FUNCTION :: Displays options menu for Invoke-Obfuscation. 1677 | 1678 | Invoke-Obfuscation Function: Show-OptionsMenu 1679 | Author: Daniel Bohannon (@danielhbohannon) 1680 | License: Apache License, Version 2.0 1681 | Required Dependencies: None 1682 | Optional Dependencies: None 1683 | 1684 | .DESCRIPTION 1685 | 1686 | Show-OptionsMenu displays options menu for Invoke-Obfuscation. 1687 | 1688 | .EXAMPLE 1689 | 1690 | C:\PS> Show-OptionsMenu 1691 | 1692 | .NOTES 1693 | 1694 | This is a personal project developed by Daniel Bohannon while an employee at MANDIANT, A FireEye Company. 1695 | 1696 | .LINK 1697 | 1698 | http://www.danielbohannon.com 1699 | #> 1700 | 1701 | # Set potentially-updated script-level values in $Script:OptionsMenu before displaying. 1702 | $Counter = 0 1703 | ForEach($Line in $Script:OptionsMenu) 1704 | { 1705 | If($Line[0].ToLower().Trim() -eq 'scriptpath') {$Script:OptionsMenu[$Counter][1] = $Script:ScriptPath} 1706 | If($Line[0].ToLower().Trim() -eq 'scriptblock') {$Script:OptionsMenu[$Counter][1] = $Script:ScriptBlock} 1707 | If($Line[0].ToLower().Trim() -eq 'commandlinesyntax') {$Script:OptionsMenu[$Counter][1] = $Script:CliSyntax} 1708 | If($Line[0].ToLower().Trim() -eq 'executioncommands') {$Script:OptionsMenu[$Counter][1] = $Script:ExecutionCommands} 1709 | If($Line[0].ToLower().Trim() -eq 'obfuscatedcommand') 1710 | { 1711 | # Only add obfuscatedcommand if it is different than scriptblock (to avoid showing obfuscatedcommand before it has been obfuscated). 1712 | If($Script:ObfuscatedCommand -cne $Script:ScriptBlock) {$Script:OptionsMenu[$Counter][1] = $Script:ObfuscatedCommand} 1713 | Else {$Script:OptionsMenu[$Counter][1] = ''} 1714 | } 1715 | If($Line[0].ToLower().Trim() -eq 'obfuscationlength') 1716 | { 1717 | # Only set/display ObfuscationLength if there is an obfuscated command. 1718 | If(($Script:ObfuscatedCommand.Length -gt 0) -AND ($Script:ObfuscatedCommand -cne $Script:ScriptBlock)) {$Script:OptionsMenu[$Counter][1] = $Script:ObfuscatedCommand.Length} 1719 | Else {$Script:OptionsMenu[$Counter][1] = ''} 1720 | } 1721 | 1722 | $Counter++ 1723 | } 1724 | 1725 | # Output menu. 1726 | Write-Host "`n`nSHOW OPTIONS" -NoNewLine -ForegroundColor Cyan 1727 | Write-Host " ::" -NoNewLine 1728 | Write-Host " Yellow" -NoNewLine -ForegroundColor Yellow 1729 | Write-Host " options can be set by entering" -NoNewLine 1730 | Write-Host " SET OPTIONNAME VALUE" -NoNewLine -ForegroundColor Green 1731 | Write-Host ".`n" 1732 | ForEach($Option in $Script:OptionsMenu) 1733 | { 1734 | $OptionTitle = $Option[0] 1735 | $OptionValue = $Option[1] 1736 | $CanSetValue = $Option[2] 1737 | 1738 | Write-Host $LineSpacing -NoNewLine 1739 | 1740 | # For options that can be set by user, output as Yellow. 1741 | If($CanSetValue) {Write-Host $OptionTitle -NoNewLine -ForegroundColor Yellow} 1742 | Else {Write-Host $OptionTitle -NoNewLine} 1743 | Write-Host ": " -NoNewLine 1744 | 1745 | # Handle coloring and multi-value output for ExecutionCommands and ObfuscationLength. 1746 | If($OptionTitle -eq 'ObfuscationLength') 1747 | { 1748 | Write-Host $OptionValue -ForegroundColor Cyan 1749 | } 1750 | ElseIf($OptionTitle -eq 'ScriptBlock') 1751 | { 1752 | Out-ScriptContents $OptionValue 1753 | } 1754 | ElseIf($OptionTitle -eq 'CommandLineSyntax') 1755 | { 1756 | # CLISyntax output. 1757 | $SetSyntax = '' 1758 | If(($Script:ScriptPath.Length -gt 0) -AND ($Script:ScriptPath -ne 'N/A')) 1759 | { 1760 | $SetSyntax = " -ScriptPath '$Script:ScriptPath'" 1761 | } 1762 | ElseIf(($Script:ScriptBlock.Length -gt 0) -AND ($Script:ScriptPath -eq 'N/A')) 1763 | { 1764 | $SetSyntax = " -ScriptBlock {$Script:ScriptBlock}" 1765 | } 1766 | 1767 | $CommandSyntax = '' 1768 | If($OptionValue.Count -gt 0) 1769 | { 1770 | $CommandSyntax = " -Command '" + ($OptionValue -Join ',') + "' -Quiet" 1771 | } 1772 | 1773 | If(($SetSyntax -ne '') -OR ($CommandSyntax -ne '')) 1774 | { 1775 | $CliSyntaxToOutput = "Invoke-Obfuscation" + $SetSyntax + $CommandSyntax 1776 | Write-Host $CliSyntaxToOutput -ForegroundColor Cyan 1777 | } 1778 | Else 1779 | { 1780 | Write-Host '' 1781 | } 1782 | } 1783 | ElseIf($OptionTitle -eq 'ExecutionCommands') 1784 | { 1785 | # ExecutionCommands output. 1786 | If($OptionValue.Count -gt 0) {Write-Host ''} 1787 | $Counter = 0 1788 | ForEach($ExecutionCommand in $OptionValue) 1789 | { 1790 | $Counter++ 1791 | If($ExecutionCommand.Length -eq 0) {Write-Host ''; Continue} 1792 | 1793 | $ExecutionCommand = $ExecutionCommand.Replace('$ScriptBlock','~').Split('~') 1794 | Write-Host " $($ExecutionCommand[0])" -NoNewLine -ForegroundColor Cyan 1795 | Write-Host '$ScriptBlock' -NoNewLine -ForegroundColor Magenta 1796 | 1797 | # Handle output formatting when SHOW OPTIONS is run. 1798 | If(($OptionValue.Count -gt 0) -AND ($Counter -lt $OptionValue.Count)) 1799 | { 1800 | Write-Host $ExecutionCommand[1] -ForegroundColor Cyan 1801 | } 1802 | Else 1803 | { 1804 | Write-Host $ExecutionCommand[1] -NoNewLine -ForegroundColor Cyan 1805 | } 1806 | 1807 | } 1808 | Write-Host '' 1809 | } 1810 | ElseIf($OptionTitle -eq 'ObfuscatedCommand') 1811 | { 1812 | Out-ScriptContents $OptionValue 1813 | } 1814 | Else 1815 | { 1816 | Write-Host $OptionValue -ForegroundColor Magenta 1817 | } 1818 | } 1819 | 1820 | } 1821 | 1822 | 1823 | Function Show-HelpMenu 1824 | { 1825 | <# 1826 | .SYNOPSIS 1827 | 1828 | HELPER FUNCTION :: Displays help menu for Invoke-Obfuscation. 1829 | 1830 | Invoke-Obfuscation Function: Show-HelpMenu 1831 | Author: Daniel Bohannon (@danielhbohannon) 1832 | License: Apache License, Version 2.0 1833 | Required Dependencies: None 1834 | Optional Dependencies: None 1835 | 1836 | .DESCRIPTION 1837 | 1838 | Show-HelpMenu displays help menu for Invoke-Obfuscation. 1839 | 1840 | .EXAMPLE 1841 | 1842 | C:\PS> Show-HelpMenu 1843 | 1844 | .NOTES 1845 | 1846 | This is a personal project developed by Daniel Bohannon while an employee at MANDIANT, A FireEye Company. 1847 | 1848 | .LINK 1849 | 1850 | http://www.danielbohannon.com 1851 | #> 1852 | 1853 | # Show Help Menu. 1854 | Write-Host "`n`nHELP MENU" -NoNewLine -ForegroundColor Cyan 1855 | Write-Host " :: Available" -NoNewLine 1856 | Write-Host " options" -NoNewLine -ForegroundColor Yellow 1857 | Write-Host " shown below:`n" 1858 | ForEach($InputOptionsList in $AllAvailableInputOptionsLists) 1859 | { 1860 | $InputOptionsCommands = $InputOptionsList[0] 1861 | $InputOptionsDescription = $InputOptionsList[1] 1862 | 1863 | # Add additional coloring to string encapsulated by <> if it exists in $InputOptionsDescription. 1864 | If($InputOptionsDescription.Contains('<') -AND $InputOptionsDescription.Contains('>')) 1865 | { 1866 | $FirstPart = $InputOptionsDescription.SubString(0,$InputOptionsDescription.IndexOf('<')) 1867 | $MiddlePart = $InputOptionsDescription.SubString($FirstPart.Length+1) 1868 | $MiddlePart = $MiddlePart.SubString(0,$MiddlePart.IndexOf('>')) 1869 | $LastPart = $InputOptionsDescription.SubString($FirstPart.Length+$MiddlePart.Length+2) 1870 | Write-Host "$LineSpacing $FirstPart" -NoNewLine 1871 | Write-Host $MiddlePart -NoNewLine -ForegroundColor Cyan 1872 | Write-Host $LastPart -NoNewLine 1873 | } 1874 | Else 1875 | { 1876 | Write-Host "$LineSpacing $InputOptionsDescription" -NoNewLine 1877 | } 1878 | 1879 | $Counter = 0 1880 | ForEach($Command in $InputOptionsCommands) 1881 | { 1882 | $Counter++ 1883 | Write-Host $Command.ToUpper() -NoNewLine -ForegroundColor Yellow 1884 | If($Counter -lt $InputOptionsCommands.Count) {Write-Host ',' -NoNewLine} 1885 | } 1886 | Write-Host '' 1887 | } 1888 | } 1889 | 1890 | 1891 | Function Show-Tutorial 1892 | { 1893 | <# 1894 | .SYNOPSIS 1895 | 1896 | HELPER FUNCTION :: Displays tutorial information for Invoke-Obfuscation. 1897 | 1898 | Invoke-Obfuscation Function: Show-Tutorial 1899 | Author: Daniel Bohannon (@danielhbohannon) 1900 | License: Apache License, Version 2.0 1901 | Required Dependencies: None 1902 | Optional Dependencies: None 1903 | 1904 | .DESCRIPTION 1905 | 1906 | Show-Tutorial displays tutorial information for Invoke-Obfuscation. 1907 | 1908 | .EXAMPLE 1909 | 1910 | C:\PS> Show-Tutorial 1911 | 1912 | .NOTES 1913 | 1914 | This is a personal project developed by Daniel Bohannon while an employee at MANDIANT, A FireEye Company. 1915 | 1916 | .LINK 1917 | 1918 | http://www.danielbohannon.com 1919 | #> 1920 | 1921 | Write-Host "`n`nTUTORIAL" -NoNewLine -ForegroundColor Cyan 1922 | Write-Host " :: Here is a quick tutorial showing you how to get your obfuscation on:" 1923 | 1924 | Write-Host "`n1) " -NoNewLine -ForegroundColor Cyan 1925 | Write-Host "Load a scriptblock (SET SCRIPTBLOCK) or a script path/URL (SET SCRIPTPATH)." 1926 | Write-Host " SET SCRIPTBLOCK Write-Host 'This is my test command' -ForegroundColor Green" -ForegroundColor Green 1927 | 1928 | Write-Host "`n2) " -NoNewLine -ForegroundColor Cyan 1929 | Write-Host "Navigate through the obfuscation menus where the options are in" -NoNewLine 1930 | Write-Host " YELLOW" -NoNewLine -ForegroundColor Yellow 1931 | Write-Host "." 1932 | Write-Host " GREEN" -NoNewLine -ForegroundColor Green 1933 | Write-Host " options apply obfuscation." 1934 | Write-Host " Enter" -NoNewLine 1935 | Write-Host " BACK" -NoNewLine -ForegroundColor Yellow 1936 | Write-Host "/" -NoNewLine 1937 | Write-Host "CD .." -NoNewLine -ForegroundColor Yellow 1938 | Write-Host " to go to previous menu and" -NoNewLine 1939 | Write-Host " HOME" -NoNewline -ForegroundColor Yellow 1940 | Write-Host "/" -NoNewline 1941 | Write-Host "MAIN" -NoNewline -ForegroundColor Yellow 1942 | Write-Host " to go to home menu.`n E.g. Enter" -NoNewLine 1943 | Write-Host " ENCODING" -NoNewLine -ForegroundColor Yellow 1944 | Write-Host " & then" -NoNewLine 1945 | Write-Host " 5" -NoNewLine -ForegroundColor Green 1946 | Write-Host " to apply SecureString obfuscation." 1947 | 1948 | Write-Host "`n3) " -NoNewLine -ForegroundColor Cyan 1949 | Write-Host "Enter" -NoNewLine 1950 | Write-Host " TEST" -NoNewLine -ForegroundColor Yellow 1951 | Write-Host "/" -NoNewLine 1952 | Write-Host "EXEC" -NoNewLine -ForegroundColor Yellow 1953 | Write-Host " to test the obfuscated command locally.`n Enter" -NoNewLine 1954 | Write-Host " SHOW" -NoNewLine -ForegroundColor Yellow 1955 | Write-Host " to see the currently obfuscated command." 1956 | 1957 | Write-Host "`n4) " -NoNewLine -ForegroundColor Cyan 1958 | Write-Host "Enter" -NoNewLine 1959 | Write-Host " COPY" -NoNewLine -ForegroundColor Yellow 1960 | Write-Host "/" -NoNewLine 1961 | Write-Host "CLIP" -NoNewLine -ForegroundColor Yellow 1962 | Write-Host " to copy obfuscated command out to your clipboard." 1963 | Write-Host " Enter" -NoNewLine 1964 | Write-Host " OUT" -NoNewLine -ForegroundColor Yellow 1965 | Write-Host " to write obfuscated command out to disk." 1966 | 1967 | Write-Host "`n5) " -NoNewLine -ForegroundColor Cyan 1968 | Write-Host "Enter" -NoNewLine 1969 | Write-Host " RESET" -NoNewLine -ForegroundColor Yellow 1970 | Write-Host " to remove all obfuscation and start over.`n Enter" -NoNewLine 1971 | Write-Host " UNDO" -NoNewLine -ForegroundColor Yellow 1972 | Write-Host " to undo last obfuscation.`n Enter" -NoNewLine 1973 | Write-Host " HELP" -NoNewLine -ForegroundColor Yellow 1974 | Write-Host "/" -NoNewLine 1975 | Write-Host "?" -NoNewLine -ForegroundColor Yellow 1976 | Write-Host " for help menu." 1977 | 1978 | Write-Host "`nAnd finally the obligatory `"Don't use this for evil, please`"" -NoNewLine -ForegroundColor Cyan 1979 | Write-Host " :)" -ForegroundColor Green 1980 | } 1981 | 1982 | 1983 | Function Out-ScriptContents 1984 | { 1985 | <# 1986 | .SYNOPSIS 1987 | 1988 | HELPER FUNCTION :: Displays current obfuscated command for Invoke-Obfuscation. 1989 | 1990 | Invoke-Obfuscation Function: Out-ScriptContents 1991 | Author: Daniel Bohannon (@danielhbohannon) 1992 | License: Apache License, Version 2.0 1993 | Required Dependencies: None 1994 | Optional Dependencies: None 1995 | 1996 | .DESCRIPTION 1997 | 1998 | Out-ScriptContents displays current obfuscated command for Invoke-Obfuscation. 1999 | 2000 | .PARAMETER ScriptContents 2001 | 2002 | Specifies the string containing your payload. 2003 | 2004 | .PARAMETER PrintWarning 2005 | 2006 | Switch to output redacted form of ScriptContents if they exceed 8,190 characters. 2007 | 2008 | .EXAMPLE 2009 | 2010 | C:\PS> Out-ScriptContents 2011 | 2012 | .NOTES 2013 | 2014 | This is a personal project developed by Daniel Bohannon while an employee at MANDIANT, A FireEye Company. 2015 | 2016 | .LINK 2017 | 2018 | http://www.danielbohannon.com 2019 | #> 2020 | 2021 | Param( 2022 | [Parameter(ValueFromPipeline = $true)] 2023 | [String] 2024 | $ScriptContents, 2025 | 2026 | [Switch] 2027 | $PrintWarning 2028 | ) 2029 | 2030 | If($ScriptContents.Length -gt $CmdMaxLength) 2031 | { 2032 | # Output ScriptContents, handling if the size of ScriptContents exceeds $CmdMaxLength characters. 2033 | $RedactedPrintLength = $CmdMaxLength/5 2034 | 2035 | # Handle printing redaction message in middle of screen. #OCD 2036 | $CmdLineWidth = (Get-Host).UI.RawUI.BufferSize.Width 2037 | $RedactionMessage = "" 2038 | $CenteredRedactionMessageStartIndex = (($CmdLineWidth-$RedactionMessage.Length)/2) - "[*] ObfuscatedCommand: ".Length 2039 | $CurrentRedactionMessageStartIndex = ($RedactedPrintLength % $CmdLineWidth) 2040 | 2041 | If($CurrentRedactionMessageStartIndex -gt $CenteredRedactionMessageStartIndex) 2042 | { 2043 | $RedactedPrintLength = $RedactedPrintLength-($CurrentRedactionMessageStartIndex-$CenteredRedactionMessageStartIndex) 2044 | } 2045 | Else 2046 | { 2047 | $RedactedPrintLength = $RedactedPrintLength+($CenteredRedactionMessageStartIndex-$CurrentRedactionMessageStartIndex) 2048 | } 2049 | 2050 | Write-Host $ScriptContents.SubString(0,$RedactedPrintLength) -NoNewLine -ForegroundColor Magenta 2051 | Write-Host $RedactionMessage -NoNewLine -ForegroundColor Yellow 2052 | Write-Host $ScriptContents.SubString($ScriptContents.Length-$RedactedPrintLength) -ForegroundColor Magenta 2053 | } 2054 | Else 2055 | { 2056 | Write-Host $ScriptContents -ForegroundColor Magenta 2057 | } 2058 | 2059 | # Make sure final command doesn't exceed cmd.exe's character limit. 2060 | If($ScriptContents.Length -gt $CmdMaxLength) 2061 | { 2062 | If($PSBoundParameters['PrintWarning']) 2063 | { 2064 | Write-Host "`nWARNING: This command exceeds the cmd.exe maximum length of $CmdMaxLength." -ForegroundColor Red 2065 | Write-Host " Its length is" -NoNewLine -ForegroundColor Red 2066 | Write-Host " $($ScriptContents.Length)" -NoNewLine -ForegroundColor Yellow 2067 | Write-Host " characters." -ForegroundColor Red 2068 | } 2069 | } 2070 | } 2071 | 2072 | 2073 | Function Show-AsciiArt 2074 | { 2075 | <# 2076 | .SYNOPSIS 2077 | 2078 | HELPER FUNCTION :: Displays random ASCII art for Invoke-Obfuscation. 2079 | 2080 | Invoke-Obfuscation Function: Show-AsciiArt 2081 | Author: Daniel Bohannon (@danielhbohannon) 2082 | License: Apache License, Version 2.0 2083 | Required Dependencies: None 2084 | Optional Dependencies: None 2085 | 2086 | .DESCRIPTION 2087 | 2088 | Show-AsciiArt displays random ASCII art for Invoke-Obfuscation, and also displays ASCII art during script startup. 2089 | 2090 | .EXAMPLE 2091 | 2092 | C:\PS> Show-AsciiArt 2093 | 2094 | .NOTES 2095 | 2096 | Credit for ASCII art font generation: http://patorjk.com/software/taag/ 2097 | This is a personal project developed by Daniel Bohannon while an employee at MANDIANT, A FireEye Company. 2098 | 2099 | .LINK 2100 | 2101 | http://www.danielbohannon.com 2102 | #> 2103 | [CmdletBinding()] Param ( 2104 | [Parameter(Position = 0)] 2105 | [ValidateNotNullOrEmpty()] 2106 | [Switch] 2107 | $Random 2108 | ) 2109 | 2110 | # Create multiple ASCII art title banners. 2111 | $Spacing = "`t" 2112 | $InvokeObfuscationAscii = @() 2113 | $InvokeObfuscationAscii += $Spacing + ' ____ __ ' 2114 | $InvokeObfuscationAscii += $Spacing + ' / _/___ _ ______ / /_____ ' 2115 | $InvokeObfuscationAscii += $Spacing + ' / // __ \ | / / __ \/ //_/ _ \______ ' 2116 | $InvokeObfuscationAscii += $Spacing + ' _/ // / / / |/ / /_/ / ,< / __/_____/ ' 2117 | $InvokeObfuscationAscii += $Spacing + '/______ /__|_________/_/|_|\___/ __ _ ' 2118 | $InvokeObfuscationAscii += $Spacing + ' / __ \/ /_ / __/_ ________________ _/ /_(_)___ ____ ' 2119 | $InvokeObfuscationAscii += $Spacing + ' / / / / __ \/ /_/ / / / ___/ ___/ __ `/ __/ / __ \/ __ \' 2120 | $InvokeObfuscationAscii += $Spacing + '/ /_/ / /_/ / __/ /_/ (__ ) /__/ /_/ / /_/ / /_/ / / / /' 2121 | $InvokeObfuscationAscii += $Spacing + '\____/_.___/_/ \__,_/____/\___/\__,_/\__/_/\____/_/ /_/ ' 2122 | 2123 | # Ascii art to run only during script startup. 2124 | If(!$PSBoundParameters['Random']) 2125 | { 2126 | $ArrowAscii = @() 2127 | $ArrowAscii += ' | ' 2128 | $ArrowAscii += ' | ' 2129 | $ArrowAscii += ' \ / ' 2130 | $ArrowAscii += ' V ' 2131 | 2132 | # Show actual obfuscation example (generated with this tool) in reverse. 2133 | Write-Host "`nIEX( ( '36{78Q55@32t61_91{99@104X97{114Q91-32t93}32t93}32t34@110m111@105}115X115-101m114_112@120@69-45{101@107X111m118m110-73Q124Q32X41Q57@51-93Q114_97_104t67t91{44V39Q112_81t109@39}101{99@97}108{112}101}82_45m32_32X52{51Q93m114@97-104{67t91t44t39V98t103V48t39-101}99}97V108}112t101_82_45{32@41X39{41_112t81_109_39m43{39-110t101@112{81t39X43@39t109_43t112_81Q109t101X39Q43m39}114Q71_112{81m109m39@43X39V32Q40}32m39_43_39{114-111m108t111t67{100m110{117Q39_43m39-111-114Q103_101t114@39m43-39{111t70-45}32m41}98{103V48V110Q98t103{48@39{43{39-43{32t98m103_48{111@105t98@103V48-39@43{39_32-32V43V32}32t98t103@48X116m97V99t98X103t48_39V43m39@43-39X43Q39_98@103@48}115V117V102Q98V79m45@98m39Q43{39X103_39X43Q39V48}43-39}43t39}98-103{48V101_107Q39t43X39_111X118X110V39X43}39t98_103{48@43}32_98{103}48{73{98-39@43t39m103_39}43{39{48Q32t39X43X39-32{40V32t41{39Q43V39m98X103{39_43V39{48-116{115Q79{39_43_39}98}103m48{39Q43t39X32X43{32_98@103-39@43m39X48_72-39_43t39V45m39t43Q39_101Q98}103_48-32_39Q43V39V32t39V43}39m43Q32V98X39Q43_39@103_48V39@43Q39@116X73t82V119m98-39{43_39}103Q48X40_46_32m39}40_40{34t59m91@65V114V114@97_121}93Q58Q58V82Q101Q118Q101{114}115_101m40_36_78m55@32t41t32-59{32}73{69V88m32{40t36V78t55}45Q74m111@105-110m32X39V39-32}41'.SpLiT( '{_Q-@t}mXV' ) |ForEach-Object { ([Int]`$_ -AS [Char]) } ) -Join'' )" -ForegroundColor Cyan 2134 | Start-Sleep -Milliseconds 650 2135 | ForEach($Line in $ArrowAscii) {Write-Host $Line -NoNewline; Write-Host $Line -NoNewline; Write-Host $Line -NoNewline; Write-Host $Line} 2136 | Start-Sleep -Milliseconds 100 2137 | 2138 | Write-Host "`$N7 =[char[ ] ] `"noisserpxE-ekovnI| )93]rahC[,'pQm'ecalpeR- 43]rahC[,'bg0'ecalpeR- )')pQm'+'nepQ'+'m+pQme'+'rGpQm'+' ( '+'roloCdnu'+'orger'+'oF- )bg0nbg0'+'+ bg0oibg0'+' + bg0tacbg0'+'+'+'bg0sufbO-b'+'g'+'0+'+'bg0ek'+'ovn'+'bg0+ bg0Ib'+'g'+'0 '+' ( )'+'bg'+'0tsO'+'bg0'+' + bg'+'0H'+'-'+'ebg0 '+' '+'+ b'+'g0'+'tIRwb'+'g0(. '((`";[Array]::Reverse(`$N7 ) ; IEX (`$N7-Join '' )" -ForegroundColor Magenta 2139 | Start-Sleep -Milliseconds 650 2140 | ForEach($Line in $ArrowAscii) {Write-Host $Line -NoNewline; Write-Host $Line -NoNewline; Write-Host $Line} 2141 | Start-Sleep -Milliseconds 100 2142 | 2143 | Write-Host ".(`"wRIt`" + `"e-H`" + `"Ost`") ( `"I`" +`"nvoke`"+`"-Obfus`"+`"cat`" + `"io`" +`"n`") -ForegroundColor ( 'Gre'+'en')" -ForegroundColor Yellow 2144 | Start-Sleep -Milliseconds 650 2145 | ForEach($Line in $ArrowAscii) {Write-Host $Line -NoNewline; Write-Host $Line} 2146 | Start-Sleep -Milliseconds 100 2147 | 2148 | Write-Host "Write-Host `"Invoke-Obfuscation`" -ForegroundColor Green" -ForegroundColor White 2149 | Start-Sleep -Milliseconds 650 2150 | ForEach($Line in $ArrowAscii) {Write-Host $Line} 2151 | Start-Sleep -Milliseconds 100 2152 | 2153 | # Write out below string in interactive format. 2154 | Start-Sleep -Milliseconds 100 2155 | ForEach($Char in [Char[]]'Invoke-Obfuscation') 2156 | { 2157 | Start-Sleep -Milliseconds (Get-Random -Input @(25..200)) 2158 | Write-Host $Char -NoNewline -ForegroundColor Green 2159 | } 2160 | 2161 | Start-Sleep -Milliseconds 900 2162 | Write-Host "" 2163 | Start-Sleep -Milliseconds 300 2164 | Write-Host 2165 | 2166 | # Display primary ASCII art title banner. 2167 | $RandomColor = (Get-Random -Input @('Green','Cyan','Yellow')) 2168 | ForEach($Line in $InvokeObfuscationAscii) 2169 | { 2170 | Write-Host $Line -ForegroundColor $RandomColor 2171 | } 2172 | } 2173 | Else 2174 | { 2175 | # ASCII option in Invoke-Obfuscation interactive console. 2176 | 2177 | } 2178 | 2179 | # Output tool banner after all ASCII art. 2180 | Write-Host "" 2181 | Write-Host "`tTool :: Invoke-Obfuscation" -ForegroundColor Magenta 2182 | Write-Host "`tAuthor :: Daniel Bohannon (DBO)" -ForegroundColor Magenta 2183 | Write-Host "`tTwitter :: @danielhbohannon" -ForegroundColor Magenta 2184 | Write-Host "`tBlog :: http://danielbohannon.com" -ForegroundColor Magenta 2185 | Write-Host "`tGithub :: https://github.com/danielbohannon/Invoke-Obfuscation" -ForegroundColor Magenta 2186 | Write-Host "`tVersion :: 1.8" -ForegroundColor Magenta 2187 | Write-Host "`tLicense :: Apache License, Version 2.0" -ForegroundColor Magenta 2188 | Write-Host "`tNotes :: If(!`$Caffeinated) {Exit}" -ForegroundColor Magenta 2189 | } 2190 | --------------------------------------------------------------------------------