{"id":353771,"date":"2024-08-30T12:41:42","date_gmt":"2024-08-30T12:41:42","guid":{"rendered":"https:\/\/www.ninjaone.com\/script-hub\/verificacion-del-hash-powershell\/"},"modified":"2024-10-13T19:08:45","modified_gmt":"2024-10-13T19:08:45","slug":"verificacion-del-hash-powershell","status":"publish","type":"script_hub","link":"https:\/\/www.ninjaone.com\/es\/script-hub\/verificacion-del-hash-powershell\/","title":{"rendered":"C\u00f3mo utilizar PowerShell para la verificaci\u00f3n del hash de archivos en seguridad de TI"},"content":{"rendered":"<p>En el panorama inform\u00e1tico actual, garantizar la integridad y seguridad de los datos es primordial. Un m\u00e9todo eficaz para verificar la integridad de los archivos es utilizar valores hash. Un valor hash act\u00faa como una huella digital de los archivos, lo que permite a los profesionales de TI verificar si los archivos han sido manipulados o corrompidos. Este post profundizar\u00e1 en un script de PowerShell dise\u00f1ado para buscar archivos con valores hash espec\u00edficos, lo que lo convierte en una herramienta inestimable para los profesionales de TI y los<a href=\"https:\/\/www.ninjaone.com\/es\/que-es-un-msp\" target=\"_blank\" rel=\"noopener\"> proveedores de servicios gestionados (MSP)<\/a>.<\/p>\n<h2>Background<\/h2>\n<p>El script PowerShell para la verificaci\u00f3n del hash est\u00e1 dise\u00f1ado para alertar a los usuarios si se encuentra un archivo con un hash y una extensi\u00f3n especificados dentro de un directorio determinado y sus subdirectorios. El hashing de archivos es una pr\u00e1ctica habitual en inform\u00e1tica para verificar la integridad de los archivos y detectar cambios no autorizados. Este script simplifica y automatiza el proceso, facilitando a los profesionales de TI la tarea de garantizar la seguridad e integridad de sus sistemas.<\/p>\n<h2>El script para la verificaci\u00f3n del hash<\/h2>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\">#Requires -Version 5.1\r\n\r\n&lt;#\r\n.SYNOPSIS\r\n    Alerts if a file with the extension and specified hash is found in the given search directory or subdirectories. Warning: Hashing large files may impact performance.\r\n.DESCRIPTION\r\n    Alerts if a file with the extension and specified hash is found in the given search directory or subdirectories. Warning: Hashing large files may impact performance.\r\n.EXAMPLE\r\n    -Hash \"F55A61A82F4F5943F86565E1FA2CCB4F\" -SearchPath \"C:\" -FileType \".ico\" -CustomField \"multiline\"\r\n    WARNING: Backslash missing from the search path. Changing it to C:\\.\r\n    WARNING: File with MD5 hash of F55A61A82F4F5943F86565E1FA2CCB4F found!\r\n\r\n    File Name         Path                                                                                    \r\n    ---------         ----                                                                                    \r\n    zoo_ecosystem.ico C:\\Users\\Administrator\\Desktop\\Find-FileHash\\Test Folder 1\\zoo_ecosystem.ico            \r\n    zoo_ecosystem.ico C:\\Users\\Administrator\\Desktop\\Find-FileHash\\TestFolder1\\Test Folder 1\\zoo_ecosystem.ico\r\n    zoo_ecosystem.ico C:\\Users\\Administrator\\Desktop\\Find-FileHash\\TestFolder2\\Test Folder 1\\zoo_ecosystem.ico\r\n\r\n    Attempting to set Custom Field 'multiline'.\r\n    Successfully set Custom Field 'multiline'!\r\n\r\nPARAMETER: -Hash \"REPLACEMEWITHAVALIDHASH\"\r\n    Files with this hash should cause the alert to trigger.\r\n\r\nPARAMETER: -Algorithm \"MD5\"\r\n    Hashing algorithm used for the above hash.\r\n\r\nPARAMETER: -SearchPath \"C:\\ReplaceMeWithAValidSearchPath\"\r\n   Specifies one or more starting directories for the search, separated by commas. The search will recursively include all subdirectories from these starting points.\r\n\r\nPARAMETER: -Timeout \"15\"\r\n    Once this timeout is reached, the script will stop searching for files that match your given hash.\r\n\r\nPARAMETER: -FileType \".exe\"\r\n    Specifies the file extension to filter the search. Only files with this extension will be analyzed for a hash match. Example: '.exe'\r\n\r\nPARAMETER: -CustomField \"NameOfMultiLineCustomField\"\r\n    Specifies the name of an optional multiline custom field where results can be sent. \r\n\r\n.NOTES\r\n    Minimum OS Architecture Supported: Windows 10, Windows Server 2016\r\n    Release Notes: Initial Release\r\nBy using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https:\/\/www.ninjaone.com\/terms-of-use.\r\n    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. \r\n    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. \r\n    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. \r\n    Warranty Disclaimer: The script is provided \u201cas is\u201d and \u201cas available\u201d, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. \r\n    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. \r\n    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. \r\n    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).\r\n#&gt;\r\n\r\n[CmdletBinding()]\r\nparam (\r\n    [Parameter()]\r\n    [String]$Hash,\r\n    [Parameter()]\r\n    [String]$SearchPath = \"C:\\Windows\",\r\n    [Parameter()]\r\n    [String]$FileType,\r\n    [Parameter()]\r\n    [Int]$Timeout = 15,\r\n    [Parameter()]\r\n    [String]$Algorithm = \"MD5\",\r\n    [Parameter()]\r\n    [String]$CustomField\r\n)\r\n\r\nbegin {\r\n    # Set parameters using dynamic script variables.\r\n    if ($env:hash -and $env:hash -notlike \"null\") { $Hash = $env:hash }\r\n    if ($env:hashType -and $env:hashType -notlike \"null\") { $Algorithm = $env:hashType }\r\n    if ($env:searchPath -and $env:searchPath -notlike \"null\") { $SearchPath = $env:searchPath }\r\n    if ($env:timeoutInMinutes -and $env:timeoutInMinutes -notlike \"null\") { $Timeout = $env:timeoutInMinutes }\r\n    if ($env:fileExtensionToSearchFor -and $env:fileExtensionToSearchFor -notlike \"null\") { $FileType = $env:fileExtensionToSearchFor }\r\n    if ($env:customFieldName -and $env:customFieldName -notlike \"null\") { $CustomField = $env:customFieldName }\r\n\r\n    # If given a comma-separated list, split the paths.\r\n    $PathsToSearch = New-Object System.Collections.Generic.List[String]\r\n    if ($SearchPath -match \",\") {\r\n        $SearchPath -split \",\" | ForEach-Object { $PathsToSearch.Add($_.Trim()) }\r\n    }\r\n    else {\r\n        $PathsToSearch.Add($SearchPath)\r\n    }\r\n\r\n    $ReplacementPaths = New-Object System.Collections.Generic.List[Object]\r\n    $PathsToRemove = New-Object System.Collections.Generic.List[String]\r\n\r\n    # If given a drive without the backslash add it in.\r\n    $PathsToSearch | ForEach-Object {\r\n        if ($_ -notmatch '^[A-Z]:\\\\$' -and $_ -match '^[A-Z]:$') {\r\n            $NewPath = \"$_\\\"\r\n            $ReplacementPaths.Add(\r\n                [PSCustomObject]@{\r\n                    Index   = $PathsToSearch.IndexOf(\"$_\")\r\n                    NewPath = $NewPath\r\n                }\r\n            )\r\n                \r\n            Write-Warning \"Backslash missing from the search path. Changing it to $NewPath.\"\r\n        }\r\n    }\r\n\r\n    # Apply replacements\r\n    $ReplacementPaths | ForEach-Object {\r\n        $PathsToSearch[$_.index] = $_.NewPath \r\n    }\r\n\r\n    # Check if the search path is valid.\r\n    $PathsToSearch | ForEach-Object {\r\n        if (-not (Test-Path $_)) {\r\n            Write-Host -Object \"[Error] $_ does not exist!\"\r\n            $PathsToRemove.Add($_)\r\n            $ExitCode = 1\r\n        }\r\n    }\r\n\r\n    $PathsToRemove | ForEach-Object {\r\n        $PathsToSearch.Remove($_) | Out-Null\r\n    }\r\n\r\n\r\n    # Error out if no valid paths to search.\r\n    if ($PathsToSearch.Count -eq 0) {\r\n        Write-Host \"[Error] No valid paths to search!\"\r\n        exit 1\r\n    }\r\n\r\n    # A file extension is required.\r\n    if (-not $FileType) {\r\n        Write-Host -Object \"[Error] File Type is required!\"\r\n        exit 1\r\n    }\r\n\r\n    # If we were given the extension without the . we'll add it back in\r\n    if ($FileType -notmatch '^\\.') {\r\n        $FileType = \".$FileType\"\r\n        Write-Warning -Message \"Extension missing changing filetype to $FileType.\"\r\n    }\r\n\r\n    # The timeout has to be between 1 and 120\r\n    if ($Timeout -lt 1 -or $Timeout -gt 120) {\r\n        Write-Host \"[Error] Invalid timeout given of $Timeout minutes. Please enter a value between 1 and 120.\"\r\n        exit 1\r\n    }\r\n\r\n    # PowerShell 5.1 supports more algorithms than this, however PowerShell 7 does not.\r\n    $ValidAlgorithms = \"SHA1\", \"SHA256\", \"SHA384\", \"SHA512\", \"MD5\"\r\n    if ($ValidAlgorithms -notcontains $Algorithm) {\r\n        Write-Host \"[Error] Invalid Algorithm selected. Only SHA1, SHA256, SHA384, SHA512 and MD5 are supported.\"\r\n        exit 1\r\n    }\r\n\r\n    # Helper function to make it easier to set custom fields.\r\n    function Set-NinjaProperty {\r\n        [CmdletBinding()]\r\n        Param(\r\n            [Parameter(Mandatory = $True)]\r\n            [String]$Name,\r\n            [Parameter()]\r\n            [String]$Type,\r\n            [Parameter(Mandatory = $True, ValueFromPipeline = $True)]\r\n            $Value,\r\n            [Parameter()]\r\n            [String]$DocumentName\r\n        )\r\n    \r\n        $Characters = $Value | Measure-Object -Character | Select-Object -ExpandProperty Characters\r\n        if ($Characters -ge 10000) {\r\n            throw [System.ArgumentOutOfRangeException]::New(\"Character limit exceeded, value is greater than 10,000 characters.\")\r\n        }\r\n        \r\n        # If we're requested to set the field value for a Ninja document we'll specify it here.\r\n        $DocumentationParams = @{}\r\n        if ($DocumentName) { $DocumentationParams[\"DocumentName\"] = $DocumentName }\r\n        \r\n        # This is a list of valid fields that can be set. If no type is given, it will be assumed that the input doesn't need to be changed.\r\n        $ValidFields = \"Attachment\", \"Checkbox\", \"Date\", \"Date or Date Time\", \"Decimal\", \"Dropdown\", \"Email\", \"Integer\", \"IP Address\", \"MultiLine\", \"MultiSelect\", \"Phone\", \"Secure\", \"Text\", \"Time\", \"URL\", \"WYSIWYG\"\r\n        if ($Type -and $ValidFields -notcontains $Type) { Write-Warning \"$Type is an invalid type! Please check here for valid types. https:\/\/ninjarmm.zendesk.com\/hc\/en-us\/articles\/16973443979789-Command-Line-Interface-CLI-Supported-Fields-and-Functionality\" }\r\n        \r\n        # The field below requires additional information to be set\r\n        $NeedsOptions = \"Dropdown\"\r\n        if ($DocumentName) {\r\n            if ($NeedsOptions -contains $Type) {\r\n                # We'll redirect the error output to the success stream to make it easier to error out if nothing was found or something else went wrong.\r\n                $NinjaPropertyOptions = Ninja-Property-Docs-Options -AttributeName $Name @DocumentationParams 2&gt;&amp;1\r\n            }\r\n        }\r\n        else {\r\n            if ($NeedsOptions -contains $Type) {\r\n                $NinjaPropertyOptions = Ninja-Property-Options -Name $Name 2&gt;&amp;1\r\n            }\r\n        }\r\n        \r\n        # If an error is received it will have an exception property, the function will exit with that error information.\r\n        if ($NinjaPropertyOptions.Exception) { throw $NinjaPropertyOptions }\r\n        \r\n        # The below type's require values not typically given in order to be set. The below code will convert whatever we're given into a format ninjarmm-cli supports.\r\n        switch ($Type) {\r\n            \"Checkbox\" {\r\n                # While it's highly likely we were given a value like \"True\" or a boolean datatype it's better to be safe than sorry.\r\n                $NinjaValue = [System.Convert]::ToBoolean($Value)\r\n            }\r\n            \"Date or Date Time\" {\r\n                # Ninjarmm-cli expects the  Date-Time to be in Unix Epoch time so we'll convert it here.\r\n                $Date = (Get-Date $Value).ToUniversalTime()\r\n                $TimeSpan = New-TimeSpan (Get-Date \"1970-01-01 00:00:00\") $Date\r\n                $NinjaValue = $TimeSpan.TotalSeconds\r\n            }\r\n            \"Dropdown\" {\r\n                # Ninjarmm-cli is expecting the guid of the option we're trying to select. So we'll match up the value we were given with a guid.\r\n                $Options = $NinjaPropertyOptions -replace '=', ',' | ConvertFrom-Csv -Header \"GUID\", \"Name\"\r\n                $Selection = $Options | Where-Object { $_.Name -eq $Value } | Select-Object -ExpandProperty GUID\r\n        \r\n                if (-not $Selection) {\r\n                    throw [System.ArgumentOutOfRangeException]::New(\"Value is not present in dropdown\")\r\n                }\r\n        \r\n                $NinjaValue = $Selection\r\n            }\r\n            default {\r\n                # All the other types shouldn't require additional work on the input.\r\n                $NinjaValue = $Value\r\n            }\r\n        }\r\n        \r\n        # We'll need to set the field differently depending on if its a field in a Ninja Document or not.\r\n        if ($DocumentName) {\r\n            $CustomField = Ninja-Property-Docs-Set -AttributeName $Name -AttributeValue $NinjaValue @DocumentationParams 2&gt;&amp;1\r\n        }\r\n        else {\r\n            $CustomField = Ninja-Property-Set -Name $Name -Value $NinjaValue 2&gt;&amp;1\r\n        }\r\n        \r\n        if ($CustomField.Exception) {\r\n            throw $CustomField\r\n        }\r\n    }\r\n\r\n    # Test for local administrator rights\r\n    function Test-IsElevated {\r\n        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()\r\n        $p = New-Object System.Security.Principal.WindowsPrincipal($id)\r\n        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)\r\n    }\r\n\r\n    $ExitCode = 0\r\n}\r\nprocess {\r\n    if (-not (Test-IsElevated)) {\r\n        Write-Host -Object \"[Error] Access Denied. Please run with Administrator privileges.\"\r\n        exit 1\r\n    }\r\n\r\n    # If we're given a file instead of a folder, we'll check if it matches anyways.\r\n    $PathsToSearch | ForEach-Object {\r\n        if (-not (Get-Item $_).PSIsContainer) {\r\n            Write-Warning \"The search path you gave is actually a file not a folder. Checking the hash of the file...\"\r\n        }\r\n    }\r\n    \r\n    $HashJobs = New-Object System.Collections.Generic.List[object]\r\n    $MatchingFiles = New-Object System.Collections.Generic.List[object]\r\n    $CustomFieldValue = New-Object System.Collections.Generic.List[string]\r\n\r\n    # We'll use a PowerShell job so that we can timeout appropriately.\r\n    $PathsToSearch | ForEach-Object {\r\n        $HashJobs.Add(\r\n            (\r\n                Start-Job -ScriptBlock {\r\n                    param($SearchPath, $FileType, $Algorithm, $Hash)\r\n                    $Files = Get-ChildItem -Path $SearchPath -Filter \"*$FileType\" -File -Recurse\r\n                    $Files | ForEach-Object {\r\n                        $CurrentHash = Get-FileHash -Path $_.FullName -Algorithm $Algorithm\r\n                        if ($CurrentHash.Hash -match $Hash) { $_.FullName }\r\n                    }\r\n                } -ArgumentList $_, $FileType, $Algorithm, $Hash\r\n            )\r\n        )\r\n    }\r\n\r\n    $TimeoutInSeconds = $Timeout * 60\r\n    $StartTime = Get-Date\r\n\r\n    # Wait for all jobs to complete or timeout\r\n    foreach ($HashJob in $HashJobs) {\r\n        # Calculate the remaining time\r\n        $TimeElapsed = (Get-Date) - $StartTime\r\n        $RemainingTime = $TimeoutInSeconds - $TimeElapsed.TotalSeconds\r\n    \r\n        # If there is no remaining time, break the loop\r\n        if ($RemainingTime -le 0) {\r\n            break\r\n        }\r\n    \r\n        # Wait for the current job with the remaining time as the timeout\r\n        $HashJob | Wait-Job -Timeout $RemainingTime | Out-Null\r\n    }\r\n\r\n    # If we failed to complete the job, we'll output a warning.\r\n    $IncompleteJobs = $HashJobs | Get-Job | Where-Object { $_.State -eq \"Running\" }\r\n    if ($IncompleteJobs) {\r\n        Write-Host \"[Error] The timeout period of $Timeout minutes has been reached, but some files still require a hash check!\"\r\n        $CustomFieldValue.Add(\"[Error] The timeout period of $Timeout minutes has been reached, but some files still require a hash check!\")\r\n        $ExitCode = 1\r\n    }\r\n\r\n    # Receive the data from the job.\r\n    $HashJobs | Receive-Job -ErrorAction SilentlyContinue -ErrorVariable JobErrors | ForEach-Object {\r\n        $MatchingFiles.Add(\r\n            [PSCustomObject]@{\r\n                \"File Name\" = $(Split-Path $_ -Leaf)\r\n                Path        = $_\r\n            }\r\n        )\r\n    }\r\n\r\n    # If we have any matching files, we'll output them here.\r\n    if ($MatchingFiles) {\r\n        Write-Warning -Message \"File with $Algorithm hash of $Hash found!\"\r\n        $MatchingFiles | Format-Table -AutoSize | Out-String | Write-Host\r\n        $MatchingFiles | Select-Object -ExpandProperty Path | ForEach-Object { $CustomFieldValue.Add($_) }\r\n    }\r\n    else {\r\n        Write-Host -Object \"No files found with $Hash.\"\r\n    }\r\n\r\n    # If we received any failures or errors, we'll output that here.\r\n    $FailedJobs = $HashJobs | Get-Job | Where-Object { $_.State -ne \"Completed\" -and $_.State -ne \"Running\" }\r\n    if ($FailedJobs -or $JobErrors) {\r\n        Write-Host \"\"\r\n        Write-Host \"[Error] Failed to get the hash of certain files due to an error.\"\r\n        $CustomFieldValue.Add(\" \")\r\n        $CustomFieldValue.Add(\"[Error] Failed to get the hash of certain files due to an error.\")\r\n        if ($JobErrors) {\r\n            Write-Host \"\"\r\n            $JobErrors | ForEach-Object { Write-Host \"[Error] $($_.Exception.Message)\" }\r\n            $CustomFieldValue.Add(\" \")\r\n            $JobErrors | ForEach-Object { $CustomFieldValue.Add(\"[Error] $($_.Exception.Message)\") }\r\n        }\r\n        $ExitCode = 1\r\n    }\r\n\r\n    $HashJobs | Remove-Job -Force\r\n\r\n    # If we're given a custom field, we'll attempt to save the results to it.\r\n    if ($CustomField) {\r\n        try {\r\n            Write-Host \"Attempting to set Custom Field '$CustomField'.\"\r\n            Set-NinjaProperty -Name $CustomField -Value ($CustomFieldValue | Out-String)\r\n            Write-Host \"Successfully set Custom Field '$CustomField'!\"\r\n        }\r\n        catch {\r\n            if (-not $_.Exception.Message) {\r\n                Write-Host \"[Error] $($_.Message)\"\r\n            }\r\n            else {\r\n                Write-Host \"[Error] $($_.Exception.Message)\"\r\n            }\r\n            $ExitCode = 1\r\n        }\r\n        \r\n    }\r\n\r\n    exit $ExitCode\r\n}\r\nend {\r\n    \r\n    \r\n    \r\n}<\/pre>\n<p>&nbsp;<\/p>\n\n<div class=\"blog-cta-new blog-cta-style-1\"><div class=\"cta-left\"><h2><\/h2><p><\/p><\/div><div class=\"cta-right\"><a class=\"button\" href=\"\"><\/a><\/div><\/div>\n<h2>An\u00e1lisis detallado<\/h2>\n<p>El script para la verificaci\u00f3n del hash comienza con informaci\u00f3n de metadatos, que incluye una sinopsis, una descripci\u00f3n y un ejemplo de uso. Establece par\u00e1metros que el usuario puede especificar, como el valor hash, la ruta de b\u00fasqueda, el tipo de archivo, el algoritmo hash, el periodo de tiempo de espera y un campo personalizado opcional para los resultados de salida.<\/p>\n<h3>Configuraci\u00f3n de par\u00e1metros<\/h3>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"1\" data-aria-level=\"1\"><strong>Hash<\/strong>: El valor hash espec\u00edfico a buscar.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"2\" data-aria-level=\"1\"><strong>SearchPath<\/strong>: El directorio para iniciar la b\u00fasqueda, por defecto C:Windows.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"3\" data-aria-level=\"1\"><strong>FileType<\/strong>: La extensi\u00f3n de archivo por la que filtrar.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"4\" data-aria-level=\"1\"><strong>Timeout<\/strong>: El tiempo m\u00e1ximo de b\u00fasqueda, por defecto 15 minutos.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"5\" data-aria-level=\"1\"><strong>Algorithm<\/strong>: El algoritmo hash, por defecto MD5.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"6\" data-aria-level=\"1\"><strong>CustomField<\/strong>: Un campo opcional para almacenar los resultados.<\/li>\n<\/ul>\n<p>El script para la verificaci\u00f3n del hash ajusta din\u00e1micamente estos par\u00e1metros en funci\u00f3n de las variables de entorno, si est\u00e1n configuradas.<\/p>\n<h3>Validaci\u00f3n de rutas y tipos de archivo<\/h3>\n<p>El script para la verificaci\u00f3n del hash valida las rutas de b\u00fasqueda, asegur\u00e1ndose de que existen y est\u00e1n formateadas correctamente. A\u00f1ade una barra invertida a las letras de unidad si faltan y comprueba si la ruta proporcionada es un archivo en lugar de una carpeta, emitiendo advertencias y ajust\u00e1ndose en consecuencia.<\/p>\n<h3>Gesti\u00f3n de trabajos para el c\u00e1lculo de hash<\/h3>\n<p>Para gestionar c\u00e1lculos hash potencialmente largos, el script utiliza trabajos PowerShell. Inicia un trabajo para cada ruta de b\u00fasqueda, buscando recursivamente archivos con la extensi\u00f3n especificada y calculando sus valores hash. Los resultados se recogen y se comparan con el valor hash proporcionado.<\/p>\n<h3>Tiempo de espera y gesti\u00f3n de errores<\/h3>\n<p>El script para la verificaci\u00f3n del hash incluye un mecanismo de tiempo de espera para detener la b\u00fasqueda despu\u00e9s de un periodo especificado, evitando que se ejecute indefinidamente. Recoge cualquier error encontrado durante la ejecuci\u00f3n del trabajo y proporciona mensajes de error detallados al usuario.<\/p>\n<h3>Integraci\u00f3n de campos personalizados<\/h3>\n<p>Si se especifica un campo personalizado, el script intenta guardar los resultados en \u00e9l mediante la funci\u00f3n Set-NinjaProperty, que gestiona varios tipos de campos personalizados y garantiza que los datos tengan el formato correcto y est\u00e9n dentro de los l\u00edmites de caracteres.<\/p>\n<h3>Resultado final<\/h3>\n<p>El script para la verificaci\u00f3n del hash muestra los archivos coincidentes, los errores encontrados e intenta establecer el campo personalizado con los resultados. Concluye saliendo con un c\u00f3digo de estado apropiado en funci\u00f3n del \u00e9xito o fracaso de las operaciones.<\/p>\n<h2>Posibles casos de uso<\/h2>\n<p>Imagina a un profesional de TI responsable de mantener la integridad de los archivos de distribuci\u00f3n de software en una red. Utilizando este script para la verificaci\u00f3n del hash, puede escanear regularmente los directorios donde se almacenan los paquetes de software, asegur\u00e1ndose de que no se han realizado cambios no autorizados. Por ejemplo, si el hash de un archivo .exe cr\u00edtico cambia, podr\u00eda indicar manipulaci\u00f3n o corrupci\u00f3n, lo que requiere una investigaci\u00f3n inmediata.<\/p>\n<h2>Comparaciones<\/h2>\n<p>Los m\u00e9todos tradicionales de verificaci\u00f3n de la integridad de los archivos suelen implicar comprobaciones manuales de hash mediante herramientas como certutil en Windows. Este script automatiza y agiliza el proceso, proporcionando una soluci\u00f3n m\u00e1s eficaz y completa. Tambi\u00e9n se integra perfectamente con otros scripts y herramientas utilizados por los profesionales de TI, lo que aumenta su utilidad en diversos escenarios.<\/p>\n<h2>FAQ<\/h2>\n<p><strong>\u00bfC\u00f3mo especificar varios directorios para la b\u00fasqueda?<\/strong><br \/>\nUtiliza una lista separada por comas en el par\u00e1metro -SearchPath.<\/p>\n<p><strong>\u00bfQu\u00e9 algoritmos hash son compatibles?<\/strong><br \/>\nEl script para la verificaci\u00f3n del hash admite MD5, SHA1, SHA256, SHA384 y SHA512.<\/p>\n<p><strong>\u00bfPuedo aumentar el tiempo de espera m\u00e1s all\u00e1 de 120 minutos?<\/strong><br \/>\nNo, el tiempo m\u00e1ximo de espera permitido es de 120 minutos por razones de rendimiento y practicidad.<\/p>\n<h2>Implicaciones<\/h2>\n<p>El uso de este script para la verificaci\u00f3n del hash ayuda a los profesionales de TI a garantizar la integridad de los archivos cr\u00edticos, reduciendo el riesgo de brechas de seguridad causadas por archivos manipulados o da\u00f1ados. Al automatizar el proceso de verificaci\u00f3n del hash, ahorra tiempo y proporciona un m\u00e9todo fiable para mantener la integridad de los datos en grandes redes.<\/p>\n<h2>Recomendaciones<\/h2>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"7\" data-aria-level=\"1\">Actualiza y mant\u00e9n peri\u00f3dicamente el script para la verificaci\u00f3n del hash para adaptarlo a nuevos algoritmos hash y tipos de archivo.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"8\" data-aria-level=\"1\">Programa la ejecuci\u00f3n del script para la verificaci\u00f3n del hash a intervalos regulares para supervisar continuamente la integridad de los archivos.<\/li>\n<\/ul>\n<ul>\n<li data-leveltext=\"\uf0b7\" data-font=\"Symbol\" data-listid=\"1\" data-list-defn-props=\"{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;\uf0b7&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}\" data-aria-posinset=\"9\" data-aria-level=\"1\">Utiliza la funci\u00f3n de campos personalizados para registrar los resultados en una ubicaci\u00f3n central para facilitar el acceso y la revisi\u00f3n.<\/li>\n<\/ul>\n<h2>Reflexiones finales<\/h2>\n<p>La incorporaci\u00f3n de scripts de PowerShell como \u00e9ste para la verificaci\u00f3n del hash a tu conjunto de herramientas inform\u00e1ticas mejora tu capacidad para <a href=\"https:\/\/www.ninjaone.com\/es\/blog\/seguridad-fuerza-de-trabajo-movil\/\" target=\"_blank\" rel=\"noopener\">mantener la integridad y la seguridad de los datos<\/a>. Herramientas como <a href=\"https:\/\/www.ninjaone.com\/es\/\" target=\"_blank\" rel=\"noopener\">NinjaOne<\/a> pueden agilizar a\u00fan m\u00e1s estos procesos, ofreciendo funciones avanzadas e integraciones que hacen que la gesti\u00f3n de los sistemas inform\u00e1ticos sea m\u00e1s eficiente y eficaz. Al aprovechar estas tecnolog\u00edas, los profesionales de TI pueden proteger mejor sus entornos y garantizar la fiabilidad de sus datos.<\/p>\n","protected":false},"author":35,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"_relevanssi_hide_post":"","_relevanssi_hide_content":"","_relevanssi_pin_for_all":"","_relevanssi_pin_keywords":"","_relevanssi_unpin_keywords":"","_relevanssi_related_keywords":"","_relevanssi_related_include_ids":"","_relevanssi_related_exclude_ids":"","_relevanssi_related_no_append":"","_relevanssi_related_not_related":"","_relevanssi_related_posts":"","_relevanssi_noindex_reason":"","_lmt_disableupdate":"","_lmt_disable":""},"operating_system":[4212],"use_cases":[4259,4262],"class_list":["post-353771","script_hub","type-script_hub","status-publish","hentry","script_hub_category-windows","use_cases-configuracion-general","use_cases-mantenimiento"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub\/353771","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/script_hub"}],"about":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/types\/script_hub"}],"author":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/comments?post=353771"}],"wp:attachment":[{"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/media?parent=353771"}],"wp:term":[{"taxonomy":"script_hub_category","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/operating_system?post=353771"},{"taxonomy":"use_cases","embeddable":true,"href":"https:\/\/www.ninjaone.com\/es\/wp-json\/wp\/v2\/use_cases?post=353771"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}