Set SEHOP flags (DisableExceptionChainValidation) in registry. 

The script sets both the SEHOP computer-wide default flag in 

    HKLM:\System\CurrentControlSet\Control\Session Manager\kernel 

and the SEHOP per-process IFEO flags in 

    HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options

Note that SEHOP IFEO flags always override the computer-wide default flag.

PowerShell
Edit|Remove
############################################################################################
#
#
#	Name:
#
#		SetSehop.ps1
#
#	About:
#
#		Set SEHOP flags (DisableExceptionChainValidation) in registry. 
#
#		The script sets both the SEHOP computer-wide default flag in 
#
#			HKLM:\System\CurrentControlSet\Control\Session Manager\kernel 
#
#		and the SEHOP per-process IFEO flags in 
#
#			HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
#
#		Note that SEHOP IFEO flags always override the computer-wide default flag.
#
#	Parameters:
#
#		-DefaultState ["","Enabled","Disabled"] = ""
#		
#			Sets the value of the computer-wide default flag. Default parameter value is 
#			"uncofigured", i.e. the empty string "", which causes no change to the current
#			state.
#
#		-OptOut [<app1.exe>,..,<appN.exe>] = $null
#
#			Sets the list of programs that always have SEHOP disabled regardless of the 
#			computer-wide default flag. Default parameter value is "unconfigured",
#			i.e. $null, which causes no change to the current state.
#
#		-OptIn [<app1.exe>,..,<appN.exe>] = $null
#
#			Sets the list of programs that always have SEHOP enabled regardless of the 
#			computer-wide default flag. Default parameter value is "unconfigured",
#			i.e. $null, which causes no change to the current state.
#
#		-Strict [switch]
#
#			Sets the above parameters to their most strict values, i.e.
#			-DefaultState Enabled -OptOut @() -OptIn $null.
#
#		An OptIn or OptOut value of $null means that the script will not touch the 
#		current IFEO list of OptIn or OptOut programs, respectively.
#
#		An OptIn or OptOut value of @(), i.e. the empty list, means that the script 
#		will not allow *ANY* IFEO per-process Enable or Disable exceptions, 
#		respectively.
#
#	Notes:
#
#		The .NET Registry Class seems to be the most suitable API for programming 
#		registry changes. In contrast, the PowerShell Registry Provider seems to 
#		be more suitable for interactive use than programming. The WMI Registry 
#		Provider StdRegProv was not used since offered no apparent advantages to 
#		the .NET provider.
#
#		PowerShell Get-Item returns a .NET RegistryKey object BUT opens existing 
#		keys in READ-ONLY mode! Consequently, $key.SetValue() cannot be used to 
#		change EXISTING values on such keys. Instead use Set-ItemProperty for this
#		purpose.
#
#	Resources:
#
#		SEHOP and IFEO
#		http://support.microsoft.com/kb/956607
#		http://blogs.technet.com/srd/archive/2009/02/02/preventing-the-exploitation-of-seh-overwrites-with-sehop.aspx
#		http://blogs.technet.com/srd/archive/2009/11/20/sehop-per-process-opt-in-support-in-windows-7.aspx
#		http://blogs.msdn.com/junfeng/archive/2004/04/28/121871.aspx
#		
#		.NET Registry Class
#		http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.aspx
# 		http://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey_members.aspx
#
#		PowerShell Registry Provider
#		http://powershell.com/cs/blogs/ebook/archive/2009/03/30/chapter-16-the-registry.aspx
#
#		WMI StdRegProv Class
#		http://msdn.microsoft.com/en-us/library/aa393664(VS.85).aspx
#
#	Examples:
#
#		EXAMPLE 1. No touch.
#
#		List the current state but do not change any settings.
#
#		PSH> .\SetSehop.ps1
#
#		EXAMPLE 2. The most secure configuration.
#
#		Enable computer-wide SEHOP and remove *ALL* per-process IFEO exceptions
#		that disable SEHOP (i.e. OptOut programs). Do not touch per-process IFEO   
#		exceptions that enable SEHOP (i.e. OptIn programs).
#		 
#		PSH> .\SetSehop.ps1 -Strict # or
#		PSH> .\SetSehop.ps1 -DefaultState Enabled -OptOut @() -OptIn $null
#		
#		EXAMPLE 3. The least secure configuration.
#
#		Disable computer-wide SEHOP and remove *ALL* per-process IFEO exceptions 
#		that enable SEHOP (i.e. OptIn programs). Do not touch per-process IFEO 
#		exceptions that disable SEHOP (i.e. OptOut programs).
#		 
#		PSH> .\SetSehop.ps1 -DefaultState Disabled -OptIn @()
#		
#		EXAMPLE 4. The pragmatic configuration.
#
#		Enable computer-wide SEHOP and remove per-process IFEO exceptions that 
#		disable SEHOP (i.e. OptOut programs) *EXCEPT* for legacyApp.exe. Do not
#		touch per-process IFEO exceptions that enable SEHOP (i.e. OptIn programs).
#
#		PSH> .\SetSehop.ps1 -DefaultState Enabled -OptOut legacyApp.exe
#
#		EXAMPLE 5. The conservative configuration.
#
#		Disable computer-wide SEHOP and add per-process IFEO exceptions that enable
#		SEHOP (i.e. OptIn programs) for a selection of exposed applications that
#		also has been tested to work with this setting. Do not touch per-process 
#		IFEO exceptions that disable SEHOP (i.e. OptOut programs).
#
#		PSH> .\SetSehop.ps1 -DefaultState Disabled -OptIn AcroRd32.exe,`  
#				IExplore.exe,Outlook.exe,Winword.exe,Excel.exe,PowerPoint.exe
#
#
############################################################################################

