Skip to content

PowerShell: Removes any digital signatures from Files

I created a small helper that finds all signed PowerShell files remove any digital signatures attached to them.
Supported File types are: psm1, ps1, psd1, and ps1xml – All other files are ignored!

function Remove-Signature
	{
	<#
	         .SYNOPSIS
	         Finds all signed PowerShell files removes any digital signatures attached to them.

	         .DESCRIPTION
	         Finds all signed PowerShell files removes any digital signatures attached to them.
	         Supported Filetypes are: psm1, ps1, psd1, and ps1xml - All other Files are ignored!

	         .PARAMETER Path
	         Single File or Path you want to parse for digital signatures. (Mandatory)

	         .PARAMETER Recurse
	         Recurse through all subdirectories of the path provided. The default is not work recursively (Optional)

	         .EXAMPLE
	         PS C:\> Remove-Signature -Path 'C:\Temp\Export-DistributionGroup2Cloud.ps1'

	         Removes all digital signatures from 'C:\Temp\Export-DistributionGroup2Cloud.ps1'

	         .EXAMPLE
	         PS C:\> Remove-Signature -Path 'C:\Temp' -Recurse

	         Removes all digital signatures from psm1, ps1, psd1, and ps1xml files found in 'C:\Temp' and below (recursively).

	         .NOTES
	         Based on the ideas and work of the original Authors: Adrian Rodriguez and Zachary Loeber

	         .LINK
	         http://www.the-little-things.net

	         .LINK
	         https://psrdrgz.github.io/RemoveAuthenticodeSignature/
	   #>

	[CmdletBinding(ConfirmImpact = 'Low',
	SupportsShouldProcess)]
	param
	(
	 [Parameter(Mandatory,
			 ValueFromPipeline,
			 ValueFromPipelineByPropertyName,
			 Position = 1,
	 HelpMessage = 'Single File or Path you want to parse for digital signatures.')]
	 [ValidateNotNullOrEmpty()]
	 [Alias('FilePath')]
	 [string]
	 $Path,
	 [Parameter(ValueFromPipeline,
			 ValueFromPipelineByPropertyName,
	 Position = 2)]
	 [switch]
	 $Recurse = $false
	)

	begin
	{
	 $paramGetChildItem = @{
		 Path    = $Path
		 File    = $true
		 Include = '*.psm1', '*.ps1', '*.psd1', '*.ps1xml'
	 }

	 if ($Recurse)
	 {
		 Write-Verbose -Message 'Work recursively'
		 $paramGetChildItem.Recurse = $true
	 }
	}

	process
	{

	 $FilesToProcess = (Get-ChildItem @paramGetChildItem)

	 $FilesToProcess | ForEach-Object -Process {
		 $SignatureStatus = (Get-AuthenticodeSignature -FilePath $_).Status
		 $ScriptFileFullName = $_.FullName

		 if ($SignatureStatus -ne 'NotSigned')
		 {
			 try
			 {
				 $paramGetContent = @{
					 Path          = $ScriptFileFullName
					 ErrorAction   = 'Stop'
					 WarningAction = 'Continue'
				 }
				 $Content = (Get-Content @paramGetContent)

				 $paramNewObject = @{
					 TypeName      = 'System.Text.StringBuilder'
					 ErrorAction   = 'Stop'
					 WarningAction = 'Continue'
				 }
				 $StringBuilder = (New-Object @paramNewObject)

				 foreach ($Line in $Content)
				 {
					 if ($Line -match '^# SIG # Begin signature block|^<!-- SIG # Begin signature block -->')
					 {
						 break
					 }
					 else
					 {
						 $null = $StringBuilder.AppendLine($Line)
					 }
				 }
				 if ($pscmdlet.ShouldProcess("$ScriptFileFullName"))
				 {
					 $paramSetContent = @{
						 Path          = $ScriptFileFullName
						 Value         = $StringBuilder.ToString()
						 Force         = $true
						 Confirm       = $false
						 Encoding      = 'UTF8'
						 ErrorAction   = 'Stop'
						 WarningAction = 'Continue'
					 }
					 $null = (Set-Content @paramSetContent)

					 Write-Verbose -Message ('Removed signature from {0}' -f $ScriptFileFullName)
				 }
			 }
			 catch
			 {
				 # Get error record
				 [Management.Automation.ErrorRecord]$e = $_

				 # Retrieve information about runtime error
				 $info = [PSCustomObject]@{
					 Exception = $e.Exception.Message
					 Reason    = $e.CategoryInfo.Reason
					 Target    = $e.CategoryInfo.TargetName
					 Script    = $e.InvocationInfo.ScriptName
					 Line      = $e.InvocationInfo.ScriptLineNumber
					 Column    = $e.InvocationInfo.OffsetInLine
				 }

				 # Output information. Post-process collected info, and log info (optional)
				 Write-Verbose -Message $info

				 Write-Error -Message ($info.Exception) -TargetObject ($info.Target) -ErrorAction Stop
				 break
			 }
		 }
		 else
		 {
			 Write-Verbose -Message ('No signature found in {0}' -f $ScriptFileFullName)
		 }
	 }
	}

	end
	{
	 Write-Verbose -Message 'Remove-Signature Done'
	}
	}
	

This is also part of my PowerShell-collection repository.

Published inPowerShell

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *