Skip to content

Commit 187978c

Browse files
committed
code refactoring
1 parent 8ea7643 commit 187978c

File tree

4 files changed

+175
-134
lines changed

4 files changed

+175
-134
lines changed

analysis.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package main
2+
3+
import (
4+
"crypto/md5"
5+
"crypto/rc4"
6+
b64 "encoding/base64"
7+
"fmt"
8+
"io/ioutil"
9+
"log"
10+
"os"
11+
"path/filepath"
12+
13+
"github.com/hillu/go-yara"
14+
)
15+
16+
// FileAnalysis sub-routine for file analysis (used in registry / task scheduler / startmenu scan)
17+
func FileAnalysis(path string, pQuarantine string, pKill bool, pAggressive bool, pNotifications bool, pVerbose bool, rules *yara.Rules, sourceIndex string) {
18+
var err error
19+
var content []byte
20+
var result yara.MatchRules
21+
22+
content, err = ioutil.ReadFile(path)
23+
if err != nil && pVerbose {
24+
log.Println(path, err)
25+
}
26+
27+
fileHash := fmt.Sprintf("%x", md5.Sum(content))
28+
if !StringInSlice(fileHash, filescanHistory) {
29+
if pVerbose {
30+
log.Println("[INFO] ["+sourceIndex+"] Analyzing", path)
31+
}
32+
33+
result = PerformYaraScan(content, rules, pVerbose)
34+
35+
if len(result) > 0 {
36+
// windows notifications
37+
if pNotifications {
38+
NotifyUser("YARA match", path+" match "+fmt.Sprint(len(result))+" rules")
39+
}
40+
41+
// logging
42+
for _, match := range result {
43+
log.Println("[ALERT]", "["+sourceIndex+"] YARA match", path, match.Namespace, match.Rule)
44+
}
45+
46+
// kill
47+
if pKill {
48+
killQueue = append(killQueue, path)
49+
}
50+
51+
// dump matching file to quarantine
52+
if len(pQuarantine) > 0 {
53+
log.Println("[INFO]", "Dumping file", path)
54+
err := QuarantineFile(filepath.Base(path), pQuarantine)
55+
if err != nil {
56+
log.Println("[ERROR]", "Cannot quarantine file", path, err)
57+
}
58+
}
59+
} else {
60+
filescanHistory = append(filescanHistory, fileHash)
61+
}
62+
}
63+
}
64+
65+
// MemoryAnalysis sub-routine for running processes analysis
66+
func MemoryAnalysis(proc ProcessInformation, pQuarantine string, pKill bool, pAggressive bool, pNotifications bool, pVerbose bool, rules *yara.Rules) {
67+
memoryHash := fmt.Sprintf("%x", md5.Sum(proc.ProcessMemory))
68+
69+
// if hash isn't already whitelisted, yara scan it
70+
if !StringInSlice(memoryHash, memoryscanHistory) {
71+
if pVerbose {
72+
log.Println("[INFO] [MEMORY] Analyzing", proc.ProcessName, "PID:", proc.PID)
73+
}
74+
75+
result := PerformYaraScan(proc.ProcessMemory, rules, pVerbose)
76+
if len(result) > 0 {
77+
// windows notifications
78+
if pNotifications {
79+
NotifyUser("YARA match", proc.ProcessName+" - PID:"+fmt.Sprint(proc.PID)+" match "+fmt.Sprint(len(result))+" rules")
80+
}
81+
82+
// logging
83+
for _, match := range result {
84+
log.Println("[ALERT]", "[MEMORY] YARA match", proc.ProcessName, "PID:", fmt.Sprint(proc.PID), match.Namespace, match.Rule)
85+
}
86+
87+
// dump matching process to quarantine
88+
if len(pQuarantine) > 0 {
89+
log.Println("[INFO]", "DUMPING PID", proc.PID)
90+
err := QuarantineProcess(proc, pQuarantine)
91+
if err != nil {
92+
log.Println("[ERROR]", "Cannot quarantine PID", proc.PID, err)
93+
}
94+
}
95+
96+
// killing process
97+
if pKill {
98+
log.Println("[INFO]", "KILLING PID", proc.PID)
99+
KillProcessByID(proc.PID, pVerbose)
100+
}
101+
} else {
102+
memoryscanHistory = append(memoryscanHistory, memoryHash)
103+
}
104+
}
105+
}
106+
107+
// QuarantineProcess dump process memory and cipher them in quarantine folder
108+
func QuarantineProcess(proc ProcessInformation, quarantinePath string) (err error) {
109+
110+
err = quarantineContent(proc.ProcessMemory, proc.ProcessName+fmt.Sprint(proc.PID)+".mem", quarantinePath)
111+
if err != nil {
112+
return err
113+
}
114+
115+
err = QuarantineFile(proc.ProcessPath, quarantinePath)
116+
if err != nil {
117+
return err
118+
}
119+
120+
return nil
121+
}
122+
123+
// QuarantineFile dump specified file and cipher them in quarantine folder
124+
func QuarantineFile(path, quarantinePath string) (err error) {
125+
fileContent, err := ioutil.ReadFile(path)
126+
if err != nil {
127+
return err
128+
}
129+
130+
err = quarantineContent(fileContent, filepath.Base(path), quarantinePath)
131+
if err != nil {
132+
return err
133+
}
134+
135+
return nil
136+
}
137+
138+
// quarantineContent copy and encrypt suspicious content
139+
func quarantineContent(content []byte, filename string, quarantinePath string) (err error) {
140+
_, err = os.Stat(quarantinePath)
141+
if os.IsNotExist(err) {
142+
if err := os.MkdirAll(quarantinePath, 0600); err != nil {
143+
return err
144+
}
145+
}
146+
147+
c, err := rc4.NewCipher([]byte("irma"))
148+
if err != nil {
149+
return err
150+
}
151+
152+
xPE := make([]byte, len(content))
153+
c.XORKeyStream(xPE, content)
154+
err = ioutil.WriteFile(quarantinePath+"/"+filename+".irma", []byte(b64.StdEncoding.EncodeToString(xPE)), 0644)
155+
if err != nil {
156+
return err
157+
}
158+
159+
return nil
160+
}

