parent
65ebd1142b
commit
3d892725b8
@ -1,6 +1,8 @@ |
||||
#!/bin/bash |
||||
go build -o execguard |
||||
sudo cp execguard /usr/local/bin/ |
||||
sudo ./execguard --update /usr/local/bin/execguard |
||||
echo -e "Running execguard...Hit CTRL+C to end." |
||||
sudo execguard |
||||
if [ $? -eq 0 ]; then |
||||
sudo cp execguard /usr/local/bin/ |
||||
sudo ./execguard --update /usr/local/bin/execguard |
||||
echo -e "Running execguard...Hit CTRL+C to end." |
||||
sudo execguard |
||||
fi |
||||
|
||||
@ -1,4 +1,4 @@ |
||||
package monitor |
||||
package monitor_running_bins |
||||
|
||||
import ( |
||||
"execguard/core/alert" |
||||
@ -0,0 +1,138 @@ |
||||
package new_file_monitor |
||||
|
||||
import ( |
||||
"execguard/core/alert" |
||||
"fmt" |
||||
"log" |
||||
"os" |
||||
"os/exec" |
||||
"path/filepath" |
||||
"time" |
||||
"sync" |
||||
"database/sql" |
||||
"io" |
||||
"strings" |
||||
|
||||
"github.com/fsnotify/fsnotify" |
||||
) |
||||
|
||||
var ( |
||||
alertCache sync.Map |
||||
) |
||||
|
||||
func Monitor_new_files(dirs []string, db *sql.DB, log log.Logger, scannerPath string) { |
||||
// Create new watcher
|
||||
watcher, err := fsnotify.NewWatcher() |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
defer watcher.Close() |
||||
|
||||
// Start listening for events
|
||||
go func() { |
||||
for { |
||||
select { |
||||
case event, ok := <-watcher.Events: |
||||
if !ok { |
||||
return |
||||
} |
||||
// Check if the event is a file creation
|
||||
if event.Op&fsnotify.Create == fsnotify.Create { |
||||
if strings.HasSuffix(event.Name, ".tmp") || strings.HasSuffix(event.Name, ".swp") { |
||||
continue |
||||
} |
||||
// Give the file a moment to finish writing (if downloading)
|
||||
time.Sleep(2 * time.Second) |
||||
|
||||
// Check if it's a file (not a directory)
|
||||
fileInfo, err := os.Stat(event.Name) |
||||
if err != nil { |
||||
log.Printf("Error checking file: %v", err) |
||||
continue |
||||
} |
||||
|
||||
if !fileInfo.IsDir() { |
||||
//exists, err := isFileNonEmpty(event.Name)
|
||||
//if err != nil {
|
||||
// log.Printf("Error checking file size: %v", err)
|
||||
// continue
|
||||
//}
|
||||
if fileInfo.Size() > 0 { |
||||
log.Printf("New file detected: %s\n", event.Name) |
||||
go scanFile(event.Name, scannerPath, db, log) |
||||
} |
||||
} |
||||
} |
||||
case err, ok := <-watcher.Errors: |
||||
if !ok { |
||||
return |
||||
} |
||||
log.Println("Error:", err) |
||||
} |
||||
} |
||||
}() |
||||
|
||||
for _, dir := range dirs { |
||||
// Add the folder to watch
|
||||
err = watcher.Add(dir) |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
} |
||||
|
||||
select {} |
||||
} |
||||
|
||||
func scanFile(filePath string, scannerPath string, db *sql.DB, log log.Logger) { |
||||
time.Sleep(time.Duration(300) * time.Millisecond) |
||||
// Get just the filename for cleaner output
|
||||
fileName := filepath.Base(filePath) |
||||
|
||||
log.Printf("Scanning file: %s\n", fileName) |
||||
|
||||
cmd := exec.Command(scannerPath, "-v", filePath) |
||||
output, err := cmd.CombinedOutput() |
||||
|
||||
if err != nil { |
||||
log.Printf("Error scanning %s: %v\n", fileName, err) |
||||
} |
||||
|
||||
log.Printf("Scan results for %s:\n%s\n", fileName, string(output)) |
||||
|
||||
// Check the exit status (0 = clean, 1 = virus found)
|
||||
if cmd.ProcessState.ExitCode() == 1 { |
||||
log.Printf("WARNING: Virus detected in %s\n", fileName) |
||||
|
||||
if _, seen := alertCache.LoadOrStore(filePath, struct{}{}); !seen { |
||||
go alert.SendAlert(fmt.Sprintf("Virus detected!: %s", filePath), db, log) |
||||
time.AfterFunc(10*time.Minute, func() { |
||||
alertCache.Delete(filePath) |
||||
}) |
||||
} |
||||
|
||||
} else if cmd.ProcessState.ExitCode() == 0 { |
||||
log.Printf("File %s is clean\n", fileName) |
||||
} |
||||
} |
||||
|
||||
func isFileNonEmpty(filename string) (bool, error) { |
||||
file, err := os.Open(filename) |
||||
if err != nil { |
||||
return false, err |
||||
} |
||||
defer file.Close() |
||||
|
||||
// Seek to the end
|
||||
_, err = file.Seek(0, io.SeekEnd) |
||||
if err != nil { |
||||
return false, err |
||||
} |
||||
|
||||
// Get current position (which is file size)
|
||||
pos, err := file.Seek(0, io.SeekCurrent) |
||||
if err != nil { |
||||
return false, err |
||||
} |
||||
|
||||
return pos > 0, nil |
||||
} |
||||
Loading…
Reference in new issue