-
Notifications
You must be signed in to change notification settings - Fork 0
/
scan.go
146 lines (122 loc) · 4.47 KB
/
scan.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package commands
import (
"fmt"
"os"
"strings"
"sync"
log "github.com/Sirupsen/logrus"
"github.com/fatih/structs"
"github.com/malice-plugins/pkgs/database/elasticsearch"
"github.com/malice-plugins/pkgs/utils"
"github.com/maliceio/malice/config"
"github.com/maliceio/malice/malice/database"
"github.com/maliceio/malice/malice/docker/client"
"github.com/maliceio/malice/malice/docker/client/container"
"github.com/maliceio/malice/malice/persist"
"github.com/maliceio/malice/plugins"
"github.com/pkg/errors"
)
// cmdScan scans a sample with all appropriate malice plugins
func cmdScan(path string, logs bool) error {
if len(path) > 0 {
// Check that file exists
if _, err := os.Stat(path); os.IsNotExist(err) {
log.Fatal(path + ": no such file or directory")
}
docker := client.NewDockerClient()
// clean stale containers from previous runs
containers, err := container.List(docker, true)
if err != nil {
return errors.Wrap(err, "failed to list containers")
}
for _, contr := range containers {
if utils.StringInSlice("malice", contr.Names) {
err = container.Remove(docker, contr.ID, true, true, true)
if err != nil {
return errors.Wrapf(err, "failed to remove container: %s", contr.Names[0])
}
}
}
elasticsearchInDocker := false
es := elasticsearch.Database{
Index: utils.Getopt("MALICE_ELASTICSEARCH_INDEX", "malice"),
Type: utils.Getopt("MALICE_ELASTICSEARCH_TYPE", "samples"),
URL: utils.Getopt("MALICE_ELASTICSEARCH_URL", config.Conf.DB.URL),
Username: utils.Getopt("MALICE_ELASTICSEARCH_USERNAME", config.Conf.DB.Username),
Password: utils.Getopt("MALICE_ELASTICSEARCH_PASSWORD", config.Conf.DB.Password),
}
// This assumes you haven't set up an elasticsearch instance and that malice should create one
if strings.EqualFold(es.URL, "http://localhost:9200") {
elasticsearchInDocker = true
// Check that database is running
if _, running, _ := container.Running(docker, config.Conf.DB.Name); !running {
log.Error("database is NOT running, starting now...")
err := database.Start(docker, es, logs)
if err != nil {
return errors.Wrap(err, "failed to start to database")
}
}
}
// Initialize the malice database
es.Init()
// Check Plugin Status
if plugins.InstalledPluginsCheck(docker) {
log.Debug("All enabled plugins are installed.")
} else {
// Prompt user to install all plugins?
fmt.Println("All enabled plugins not installed would you like to install them now? (yes/no)")
fmt.Println("[Warning] This can take a while if it is the first time you have ran Malice.")
if utils.AskForConfirmation() {
plugins.UpdateEnabledPlugins(docker)
}
}
es.Plugins = database.GetPluginsByCategory()
file := persist.File{Path: path}
file.Init()
// Output File Hashes
file.ToMarkdownTable()
// fmt.Println(string(file.ToJSON()))
//////////////////////////////////////
// Copy file to malice volume
container.CopyToVolume(docker, file)
//////////////////////////////////////
// Write all file data to the Database
resp, err := es.StoreFileInfo(structs.Map(file))
if err != nil {
return errors.Wrap(err, "scan cmd failed to store file info")
}
scanID := resp.Id
/////////////////////////////////////////////////////////////////
// Run all Intel Plugins on the md5 hash associated with the file
plugins.RunIntelPlugins(docker, file.SHA1, scanID, true, elasticsearchInDocker)
// Get file's mime type
mimeType, err := persist.GetMimeType(docker, file.SHA256)
if err != nil {
return errors.Wrap(err, "failed to get file's mime type")
}
log.Debug("looking for plugins that will run on: ", mimeType)
// Iterate over all applicable installed plugins
pluginsForMime := plugins.GetPluginsForMime(mimeType, true)
log.Debug("found these plugins: ")
for _, plugin := range pluginsForMime {
log.Debugf(" - %v", plugin.Name)
}
var wg sync.WaitGroup
wg.Add(len(pluginsForMime))
for _, plugin := range pluginsForMime {
log.Debugf(">>>>> RUNNING Plugin: %s >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", plugin.Name)
// Start Plugin Container
// TODO: don't use the default of true for --logs
go plugin.StartPlugin(docker, file.SHA256, scanID, true, elasticsearchInDocker, &wg)
}
wg.Wait() // this waits for the counter to be 0
log.Debug("Done with plugins.")
} else {
log.Error("please supply a valid file to scan")
}
return nil
}
// APIScan is an API wrapper for cmdScan
func APIScan(file string) error {
return cmdScan(file, false)
}