filehelper.go

Lines changed: 0 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
package main
22

33
import (
4-
"crypto/md5"
5-
"crypto/rc4"
6-
b64 "encoding/base64"
74
"errors"
8-
"fmt"
95
"io/ioutil"
106
"log"
117
"os"
@@ -60,50 +56,6 @@ func ListUserWorkspaceFiles(verbose bool) (files []string) {
6056
return files
6157
}
6258

63-
// FileAnalysis sub-routine for file analysis (used in registry / task scheduler / startmenu scan)
64-
func FileAnalysis(path string, pQuarantine string, pKill bool, pAggressive bool, pNotifications bool, pVerbose bool, rules *yara.Rules, sourceIndex string) {
65-
var err error
66-
var content []byte
67-
var result yara.MatchRules
68-
69-
content, err = ioutil.ReadFile(path)
70-
if err != nil && pVerbose {
71-
log.Println(path, err)
72-
}
73-
74-
fileHash := fmt.Sprintf("%x", md5.Sum(content))
75-
if !StringInSlice(fileHash, filescanHistory) {
76-
if pVerbose {
77-
log.Println("[INFO] ["+sourceIndex+"] Analyzing", path)
78-
}
79-
80-
result, err = YaraScan(content, rules)
81-
if len(result) > 0 {
82-
// windows notifications
83-
if pNotifications {
84-
NotifyUser("YARA match", path+" match "+fmt.Sprint(len(result))+" rules")
85-
}
86-
87-
// logging
88-
for _, match := range result {
89-
log.Println("[ALERT]", "YARA match", path, match.Namespace, match.Rule)
90-
}
91-
92-
// dump matching process to quarantine
93-
if len(pQuarantine) > 0 {
94-
log.Println("[INFO]", "DUMPING FILE", path)
95-
err := QuarantineFile(content, filepath.Base(path), pQuarantine)
96-
if err != nil {
97-
log.Println("[ERROR]", "Cannot quarantine file", path, err)
98-
}
99-
}
100-
}
101-
102-
filescanHistory = append(filescanHistory, fileHash)
103-
}
104-
105-
}
106-
10759
// ListEnvironmentPathFiles list all files in PATH directories
10860
func ListEnvironmentPathFiles(verbose bool) (files []string) {
10961
env := os.Getenv("PATH")
@@ -232,48 +184,3 @@ func RetrivesFilesFromUserPath(path string, listFiles bool, includeFileExtension
232184

233185
return p, nil
234186
}
235-
236-
// QuarantineFile copy and encrypt suspicious file
237-
func QuarantineFile(content []byte, filename string, quarantinePath string) (err error) {
238-
_, err = os.Stat(quarantinePath)
239-
if os.IsNotExist(err) {
240-
if err := os.MkdirAll(quarantinePath, 0600); err != nil {
241-
return err
242-
}
243-
}
244-
245-
c, err := rc4.NewCipher([]byte("irma"))
246-
if err != nil {
247-
return err
248-
}
249-
250-
xPE := make([]byte, len(content))
251-
c.XORKeyStream(xPE, content)
252-
err = ioutil.WriteFile(quarantinePath+"/"+filename+".irma", []byte(b64.StdEncoding.EncodeToString(xPE)), 0644)
253-
if err != nil {
254-
return err
255-
}
256-
257-
return nil
258-
}
259-
260-
// QuarantineProcess dump process executable and memory and cipher them in quarantine folder
261-
func QuarantineProcess(proc ProcessInformation, quarantinePath string) (err error) {
262-
263-
err = QuarantineFile(proc.ProcessMemory, proc.ProcessName+fmt.Sprint(proc.PID)+".mem", quarantinePath)
264-
if err != nil {
265-
return err
266-
}
267-
268-
procPEContent, err := ioutil.ReadFile(proc.ProcessPath)
269-
if err != nil {
270-
return err
271-
}
272-
273-
err = QuarantineFile(procPEContent, proc.ProcessName+fmt.Sprint(proc.PID)+".pe", proc.ProcessPath)
274-
if err != nil {
275-
return err
276-
}
277-
278-
return nil
279-
}

main.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ var (
1717
notificationsHistory []string
1818
filescanHistory []string
1919
memoryscanHistory []string
20+
killQueue []string
2021
)
2122

2223
var defaultScannedFileExtensions = []string{".txt", ".csv", ".htm", ".html", ".flv", ".f4v", ".avi", ".3gp", ".3g2", ".3gp2", ".3p2", ".divx", ".mp4", ".mkv", ".mov", ".qt", ".asf", ".wmv", ".rm", ".rmvb", ".vob", ".dat", ".mpg", ".mpeg", ".bik", ".fcs", ".mp3", ".mpeg3", ".flac", ".ape", ".ogg", ".aac", ".m4a", ".wma", ".ac3", ".wav", ".mka", ".rm", ".ra", ".ravb", ".mid", ".midi", ".cda", ".jpg", ".jpe", ".jpeg", ".jff", ".gif", ".png", ".bmp", ".tif", ".tiff", ".emf", ".wmf", ".eps", ".psd", ".cdr", ".swf", ".exe", ".lnk", ".dll", ".ps1", ".scr", ".ocx", ".com", ".sys", ".class", ".o", ".so", ".elf", ".prx", ".vb", ".vbs", ".js", ".bat", ".cmd", ".msi", ".msp", ".deb", ".rpm", ".sh", ".pl", ".dylib", ".doc", ".dot", ".docx", ".dotx", ".docm", ".dotm", ".xsl", ".xls", ".xlsx", ".xltx", ".xlsm", ".xltm", ".xlam", ".xlsb", ".ppt", ".pot", ".pps", ".pptx", ".potx", ".pptm", ".potm", ".ppsx", ".ppsm", ".rtf", ".pdf", ".msg", ".eml", ".vsd", ".vss", ".vst", ".vdx", ".vsx", ".vtx", ".xps", ".oxps", ".one", ".onepkg", ".xsn", ".odt", ".ods", ".odp", ".sxw", ".pub", ".mdb", ".accdb", ".accde", ".accdr", ".accdc", ".chm", ".mht", ".zip", ".7z", ".7-z", ".rar", ".iso", ".cab", ".jar", ".bz", ".bz2", ".tbz", ".tbz2", ".gz", ".tgz", ".arj", ".dmg", ".smi", ".img", ".xar"}
@@ -68,11 +69,11 @@ func main() {
6869
log.Println("[INIT]", len(rules.GetRules()), "YARA rules compiled")
6970
log.Println("[INFO] Start scanning Memory / Registry / StartMenu / Task Scheduler / Filesystem")
7071
go MemoryAnalysisRoutine(*pDump, *pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
71-
go RegistryAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
72-
go StartMenuAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
73-
go TaskSchedulerAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
74-
go WindowsFileSystemAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
75-
go UserFileSystemAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
72+
//go RegistryAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
73+
//go StartMenuAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
74+
//go TaskSchedulerAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
75+
//go WindowsFileSystemAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
76+
//go UserFileSystemAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
7677

7778
for true {
7879
time.Sleep(3600 * time.Second)

procsmemory.go

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -41,45 +41,18 @@ func MemoryAnalysisRoutine(pDump string, pQuarantine string, pKill bool, pAggres
4141

4242
// analyze process memory and executable
4343
for _, proc := range procs {
44-
result := PerformYaraScan(proc.ProcessMemory, rules, pVerbose)
45-
if len(result) == 0 {
46-
procPE, err := ioutil.ReadFile(proc.ProcessPath)
47-
if err != nil && pVerbose {
48-
log.Println("[ERROR]", err)
49-
}
50-
result = PerformYaraScan(procPE, rules, pVerbose)
51-
}
52-
53-
if len(result) > 0 {
54-
// windows notifications
55-
if pNotifications {
56-
NotifyUser("YARA match", proc.ProcessName+" - PID:"+fmt.Sprint(proc.PID)+" match "+fmt.Sprint(len(result))+" rules")
57-
}
58-
59-
// logging
60-
for _, match := range result {
61-
log.Println("[ALERT]", "YARA match", proc.ProcessName, "PID:", fmt.Sprint(proc.PID), match.Namespace, match.Rule)
62-
}
63-
64-
// dump matching process to quarantine
65-
if len(pQuarantine) > 0 {
66-
log.Println("[INFO]", "DUMPING PID", proc.PID)
67-
err := QuarantineProcess(proc, pQuarantine)
68-
if err != nil {
69-
log.Println("[ERROR]", "Cannot quarantine PID", proc.PID, err)
70-
}
71-
}
72-
73-
// killing process
74-
if pKill {
75-
if pVerbose {
76-
log.Println("[INFO]", "KILLING PID", proc.PID)
77-
}
78-
KillProcessByID(proc.PID, pVerbose)
79-
}
8044

45+
// parsing kill queue
46+
if StringInSlice(proc.ProcessPath, killQueue) && pKill {
47+
log.Println("[INFO]", "KILLING PID", proc.PID)
48+
KillProcessByID(proc.PID, pVerbose)
49+
} else {
50+
MemoryAnalysis(proc, pQuarantine, pKill, pAggressive, pNotifications, pVerbose, rules)
51+
FileAnalysis(proc.ProcessPath, pQuarantine, pKill, pAggressive, pNotifications, pVerbose, rules, "MEMORY")
8152
}
8253
}
54+
killQueue = nil
55+
8356
time.Sleep(5 * time.Second)
8457
}
8558
}

0 commit comments

Comments
 (0)