Skip to content

Commit

Permalink
code refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
codeyourweb committed Dec 31, 2020
1 parent 8ea7643 commit 187978c
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 134 deletions.
160 changes: 160 additions & 0 deletions analysis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package main

import (
"crypto/md5"
"crypto/rc4"
b64 "encoding/base64"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"

"github.com/hillu/go-yara"
)

// FileAnalysis sub-routine for file analysis (used in registry / task scheduler / startmenu scan)
func FileAnalysis(path string, pQuarantine string, pKill bool, pAggressive bool, pNotifications bool, pVerbose bool, rules *yara.Rules, sourceIndex string) {
var err error
var content []byte
var result yara.MatchRules

content, err = ioutil.ReadFile(path)
if err != nil && pVerbose {
log.Println(path, err)
}

fileHash := fmt.Sprintf("%x", md5.Sum(content))
if !StringInSlice(fileHash, filescanHistory) {
if pVerbose {
log.Println("[INFO] ["+sourceIndex+"] Analyzing", path)
}

result = PerformYaraScan(content, rules, pVerbose)

if len(result) > 0 {
// windows notifications
if pNotifications {
NotifyUser("YARA match", path+" match "+fmt.Sprint(len(result))+" rules")
}

// logging
for _, match := range result {
log.Println("[ALERT]", "["+sourceIndex+"] YARA match", path, match.Namespace, match.Rule)
}

// kill
if pKill {
killQueue = append(killQueue, path)
}

// dump matching file to quarantine
if len(pQuarantine) > 0 {
log.Println("[INFO]", "Dumping file", path)
err := QuarantineFile(filepath.Base(path), pQuarantine)
if err != nil {
log.Println("[ERROR]", "Cannot quarantine file", path, err)
}
}
} else {
filescanHistory = append(filescanHistory, fileHash)
}
}
}

// MemoryAnalysis sub-routine for running processes analysis
func MemoryAnalysis(proc ProcessInformation, pQuarantine string, pKill bool, pAggressive bool, pNotifications bool, pVerbose bool, rules *yara.Rules) {
memoryHash := fmt.Sprintf("%x", md5.Sum(proc.ProcessMemory))

// if hash isn't already whitelisted, yara scan it
if !StringInSlice(memoryHash, memoryscanHistory) {
if pVerbose {
log.Println("[INFO] [MEMORY] Analyzing", proc.ProcessName, "PID:", proc.PID)
}

result := PerformYaraScan(proc.ProcessMemory, rules, pVerbose)
if len(result) > 0 {
// windows notifications
if pNotifications {
NotifyUser("YARA match", proc.ProcessName+" - PID:"+fmt.Sprint(proc.PID)+" match "+fmt.Sprint(len(result))+" rules")
}

// logging
for _, match := range result {
log.Println("[ALERT]", "[MEMORY] YARA match", proc.ProcessName, "PID:", fmt.Sprint(proc.PID), match.Namespace, match.Rule)
}

// dump matching process to quarantine
if len(pQuarantine) > 0 {
log.Println("[INFO]", "DUMPING PID", proc.PID)
err := QuarantineProcess(proc, pQuarantine)
if err != nil {
log.Println("[ERROR]", "Cannot quarantine PID", proc.PID, err)
}
}

// killing process
if pKill {
log.Println("[INFO]", "KILLING PID", proc.PID)
KillProcessByID(proc.PID, pVerbose)
}
} else {
memoryscanHistory = append(memoryscanHistory, memoryHash)
}
}
}

// QuarantineProcess dump process memory and cipher them in quarantine folder
func QuarantineProcess(proc ProcessInformation, quarantinePath string) (err error) {

err = quarantineContent(proc.ProcessMemory, proc.ProcessName+fmt.Sprint(proc.PID)+".mem", quarantinePath)
if err != nil {
return err
}

err = QuarantineFile(proc.ProcessPath, quarantinePath)
if err != nil {
return err
}

return nil
}

// QuarantineFile dump specified file and cipher them in quarantine folder
func QuarantineFile(path, quarantinePath string) (err error) {
fileContent, err := ioutil.ReadFile(path)
if err != nil {
return err
}

err = quarantineContent(fileContent, filepath.Base(path), quarantinePath)
if err != nil {
return err
}

return nil
}

// quarantineContent copy and encrypt suspicious content
func quarantineContent(content []byte, filename string, quarantinePath string) (err error) {
_, err = os.Stat(quarantinePath)
if os.IsNotExist(err) {
if err := os.MkdirAll(quarantinePath, 0600); err != nil {
return err
}
}

c, err := rc4.NewCipher([]byte("irma"))
if err != nil {
return err
}

xPE := make([]byte, len(content))
c.XORKeyStream(xPE, content)
err = ioutil.WriteFile(quarantinePath+"/"+filename+".irma", []byte(b64.StdEncoding.EncodeToString(xPE)), 0644)
if err != nil {
return err
}

return nil
}
93 changes: 0 additions & 93 deletions filehelper.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package main

