1187 lines
47 KiB
PowerShell
1187 lines
47 KiB
PowerShell
# FileHandlers.psm1
|
|
|
|
#region FonctionDetect
|
|
|
|
function Get-OthersContent {
|
|
param (
|
|
[string]$filepath,
|
|
[string[]]$patterns
|
|
)
|
|
$results = @()
|
|
try {
|
|
$findmatch = Select-String -Path $filepath -Pattern $patterns -AllMatches
|
|
foreach ($match in $findmatch) {
|
|
|
|
$patternMatch = $match.pattern -replace '\\b',''
|
|
[string]$word= $match.line.Replace($patternMatch,'')
|
|
|
|
if (-not([string]::IsNullOrEmpty(($word -replace '^[\s=:"]+').Trim()))){
|
|
|
|
switch ($patternMatch) {
|
|
'(?:[0-9]{1,3}\.){3}[0-9]{1,3}' { $patternMatch = 'IPv4' }
|
|
'[a-fA-F0-9]{32}' { $patternMatch = 'MD5' }
|
|
'[a-fA-F0-9]{40}' { $patternMatch = 'SHA-1' }
|
|
'[a-fA-F0-9]{64}' { $patternMatch = 'SHA-256' }
|
|
default {
|
|
switch -Wildcard ($patternMatch) {
|
|
'net *' { $patternMatch = 'Commande Net User' }
|
|
default { $patternMatch = $patternMatch }
|
|
}
|
|
}
|
|
}
|
|
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = $patternMatch
|
|
Reason = $match.Line
|
|
}
|
|
$results += $result
|
|
}
|
|
}
|
|
} catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'error'
|
|
Reason = $_.Exception.Message
|
|
}
|
|
$results = $result
|
|
}
|
|
return $results
|
|
}
|
|
|
|
function Get-DocxContent {
|
|
param (
|
|
[string]$filepath,
|
|
[string[]]$patterns
|
|
)
|
|
$results = @()
|
|
Import-Module PSWriteOffice
|
|
try {
|
|
$document = Get-OfficeWord -FilePath $filepath -ReadOnly
|
|
$n = 0
|
|
foreach ($pattern in $patterns) {
|
|
$pattern = $pattern -replace '\\b', ''
|
|
[string]$findtext = $document.Find($pattern) | Select-Object text -First 2
|
|
if ($findtext) {
|
|
if ($n -le '1') {
|
|
foreach ($text in $findtext) {
|
|
$n++
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = $pattern
|
|
Reason = $text
|
|
}
|
|
$results += $result
|
|
}
|
|
} elseif ($n -gt '1') {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = $pattern
|
|
Reason = "at least " + $n + " characters found"
|
|
}
|
|
$results += $result
|
|
break }
|
|
}
|
|
}
|
|
Close-OfficeWord -Document $document
|
|
}
|
|
catch { $result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'error'
|
|
Reason = $_
|
|
}
|
|
$results = $result
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-XlsxContent {
|
|
param (
|
|
[string]$filepath,
|
|
[string[]]$patterns
|
|
)
|
|
$results = @()
|
|
Import-Module PSWriteOffice
|
|
try {
|
|
$excel = Get-OfficeExcel -FilePath $filepath
|
|
$n = 0
|
|
foreach ($pattern in $patterns) {
|
|
$pattern = $pattern -replace '\\b', ''
|
|
[string]$findtext = $excel.Search($pattern, [System.Globalization.CompareOptions]::IgnoreCase, $false) | Select-Object value -First 2
|
|
if ($findtext) {
|
|
if ($n -le '2') {
|
|
foreach ($text in $findtext) {
|
|
$n++
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = $pattern
|
|
Reason = $text
|
|
}
|
|
$results += $result
|
|
}
|
|
} else {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = $pattern
|
|
Reason = "at least " + $n + " characters found"
|
|
}
|
|
$results += $result
|
|
break }
|
|
}
|
|
}
|
|
$excel.Dispose()
|
|
}
|
|
catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'error'
|
|
Reason = $_
|
|
}
|
|
$results = $result
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-DocContent {
|
|
param (
|
|
[string]$filepath,
|
|
[string[]]$patterns,
|
|
[string]$wordinstalled
|
|
)
|
|
$results = @()
|
|
if ($wordinstalled -eq $false) {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'requires_check'
|
|
Reason = 'Word is not installed'
|
|
}
|
|
$results += $result
|
|
} else {
|
|
$wordApp = New-Object -ComObject Word.Application
|
|
$wordApp.Visible = $false
|
|
try {
|
|
$document = $wordApp.Documents.Open($filepath, [ref]$null, [ref]$true)
|
|
$n = 0
|
|
foreach ($pattern in $patterns) {
|
|
$pattern = $pattern -replace '\\b', ''
|
|
$find = $document.Content.Find | Select-Object -First 1
|
|
$find.Text = $pattern
|
|
$find.Forward = $true
|
|
$find.Wrap = 1 # wdFindContinue
|
|
$find.Execute() | Out-Null
|
|
if ($find.Found) {
|
|
if ($n -le '2') {
|
|
$n++
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = $pattern
|
|
Reason = "at least " + $n + " characters found"
|
|
}
|
|
$results = $result
|
|
} else { break }
|
|
}
|
|
}
|
|
$document.Close([ref]$false)
|
|
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($document) | Out-Null
|
|
} catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'error'
|
|
Reason = $_.Exception.Message
|
|
}
|
|
$results = $result
|
|
} finally {
|
|
$wordApp.Quit()
|
|
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($wordApp) | Out-Null
|
|
[System.GC]::Collect()
|
|
[System.GC]::WaitForPendingFinalizers()
|
|
}
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-XlsContent {
|
|
param (
|
|
[string]$filePath,
|
|
[string[]]$patterns,
|
|
[string]$excelInstalled
|
|
)
|
|
$results = @()
|
|
|
|
if ($excelInstalled -eq $false) {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filePath
|
|
pattern = 'requires_check'
|
|
Reason = 'Excel is not installed'
|
|
}
|
|
$results += $result
|
|
} else {
|
|
$excelApp = New-Object -ComObject Excel.Application
|
|
$excelApp.Visible = $false
|
|
try {
|
|
$workbook = $excelApp.Workbooks.Open($filePath, [ref]$null, [ref]$true)
|
|
$n = 0
|
|
foreach ($pattern in $patterns) {
|
|
$pattern = $pattern -replace '\\b', ''
|
|
foreach ($sheet in $workbook.Sheets) {
|
|
$cells = $sheet.Cells.Find($pattern)
|
|
if ($null -ne $cells) {
|
|
if ($n -le '2') {
|
|
$n++
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filePath
|
|
pattern = $pattern
|
|
Reason = "at least " + $n + " characters found"
|
|
}
|
|
$results = $result
|
|
} else { break }
|
|
}
|
|
}
|
|
}
|
|
$workbook.Close([ref]$false)
|
|
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook) | Out-Null
|
|
} catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filePath
|
|
pattern = 'error'
|
|
Reason = $_.Exception.Message
|
|
}
|
|
$results = $result
|
|
} finally {
|
|
$excelApp.Quit()
|
|
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelApp) | Out-Null
|
|
[System.GC]::Collect()
|
|
[System.GC]::WaitForPendingFinalizers()
|
|
}
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-PPTContent {
|
|
param (
|
|
[string]$filepath,
|
|
[string[]]$patterns,
|
|
[string]$wordinstalled
|
|
)
|
|
$results = @()
|
|
if ($wordinstalled -eq $false) {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'requires_check'
|
|
Reason = 'Office is not installed'
|
|
}
|
|
$results += $result
|
|
}
|
|
else {
|
|
try {
|
|
$MSPPT = New-Object -ComObject powerpoint.application
|
|
$PRES = $MSPPT.Presentations.Open($filepath, $true, $true, $false)
|
|
|
|
$n = 0
|
|
|
|
foreach($Slide in $PRES.Slides) {
|
|
foreach ($Shape in $Slide.Shapes) {
|
|
|
|
if ($Shape.HasTextFrame -eq "-1") {
|
|
$text = $Shape.TextFrame.TextRange.Text
|
|
|
|
foreach ($pattern in $patterns) {
|
|
|
|
$pattern = $pattern -replace '\\b', ''
|
|
|
|
if ($text -match $pattern) {
|
|
|
|
if ($n -le '2') {
|
|
|
|
$n++
|
|
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = $pattern
|
|
Reason = "at least " + $n + " characters found"
|
|
}
|
|
$results = $result
|
|
} else { break }
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$MSPPT.PresentationClose
|
|
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($MSPPT) | Out-Null
|
|
} catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'error'
|
|
Reason = $_.Exception.Message
|
|
}
|
|
$results = $result
|
|
} finally {
|
|
$MSPPT.Quit()
|
|
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($MSPPT) | Out-Null
|
|
[System.GC]::Collect()
|
|
[System.GC]::WaitForPendingFinalizers()
|
|
}
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-OdsContent {
|
|
param (
|
|
[string]$filePath,
|
|
[string[]]$patterns
|
|
)
|
|
$results = @()
|
|
|
|
|
|
# Open ODS file
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
$zip = [System.IO.Compression.ZipFile]::OpenRead($filePath)
|
|
|
|
# Extract contenant
|
|
$contentXmlEntry = $zip.Entries | Where-Object { $_.FullName -eq "content.xml" }
|
|
$reader = [System.IO.StreamReader]::new($contentXmlEntry.Open())
|
|
$contentXml = $reader.ReadToEnd()
|
|
$reader.Close()
|
|
$zip.Dispose()
|
|
|
|
# Analys file XML
|
|
[xml]$xmlContent = $contentXml
|
|
|
|
# Read text XML
|
|
$textContent = $xmlContent.'document-content'.InnerText
|
|
|
|
$n = 0
|
|
foreach ($pattern in $patterns) {
|
|
$pattern = $pattern -replace '\\b', ''
|
|
if ($textContent -match $pattern) {
|
|
if ($n -le '2') {
|
|
$n++
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filePath
|
|
Pattern = $pattern
|
|
Reason = "at least " + $n + " characters found"
|
|
}
|
|
$results = $result
|
|
}
|
|
}
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-Pdfcontent {
|
|
param (
|
|
[string]$filepath,
|
|
[string[]]$patterns
|
|
)
|
|
|
|
$results = @()
|
|
Import-Module PSWritePDF
|
|
try {
|
|
$text = (Convert-PDFToText -FilePath $filepath) -join "`n"
|
|
$n = 0
|
|
foreach ($pattern in $passwordPatterns) {
|
|
if ($text -match $pattern) {
|
|
if ($n -le '2') {
|
|
$n++
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = $pattern
|
|
Reason = "at least " + $n + " characters found"
|
|
}
|
|
$results = $result
|
|
} else { break }
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'error'
|
|
Reason = $_.Exception.Message
|
|
}
|
|
$results = $result
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-Xmlcontent {
|
|
param (
|
|
[string]$filepath,
|
|
[string[]]$patterns
|
|
)
|
|
$results = @()
|
|
$xmlContent = Get-Content -Path $filepath -Raw
|
|
if ($xmlContent -match 'cpassword') {
|
|
$xml = [xml]$xmlContent
|
|
# Check for cpassword
|
|
$cpasswords = @()
|
|
if ($xml.Groups.User) {
|
|
$cpasswords = $xml | Select-Xml "/Groups/User/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
} elseif ($xml.NTServices.NTService) {
|
|
$cpasswords = $xml | Select-Xml "/NTServices/NTService/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
} elseif ($xml.ScheduledTasks.Task) {
|
|
$cpasswords = $xml | Select-Xml "/ScheduledTasks/Task/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
} elseif ($xml.DataSources.DataSource) {
|
|
$cpasswords = $xml | Select-Xml "/DataSources/DataSource/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
} elseif ($xml.Printers.SharedPrinter) {
|
|
$cpasswords = $xml | Select-Xml "/Printers/SharedPrinter/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
} elseif ($xml.Drives.Drive) {
|
|
$cpasswords = $xml | Select-Xml "/Drives/Drive/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
}
|
|
if ($cpasswords) {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
Pattern = 'cpassword'
|
|
Reason = $cpasswords
|
|
}
|
|
$results += $result
|
|
}
|
|
}
|
|
elseif ($xmlContent -match 'DefaultUserName') {
|
|
|
|
$xml = [xml]$xmlContent
|
|
# Check for AutoLogon
|
|
$userName = ""
|
|
$password = ""
|
|
foreach ($registry in $xml.RegistrySettings.Registry) {
|
|
if ($registry.Properties.name -eq "DefaultUserName") {
|
|
$userName = $registry.Properties.value
|
|
}
|
|
if ($registry.Properties.name -eq "DefaultPassword") {
|
|
$password = $registry.Properties.value
|
|
}
|
|
}
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
Pattern = 'AutoLogon'
|
|
Reason = "$userName : $password"
|
|
}
|
|
$results += $result
|
|
}
|
|
else {
|
|
$xml = [xml]$xmlContent
|
|
foreach ($pattern in $patterns) {
|
|
$findmatches = $xmlContent | Select-String -Pattern $pattern
|
|
foreach ($match in $findmatches) {
|
|
|
|
switch ($pattern) {
|
|
'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b' { $pattern = 'IPv4' }
|
|
'\b[a-fA-F0-9]{32}\b' { $pattern = 'MD5' }
|
|
'\b[a-fA-F0-9]{40}\b' { $pattern = 'SHA-1' }
|
|
'\b[a-fA-F0-9]{64}\b' { $pattern = 'SHA-256' }
|
|
default {
|
|
switch -Wildcard ($pattern) {
|
|
'net *' { $pattern = 'Commande Net User' }
|
|
default { $pattern = $pattern }
|
|
}
|
|
}
|
|
}
|
|
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
Pattern = $pattern
|
|
Reason = $match.Matches.Value
|
|
}
|
|
$results += $result
|
|
}
|
|
}
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-Executablescontent {
|
|
|
|
param (
|
|
[string]$filepath
|
|
)
|
|
|
|
$results = @()
|
|
if ($filepath -notlike '*.jar') {
|
|
$signature = Get-AuthenticodeSignature -FilePath $filepath
|
|
if ($signature.Status -ne 'Valid') {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = "NotSigned"
|
|
Reason = 'File is Not Signed'
|
|
}
|
|
$results = $result
|
|
}
|
|
} else {
|
|
$isSigned = $false
|
|
try {
|
|
$zip = [System.IO.Compression.ZipFile]::OpenRead($filepath)
|
|
foreach ($entry in $zip.Entries) {
|
|
if ($entry.FullName -like "META-INF/*.SF") {
|
|
$isSigned = $true
|
|
break
|
|
}
|
|
}
|
|
$zip.Dispose()
|
|
} catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'error'
|
|
Reason = $_.Exception.Message
|
|
}
|
|
$results = $result
|
|
}
|
|
|
|
if (!$isSigned) {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = "NotSigned"
|
|
Reason = "Jar file not signed"
|
|
}
|
|
$results = $result
|
|
}
|
|
}
|
|
$results
|
|
}
|
|
|
|
function Get-Zipprotectedbypass {
|
|
param (
|
|
[string]$filepath,
|
|
[string]$zipinstalled
|
|
)
|
|
$extension = [System.IO.Path]::GetExtension($filePath).TrimStart('.')
|
|
if ($extension -eq "zip" ) {
|
|
try {
|
|
$zip = [System.IO.Compression.ZipFile]::OpenRead($filepath)
|
|
|
|
foreach ($entry in $zip.Entries) {
|
|
$stream = $entry.Open()
|
|
[byte[]]$buffer = New-Object byte[] 10
|
|
$stream.Read($buffer, 0, $buffer.Length) | Out-Null
|
|
$stream.Close()
|
|
break
|
|
}
|
|
|
|
$zip.Dispose()
|
|
return $null
|
|
}
|
|
catch {
|
|
if ($_.Exception.Message -match "(Read|Block|Password|Encrypted)") {
|
|
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Zip protected'
|
|
Reason = 'File protected by password'
|
|
}
|
|
|
|
return $result
|
|
} else {
|
|
Write-Host "Erreur inattendue : $_"
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Zip check error'
|
|
Reason = 'Error to read zip : $_'
|
|
}
|
|
return $result
|
|
}
|
|
}
|
|
} elseif ($zipinstalled) {
|
|
|
|
$sevenZipPath = $zipinstalled + "7z.exe"
|
|
$output = & "$sevenZipPath" t "$filepath" -pBadPasswordConf 2>&1
|
|
if ($output -match "Wrong password") {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Zip protected'
|
|
Reason = 'File protected by password'
|
|
}
|
|
return $result
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function Get-Requiredcheckcontent {
|
|
|
|
param (
|
|
[string]$filepath
|
|
)
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'check required'
|
|
Reason = 'Binary does not match'
|
|
}
|
|
|
|
return $result
|
|
}
|
|
|
|
function Get-CertifsContent {
|
|
param (
|
|
[string]$filePath
|
|
)
|
|
|
|
$results = @()
|
|
try {
|
|
# Try to load certificat with class .NET X509Certificate2
|
|
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
|
|
$cert.Import($filePath)
|
|
if (!$cert.Thumbprint) { $result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Certificate Empty'
|
|
Reason = 'Certificate without Thumbprint'
|
|
}
|
|
$results = $result }
|
|
if ($cert.PrivateKey) { $result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Certificate private key'
|
|
Reason = 'certificate with exportable private key'
|
|
}
|
|
$results += $result }
|
|
$cert.Dispose()
|
|
}
|
|
catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Protected Certificate'
|
|
Reason = ($_.Exception.Message).split(":").split("`n")[1].Trim()
|
|
}
|
|
$results = $result
|
|
}
|
|
return $results
|
|
}
|
|
|
|
function Get-P7bCertContent {
|
|
param (
|
|
[string]$filePath
|
|
)
|
|
$results = @()
|
|
try {
|
|
# Create certificate collection contenant P7B ou P7C
|
|
$certCollection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
|
|
$certCollection.Import($filePath)
|
|
|
|
# browse all certificate present in P7B/P7C
|
|
foreach ($cert in $certCollection) {
|
|
if (!$cert.Thumbprint) {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Certificate Empty'
|
|
Reason = 'Certificate without Thumbprint'
|
|
}
|
|
$results += $result
|
|
}
|
|
if ($cert.PrivateKey) {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Certificate private key'
|
|
Reason = 'certificate with exportable private key'
|
|
}
|
|
$results += $result
|
|
}
|
|
$cert.Dispose()
|
|
}
|
|
}
|
|
catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Protected Certificate'
|
|
Reason = $_.Exception.Message
|
|
}
|
|
$results = $result
|
|
}
|
|
return $results
|
|
}
|
|
|
|
function Get-HiddenFilesInImage {
|
|
param (
|
|
[string]$filePath
|
|
)
|
|
|
|
$fileInfo = Get-Item $filePath
|
|
$fileSizeMB = [math]::Round($fileInfo.Length / 1MB, 2)
|
|
|
|
# Skip file more than 4 Mo
|
|
if ($fileSizeMB -gt 4) {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Large size'
|
|
Reason = "File ignored: (size: $fileSizeMB MB)"
|
|
}
|
|
return $result
|
|
}
|
|
|
|
try {
|
|
# read binary and convert file to Hexa
|
|
$fileBytes = [System.IO.File]::ReadAllBytes($filePath)
|
|
$fileHex = [BitConverter]::ToString($fileBytes) -replace '-'
|
|
|
|
$magicNumbers = [ordered]@{
|
|
"MSI" = "D0CF11E0A1B11AE1" # MSI or office
|
|
"RAR" = "526172211A0700"; # RAR file
|
|
"ZIP" = "504B0304"; # ZIP file
|
|
"7z" = "377ABCAF271C"; # 7z file
|
|
"EXE" = "4D5A"; # EXE file (MZ header)
|
|
}
|
|
|
|
foreach ($key in $magicNumbers.Keys) {
|
|
$magicNumber = $magicNumbers[$key]
|
|
$currentIndex = 0
|
|
|
|
if ($fileHex -match $magicNumber) {
|
|
|
|
if ($key -eq "EXE") {
|
|
while ($fileHex.IndexOf($magicNumber, $currentIndex) -ne -1) {
|
|
$startIndex = $fileHex.IndexOf($magicNumber, $currentIndex)
|
|
# Extract the part after the Magic Number (limited to 400 bytes after)
|
|
$remainingHex = $fileHex.Substring($startIndex + $magicNumber.Length, [Math]::Min(200 * 2, $fileHex.Length - ($startIndex + $magicNumber.Length)))
|
|
|
|
# Check for the presence of the special string "0000004000" in this range
|
|
if ($remainingHex -match "0000004000") {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Suspicious Image'
|
|
Reason = "EXE file with '0000004000' string detected"
|
|
}
|
|
return $result
|
|
}
|
|
|
|
# Continue the search from the next index
|
|
$currentIndex = $startIndex + $magicNumber.Length
|
|
}
|
|
}
|
|
elseif ($key -eq "ZIP") {
|
|
|
|
# Find the index where the ZIP file starts
|
|
$startIndex = $fileHex.IndexOf($magicNumber, $currentIndex) / 2 # Divide by 2 because each hexadecimal represents 2 characters
|
|
|
|
# Extract the ZIP bytes starting from this index
|
|
$zipBytes = $fileBytes[$startIndex..($fileBytes.Length - 1)]
|
|
|
|
$tempDir = [System.IO.Path]::GetTempPath()
|
|
$fileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($filePath)
|
|
$tempZipPath = [System.IO.Path]::Combine($tempDir, "$fileNameWithoutExtension.zip")
|
|
[System.IO.File]::WriteAllBytes($tempZipPath, $zipBytes)
|
|
|
|
# Read the ZIP file and list the files
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
$zip = [System.IO.Compression.ZipFile]::OpenRead($tempZipPath)
|
|
|
|
# List the files inside the ZIP
|
|
$fileNames = $zip.Entries | Select-Object -ExpandProperty FullName
|
|
$fileNames | ForEach-Object { Write-Host "File in ZIP: $_" }
|
|
|
|
$zip.Dispose()
|
|
|
|
# Delete the temporary file
|
|
Remove-Item $tempZipPath
|
|
|
|
# Return the result
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filePath
|
|
Pattern = 'Suspicious Image'
|
|
Reason = "ZIP detected in pictures. Containing: $($fileNames -join ', ')"
|
|
}
|
|
return $result
|
|
}
|
|
else {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Suspicious Image'
|
|
Reason = "File $key detected in the image"
|
|
}
|
|
return $result
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
$result = [PSCustomObject]@{
|
|
FilePath = $filepath
|
|
pattern = 'Error'
|
|
Reason = "Details : $_"
|
|
}
|
|
return $result
|
|
}
|
|
}
|
|
|
|
#endregion FonctionDetect
|
|
|
|
# Add other functions for different file types...
|
|
|
|
function Get-CompressedFileType {
|
|
param (
|
|
[string]$filePath,
|
|
[object[]]$detectedType
|
|
)
|
|
|
|
|
|
# More check fot DOCX, XLSX, ODT, ODS ou JAR PPTX zip
|
|
if ($detectedType -contains "docx" -or $detectedType -contains "jar") {
|
|
try {
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
$zip = [System.IO.Compression.ZipFile]::OpenRead($filePath)
|
|
|
|
$fileNames = $zip.Entries | Select-Object -ExpandProperty FullName
|
|
|
|
if ($fileNames -contains "word/document.xml") {
|
|
$detectedType = "docx"
|
|
}
|
|
elseif ($fileNames -contains "xl/workbook.xml") {
|
|
$detectedType = "xlsx"
|
|
}
|
|
elseif ($fileNames -contains "ppt/presentation.xml") {
|
|
$detectedType = "pptx"
|
|
}
|
|
elseif ($fileNames -contains "visio/document.xml") {
|
|
$detectedType = "vsdx"
|
|
}
|
|
elseif ($fileNames -contains "content.xml") {
|
|
$mimetypeEntry = $zip.Entries | Where-Object { $_.FullName -eq "mimetype" }
|
|
if ($mimetypeEntry -ne $null) {
|
|
$reader = [System.IO.StreamReader]::new($mimetypeEntry.Open())
|
|
$mimetype = $reader.ReadToEnd()
|
|
$reader.Close()
|
|
|
|
switch ($mimetype) {
|
|
"application/vnd.oasis.opendocument.spreadsheet" {
|
|
$detectedType = "ods"
|
|
}
|
|
"application/vnd.oasis.opendocument.text" {
|
|
$detectedType = "odt"
|
|
}
|
|
"application/vnd.oasis.opendocument.presentation" {
|
|
$detectedType = "odp"
|
|
}
|
|
"application/vnd.oasis.opendocument.text-template" {
|
|
$detectedType = "ott"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
elseif ($fileNames -contains "META-INF/MANIFEST.MF") {
|
|
$detectedType = "jar"
|
|
}
|
|
else { $detectedType = "others" }
|
|
$zip.Dispose()
|
|
}
|
|
catch {
|
|
$detectedType = "requires_check"
|
|
}
|
|
}
|
|
elseif ($detectedType -contains "doc") {
|
|
|
|
$a = [System.IO.File]::ReadAllBytes($filePath)
|
|
$content = [System.Text.Encoding]::ASCII.GetString($a)
|
|
|
|
if ($content.Contains("Word.Document")) {
|
|
$detectedType = "doc"
|
|
} elseif ($content.Contains("MSI") -or $content.Contains("Installer")) {
|
|
$detectedType = "msi"
|
|
} elseif ($content.Contains("Excel") ) {
|
|
$detectedType = "xls"
|
|
} elseif ($content.Contains("PowerPoint")) {
|
|
$detectedType = "ppt"
|
|
} elseif ($content.Contains("Microsoft Visio")) {
|
|
$detectedType = "vsd"
|
|
} else {
|
|
#check for db files
|
|
$offsetBytes = [System.IO.File]::ReadAllBytes($filePath)[1024..1050]
|
|
$offsetAscii = [System.Text.Encoding]::ASCII.GetString($offsetBytes).Trim()
|
|
$filteredAscii = ($offsetAscii -split '').Where{ $_ -match '[A-Za-z ]' } -join ''
|
|
|
|
if ($filteredAscii -replace '\s+', ' ' -eq "Root Entry") {
|
|
$detectedType = "db"
|
|
}
|
|
else {
|
|
$detectedType = "others"
|
|
}
|
|
}
|
|
}
|
|
return $detectedType
|
|
}
|
|
function Get-FileType {
|
|
param (
|
|
[string]$filePath,
|
|
[object]$jsonContent
|
|
)
|
|
|
|
$detectedType = "others"
|
|
$extension = [System.IO.Path]::GetExtension($filePath).TrimStart('.')
|
|
$fileHeaderHex = [System.IO.File]::ReadAllBytes($filePath)[0..16] | ForEach-Object { "{0:X2}" -f $_ }
|
|
$fileHeaderHex = ($fileHeaderHex -join '').Trim()
|
|
|
|
if ($fileHeaderHex.Length -eq 0) {
|
|
return "empty"
|
|
}
|
|
$matchFound = $false
|
|
foreach ($entry in $jsonContent.magic_numbers) {
|
|
if ($matchFound) { break }
|
|
|
|
foreach ($expectedMagic in $entry.magic) {
|
|
if ($matchFound) { break }
|
|
|
|
if ($expectedMagic.Length -le $fileHeaderHex.Length) {
|
|
$difference = Compare-Object -ReferenceObject $expectedMagic -DifferenceObject ($fileHeaderHex.Substring(0, $expectedMagic.Length)) -SyncWindow 0
|
|
|
|
if ($difference.Count -eq 0) {
|
|
if ($entry.offset) {
|
|
foreach ($offsetItem in $entry.offset) {
|
|
$offsetPosition = $expectedOffsetValue = $null
|
|
$offsetPosition = $offsetItem[0]
|
|
$expectedOffsetValue = $offsetItem[1]
|
|
$lastpostition = $offsetPosition + ($expectedOffsetValue.Length/2)-1
|
|
|
|
$CustomfileHeaderHex = [System.IO.File]::ReadAllBytes($filePath)[$offsetPosition..$lastpostition] | ForEach-Object { "{0:X2}" -f $_ }
|
|
$specificBytes = ($CustomfileHeaderHex -join '').Trim()
|
|
|
|
if ($specificBytes -eq $expectedOffsetValue) {
|
|
if ($extension -notin $entry.extensions) {
|
|
$detectedType = 'requires_check'
|
|
} else {
|
|
$detectedType = $extension
|
|
}
|
|
$matchFound = $true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if ($extension -notin $entry.extensions) {
|
|
$detectedType = 'requires_check'
|
|
}
|
|
else {
|
|
if ($entry.extensions -contains "docx" -or $entry.extensions -contains "doc") {
|
|
$detectedType = Get-CompressedFileType -filePath $filePath -detectedType $entry.extensions
|
|
}
|
|
if ($detectedType -eq "others" -and $extension -in $entry.extensions) {
|
|
$detectedType = $extension
|
|
} elseif ($detectedType -ne $extension -and $detectedType -ne "others") {
|
|
$detectedType = 'requires_check'
|
|
}
|
|
}
|
|
$matchFound = $true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($detectedType -eq 'others' -and $extension -in $jsonContent.magic_numbers.extensions) {
|
|
$detectedType = 'requires_check'
|
|
}
|
|
|
|
if ($detectedType -eq "others") {
|
|
$firstLine = Get-Content -Path $filePath -TotalCount 1
|
|
if ($firstLine -match '^<\?xml') {
|
|
$detectedType = "xml"
|
|
}
|
|
}
|
|
|
|
return $detectedType
|
|
}
|
|
# SIG # Begin signature block
|
|
# MIImVgYJKoZIhvcNAQcCoIImRzCCJkMCAQExDzANBglghkgBZQMEAgEFADB5Bgor
|
|
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
|
|
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCC8KZNcKCzMj87C
|
|
# Xm3TUdHfsYDelwrkLm78Scnqq3gb1qCCH+wwggWNMIIEdaADAgECAhAOmxiO+dAt
|
|
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
|
|
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
|
|
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
|
|
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
|
|
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
|
|
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
|
|
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
|
|
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
|
|
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
|
|
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
|
|
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
|
|
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
|
|
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
|
|
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
|
|
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
|
|
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
|
|
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
|
|
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
|
|
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
|
|
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
|
|
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
|
|
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
|
|
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
|
|
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
|
|
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
|
|
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
|
|
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
|
|
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
|
|
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
|
|
# twGpn1eqXijiuZQwggYoMIIEEKADAgECAhBrxlWg9go45bxtH9Zi+WCgMA0GCSqG
|
|
# SIb3DQEBCwUAMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBT
|
|
# eXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBD
|
|
# QTAeFw0yNDExMDYwOTQ0MjlaFw0yNTExMDYwOTQ0MjhaME4xCzAJBgNVBAYTAkZS
|
|
# MQ8wDQYDVQQHDAZUb3Vsb24xFjAUBgNVBAoMDU1laGRpIERha2hhbWExFjAUBgNV
|
|
# BAMMDU1laGRpIERha2hhbWEwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIB
|
|
# gQCsFc3e5PwEJuycVRR54Qp8hFEckVwj7u1hMc7fejXKC/oR+uixlujLAHA9NcGX
|
|
# jcQIXNP3GmezLF3Tj6Jvcs/kNT/a5zqjI5HEfIap7EHwf03f5060+Rc21v1UDjzj
|
|
# DZzi9xFFum8eeGLc4pTzUB3wP3+M+mY7d5QlTjIxZSNnMBisJE8ASqG9JtRcQmIz
|
|
# HACI70xRCQVV8ZjJ8J+Shr6wkNdDy/IjR+Y9VkMRIJozWR+pqbKuQOIDBSxQYVHg
|
|
# bT+gsLOfvHkBPJN0ZQe7eJdG7J78Z1nzNH9yXhZ0HHdPB80tUwM0HC1n4LO3kki/
|
|
# IBmg4Qq/UyMMQd826fJk3ylbAlf8w7N80INQcLLBGVECmWI21d9f3l5usvWDa+mJ
|
|
# ma57c6GUDY05Jg5owLgNREZsyRt5rOlg68NLmz9tuEkJA1D4ntpKq0KZc3HJv04x
|
|
# XTcfTEqbKYr7vZ//ENsell5UdUQxL6rGJzazhsK02ZcmasICiHNLfG/tBaolCbeM
|
|
# 8ekCAwEAAaOCAXgwggF0MAwGA1UdEwEB/wQCMAAwPQYDVR0fBDYwNDAyoDCgLoYs
|
|
# aHR0cDovL2Njc2NhMjAyMS5jcmwuY2VydHVtLnBsL2Njc2NhMjAyMS5jcmwwcwYI
|
|
# KwYBBQUHAQEEZzBlMCwGCCsGAQUFBzABhiBodHRwOi8vY2NzY2EyMDIxLm9jc3At
|
|
# Y2VydHVtLmNvbTA1BggrBgEFBQcwAoYpaHR0cDovL3JlcG9zaXRvcnkuY2VydHVt
|
|
# LnBsL2Njc2NhMjAyMS5jZXIwHwYDVR0jBBgwFoAU3XRdTADbe5+gdMqxbvc8wDLA
|
|
# cM0wHQYDVR0OBBYEFAG3sIcT8bRm7QyFu8699Gpkr5NmMEsGA1UdIAREMEIwCAYG
|
|
# Z4EMAQQBMDYGCyqEaAGG9ncCBQEEMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3
|
|
# LmNlcnR1bS5wbC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDgYDVR0PAQH/BAQD
|
|
# AgeAMA0GCSqGSIb3DQEBCwUAA4ICAQCJ58BnchFNGzLksJ9oHFEWTs643G+PKOHr
|
|
# 9RmrKSB/4MtPriG5iez+MFsGqYwkYd5QzqOIYg24ctfbWXJWG8Xj+YMfp1r+hkYq
|
|
# O0Abpv26sZ1ZjNGgGUbb3z7KqhY+IdVpZf2aG/Rycl5dE2LbhWqp9h24WfQCIS/e
|
|
# XxH7HmM9SEBHYbfOqlEA+RF/gRGYCQOg0ui2j0ZzIOrQGj3Njn/5rzP9OmPmLt4h
|
|
# DsixjFWgu598XmRKj5KW1MShFIjUuUzSmOWDgKA16lJi6LggdFAB/MImiDH48v8N
|
|
# /9R9En24pUGGj2XOgBX5SZ4kj+VN1YaY1vYPFp3wLu85zpgRZgZQC+WurX8s1tRn
|
|
# iCIj/+ajUB4G4TcbTz6k16X1Yz9ba1y7p/hJB92uDW7esMGgqzEv+Osd11bVoNmv
|
|
# CE8Twsz0cuFJqBtVZIycCkgw/AVyJIsNS6RADi94PvbOf8rty8HV3bHmm6O4wJVc
|
|
# 5ch50bL7JVyYTPN5OTzXSDx62wKi5ePZvEF7RX3cQlTQMYticde91khs2n2FZ06K
|
|
# Uin5DtQgxy0Q1ufFIDZthsk5AaSWiZzFgAgJt8JaQGPyGAYl2Sr8a/gMLpcBsPwI
|
|
# zdlDUOJwyHPxlR9ZiraUzF/1SSN7CgjqFSDAAZ+i4i8gZsPpU38GtBSLrw/CrnUB
|
|
# /KGcFNMvszCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcN
|
|
# AQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcG
|
|
# A1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3Rl
|
|
# ZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkG
|
|
# A1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdp
|
|
# Q2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCC
|
|
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8Ty
|
|
# kTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsm
|
|
# c5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTn
|
|
# KC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2
|
|
# R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0
|
|
# QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/
|
|
# oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1ps
|
|
# lPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhI
|
|
# fxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8
|
|
# I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkU
|
|
# EBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1G
|
|
# nrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEA
|
|
# MB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC
|
|
# 0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYB
|
|
# BQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5k
|
|
# aWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0
|
|
# LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSG
|
|
# Mmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQu
|
|
# Y3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0B
|
|
# AQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7
|
|
# cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2p
|
|
# Vs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxk
|
|
# Jodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpkn
|
|
# G6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2
|
|
# n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fm
|
|
# w0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvt
|
|
# Cl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU
|
|
# 5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8K
|
|
# vYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/
|
|
# GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwgga5MIIE
|
|
# oaADAgECAhEAmaOACiZVO2Wr3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkG
|
|
# A1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAl
|
|
# BgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMb
|
|
# Q2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2
|
|
# MDUxODA1MzIxOFowVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRh
|
|
# IFN5c3RlbXMgUy5BLjEkMCIGA1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIx
|
|
# IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOcz
|
|
# cz5jXXp1ur5cTbq96y34vuTmflN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8
|
|
# ewTS4IndU8s7VS5+djSoMcbvIKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd62
|
|
# 7h27a8RdrT1PH9ud0IF+njvMk2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBk
|
|
# bbxYDB7SYOouu9Tj1yHIohzuC8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPW
|
|
# XMEmhu1gMXgv8aGUsRdaCtVD2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+F
|
|
# A+yQN9n/kZtMLK+Wo837Q4QOZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7
|
|
# TF3HybZtYvj9lDV2nT8mFSkcSkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5M
|
|
# CAOIG5knN4Q/JHuurfTI5XDYO962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNr
|
|
# UA9g7qf/rCkKbWpQ5boufUnq1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6Pz
|
|
# kDpwZo4SlADaCi2JSplKShBSND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyM
|
|
# J4rBJAcOSnAWd18Jx5n858JSqPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMB
|
|
# Af8wHQYDVR0OBBYEFN10XUwA23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLah
|
|
# VDkCw6A/joq8+tT4HKbROg79MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggr
|
|
# BgEFBQcDAzAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9j
|
|
# dG5jYTIuY3JsMGwGCCsGAQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1
|
|
# YmNhLm9jc3AtY2VydHVtLmNvbTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRv
|
|
# cnkuY2VydHVtLnBsL2N0bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYI
|
|
# KwYBBQUHAgEWGGh0dHA6Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwF
|
|
# AAOCAgEAdYhYD+WPUCiaU58Q7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumY
|
|
# lARMgwRzLRUStJl490L94C9LGF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48I
|
|
# fICJTZVJeChDUyuQy6rGDxLUUAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8
|
|
# ipNGxHBIutiRsWrhWM2f8pXdd3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4Gb
|
|
# lLQigO0ugh7bWRLDm0CdY9rNLqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3Ph
|
|
# RSC4Am1/7mATwZWwSD+B7eMcZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikS
|
|
# f+lIe5Iv6RY3/bFAEloMU+vUBfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827N
|
|
# S2x7gCBibESYkOh1/w1tVxTpV2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruW
|
|
# myOEMLOGGniR+x+zPF/2DaGgK2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZ
|
|
# o0LHuH8X3n9C+xN4YaNjt2ywzOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKe
|
|
# TTyYeEEUz/Qwt4HOUBCrW602NCmvO1nm+/80nLy5r0AZvCQxaQ4wgga8MIIEpKAD
|
|
# AgECAhALrma8Wrp/lYfG+ekE4zMEMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYT
|
|
# AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQg
|
|
# VHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjQw
|
|
# OTI2MDAwMDAwWhcNMzUxMTI1MjM1OTU5WjBCMQswCQYDVQQGEwJVUzERMA8GA1UE
|
|
# ChMIRGlnaUNlcnQxIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDI0MIIC
|
|
# IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvmpzn/aVIauWMLpbbeZZo7Xo
|
|
# /ZEfGMSIO2qZ46XB/QowIEMSvgjEdEZ3v4vrrTHleW1JWGErrjOL0J4L0HqVR1cz
|
|
# SzvUQ5xF7z4IQmn7dHY7yijvoQ7ujm0u6yXF2v1CrzZopykD07/9fpAT4BxpT9vJ
|
|
# oJqAsP8YuhRvflJ9YeHjes4fduksTHulntq9WelRWY++TFPxzZrbILRYynyEy7rS
|
|
# 1lHQKFpXvo2GePfsMRhNf1F41nyEg5h7iOXv+vjX0K8RhUisfqw3TTLHj1uhS66Y
|
|
# X2LZPxS4oaf33rp9HlfqSBePejlYeEdU740GKQM7SaVSH3TbBL8R6HwX9QVpGnXP
|
|
# lKdE4fBIn5BBFnV+KwPxRNUNK6lYk2y1WSKour4hJN0SMkoaNV8hyyADiX1xuTxK
|
|
# aXN12HgR+8WulU2d6zhzXomJ2PleI9V2yfmfXSPGYanGgxzqI+ShoOGLomMd3mJt
|
|
# 92nm7Mheng/TBeSA2z4I78JpwGpTRHiT7yHqBiV2ngUIyCtd0pZ8zg3S7bk4QC4R
|
|
# rcnKJ3FbjyPAGogmoiZ33c1HG93Vp6lJ415ERcC7bFQMRbxqrMVANiav1k425zYy
|
|
# FMyLNyE1QulQSgDpW9rtvVcIH7WvG9sqYup9j8z9J1XqbBZPJ5XLln8mS8wWmdDL
|
|
# nBHXgYly/p1DhoQo5fkCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNV
|
|
# HRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYG
|
|
# Z4EMAQQCMAsGCWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGog
|
|
# j57IbzAdBgNVHQ4EFgQUn1csA3cOKBWQZqVjXu5Pkh92oFswWgYDVR0fBFMwUTBP
|
|
# oE2gS4ZJaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0
|
|
# UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMw
|
|
# gYAwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEF
|
|
# BQcwAoZMaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3Rl
|
|
# ZEc0UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsF
|
|
# AAOCAgEAPa0eH3aZW+M4hBJH2UOR9hHbm04IHdEoT8/T3HuBSyZeq3jSi5GXeWP7
|
|
# xCKhVireKCnCs+8GZl2uVYFvQe+pPTScVJeCZSsMo1JCoZN2mMew/L4tpqVNbSpW
|
|
# O9QGFwfMEy60HofN6V51sMLMXNTLfhVqs+e8haupWiArSozyAmGH/6oMQAh078qR
|
|
# h6wvJNU6gnh5OruCP1QUAvVSu4kqVOcJVozZR5RRb/zPd++PGE3qF1P3xWvYViUJ
|
|
# Lsxtvge/mzA75oBfFZSbdakHJe2BVDGIGVNVjOp8sNt70+kEoMF+T6tptMUNlehS
|
|
# R7vM+C13v9+9ZOUKzfRUAYSyyEmYtsnpltD/GWX8eM70ls1V6QG/ZOB6b6Yum1Hv
|
|
# IiulqJ1Elesj5TMHq8CWT/xrW7twipXTJ5/i5pkU5E16RSBAdOp12aw8IQhhA/vE
|
|
# bFkEiF2abhuFixUDobZaA0VhqAsMHOmaT3XThZDNi5U2zHKhUs5uHHdG6BoQau75
|
|
# KiNbh0c+hatSF+02kULkftARjsyEpHKsF7u5zKRbt5oK5YGwFvgc4pEVUNytmB3B
|
|
# pIiowOIIuDgP5M9WArHYSAR16gc0dP2XdkMEP5eBsX7bf/MGN4K3HP50v/01ZHo/
|
|
# Z5lGLvNwQ7XHBx1yomzLP8lx4Q1zZKDyHcp4VQJLu2kWTsKsOqQxggXAMIIFvAIB
|
|
# ATBqMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1z
|
|
# IFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQa8ZV
|
|
# oPYKOOW8bR/WYvlgoDANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQow
|
|
# CKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC
|
|
# AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCDRDzs2Ytj0Dqx5LB+l
|
|
# pxX4cE0yDiFZ7vG8rNTLXz+KKzANBgkqhkiG9w0BAQEFAASCAYAmmXOJQfsI38xT
|
|
# YThT8Zio6kQKcmRUHLHq0J2JLdGFflBy76meillnESCwNczrmd1kdGRpiyxegDt3
|
|
# 1afBoTZ5tq+3ZXW1TebagwAhp6pxoav+AVdCgvKBrzKiEisDuPQppyNGQfhTZ3sR
|
|
# SxQLrXtPGaODfgABeYfe0xHzGKre2eEP07TY0IEFC1Ncn6k0cgP4+B4gXwRfkoHM
|
|
# Rk2iRB1WHYzX1/BXUkp7ET+w2X5hJZYxLn8/Th9RkCxuzk8ctQVbfbuV4r6hC6Zs
|
|
# TWorfMPF6JPMtrxAEfoDcB241xm9OnN7PnI7en7+Jq6otGwDr3k13YbxBphySY1s
|
|
# DkNVGVQr1qaVExefm4dRO/PenInWMlduwWWSzkmdB0m0GpuxwsmXsixYyR77SU7O
|
|
# jJ8/sTTsGNqIgS6+Mv+RLBGsHvAAedD4kPzfJMSg5yE+tFdd50sTpAgi1exuFKrW
|
|
# c99a+xhSBMmt/oss228cbQF+2/VrwdFi3yJUWZVcfoaAdFFy092hggMgMIIDHAYJ
|
|
# KoZIhvcNAQkGMYIDDTCCAwkCAQEwdzBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMO
|
|
# RGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNB
|
|
# NDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhALrma8Wrp/lYfG+ekE4zMEMA0G
|
|
# CWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG
|
|
# 9w0BCQUxDxcNMjQxMTEzMjMzOTE2WjAvBgkqhkiG9w0BCQQxIgQgu+gdumT7pwD4
|
|
# cDnOysQNtr2j8VfIX4zHfQPV4WwSmT4wDQYJKoZIhvcNAQEBBQAEggIAB0FkcEJO
|
|
# h2KNBz+gTFA1lq4o1Fy+2LFOvsxjNQPyimcQ0Ft4I3MmnsT3HNGuGK0Q14ojZk8j
|
|
# 27sDCmwwG5N1nryWWxLcul2qWrPhN2dxgp22ikuCHhTU6VFFXvKpnEd4AsghbuaD
|
|
# gAGXYglB3JKwFrPm2trD0zN4VA/RhzH/O6dvTQSdFXkOAESCvv4mG8n9BwpSSkha
|
|
# DxHvu+lDfhIogAIjviMgq3Sbpd0R9Y9XWepr4aRbcqmwo6FVyqs4/ToSMZxcNb8g
|
|
# yu6z9U9ioJeghEUhJPWe1m1JcgTFdValtHkG/v1j+JXBiyDziCrrKGoAZadJ83Yl
|
|
# wHjF63hk3f4RC+xfY4IzcVnYBaaoSFvQdLbmRHJcxWho/Te7acX0K/Tr/vFVW4IW
|
|
# DXWlqpkKTGxjHeLZrrQkURE6FPBk0UaJRYwaXpofkfvfO7/BAbf0h7s8sGku2JA1
|
|
# wa6ck7wKCSHW9UDi9u+Q2+3GlB7vstcCO6nZ8WmswNtg87v9bU/Rd8nXAy4yYIUp
|
|
# af1LEMEk310zN8/RJCq2ZYfZ1/XQShBFCJk97D1IeeMz64TAUdyTxquiz3V8KeqQ
|
|
# nFm9woD/YYzv/RSU0/iSYZRAMKUCQbSZm31M1UUuKTW6bxUiRXAuEP5ltnLeGugd
|
|
# iFgJIrU+wyu+iggEVWDsCtH4OnfLWt0iLXM=
|
|
# SIG # End signature block
|