How to Monitor File Modifications and Ensure Integrity Using PowerShell

In the IT world, maintaining the integrity and security of files is paramount. IT professionals and Managed Service Providers (MSPs) need reliable methods to monitor file modifications to prevent unauthorized changes, ensure compliance, and maintain system stability. This blog post explores a powerful PowerShell script designed to check if a file exists, determine if it has been modified within a specified timeframe, and verify its integrity using a hash check.

Background

IT professionals and MSPs often face the challenge of ensuring files remain unaltered unless explicitly changed by authorized personnel. Unauthorized modifications can lead to security breaches, data corruption, and compliance issues. To tackle these challenges, a robust solution is required to monitor file changes and ensure file integrity. This PowerShell script offers a streamlined approach to address these needs, providing alerts based on specific conditions, such as file changes or the lack thereof.

The Script

<#
.SYNOPSIS
    Checks whether a file is present and if it has been updated within your specified time frame or fails a hash check.
.DESCRIPTION
    Checks whether a file is present and if it has been updated within your specified time frame or fails a hash check.

PARAMETER: -Alert "Alert If Change" or -Alert "Alert If No Change"
    Raise an alert if the file has or hasn't been modified based on your other parameters.

PARAMETER: -Hash "REPLACEMEC32D73431CED24FF114B2A216671C60117AF5012B40"
    The hash or checksum to verify that the file hasn't been modified.
PARAMETER: -Algorithm "SHA256"
    The hashing algorithm used for your inputted hash.
.EXAMPLE
    -Path "C:\TestFile.txt" -Hash "REPLACEME04C6F26CC32D73431CED24FF114B2A216671C60117AF5012B40" -Alert "Alert If No Change"

    C:\TestFile.txt exists!
    Hash Given: REPLACEME04C6F26CC32D73431CED24FF114B2A216671C60117AF5012B40
    Current Hash: 35BAFB1CE99AEF3AB068AFBAABAE8F21FD9B9F02D3A9442E364FA92C0B3EEEF0
    Hash mismatch!

.EXAMPLE
    -Path "C:\TestFile.txt" -Hash "35BAFB1CE99AEF3AB068AFBAABAE8F21FD9B9F02D3A9442E364FA92C0B3BEEF0" -Alert "Alert If No Change"

    C:\TestFile.txt exists!
    Hash Given: 35BAFB1CE99AEF3AB068AFBAABAE8F21FD9B9F02D3A9442E364FA92C0B3BEEF0
    Current Hash: 35BAFB1CE99AEF3AB068AFBAABAE8F21FD9B9F02D3A9442E364FA92C0B3BEEF0
    Hash matches!
    [Alert] File has not been modified!

PARAMETER: -Days "REPLACEMEWITHANUMBER"
    Raise an alert if the file hasn't been modified within the specified number of days. 
    Minutes and Hours are added to this time.

PARAMETER: -Hours "REPLACEMEWITHANUMBER"
    Raise an alert if the file hasn't been modified within the specified number of hours. 
    Days and Minutes are added to this time.

PARAMETER: -Minutes "REPLACEMEWITHANUMBER"
    Raise an alert if the file hasn't been modified within the specified number of minutes. 
    Days and Hours are added to this time.
.EXAMPLE
    -Path "C:\TestFile.txt" -Days 365 -Alert "Alert If Change"

    C:\TestFile.txt exists!
    Checking if the file was modified in the last 365 day(s) 00 hour(s) 00 minute(s)
    File was last modified on 02/07/2024 14:59:56.
    File has been updated within the time period.
    [Alert] File has been modified!
.EXAMPLE
    -Path "C:\TestFile.txt" -Days 30 -Alert "Alert If Change"

    C:\TestFile.txt exists!
    Checking if the file was modified in the last 30 day(s) 00 hour(s) 00 minute(s)
    File was last modified on 05/15/2023 15:13:55.
    File has not been modified within the time period.

.OUTPUTS
    None
.NOTES
    Minimum OS Architecture Supported: Windows 8+, Server 2012+
    Release Notes:
    Initial Release
By 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.
    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. 
    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. 
    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. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, 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. 
    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. 
    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. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param (
    [Parameter()]
    [String]$Alert,
    [Parameter()]
    [String]$Path,
    [Parameter()]
    [String]$Hash,
    [Parameter()]
    [String]$Algorithm = "SHA256",
    [Parameter()]
    [int]$Days,
    [Parameter()]
    [int]$Hours,
    [Parameter()]
    [int]$Minutes
)