import (
"crypto/md5"
"crypto/rc4"
b64 "encoding/base64"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -60,50 +56,6 @@ func ListUserWorkspaceFiles(verbose bool) (files []string) {
return files
}

// FileAnalysis sub-routine for file analysis (used in registry / task scheduler / startmenu scan)
func FileAnalysis(path string, pQuarantine string, pKill bool, pAggressive bool, pNotifications bool, pVerbose bool, rules *yara.Rules, sourceIndex string) {
var err error
var content []byte
var result yara.MatchRules

content, err = ioutil.ReadFile(path)
if err != nil && pVerbose {
log.Println(path, err)
}

fileHash := fmt.Sprintf("%x", md5.Sum(content))
if !StringInSlice(fileHash, filescanHistory) {
if pVerbose {
log.Println("[INFO] ["+sourceIndex+"] Analyzing", path)
}

result, err = YaraScan(content, rules)
if len(result) > 0 {
// windows notifications
if pNotifications {
NotifyUser("YARA match", path+" match "+fmt.Sprint(len(result))+" rules")
}

// logging
for _, match := range result {
log.Println("[ALERT]", "YARA match", path, match.Namespace, match.Rule)
}

// dump matching process to quarantine
if len(pQuarantine) > 0 {
log.Println("[INFO]", "DUMPING FILE", path)
err := QuarantineFile(content, filepath.Base(path), pQuarantine)
if err != nil {
log.Println("[ERROR]", "Cannot quarantine file", path, err)
}
}
}

filescanHistory = append(filescanHistory, fileHash)
}

}

// ListEnvironmentPathFiles list all files in PATH directories
func ListEnvironmentPathFiles(verbose bool) (files []string) {
env := os.Getenv("PATH")
Expand Down Expand Up @@ -232,48 +184,3 @@ func RetrivesFilesFromUserPath(path string, listFiles bool, includeFileExtension

return p, nil
}

// QuarantineFile copy and encrypt suspicious file
func QuarantineFile(content []byte, filename string, quarantinePath string) (err error) {
_, err = os.Stat(quarantinePath)
if os.IsNotExist(err) {
if err := os.MkdirAll(quarantinePath, 0600); err != nil {
return err
}
}

c, err := rc4.NewCipher([]byte("irma"))
if err != nil {
return err
}

xPE := make([]byte, len(content))
c.XORKeyStream(xPE, content)
err = ioutil.WriteFile(quarantinePath+"/"+filename+".irma", []byte(b64.StdEncoding.EncodeToString(xPE)), 0644)
if err != nil {
return err
}

return nil
}

// QuarantineProcess dump process executable and memory and cipher them in quarantine folder
func QuarantineProcess(proc ProcessInformation, quarantinePath string) (err error) {

err = QuarantineFile(proc.ProcessMemory, proc.ProcessName+fmt.Sprint(proc.PID)+".mem", quarantinePath)
if err != nil {
return err
}

procPEContent, err := ioutil.ReadFile(proc.ProcessPath)
if err != nil {
return err
}

err = QuarantineFile(procPEContent, proc.ProcessName+fmt.Sprint(proc.PID)+".pe", proc.ProcessPath)
if err != nil {
return err
}

return nil
}
11 changes: 6 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var (
notificationsHistory []string
filescanHistory []string
memoryscanHistory []string
killQueue []string
)

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"}
Expand Down Expand Up @@ -68,11 +69,11 @@ func main() {
log.Println("[INIT]", len(rules.GetRules()), "YARA rules compiled")
log.Println("[INFO] Start scanning Memory / Registry / StartMenu / Task Scheduler / Filesystem")
go MemoryAnalysisRoutine(*pDump, *pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
go RegistryAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
go StartMenuAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
go TaskSchedulerAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
go WindowsFileSystemAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
go UserFileSystemAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
//go RegistryAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
//go StartMenuAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
//go TaskSchedulerAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
//go WindowsFileSystemAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)
//go UserFileSystemAnalysisRoutine(*pQuarantine, *pKill, *pAggressive, *pNotifications, *pVerbose, rules)

for true {
time.Sleep(3600 * time.Second)
Expand Down
45 changes: 9 additions & 36 deletions procsmemory.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,45 +41,18 @@ func MemoryAnalysisRoutine(pDump string, pQuarantine string, pKill bool, pAggres

// analyze process memory and executable
for _, proc := range procs {
result := PerformYaraScan(proc.ProcessMemory, rules, pVerbose)
if len(result) == 0 {
procPE, err := ioutil.ReadFile(proc.ProcessPath)
if err != nil && pVerbose {
log.Println("[ERROR]", err)
}
result = PerformYaraScan(procPE, rules, pVerbose)
}

if len(result) > 0 {
// windows notifications
if pNotifications {
NotifyUser("YARA match", proc.ProcessName+" - PID:"+fmt.Sprint(proc.PID)+" match "+fmt.Sprint(len(result))+" rules")
}

// logging
for _, match := range result {
log.Println("[ALERT]", "YARA match", proc.ProcessName, "PID:", fmt.Sprint(proc.PID), match.Namespace, match.Rule)
}

// dump matching process to quarantine
if len(pQuarantine) > 0 {
log.Println("[INFO]", "DUMPING PID", proc.PID)
err := QuarantineProcess(proc, pQuarantine)
if err != nil {
log.Println("[ERROR]", "Cannot quarantine PID", proc.PID, err)
}
}

// killing process
if pKill {
if pVerbose {
log.Println("[INFO]", "KILLING PID", proc.PID)
}
KillProcessByID(proc.PID, pVerbose)
}

// parsing kill queue
if StringInSlice(proc.ProcessPath, killQueue) && pKill {
log.Println("[INFO]", "KILLING PID", proc.PID)
KillProcessByID(proc.PID, pVerbose)
} else {
MemoryAnalysis(proc, pQuarantine, pKill, pAggressive, pNotifications, pVerbose, rules)
FileAnalysis(proc.ProcessPath, pQuarantine, pKill, pAggressive, pNotifications, pVerbose, rules, "MEMORY")
}
}
killQueue = nil

time.Sleep(5 * time.Second)
}
}
Expand Down

0 comments on commit 187978c

Please sign in to comment.