[cmdletbinding( SupportsShouldProcess=$true, ConfirmImpact="High" )]

Param
(
	[ValidateSet("","Enabled","Disabled")] [string] $DefaultState = "",
	[Array] $OptIn = $null,
	[Array] $OptOut = $null,
	[switch] $Strict = $false
);

#
#	Enable -Strict PowerShell parsing
#

Set-PSDebug -Strict
Set-StrictMode -Version "Latest"

#
#	Assign -Strict parameter values (i.e. the most secure configuration)
#

if( $Strict )
{
	$DefaultState = "Enabled";
	$OptOut = @();
	$OptIn = $null;
}

#
#	Shortcuts for SEHOP registry values
#

$sehopPath = "hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\kernel";
$ifeoPath = "hklm:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options";
$sehopName = "DisableExceptionChainValidation";
$sehopEnabled = 0;
$sehopDisabled = 1;

#
#	Set the SEHOP computer-wide default value (if different from current state)
#

# get current SEHOP computer-wide default value

$key = get-item $sehopPath;	 # this key is guaranteed to exist

$valueExist = $key.GetValueNames() -contains $sehopName;

if( $valueExist )
{
	if( $key.GetValueKind($sehopName) -eq "dword" )
	{
		$value = $key.GetValue($sehopName);
	}
	else
	{
		$key.DeleteValue($sehopName);	# get rid of wrong value type
		
		$valueExist = $false;			# pretend value did not exist
	}
}

if( -not $valueExist )
{
	$value = "<UNDEFINED>";				# show that value was missing
}

if( $defaultState -ne "" )
{
	# compute new SEHOP computer-wide default value
	
	$defaultValue = if( $DefaultState -eq "Enabled" ) { $sehopEnabled } else { $sehopDisabled };
	
	# change current value to new value if different
	
	if( $value -ne $defaultValue )
	{
		if( $valueExist )
		{
			# cannot use $key.SetValue() since get-item opens $key in READ-ONLY mode
			$null = set-itemproperty -Path $sehopPath -Name $sehopName -Value $defaultValue;
			
		}
		else
		{
			$null = new-itemproperty -Path $sehopPath -Name $sehopName -PropertyType "dword" -Value $defaultValue
		}
			
		Write-Verbose "Changed computer-wide SEHOP $sehopName from $value to $defaultValue"
	}
}

#
#	Get IFEO registry keys with a value named $sehopName and extract OptIns and OptOuts
#

$ifeoSehopKeys = @() + @( get-childitem "$ifeoPath\*.exe" | where { $_.Property -contains $sehopName } )

$optInValues = @() + @( $ifeoSehopKeys | where { $_.GetValue($sehopName) -eq $sehopEnabled } | % { $_.PsChildName } )

$optOutValues = @() + @( $ifeoSehopKeys | where { $_.GetValue($sehopName) -ne $sehopEnabled } | % { $_.PsChildName } )

#
#	Output current SEHOP state
#

