PowerSploit/ScriptModification/Remove-Comments.ps1

157 lines
4.9 KiB
PowerShell

function Remove-Comments
{
<#
.SYNOPSIS
Strips comments and extra whitespace from a script.
PowerSploit Function: Remove-Comments
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Remove-Comments strips out comments and unnecessary whitespace from a script. This is best used in conjunction with Out-EncodedCommand when the size of the script to be encoded might be too big.
A major portion of this code was taken from the Lee Holmes' Show-ColorizedContent script. You rock, Lee!
.PARAMETER ScriptBlock
Specifies a scriptblock containing your script.
.PARAMETER Path
Specifies the path to your script.
.EXAMPLE
C:\PS> $Stripped = Remove-Comments -Path .\ScriptWithComments.ps1
.EXAMPLE
C:\PS> Remove-Comments -ScriptBlock {
### This is my awesome script. My documentation is beyond reproach!
Write-Host 'Hello, World!' ### Write 'Hello, World' to the host
### End script awesomeness
}
Write-Host 'Hello, World!'
.EXAMPLE
C:\PS> Remove-Comments -Path Inject-Shellcode.ps1 | Out-EncodedCommand
Description
-----------
Removes extraneous whitespace and comments from Inject-Shellcode (which is notoriously large) and pipes the output to Out-EncodedCommand.
.INPUTS
System.String, System.Management.Automation.ScriptBlock
Accepts either a string containing the path to a script or a scriptblock.
.OUTPUTS
System.Management.Automation.ScriptBlock
Remove-Comments returns a scriptblock. Call the ToString method to convert a scriptblock to a string, if desired.
.LINK
http://www.exploit-monday.com
http://www.leeholmes.com/blog/2007/11/07/syntax-highlighting-in-powershell/
#>
[CmdletBinding( DefaultParameterSetName = 'FilePath' )] Param (
[Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'FilePath' )]
[ValidateNotNullOrEmpty()]
[String]
$Path,
[Parameter(Position = 0, ValueFromPipeline = $True, Mandatory = $True, ParameterSetName = 'ScriptBlock' )]
[ValidateNotNullOrEmpty()]
[ScriptBlock]
$ScriptBlock
)
Set-StrictMode -Version 2
if ($PSBoundParameters['Path'])
{
Get-ChildItem $Path -ErrorAction Stop | Out-Null
$ScriptBlockString = [IO.File]::ReadAllText((Resolve-Path $Path))
$ScriptBlock = [ScriptBlock]::Create($ScriptBlockString)
}
else
{
# Convert the scriptblock to a string so that it can be referenced with array notation
$ScriptBlockString = $ScriptBlock.ToString()
}
# Tokenize the scriptblock and return all tokens except for comments
$Tokens = [System.Management.Automation.PSParser]::Tokenize($ScriptBlock, [Ref] $Null) | Where-Object { $_.Type -ne 'Comment' }
$StringBuilder = New-Object Text.StringBuilder
# The majority of the remaining code comes from Lee Holmes' Show-ColorizedContent script.
$CurrentColumn = 1
$NewlineCount = 0
foreach($CurrentToken in $Tokens)
{
# Now output the token
if(($CurrentToken.Type -eq 'NewLine') -or ($CurrentToken.Type -eq 'LineContinuation'))
{
$CurrentColumn = 1
# Only insert a single newline. Sequential newlines are ignored in order to save space.
if ($NewlineCount -eq 0)
{
$StringBuilder.AppendLine() | Out-Null
}
$NewlineCount++
}
else
{
$NewlineCount = 0
# Do any indenting
if($CurrentColumn -lt $CurrentToken.StartColumn)
{
# Insert a single space in between tokens on the same line. Extraneous whiltespace is ignored.
if ($CurrentColumn -ne 1)
{
$StringBuilder.Append(' ') | Out-Null
}
}
# See where the token ends
$CurrentTokenEnd = $CurrentToken.Start + $CurrentToken.Length - 1
# Handle the line numbering for multi-line strings
if(($CurrentToken.Type -eq 'String') -and ($CurrentToken.EndLine -gt $CurrentToken.StartLine))
{
$LineCounter = $CurrentToken.StartLine
$StringLines = $(-join $ScriptBlockString[$CurrentToken.Start..$CurrentTokenEnd] -split '`r`n')
foreach($StringLine in $StringLines)
{
$StringBuilder.Append($StringLine) | Out-Null
$LineCounter++
}
}
# Write out a regular token
else
{
$StringBuilder.Append((-join $ScriptBlockString[$CurrentToken.Start..$CurrentTokenEnd])) | Out-Null
}
# Update our position in the column
$CurrentColumn = $CurrentToken.EndColumn
}
}
Write-Output ([ScriptBlock]::Create($StringBuilder.ToString()))
}