diff --git a/Get-ZimmermanTools.ps1 b/Get-ZimmermanTools.ps1 new file mode 100644 index 0000000..c851614 --- /dev/null +++ b/Get-ZimmermanTools.ps1 @@ -0,0 +1,440 @@ +<# +.SYNOPSIS + This script will discover and download all available programs from https://ericzimmerman.github.io and download them to $Dest +.DESCRIPTION + A file will also be created in $Dest that tracks the SHA-1 of each file, so rerunning the script will only download new versions. To redownload, remove lines from or delete the CSV file created under $Dest and rerun. +.PARAMETER Dest + The path you want to save the programs to. +.EXAMPLE + C:\PS> Get-ZimmermanTools.ps1 -Dest c:\tools + Downloads/extracts and saves details about programs to c:\tools directory. +.NOTES + Author: Eric Zimmerman + Date: January 22, 2019 +#> + +[CmdletBinding(DefaultParameterSetName="NoProxy")] +Param +( + [Parameter()] + [string]$Dest= (Resolve-Path "."), #Where to save programs to + + #Specifies a proxy server for the request, rather than connecting directly to the Internet resource. Enter the URI of a network proxy server. + [Parameter(Mandatory=$true, + ParameterSetName="ProxyAlone")] + [Parameter(Mandatory=$true, + ParameterSetName="ProxyWithCreds")] + [Parameter(Mandatory=$true, + ParameterSetName="ProxyDefaultCreds")] + [string]$Proxy, + + #Specifies a user account that has permission to use the proxy server that is specified by the Proxy parameter. + #Type a user name, such as "User01" or "Domain01\User01", or enter a PSCredential object, such as one generated by the Get-Credential cmdlet. + #This parameter is valid only when the Proxy parameter is also used in the command. You cannot use the ProxyCredential and ProxyUseDefaultCredentials parameters in the same command. + [Parameter(Mandatory=$true, + ParameterSetName="ProxyWithCreds")] + [pscredential]$ProxyCredential, + + #Indicates that the cmdlet uses the credentials of the current user to access the proxy server that is specified by the Proxy parameter. + #This parameter is valid only when the Proxy parameter is also used in the command. You cannot use the ProxyCredential and ProxyUseDefaultCredentials parameters in the same command. + [Parameter(Mandatory=$true, + ParameterSetName="ProxyDefaultCreds")] + [switch]$ProxyUseDefaultCredentials + +) + + +function Write-Color { + <# + .SYNOPSIS + Write-Color is a wrapper around Write-Host. + It provides: + - Easy manipulation of colors, + - Logging output to file (log) + - Nice formatting options out of the box. + .DESCRIPTION + Author: przemyslaw.klys at evotec.pl + Project website: https://evotec.xyz/hub/scripts/Write-Color-ps1/ + Project support: https://github.com/EvotecIT/PSWriteColor + Original idea: Josh (https://stackoverflow.com/users/81769/josh) + .EXAMPLE + Write-Color -Text "Red ", "Green ", "Yellow " -Color Red,Green,Yellow + .EXAMPLE + Write-Color -Text "This is text in Green ", + "followed by red ", + "and then we have Magenta... ", + "isn't it fun? ", + "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan + .EXAMPLE + Write-Color -Text "This is text in Green ", + "followed by red ", + "and then we have Magenta... ", + "isn't it fun? ", + "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan -StartTab 3 -LinesBefore 1 -LinesAfter 1 + .EXAMPLE + Write-Color "1. ", "Option 1" -Color Yellow, Green + Write-Color "2. ", "Option 2" -Color Yellow, Green + Write-Color "3. ", "Option 3" -Color Yellow, Green + Write-Color "4. ", "Option 4" -Color Yellow, Green + Write-Color "9. ", "Press 9 to exit" -Color Yellow, Gray -LinesBefore 1 + .EXAMPLE + Write-Color -LinesBefore 2 -Text "This little ","message is ", "written to log ", "file as well." ` + -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" -TimeFormat "yyyy-MM-dd HH:mm:ss" + Write-Color -Text "This can get ","handy if ", "want to display things, and log actions to file ", "at the same time." ` + -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" + .EXAMPLE + # Added in 0.5 + Write-Color -T "My text", " is ", "all colorful" -C Yellow, Red, Green -B Green, Green, Yellow + wc -t "my text" -c yellow -b green + wc -text "my text" -c red + .NOTES + CHANGELOG + Version 0.5 (25th April 2018) + ----------- + - Added backgroundcolor + - Added aliases T/B/C to shorter code + - Added alias to function (can be used with "WC") + - Fixes to module publishing + Version 0.4.0-0.4.9 (25th April 2018) + ------------------- + - Published as module + - Fixed small issues + Version 0.31 (20th April 2018) + ------------ + - Added Try/Catch for Write-Output (might need some additional work) + - Small change to parameters + Version 0.3 (9th April 2018) + ----------- + - Added -ShowTime + - Added -NoNewLine + - Added function description + - Changed some formatting + Version 0.2 + ----------- + - Added logging to file + Version 0.1 + ----------- + - First draft + Additional Notes: + - TimeFormat https://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx + #> + [alias('Write-Colour')] + [CmdletBinding()] + param ( + [alias ('T')] [String[]]$Text, + [alias ('C', 'ForegroundColor', 'FGC')] [ConsoleColor[]]$Color = [ConsoleColor]::White, + [alias ('B', 'BGC')] [ConsoleColor[]]$BackGroundColor = $null, + [alias ('Indent')][int] $StartTab = 0, + [int] $LinesBefore = 0, + [int] $LinesAfter = 0, + [int] $StartSpaces = 0, + [alias ('L')] [string] $LogFile = '', + [Alias('DateFormat', 'TimeFormat')][string] $DateTimeFormat = 'yyyy-MM-dd HH:mm:ss', + [alias ('LogTimeStamp')][bool] $LogTime = $true, + [ValidateSet('unknown', 'string', 'unicode', 'bigendianunicode', 'utf8', 'utf7', 'utf32', 'ascii', 'default', 'oem')][string]$Encoding = 'Unicode', + [switch] $ShowTime, + [switch] $NoNewLine + ) + $DefaultColor = $Color[0] + if ($null -ne $BackGroundColor -and $BackGroundColor.Count -ne $Color.Count) { Write-Error "Colors, BackGroundColors parameters count doesn't match. Terminated." ; return } + #if ($Text.Count -eq 0) { return } + if ($LinesBefore -ne 0) { for ($i = 0; $i -lt $LinesBefore; $i++) { Write-Host -Object "`n" -NoNewline } } # Add empty line before + if ($StartTab -ne 0) { for ($i = 0; $i -lt $StartTab; $i++) { Write-Host -Object "`t" -NoNewLine } } # Add TABS before text + if ($StartSpaces -ne 0) { for ($i = 0; $i -lt $StartSpaces; $i++) { Write-Host -Object ' ' -NoNewLine } } # Add SPACES before text + if ($ShowTime) { Write-Host -Object "[$([datetime]::Now.ToString($DateTimeFormat))]" -NoNewline} # Add Time before output + if ($Text.Count -ne 0) { + if ($Color.Count -ge $Text.Count) { + # the real deal coloring + if ($null -eq $BackGroundColor) { + for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } + } else { + for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -BackgroundColor $BackGroundColor[$i] -NoNewLine } + } + } else { + if ($null -eq $BackGroundColor) { + for ($i = 0; $i -lt $Color.Length ; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } + for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $DefaultColor -NoNewLine } + } else { + for ($i = 0; $i -lt $Color.Length ; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $Color[$i] -BackgroundColor $BackGroundColor[$i] -NoNewLine } + for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host -Object $Text[$i] -ForegroundColor $DefaultColor -BackgroundColor $BackGroundColor[0] -NoNewLine } + } + } + } + if ($NoNewLine -eq $true) { Write-Host -NoNewline } else { Write-Host } # Support for no new line + if ($LinesAfter -ne 0) { for ($i = 0; $i -lt $LinesAfter; $i++) { Write-Host -Object "`n" -NoNewline } } # Add empty line after + if ($Text.Count -ne 0 -and $LogFile -ne "") { + # Save to file + $TextToFile = "" + for ($i = 0; $i -lt $Text.Length; $i++) { + $TextToFile += $Text[$i] + } + try { + if ($LogTime) { + Write-Output -InputObject "[$([datetime]::Now.ToString($DateTimeFormat))]$TextToFile" | Out-File -FilePath $LogFile -Encoding $Encoding -Append + } else { + Write-Output -InputObject "$TextToFile" | Out-File -FilePath $LogFile -Encoding $Encoding -Append + } + } catch { + $_.Exception + } + } +} + +#Setup proxy information for Invoke-WebRequest +[hashtable]$IWRProxyConfig = @{} + +if ($Proxy){ + $IWRProxyConfig.Add("Proxy",$Proxy) +} +if ($ProxyCredential){ + $IWRProxyConfig.Add("ProxyCredential",$ProxyCredential) +} +if ($ProxyUseDefaultCredentials){ + $IWRProxyConfig.Add("ProxyUseDefaultCredentials",$true) +} + + +Write-Color -LinesBefore 1 "This script will discover and download all available programs" -BackgroundColor Blue +Write-Color "from https://ericzimmerman.github.io and download them to $Dest" -BackgroundColor Blue -LinesAfter 1 +Write-Color "A file will also be created in $Dest that tracks the SHA-1 of each file," +Write-Color "so rerunning the script will only download new versions." +Write-Color -LinesBefore 1 -Text "To redownload, remove lines from or delete the CSV file created under $Dest and rerun. Enjoy!" -LinesAfter 1 + +$TestColor = (Get-Host).ui.rawui.ForegroundColor +if ($TestColor -eq -1) +{ + $defaultColor = [ConsoleColor]::Gray +} else { + $defaultColor = $TestColor +} + +$newInstall = $false + +if(!(Test-Path -Path $Dest )) +{ + Write-Color -Text "* ", "$Dest does not exist. Creating..." -Color Green,$defaultColor + New-Item -ItemType directory -Path $Dest > $null + + $newInstall = $true +} + +$URL = "https://raw.githubusercontent.com/EricZimmerman/ericzimmerman.github.io/master/index.md" + +$WebKeyCollection = @() + +$localDetailsFile = Join-Path $Dest -ChildPath "!!!RemoteFileDetails.csv" + +if (Test-Path -Path $localDetailsFile) +{ + Write-Color -Text "* ", "Loading local details from '$Dest'..." -Color Green,$defaultColor + $LocalKeyCollection = Import-Csv -Path $localDetailsFile +} + +$toDownload = @() + +#Get zips +$progressPreference = 'silentlyContinue' +$PageContent = (Invoke-WebRequest @IWRProxyConfig -Uri $URL -UseBasicParsing).Content +$progressPreference = 'Continue' + +$regex = [regex] '(?i)\b(https)://[-A-Z0-9+&@#/%?=~_|$!:,.;]*[A-Z0-9+&@#/%=~_|$].(zip|txt)' +$matchdetails = $regex.Match($PageContent) + +Write-Color -Text "* ", "Getting available programs..." -Color Green,$defaultColor +$progressPreference = 'silentlyContinue' +while ($matchdetails.Success) { + $headers = (Invoke-WebRequest @IWRProxyConfig -Uri $matchdetails.Value -UseBasicParsing -Method Head).Headers + + $getUrl = $matchdetails.Value + $sha = $headers["x-bz-content-sha1"] + $name = $headers["x-bz-file-name"] + $size = $headers["Content-Length"] + + $details = @{ + Name = [string]$name + SHA1 = [string]$sha + URL = [string]$getUrl + Size = [string]$size + } + + $webKeyCollection += New-Object PSObject -Property $details + + $matchdetails = $matchdetails.NextMatch() +} +$progressPreference = 'Continue' + +Foreach ($webKey in $webKeyCollection) +{ + if ($newInstall) + { + $toDownload+= $webKey + continue + } + + $localFile = $LocalKeyCollection | Where-Object {$_.Name -eq $webKey.Name} + + if ($null -eq $localFile -or $localFile.SHA1 -ne $webKey.SHA1) + { + #Needs to be downloaded since SHA is different or it doesnt exist + $toDownload+= $webKey + } +} + +if ($toDownload.Count -eq 0) +{ + Write-Color -LinesBefore 1 -Text "* ", "All files current. Exiting." -Color Green,Blue -LinesAfter 1 + return +} + +$downloadedOK = @() + +$destFile = "" +$name = "" + +$i=0 +$dlCount= $toDownload.Count +Write-Color -Text "* ", "Files to download: $dlCount" -Color Green,$defaultColor +foreach($td in $toDownload) +{ + $p = [math]::round( ($i/$toDownload.Count) *100, 2 ) + + #Write-Host ($td | Format-Table | Out-String) + + try + { + $dUrl = $td.URL + $size = $td.Size + $name = $td.Name + + Write-Progress -Activity "Updating programs...." -Status "$p% Complete" -PercentComplete $p -CurrentOperation "Downloading $name" + $destFile = [IO.Path]::Combine($Dest, $name) + + $progressPreference = 'silentlyContinue' + Invoke-WebRequest @IWRProxyConfig -Uri $dUrl -OutFile $destFile -ErrorAction:Stop -UseBasicParsing + + Write-Color -Text "* ", "Downloaded $name (Size: $size)" -Color Green,Blue + + if ( $name.endswith("zip") ) + { + Expand-Archive -Path $destFile -DestinationPath $Dest -Force + } + + $downloadedOK += $td + } + catch + { + $ErrorMessage = $_.Exception.Message + Write-Color -Text "* ", "Error downloading $name ($ErrorMessage). Wait for the run to finish and try again by repeating the command" -Color Green,Red + } + finally + { + $progressPreference = 'Continue' + if ( $name.endswith("zip") ) + { + remove-item -Path $destFile + } + + } + $i+=1 +} + +#Write-Host ($webKeyCollection | Format-Table | Out-String) + +#Downloaded ok contains new stuff, but we need to account for existing stuff too +foreach($webItems in $webKeyCollection) +{ + #Check what we have locally to see if it also contains what is in the web collection + $localFile = $LocalKeyCollection | Where-Object {$_.SHA1 -eq $webItems.SHA1} + + #if its not null, we have a local file match against what is on the website, so its ok + + if ($null -ne $localFile) + { + #consider it downloaded since SHAs match + $downloadedOK+=$webItems + } +} + + +Write-Color -LinesBefore 1 -Text "* ", "Saving downloaded version information to $localDetailsFile" -Color Green,$defaultColor -LinesAfter 1 + +$downloadedOK | export-csv -Path $localDetailsFile + + +# SIG # Begin signature block +# MIIOCQYJKoZIhvcNAQcCoIIN+jCCDfYCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB +# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR +# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU3h3hKI/PCw9Fhvn2sUIunz8M +# gFmgggtAMIIFQzCCBCugAwIBAgIRAOhGMy2+0dm4G+A32Y4gvJwwDQYJKoZIhvcN +# AQELBQAwfDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3Rl +# cjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQw +# IgYDVQQDExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMTkxMjI1MDAw +# MDAwWhcNMjMwMzI0MjM1OTU5WjCBkjELMAkGA1UEBhMCVVMxDjAMBgNVBBEMBTQ2 +# MDQwMQswCQYDVQQIDAJJTjEQMA4GA1UEBwwHRmlzaGVyczEcMBoGA1UECQwTMTU2 +# NzIgUHJvdmluY2lhbCBMbjEaMBgGA1UECgwRRXJpYyBSLiBaaW1tZXJtYW4xGjAY +# BgNVBAMMEUVyaWMgUi4gWmltbWVybWFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +# MIIBCgKCAQEAtU2gix6QVzDg+YBDDNyZj1kPFwPDhTbojEup24x3swWNCI14P4dM +# Cs6SKDUPmKhe8k5aLpv9eacsgyndyYkrcSGFCwUwbTnetrn8lzOFu53Vz4sjFIMl +# mKVSPfKE7GBoBcJ8jT3LKoB7YzZF6khoQY84fOJPNOj7snfExN64J6KVQlDsgOjL +# wY720m8bN/Rn+Vp+FBXHyUIjHhhvb+o29xFmemxzfTWXhDM2oIX4kRuF/Zmfo9l8 +# n3J+iOBL/IiIVTi68adYxq3s0ASxgrQ4HO3veGgzNZ9KSB1ltXyNVGstInIs+UZP +# lKynweRQJO5cc7zK64sSotjgwlcaQdBAHQIDAQABo4IBpzCCAaMwHwYDVR0jBBgw +# FoAUDuE6qFM6MdWKvsG7rWcaA4WtNA4wHQYDVR0OBBYEFGsRm7mtwiWCh8MSEbEX +# TwjtcryvMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoG +# CCsGAQUFBwMDMBEGCWCGSAGG+EIBAQQEAwIEEDBABgNVHSAEOTA3MDUGDCsGAQQB +# sjEBAgEDAjAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzBD +# BgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29S +# U0FDb2RlU2lnbmluZ0NBLmNybDBzBggrBgEFBQcBAQRnMGUwPgYIKwYBBQUHMAKG +# Mmh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1JTQUNvZGVTaWduaW5nQ0Eu +# Y3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAfBgNVHREE +# GDAWgRRlcmljQG1pa2VzdGFtbWVyLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAhX// +# xLBhfLf4X2OPavhp/AlmnpkQU8yIZv8DjVQKJ0j8YhxClIAgyuSb/6+q+njOsxMn +# ZDoCAPlzG0P74e1nYTiw3beG6ePr3uDc9PjUBxDiHgxlI69mlXYdjiAircV5Z8iU +# TcmqJ9LpnTcrvtmQAvN1ldoSW4hmHIJuV0XLOhvAlURuPM1/C9lh0K65nH3wYIoU +# /0pELlDfIdUxL2vOLnElxCv0z07Hf9yw+3grWHJb54Vms6o/xYxZgqCu02DH0q1f +# KrNBwtDkLKKObBF54wA7LdaDGbl3CJXQVRmgokcDI/izmZJxHAHebdbj4zVFyCND +# sMRySmbR+m58q/jv3DCCBfUwggPdoAMCAQICEB2iSDBvmyYY0ILgln0z02owDQYJ +# KoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5 +# MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBO +# ZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0 +# aG9yaXR5MB4XDTE4MTEwMjAwMDAwMFoXDTMwMTIzMTIzNTk1OVowfDELMAkGA1UE +# BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2Fs +# Zm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQDExtTZWN0aWdv +# IFJTQSBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +# AoIBAQCGIo0yhXoYn0nwli9jCB4t3HyfFM/jJrYlZilAhlRGdDFixRDtsocnppnL +# lTDAVvWkdcapDlBipVGREGrgS2Ku/fD4GKyn/+4uMyD6DBmJqGx7rQDDYaHcaWVt +# H24nlteXUYam9CflfGqLlR5bYNV+1xaSnAAvaPeX7Wpyvjg7Y96Pv25MQV0SIAhZ +# 6DnNj9LWzwa0VwW2TqE+V2sfmLzEYtYbC43HZhtKn52BxHJAteJf7wtF/6POF6Yt +# VbC3sLxUap28jVZTxvC6eVBJLPcDuf4vZTXyIuosB69G2flGHNyMfHEo8/6nxhTd +# VZFuihEN3wYklX0Pp6F8OtqGNWHTAgMBAAGjggFkMIIBYDAfBgNVHSMEGDAWgBRT +# eb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUDuE6qFM6MdWKvsG7rWcaA4Wt +# NA4wDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYw +# FAYIKwYBBQUHAwMGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0gADBQBgNVHR8E +# STBHMEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNB +# Q2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEEajBoMD8GCCsG +# AQUFBzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQWRk +# VHJ1c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5j +# b20wDQYJKoZIhvcNAQEMBQADggIBAE1jUO1HNEphpNveaiqMm/EAAB4dYns61zLC +# 9rPgY7P7YQCImhttEAcET7646ol4IusPRuzzRl5ARokS9At3WpwqQTr81vTr5/cV +# lTPDoYMot94v5JT3hTODLUpASL+awk9KsY8k9LOBN9O3ZLCmI2pZaFJCX/8E6+F0 +# ZXkI9amT3mtxQJmWunjxucjiwwgWsatjWsgVgG10Xkp1fqW4w2y1z99KeYdcx0BN +# YzX2MNPPtQoOCwR/oEuuu6Ol0IQAkz5TXTSlADVpbL6fICUQDRn7UJBhvjmPeo5N +# 9p8OHv4HURJmgyYZSJXOSsnBf/M6BZv5b9+If8AjntIeQ3pFMcGcTanwWbJZGehq +# jSkEAnd8S0vNcL46slVaeD68u28DECV3FTSK+TbMQ5Lkuk/xYpMoJVcp+1EZx6El +# QGqEV8aynbG8HArafGd+fS7pKEwYfsR7MUFxmksp7As9V1DSyt39ngVR5UR43QHe +# sXWYDVQk/fBO4+L4g71yuss9Ou7wXheSaG3IYfmm8SoKC6W59J7umDIFhZ7r+YMp +# 08Ysfb06dy6LN0KgaoLtO0qqlBCk4Q34F8W2WnkzGJLjtXX4oemOCiUe5B7xn1qH +# I/+fpFGe+zmAEc3btcSnqIBv5VPU4OOiwtJbGvoyJi1qV3AcPKRYLqPzW0sH3DJZ +# 84enGm1YMYICMzCCAi8CAQEwgZEwfDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +# ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2Vj +# dGlnbyBMaW1pdGVkMSQwIgYDVQQDExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcg +# Q0ECEQDoRjMtvtHZuBvgN9mOILycMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEM +# MQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQB +# gjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBSub3DNneg8U2SV +# 3eSlV1WAf1WW3jANBgkqhkiG9w0BAQEFAASCAQBfJ7rjKfvcpG38nVyhlWsnJY5h +# udJfTzZ4Cd5CSNnf84dPyLFqMCjk6PhCzFteJ6JimvoOiCu0N0DRYjIGaL6+iKWK +# P5IBFWyNSmH3PN3ENjmOj0xTnKdodJ8Uos9GmYT7JXtodYpO2fxTKyq5yAwY1dY4 +# jmrDdQgseRoR99UTzVO7BZHsBbDj6mT3Jo1NVCD5fgz1CtMi++fFYlayOUPwDBr0 +# DnV0yg0wR6CPMH37Qx2Y6jRpD5Yk9BrypT50rY9ORayOL0qav4srjVVN8MwMHjcq +# PMarEg4Hyq+Q91i4+z0xp+PwWNuwwbdrrJaQwa6FXgbC3GJgCHqTNnVbZPh2 +# SIG # End signature block