if( ($DefaultState -eq "") -and ($OptIn -isnot [array]) -and ($OptOut -isnot [Array]) )
{
	"No configuration changes applied to the system."
}
else
{
	"Old SEHOP State:"

	$value = if($value -eq $sehopEnabled) {"Enabled"} else {"Disabled"};

	"  Default = $value";

	$ifeoSehopKeys | foreach-object {
		$program = $_.PsChildName; 
		$value = $_.GetValue($sehopName);
		$state = if ($value -eq $sehopEnabled) {"Enabled"} else {"Disabled"} ;
		"  $program = $state";
	}
}

#
#	Function that checks actual SEHOP IFEO exceptions against OptIn/OptOut 
#	and corrects any deviations. Uses recursion so that the same code can
#	be used to check both OptIn and OptOut.
#

Function SetIfeoSehop([array]$optIn=$null, [array]$optOut=$null)
{
	#
	#	Split job in two parts if both OptIn and OptOut are given.
	#	Select relevant parameters for the given job.
	#
	
	if( $OptIn -is [array] -and $OptOut -is [array] )
	{
		SetIfeoSehop -OptOut $OptOut; 							# 1. half of job
		SetIfeoSehop -OptIn $OptIn;								# 2. half of job
		return;
	}
	elseif( $OptOut -is [array] -and $OptIn -isnot [array] )	# 1. half of job
	{
		$desiredExceptions = $OptOut;
		$desiredValue = $sehopDisabled;
	}	
	elseif( $OptIn -is [array] -and $OptOut -isnot [array] )	# 2. half of job
	{
		$desiredExceptions = $OptIn;
		$desiredValue = $sehopEnabled;
	}
	else
	{
		return;													# no touch
	}
	
	#
	#	do the actual work
	#
	
	if( $desiredExceptions -is [array] )
	{
		$ifeoSehopKeys = @() + @( get-childitem "$ifeoPath\*.exe" | where { $_.Property -contains $sehopName } )

		$actualExceptions = @() + @( $ifeoSehopKeys | where { $_.GetValue($sehopName) -eq $desiredValue } | % { $_.PsChildName } )

		# check for program exception not in registry
	
		foreach( $program in $desiredExceptions )
		{
			if( $actualExceptions -notcontains $program )
			{
				if( -not (Test-Path "$ifeoPath\$program") ) 
				{
					$null = New-Item -Type Directory -Path "$ifeoPath\$program"
					
					$valueExist = $false;
				}
				else
				{
					$valueExist = (get-item "$ifeoPath\$program").Property -contains $sehopName;
				}
	
				if( $valueExist )
				{
					$null = set-itemproperty -Path "$ifeoPath\$program" -Name $sehopName -Value $desiredValue
				}
				else
				{
					$null = new-itemproperty -Path "$ifeoPath\$program" -Name $sehopName -PropertyType dword -Value $desiredValue
				}

				write-verbose "added SEHOP $sehopName = $desiredValue to the IFEO key of $program"
			}
		}
		
		# check for extra programs exceptions in registry
	
		foreach( $program in $actualExceptions )
		{
			if( $desiredExceptions -notcontains $program ) 			
			{
				# remove SEHOP value from IFEO key
				
				$null = Remove-ItemProperty -Path "$ifeoPath\$program" -Name $sehopName 
				
				write-verbose "removed SEHOP $sehopName from the IFEO key of $program"
				
				# remove IFEO key if no remaining values or subkeys
				
				$key = get-item "$ifeoPath\$program";
				
				if( ($key.ValueCount -eq 0) -and ($key.SubkeyCount -eq 0) ) 
				{
					$null = Remove-Item -Path "$ifeoPath\$program"
					
					Write-Verbose "removed empty IFEO key for $program"
				}
			}
		}
	}
}

#
#	Check parameter OptOut and OptIn against current IFEO exceptions and correct any deviations
#

SetIfeoSehop -OptOut $OptOut -OptIn $OptIn

#
#	Output new/current SEHOP state based on new registry lookups
#

"Current SEHOP State:"

$value = (Get-Item -Path $sehopPath).GetValue($sehopName);

$state = if ($value -eq $sehopEnabled) {"Enabled"} else {"Disabled"} ;

"  Default = $state"

get-childitem "$ifeoPath\*.exe" | where { $_.Property -contains $sehopName } | foreach-object {
	$program = $_.PsChildName; 
	$value = $_.GetValue($sehopName);
	$state = if ($value -eq $sehopEnabled) {"Enabled"} else {"Disabled"} ;
	"  $program = $state";
}

"Use ""SetSehop.ps1 -Strict"" to apply the most secure SEHOP configuration."