Folder Tripwire Powershell

Ian

Administrator
Joined
Oct 27, 2013
Messages
1,735
Reaction score
630
I'm working on creating a tripwire script, so that I'm alerted to certain filetypes being created in a folder. It works as expected for the most, although I had intended to receive an e-mail with ALL files changes occurring in a 5 minute period (to batch them, rather than an e-mail each time).

However, it seems to e-mail be batches of 8 files at a time and spaces sending the e-mail every 5 minutes. For example, if I triggered 80 file alerts in 1 minute, it would alert me to 8 files changing each 5 minutes, taking 10 e-mails to notify me of all changes, rather than just 1.

Can you see anything in this script that would cause this problem?

Code:
### SERVER NAME

$serverName = "TestServer"

### SET PHP FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $phpwatcher = New-Object System.IO.FileSystemWatcher
    $phpwatcher.Path = "C:\www\vhosts"
    $phpwatcher.Filter = "*.php"
    $phpwatcher.IncludeSubdirectories = $true
    $phpwatcher.EnableRaisingEvents = $true 

### SET SQL FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $sqlwatcher = New-Object System.IO.FileSystemWatcher
    $sqlwatcher.Path = "C:\www\vhosts"
    $sqlwatcher.Filter = "*.sql"
    $sqlwatcher.IncludeSubdirectories = $true
    $sqlwatcher.EnableRaisingEvents = $true 

### SET ZIP FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $zipwatcher = New-Object System.IO.FileSystemWatcher
    $zipwatcher.Path = "C:\www\vhosts"
    $zipwatcher.Filter = "*.zip"
    $zipwatcher.IncludeSubdirectories = $true
    $zipwatcher.EnableRaisingEvents = $true 

### SET RAR FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $rarwatcher = New-Object System.IO.FileSystemWatcher
    $rarwatcher.Path = "C:\www\vhosts"
    $rarwatcher.Filter = "*.rar"
    $rarwatcher.IncludeSubdirectories = $true
    $rarwatcher.EnableRaisingEvents = $true 


### SET EMAIL SETTINGS

    $From = "[email protected]"
    $To = "[email protected]"
    $SMTPServer = "smtp.example.com"
    $SMTPPort = "587"
    $Username = "[email protected]"
    $Password = "password"
    $subject = "File Change Log - $serverName"

$global:body = @()


### DEFINE PHP ACTIONS AFTER A EVENT IS DETECTED
    $phpaction = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), ${changeType}: $path"
                Add-content "$PSScriptRoot\Logs\PHP\$(get-date -f yyyy-MM-dd).txt" -value $logline
                Write-Output $logline

                $global:changes = "true"
                $global:body += $logline
                $global:body += "`r`n"
              }   

### DEFINE SQL ACTIONS AFTER A EVENT IS DETECTED
    $sqlaction = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), ${changeType}: $path"
                Add-content "$PSScriptRoot\Logs\SQL\$(get-date -f yyyy-MM-dd).txt" -value $logline
                Write-Output $logline

                $global:changes = "true"
                $global:body += $logline
                $global:body += "`r`n"
              }   

### DEFINE ZIP ACTIONS AFTER A EVENT IS DETECTED
    $zipaction = {
    
                if ($Event.SourceEventArgs.Name -notlike "*.log.zip") {
    
                $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), ${changeType}: $path"
                Add-content "$PSScriptRoot\Logs\ZIP\$(get-date -f yyyy-MM-dd).txt" -value $logline
                Write-Output $logline

                $global:changes = "true"
                $global:body += $logline
                $global:body += "`r`n"
                }
              }   

### DEFINE RAR ACTIONS AFTER A EVENT IS DETECTED
    $raraction = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), ${changeType}: $path"
                Add-content "$PSScriptRoot\Logs\RAR\$(get-date -f yyyy-MM-dd).txt" -value $logline
                Write-Output $logline

                $global:changes = "true"
                $global:body += $logline
                $global:body += "`r`n"
              }   

### DECIDE WHICH PHP EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY 
    $phpcreated = Register-ObjectEvent $phpwatcher "Created" -Action $phpaction
    $phpchanged = Register-ObjectEvent $phpwatcher "Changed" -Action $phpaction
    $phpdeleted = Register-ObjectEvent $phpwatcher "Deleted" -Action $phpaction
    $phprenamed = Register-ObjectEvent $phpwatcher "Renamed" -Action $phpaction