begin {
    # Replace parameters with dynamic script variables
    if ($env:alert -and $env:alert -notlike "null") { $Alert = $env:alert }
    if ($env:targetFilePath -and $env:targetFilePath -notlike "null") { $Path = $env:targetFilePath }
    if ($env:hash -and $env:hash -notlike "null") { $Hash = $env:hash }
    if ($env:algorithm -and $env:algorithm -notlike "null") { $Algorithm = $env:algorithm }
    if ($env:daysSinceLastModification -and $env:daysSinceLastModification -notlike "null") { $Days = $env:daysSinceLastModification }
    if ($env:hoursSinceLastModification -and $env:hoursSinceLastModification -notlike "null") { $Hours = $env:hoursSinceLastModification }
    if ($env:minutesSinceLastModification -and $env:minutesSinceLastModification -notlike "null") { $Minutes = $env:minutesSinceLastModification }

    # Test for local administrator permissions
    function Test-IsElevated {
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)
        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
    }

    if (-not (Test-IsElevated)) {
        Write-Warning -Message "Some files or folders may require local Administrator permissions to view."
    }

    # Verify the given algorithm is supported by PowerShell
    $AllowedAlgorithms = "SHA1", "SHA256", "SHA384", "SHA512", "MD5"
    if ($AllowedAlgorithms -notcontains $Algorithm) {
        Write-Host "[Error] Invalid Algorithm selected ($Algorithm)! Allowed selections are 'SHA1','SHA256','SHA384','SHA512' and 'MD5'."
        exit 1
    }

    # Check for required parameter
    if (-Not ($Path)) {
        Write-Host "[Error] A filepath is required!"
        Exit 1
    }

    switch ($Alert) {
        "Alert If Change" { Write-Verbose "Alerting if file $Path has been modified." }
        "Alert If No Change" { Write-Verbose "Alerting if file $Path has not been modified." }
        default { Write-Verbose "No alert was selected." }
    }

    $ExitCode = 0
}
process {

    # File existence check
    if ($Path -and -Not (Test-Path $Path -ErrorAction SilentlyContinue)) {
        Write-Host "[Alert] $Path does not exist!"
        Exit 1
    }
    else {
        Write-Host "$Path exists!"
    }

    # Confirm we were given a filepath and not a directory
    $File = Get-Item -Path $Path -ErrorAction SilentlyContinue
    if ($File.PSIsContainer) {
        Write-Host "[Error] Please provide a file path, not a directory."
        Exit 1
    }

    # If given the files hash verify it matches
    if ($Hash) {
        $CurrentHash = Get-FileHash -Path $File.FullName -Algorithm $Algorithm | Select-Object -ExpandProperty Hash
        Write-Host "Hash Given: $Hash"
        Write-Host "Current Hash: $CurrentHash"

        if ($Hash -notlike $CurrentHash) {
            Write-Host "Hash mismatch!"

            if($Alert -eq "Alert If Change"){
                Write-Host "[Alert] File has been modified!"
                $ExitCode = 1
            }
        }
        else {
            Write-Host "Hash matches!"

            if($Alert -eq "Alert If No Change"){
                Write-Host "[Alert] File has not been modified!"
                $ExitCode = 1
            }
        }
    }

    # Get the current date and subtract the days, hours and minutes to compare with the file 
    $Cutoff = Get-Date
    $CurrentDate = $Cutoff

    if ($Days) { $Cutoff = $Cutoff.AddDays(-$Days) }
    if ($Hours) { $Cutoff = $Cutoff.AddHours(-$Hours) }
    if ($Minutes) { $Cutoff = $Cutoff.AddMinutes(-$Minutes) }

    $TimeSpan = New-TimeSpan $Cutoff $CurrentDate

    if (($Days -or $Hours -or $Minutes) -and ($Cutoff -ne $CurrentDate)) {
        Write-Host "Checking if the file was modified in the last $($TimeSpan.ToString("dd' day(s) 'hh' hour(s) 'mm' minute(s)'"))"
        Write-Host "File was last modified on $($File.LastWriteTime)."

        if ($File.LastWriteTime -ge $Cutoff) {
            Write-Host "File has been updated within the time period."

            if($Alert -eq "Alert If Change"){
                Write-Host "[Alert] File has been modified!"
                $ExitCode = 1
            }
        }
        else {
            Write-Host "File has not been updated within the time period."

            if($Alert -eq "Alert If No Change"){
                Write-Host "[Alert] File has not been modified!"
                $ExitCode = 1
            }
        }
    }

    Exit $ExitCode
}
end {

 

Access over 300+ scripts in the NinjaOne Dojo

Get Access

Detailed Breakdown

This PowerShell script is designed to check the existence of a file, verify if it has been modified within a given timeframe, and perform a hash check to ensure file integrity. Let’s break down the script step-by-step:

  1. Parameter Definition: The script begins by defining parameters, including Alert, Path, Hash, Algorithm, Days, Hours, and Minutes. These parameters allow users to specify the file to be monitored, the expected hash, the hashing algorithm, and the timeframe for modification checks.
  2. Environment Variable Replacement: The script dynamically replaces parameters with environment variables if they are set. This flexibility allows for easy integration with automated systems and scripts.
  3. Administrator Permissions Check: A function Test-IsElevated is used to verify if the script is running with administrator privileges, ensuring it has the necessary permissions to access and monitor the specified files.
  4. Algorithm Validation: The script checks if the provided hashing algorithm is supported. Allowed algorithms include SHA1, SHA256, SHA384, SHA512, and MD5.
  5. File Existence and Type Check: The script verifies if the specified path exists and confirms it is a file, not a directory.
  6. Hash Verification: If a hash is provided, the script computes the current hash of the file using the specified algorithm and compares it to the given hash. It then alerts if there is a mismatch or if the file has not been modified based on the Alert parameter.
  7. Modification Time Check: The script calculates the cutoff time based on the provided Days, Hours, and Minutesparameters. It then compares the file’s last modification time to the cutoff time, raising an alert if the file has or has not been modified within the specified timeframe.

Potential Use Cases

Imagine an IT professional responsible for maintaining the security and integrity of sensitive configuration files on a server. Using this script, they can set up a daily check to verify if any critical files have been altered. For instance, they could use the script to monitor a configuration file, ensuring it has not been modified unexpectedly. If the script detects a change, it raises an alert, enabling the IT professional to investigate and take appropriate action.

Comparisons

Compared to other methods of monitoring file changes, such as using third-party software or manual checks, this PowerShell script offers several advantages:

  • Cost-Effectiveness: Being a PowerShell script, it eliminates the need for costly third-party solutions.
  • Customization: Users can easily modify the script to suit their specific needs.
  • Integration: The script can be integrated into existing automation workflows and systems.

FAQs

1) How do I run this script?

