Skip to content

Commit 89fd139

Browse files
committed
limit I/O on files scan
1 parent 829bbfb commit 89fd139

File tree

2 files changed

+60
-31
lines changed

2 files changed

+60
-31
lines changed

analysis.go

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,55 +9,65 @@ import (
99
"log"
1010
"os"
1111
"path/filepath"
12+
"time"
1213

1314
"github.com/hillu/go-yara"
1415
)
1516

17+
// FileDescriptor wrap path, filehash and last update into a structure. It is used for performance improvements and avoid reading file if it has not changed
18+
type FileDescriptor struct {
19+
FilePath string
20+
FileSize int64
21+
LastModified time.Time
22+
}
23+
1624
// FileAnalysis sub-routine for file analysis (used in registry / task scheduler / startmenu scan)
1725
func FileAnalysis(path string, pQuarantine string, pKill bool, pAggressive bool, pNotifications bool, pVerbose bool, rules *yara.Rules, sourceIndex string) {
26+
var f os.FileInfo
1827
var err error
1928
var content []byte
2029
var result yara.MatchRules
2130

22-
content, err = ioutil.ReadFile(path)
23-
if err != nil && pVerbose {
24-
log.Println(path, err)
25-
}
31+
if f, err = os.Stat(path); err != nil && pVerbose {
32+
log.Println("[ERROR]", path, err)
33+
} else {
34+
if RegisterFileInHistory(f, path, &filescanHistory) {
35+
content, err = ioutil.ReadFile(path)
36+
if err != nil && pVerbose {
37+
log.Println("[ERROR]", path, err)
38+
}
2639

27-
fileHash := fmt.Sprintf("%x", md5.Sum(content))
28-
if !StringInSlice(fileHash, filescanHistory) {
29-
if pVerbose {
30-
log.Println("[INFO] ["+sourceIndex+"] Analyzing", path)
31-
}
40+
if pVerbose {
41+
log.Println("[INFO] ["+sourceIndex+"] Analyzing", path)
42+
}
3243

33-
result = PerformYaraScan(content, rules, pVerbose)
44+
result = PerformYaraScan(content, rules, pVerbose)
3445

35-
if len(result) > 0 {
36-
// windows notifications
37-
if pNotifications {
38-
NotifyUser("YARA match", path+" match "+fmt.Sprint(len(result))+" rules")
39-
}
46+
if len(result) > 0 {
47+
// windows notifications
48+
if pNotifications {
49+
NotifyUser("YARA match", path+" match "+fmt.Sprint(len(result))+" rules")
50+
}
4051

41-
// logging
42-
for _, match := range result {
43-
log.Println("[ALERT]", "["+sourceIndex+"] YARA match", path, match.Namespace, match.Rule)
44-
}
52+
// logging
53+
for _, match := range result {
54+
log.Println("[ALERT]", "["+sourceIndex+"] YARA match", path, match.Namespace, match.Rule)
55+
}
4556

46-
// kill
47-
if pKill {
48-
killQueue = append(killQueue, path)
49-
}
57+
// kill
58+
if pKill {
59+
killQueue = append(killQueue, path)
60+
}
5061

51-
// dump matching file to quarantine
52-
if len(pQuarantine) > 0 {
53-
log.Println("[INFO]", "Dumping file", path)
54-
err := QuarantineFile(path, pQuarantine)
55-
if err != nil {
56-
log.Println("[ERROR]", "Cannot quarantine file", path, err)
62+
// dump matching file to quarantine
63+
if len(pQuarantine) > 0 {
64+
log.Println("[INFO]", "Dumping file", path)
65+
err := QuarantineFile(path, pQuarantine)
66+
if err != nil {
67+
log.Println("[ERROR]", "Cannot quarantine file", path, err)
68+
}
5769
}
5870
}
59-
} else {
60-
filescanHistory = append(filescanHistory, fileHash)
6171
}
6272
}
6373
}

utils.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,29 @@ package main
22

33
import (
44
"log"
5+
"os"
56

67
"github.com/gen2brain/beeep"
78
)
89

10+
// RegisterFileInHistory check if file is already known and hasn't change in files history return true if file is append to history and false if it is already known as is.
11+
func RegisterFileInHistory(f os.FileInfo, path string, history *[]FileDescriptor) bool {
12+
for i, h := range *history {
13+
if h.FilePath == path {
14+
if h.LastModified == f.ModTime() && h.FileSize == f.Size() {
15+
return false
16+
}
17+
(*history)[i].LastModified = f.ModTime()
18+
(*history)[i].FileSize = f.Size()
19+
return true
20+
}
21+
}
22+
23+
var d = FileDescriptor{FilePath: path, FileSize: f.Size(), LastModified: f.ModTime()}
24+
*history = append(*history, d)
25+
return true
26+
}
27+
928
// StringInSlice check wether or not a string already is inside a specified slice
1029
func StringInSlice(a string, list []string) bool {
1130
for _, b := range list {

0 commit comments

Comments
 (0)