### DECIDE WHICH SQL EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY 
    $sqlcreated = Register-ObjectEvent $sqlwatcher "Created" -Action $sqlaction
    $sqlchanged = Register-ObjectEvent $sqlwatcher "Changed" -Action $sqlaction
    $sqldeleted = Register-ObjectEvent $sqlwatcher "Deleted" -Action $sqlaction
    $sqlrenamed = Register-ObjectEvent $sqlwatcher "Renamed" -Action $sqlaction

### DECIDE WHICH ZIP EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY 
    $zipcreated = Register-ObjectEvent $zipwatcher "Created" -Action $zipaction
    $zipchanged = Register-ObjectEvent $zipwatcher "Changed" -Action $zipaction
    $zipdeleted = Register-ObjectEvent $zipwatcher "Deleted" -Action $zipaction
    $ziprenamed = Register-ObjectEvent $zipwatcher "Renamed" -Action $zipaction

### DECIDE WHICH RAR EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY 
    $rarcreated = Register-ObjectEvent $rarwatcher "Created" -Action $raraction
    $rarchanged = Register-ObjectEvent $rarwatcher "Changed" -Action $raraction
    $rardeleted = Register-ObjectEvent $rarwatcher "Deleted" -Action $raraction
    $rarrenamed = Register-ObjectEvent $rarwatcher "Renamed" -Action $raraction

    while ($true) {
        sleep 300

        if ($global:changes -eq "true") {

                $smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
                $smtp.EnableSSL = $true
                $smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
                $smtp.Send($From, $To, $subject, $body);

                Write-Output "E-Mail Sent"

                $global:changes = "false"
                $global:body = @()
                $global:body += "PHP Change Log - $serverName"
                $global:body += "`r`n"
        }

    }
 

Regedit32

Moderator
Joined
Mar 4, 2016
Messages
3,609
Reaction score
1,140
Ian's pop quiz for kindergarten class: The children must get both parts correct to move on to Primary School!

Part 1.

Circle the letter that is correct answer:
  1. 1 apple + 1 apple = A. 0 apples, B. 1 apple, C.11 Apples, D. 2 Apples

Part 2.
  • Are
    Untitled.png
    (the Euler–Mascheroni constant), π + e, π − e, πe, π/e, πe, π√2, ππ, eπ2, ln π, 2e, ee, Catalan's constant or Khinchin's constant rational, algebraic irrational, or transcendental? What is the irrationality measure of each of these numbers?

I'm going to need a good strong cup of coffee to wrap my head around your batch issue Ian and expect to graduate with O levels if I manage to work it out :D
 

Ian

Administrator
Joined
Oct 27, 2013
Messages
1,735
Reaction score
630
Haha, yes it is a bit of a brain twister! I'm still working on figuring it out, I'll try and simplify it down to see if I can get it to print batches of changed files every 5 mins to screen, then see if that still has the same problem. I'll keep you updated :D.
 

Regedit32

Moderator
Joined
Mar 4, 2016
Messages
3,609
Reaction score
1,140
You know how each particular file type has checking for the event:

"Changed" -Action $<some variable here>

Have you tried pausing it there before it continues, e.g.:

"Changed" -Action $<some variable>, 10000

Where 10000 represents milliseconds and thus would be a 10 second pause

Perhaps a pause here or on other events would allow the Batch time to create the message body before sending it?!


Your idea here is interesting given normally a tripwire is comparing apples with apples, i.e. you set up a constant file or filehash to be used similar to a Antivirus definitions list, to compare the state of file at time tested with the constant, which is how you know whether its been altered in any way.

But the problem in your case is if I understood correctly, you are not checking for alterations to file types, but rather, whether new files of X file type have been added to the server.


If you get it working that would be a neat way to alert you to any potential malware attack with a few additional modifications to your current Script.
 

Ian

Administrator
Joined
Oct 27, 2013
Messages
1,735
Reaction score
630
Thanks, I'll give that a try this weekend :). Yup, I'm using it as part of a malware detection script - once it's working I'll modify it to notify via e-mail, windows alerts, logging, etc... the script needs a good clean up before it's ready :D.
 

Regedit32

Moderator
Joined
Mar 4, 2016
Messages
3,609
Reaction score
1,140
You'll need to modify it to search for malware in humans too :D

The virus I contracted pre surgery last December is still affecting me 9 months on lol


stubborn bugs these days :mad:
 

Ian

Administrator
Joined
Oct 27, 2013
Messages
1,735
Reaction score
630
I think I may need a few more lines of code for that ;).

The virus I contracted pre surgery last December is still affecting me 9 months on lol

