parent
65ebd1142b
commit
3d892725b8
@ -1,6 +1,8 @@ |
|||||||
#!/bin/bash |
#!/bin/bash |
||||||
go build -o execguard |
go build -o execguard |
||||||
sudo cp execguard /usr/local/bin/ |
if [ $? -eq 0 ]; then |
||||||
sudo ./execguard --update /usr/local/bin/execguard |
sudo cp execguard /usr/local/bin/ |
||||||
echo -e "Running execguard...Hit CTRL+C to end." |
sudo ./execguard --update /usr/local/bin/execguard |
||||||
sudo execguard |
echo -e "Running execguard...Hit CTRL+C to end." |
||||||
|
sudo execguard |
||||||
|
fi |
||||||
|
|||||||
@ -1,4 +1,4 @@ |
|||||||
package monitor |
package monitor_running_bins |
||||||
|
|
||||||
import ( |
import ( |
||||||
"execguard/core/alert" |
"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