To run the script, save it as a .ps1 file and execute it in PowerShell with the appropriate parameters.

2) Can this script monitor multiple files at once?

The script is designed to monitor one file at a time. However, you can modify it to loop through multiple files if needed.

3) What happens if I don’t have administrator privileges?

The script will issue a warning, and some files or folders may not be accessible without the necessary permissions.

Implications

Using this script to monitor file changes has significant implications for IT security. It ensures that any unauthorized modifications are promptly detected, allowing for swift response and mitigation. Regular monitoring helps maintain system integrity, ensures compliance with security policies, and protects against potential breaches.

Recommendations

  • Regular Checks: Schedule regular checks to ensure continuous monitoring of critical files.
  • Integration: Integrate the script into your existing IT management and automation tools for seamless operation.
  • Backup: Always maintain backups of critical files to restore them in case of unauthorized modifications.

Final Thoughts

Monitoring file modifications is crucial for maintaining IT security and integrity. This PowerShell script provides an efficient and customizable solution for IT professionals and MSPs. By integrating this script into your workflow, you can ensure continuous monitoring and prompt detection of any unauthorized changes. For more comprehensive IT management solutions, consider exploring NinjaOne, a powerful platform designed to enhance your IT operations and security.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

How to Monitor Log Files on macOS with a Custom Bash Script

How to Monitor Log Files and Detect Specific Text on Linux Using a Bash Script

How to Use PowerShell to Monitor Text Files and Trigger Alerts for IT Professionals

How to Automate Microsoft Safety Scanner Using a PowerShell Script

Comprehensive Guide to Using PowerShell for Efficient Event Log Searches

How to Use PowerShell to Detect Open and Established Ports in Windows

×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • 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.
  • 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.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, 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.
  • 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.
  • 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.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).