Ouch :( - I hope it's not troubling you too much!
 

Ian

Administrator
Joined
Oct 27, 2013
Messages
1,735
Reaction score
630
I've simplified the script greatly (and fixed the previousl problem), but the last thing I'd like to do is to try and filter the monitored filetypes. By default, FileSystemWatcher can't handle multiple extensions - so I'm telling it to monitor "*.*". I'd like to filter the results to include "*.php, *.rar, *.zip" for example.

Do you know how I might achieve that? I've had a search and found an example for C#, but I'm not sure how to translate that to PowerShell. Once I've got that solved, the script is pretty much ready to publish :).

Here's the simplified code:

Code:
### MONITORING SETTINGS

    $serverName = "Test Server"   #server name
    $emailFreq = "10"   #number of seconds between e-mail notification batches
    $monitorFolder = "c:\"   #folder to monitor (i.e. "C:\Monitor")
    $fileFilter = "*.*"   #filetypes to monitor (i.e. "*.php")

### EMAIL SETTINGS

    $From = "[email protected]"
    $To = "[email protected]"
    $SMTPServer = "smtp.test.com"
    $SMTPPort = "587"
    $Username = "[email protected]"
    $Password = "test"


### SET PHP FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
    $filewatcher = New-Object System.IO.FileSystemWatcher
    $filewatcher.Path = $monitorFolder
    $filewatcher.Filter = $fileFilter
    $filewatcher.IncludeSubdirectories = $true
    $filewatcher.EnableRaisingEvents = $true

### DEFINE PHP ACTIONS AFTER A EVENT IS DETECTED
    $fileaction = { $path = $Event.SourceEventArgs.FullPath
                $changeType = $Event.SourceEventArgs.ChangeType
                $logline = "$(Get-Date), ${changeType}: $path"
                Write-Output $logline

                $global:changes = "true"
                $global:body += $logline
                $global:body += "`r`n"
              }  

### DECIDE WHICH PHP EVENTS SHOULD BE WATCHED + SET CHECK FREQUENCY
    $filecreated = Register-ObjectEvent $filewatcher "Created" -Action $fileaction
    $filechanged = Register-ObjectEvent $filewatcher "Changed" -Action $fileaction
    $filedeleted = Register-ObjectEvent $filewatcher "Deleted" -Action $fileaction
    $filerenamed = Register-ObjectEvent $filewatcher "Renamed" -Action $fileaction


    while ($true) {
        sleep $emailFreq

        if ($global:changes -eq "true") {

                $smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
                $smtp.EnableSSL = $true
                $smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
                $smtp.Send($From, $To, "File Change Log - $serverName", $global:body);

                Write-Output "E-Mail Sent"

                $global:changes = "false"

              
        }

    }
 
Last edited:

Regedit32

Moderator
Joined
Mar 4, 2016
Messages
3,609
Reaction score
1,140
Hi Ian

I'm staring at this on my phone, so its a little tricky to read everything.

I have an idea but can't test it till I get out of hospital and back to the Desktop. Failing that though I could convert the .php to .ps1 for you.

The method you are trying to manipulate though normally only takes one argument, but you could create an Object and pass filters to it.

You'll want to avoid .api and concentrate on .NET
 

Ian

Administrator
Joined
Oct 27, 2013
Messages
1,735
Reaction score
630
I hope everything is ok @Regedit32, I didn't realise you were in hospital at the moment. Don't worry about it for now, I'll keep plugging away at it and if I'm still stuck when you're recovered I'll be very grateful for your input :).

As it happens, I'm working on the code at the moment, so I'll hopefully have made some progress soon.
 

Trouble

Noob Whisperer
Moderator
Joined
Nov 19, 2013
Messages
13,396
Reaction score
2,318
till I get out of hospital
What's up Timothy?
Hope you're better soon and nothing too serious is going on.
Please take care and get well and please keep us posted.
In the mean time my thoughts and prayers are with you.
 

Ian

Administrator
Joined
Oct 27, 2013
Messages
1,735
Reaction score
630
I've made some good progress, so should hopefully have it fixed soon. I keep lapsing in to bad habits and mixing my coding languages.

I forgot that "true" and "false" values should be $true and $false in powershell.
 
Joined
Nov 19, 2013
Messages
6,297
Reaction score
1,274
Gosh. I wasnt following this thread. A little over my head.
I wondered what had happened to regedit and went into the profile and, subsequently, to here

Get well soon Pal.
 

Regedit32

Moderator
Joined
Mar 4, 2016
Messages
3,609
Reaction score
1,140
Thanks Dave

Hoping to get back home next weekend. The medications they have been giving me appear to finally be winning the battle.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top