dorothy2 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG +39 -14
  3. data/README.md +80 -62
  4. data/UPDATE +6 -14
  5. data/bin/dorothy2 +472 -0
  6. data/dorothy2.gemspec +22 -16
  7. data/etc/ddl/dorothive.ddl +619 -373
  8. data/etc/sources.yml.example +27 -2
  9. data/lib/doroGUI.rb +232 -0
  10. data/lib/doroParser.rb +34 -78
  11. data/lib/dorothy2.rb +288 -248
  12. data/lib/dorothy2/BFM.rb +114 -61
  13. data/lib/dorothy2/DEM.rb +3 -1
  14. data/lib/dorothy2/NAM.rb +2 -2
  15. data/lib/dorothy2/Settings.rb +2 -1
  16. data/lib/dorothy2/VSM.rb +2 -1
  17. data/lib/dorothy2/deep_symbolize.rb +2 -7
  18. data/lib/dorothy2/do-init.rb +286 -19
  19. data/lib/dorothy2/do-logger.rb +1 -1
  20. data/lib/dorothy2/do-utils.rb +382 -33
  21. data/lib/dorothy2/version.rb +1 -1
  22. data/lib/dorothy2/vtotal.rb +30 -20
  23. data/lib/mu/xtractr.rb +11 -11
  24. data/lib/mu/xtractr/stream.rb +1 -1
  25. data/lib/www/public/reset.css +153 -0
  26. data/lib/www/public/style.css +65 -0
  27. data/lib/www/views/analyses.erb +28 -0
  28. data/lib/www/views/email.erb +63 -0
  29. data/lib/www/views/flows.erb +30 -0
  30. data/lib/www/views/layout.erb +27 -0
  31. data/lib/www/views/profile.erb +49 -0
  32. data/lib/www/views/queue.erb +28 -0
  33. data/lib/www/views/resume.erb +135 -0
  34. data/lib/www/views/resume.erb~ +88 -0
  35. data/lib/www/views/samples.erb +20 -0
  36. data/lib/www/views/upload.erb +154 -0
  37. data/share/img/The_big_picture.pdf +0 -0
  38. data/test/tc_dorothy_full.rb +3 -0
  39. metadata +169 -70
  40. data/TODO +0 -27
  41. data/bin/dorothy_start +0 -225
  42. data/bin/dorothy_stop +0 -28
  43. data/bin/dparser_start +0 -94
  44. data/bin/dparser_stop +0 -31
  45. data/etc/dorothy copy.yml.example +0 -39
  46. data/etc/extensions.yml +0 -41
  47. data/share/update-dorothive.sql +0 -19
@@ -3,35 +3,43 @@
3
3
  # See the file 'LICENSE' for copying permission.
4
4
 
5
5
 
6
- ###########################
7
- ###BINARY FETCHER MODULE###
8
- ### ###
9
- ###########################
6
+ #############################
7
+ ### BINARY FETCHER MODULE ###
8
+ #############################
9
+
10
10
  #The BFM module is in charge of retreiving the binary from the sources configured in the sources.yml file.
11
11
  #It receive the source hash, and return the downloaded binaries objects.
12
+
13
+
14
+
15
+
16
+
12
17
  module Dorothy
13
18
 
14
19
  class DorothyFetcher
15
- attr_reader :bins
20
+ attr_reader :added
16
21
 
17
- #Source struct: Hash, {:dir => "#{HOME}/bins/honeypot", :typeid=> 0 ..}
18
- def initialize(source)
22
+ #Source_arr is an array e.g.: ["webgui", {"type"=>"system", "localdir"=>"/Users/akira/Downloads/doroth2_1.9.3_mail/opt/bins/webgui", "typeid"=>1}]
23
+ def initialize(source_arr)
19
24
  ndownloaded = 0
20
25
 
21
- @bins = []
22
- #case source.honeypot1[:type]
26
+ @added = Hash.new
27
+ source = source_arr[1] #source_arr[1] is a hash
28
+
29
+ source["priority"] ||= 0
30
+ source["profile"] ||= "default"
31
+
23
32
 
24
33
  case source["type"]
25
34
 
26
35
  when "ssh" then
27
- LOGGER.info "BFM", " Fetching trojan from > Honeypot"
28
36
  #file = "/opt/dionaea/var/dionaea/binaries/"
29
37
  #puts "Start to download malware"
30
38
 
31
39
  files = []
32
40
 
33
41
  begin
34
- Net::SSH.start(source["ip"], source["user"], :password => source["pass"], :port => source["port"]) do |ssh|
42
+ Net::SSH.start(source["ip"], source["username"], :password => source["pass"], :port => source["port"]) do |ssh|
35
43
  ssh.scp.download!(source["remotedir"],source["localdir"], :recursive => true) do |ch, name, sent, total|
36
44
  unless files.include? "#{source["localdir"]}/" + File.basename(name)
37
45
  ndownloaded += 1
@@ -55,7 +63,7 @@ module Dorothy
55
63
 
56
64
  begin
57
65
  unless DoroSettings.env[:testmode]
58
- Net::SSH.start(source["ip"], source["user"], :password => source["pass"], :port => source["port"]) do |ssh|
66
+ Net::SSH.start(source["host"], source["user"], :password => source["pass"], :port => source["port"]) do |ssh|
59
67
  ssh.exec "mv #{source["remotedir"]}/* #{source["remotedir"]}/../analyzed "
60
68
  end
61
69
  end
@@ -64,78 +72,123 @@ module Dorothy
64
72
  end
65
73
 
66
74
  files.each do |f|
67
- next unless load_malw(f, source[skey][:typeid])
75
+ begin
76
+ @added = QueueManager.add(f, source_arr[0], source["profile"], source["priority"])
77
+ rescue
78
+ LOGGER.error "BFM", "Error while adding the bin to the queue, skipping."
79
+ LOGGER.debug "BFM", $!
80
+ next
81
+ end
82
+ end
83
+
84
+
85
+ #Thanks to Salvatore Gervino who made the first PoC of this source-module: http://www.honeynet.it/wp-content/uploads/Mentored_Projects/salvatore_gervino-dorothy2_email.pdf
86
+ when "mail" then
87
+
88
+ @db = Insertdb.new
89
+
90
+ account = {:address=>source["host"], :username=>source["username"],
91
+ :password=>source["password"], :port=>source["port"], :ssl=>source["enable_ssl"], :n_emails => source["n_emails"] , :delete_once_downloaded => source["delete_once_downloaded"]}
92
+
93
+
94
+ mailer = Dorothy::Mailer.new(account)
95
+ begin
96
+ emails = mailer.get_emails
97
+
98
+ emails.each do |email|
99
+
100
+ LOGGER.debug "BFM", "Analyzing email: #{email.date} - #{email.from_addrs[0]} - #{email.subject} - #{email.to_addrs[0]}"
101
+
102
+
103
+ unless email.attachments.empty?
104
+ mail_id = @db.push_email_data(email)
105
+
106
+ attachment_content_type = Mail::ContentTypeElement.new(email.attachments.first.content_type)
107
+ #if the attachment is a forwarded email, treat the attachment as the original email
108
+ if attachment_content_type.main_type == 'message'
109
+
110
+ LOGGER.info "BFM", "Forwarded email from #{email.from.first} found"
111
+ email = mailer.read_from_string email.attachments.first.body.decoded
112
+ mail_id = @db.push_email_data(email, mail_id)
113
+
114
+ end
115
+
116
+
117
+ email.attachments.each do | attachment |
118
+ LOGGER.info "BFM", "Attachment found: #{attachment.filename} "
119
+ bin = source["localdir"] + "/" + Digest::MD5.hexdigest(attachment.body.decoded) + "_" + attachment.filename
120
+ Util.write( bin, attachment.body.decoded)
121
+ id = QueueManager.add(bin, source_arr[0],source["profile"], source["priority"], mail_id)
122
+ @added.store(id,[bin, source["priority"], source["profile"], source_arr[0]])
123
+ end
124
+ end
125
+
126
+ end #end for
127
+ @db.close
128
+ LOGGER.debug "BFM", "Analyzing email: End "
129
+ rescue => e
130
+ LOGGER.error "BFM", "Error while adding the bin to the queue, skipping. #{$!}"
131
+ LOGGER.debug "DB", e.backtrace
68
132
  end
69
133
 
70
134
  when "system" then
71
- LOGGER.info "BFM", "Fetching trojan from > filesystem: " + source["localdir"]
72
135
  empty = true
73
136
  Dir.foreach(source["localdir"]) do |file|
74
137
  bin = source["localdir"] + "/" + file
75
- next if File.directory?(bin) || !load_malw(bin,source["typeid"])
76
- empty = false
138
+ next if File.directory?(bin)
139
+
140
+ begin
141
+ id = QueueManager.add(bin, source_arr[0], source["profile"], source["priority"])
142
+ empty = false
143
+ @added.store(id,[bin, source["priority"], source["profile"], source_arr[0]])
144
+
145
+ rescue
146
+ LOGGER.error "BFM", "Error while adding the bin to the queue, skipping."
147
+ LOGGER.debug "BFM", $!
148
+ next
149
+ end
150
+
77
151
  end
78
- LOGGER.warn "BFM", "There are no files to analyze in the selected source" if empty
152
+ LOGGER.debug "BFM", "No binaries were found in the selected source" if empty
79
153
  else
80
- LOGGER.fatal "BFM", "Source #{skey} is not yet configured"
154
+ LOGGER.fatal "BFM", "Source type #{source["type"]} is not yet configured"
81
155
  end
82
156
  end
83
157
 
84
- private
85
- def load_malw(f, typeid, sourceinfo = nil)
158
+ #Expects an Hash as input
159
+ def self.loader(sources, daemon=false)
86
160
 
87
- filename = File.basename f
88
- bin = Loadmalw.new(f)
89
- if bin.size == 0 || bin.sha.empty?
90
- LOGGER.warn "BFM", "Warning - Empty file #{filename}, deleting and skipping.."
91
- FileUtils.rm bin.binpath
92
- return false
93
- end
161
+ infinite = true
94
162
 
95
- samplevalues = [bin.sha, bin.size, bin.dir_bin, filename, bin.md5, bin.type ]
96
- sighvalues = [bin.sha, typeid, bin.ctime, "null"]
97
163
 
98
164
  begin
99
- updatedb(samplevalues, sighvalues)
100
- rescue => e
101
- LOGGER.error "DB", $!
102
- LOGGER.debug "DB", e.inspect
103
- return false
104
- end
105
-
106
- #FileUtils.rm(bin.binpath)
107
- @bins.push bin
108
- end
109
-
165
+ while infinite #infinite loop
166
+ sources.each do |sname|
167
+ #skip if it is webgui
168
+ next if sname.first == 'webgui'
110
169
 
170
+ LOGGER.debug "BFM", "Start to fetch binaries from #{sname.first.yellow} @ #{sname[1]["localdir"]}"
111
171
 
112
- def updatedb(samplevalues, sighvalues, airisvalues=nil)
172
+ added = self.new(sname).added
173
+ LOGGER.info "BFM", "#{added.size.to_s.yellow} binaries retreived from #{sname.first.yellow}"
113
174
 
114
- db = Insertdb.new
115
- db.begin_t
175
+ added.each do |b|
176
+ LOGGER.debug "BFM", "#{b[0]}\t#{File.basename(b[1][0])}\t#{b[1][3]}"
177
+ end
116
178
 
117
- unless db.select("samples", "sha256", samplevalues[0]).one? #is bin.sha already present in my db?
118
- raise "A DB error occurred" unless db.insert("samples", samplevalues) #no it isn't, insert it
179
+ end
180
+ if daemon
181
+ LOGGER.info "BFM", "SLEEPING 10"
182
+ sleep DoroSettings.bfm[:sleeptime].to_i
183
+ end
184
+ infinite = daemon
185
+ end
119
186
 
120
- else #yes it is, don't insert in sample table
121
- date = db.select("sightings", "sample", samplevalues[0]).first["date"]
122
- LOGGER.warn "BFM", " The binary #{samplevalues[0]} has been already added on #{date}"
187
+ rescue SignalException #, RuntimeError
188
+ LOGGER.warn "BFM", "SIGINT".red + " Catched [1], exiting gracefully."
123
189
  end
124
-
125
- raise "A DB error occurred" unless db.insert("sightings", sighvalues)
126
-
127
- # explanation: I don't want to insert/analyze the same malware but I do want to
128
- # insert the sighting value anyway ("the malware X has been downloaded 1 time but
129
- # has been spoted 32 times")
130
-
131
- db.commit
132
- db.close
133
- true
134
-
135
190
  end
136
191
 
137
-
138
-
139
192
  end
140
193
 
141
194
  end
@@ -54,12 +54,14 @@ module DoroParser
54
54
 
55
55
 
56
56
 
57
- class SMTP #todo to redo
57
+ class SMTP #todo to redo ##NEW PARSER CODED BY SALVATORE
58
58
  attr_reader :hcmd
59
59
  attr_reader :hcont
60
60
  attr_accessor :body
61
61
  attr_accessor :rdata
62
62
 
63
+
64
+
63
65
  def self.body(data)
64
66
  email = TMail::Mail.parse(data)
65
67
  return email
@@ -43,14 +43,14 @@ module Dorothy
43
43
 
44
44
  def init_sniffer
45
45
  Net::SSH.start(@server, @user, :password => @pass, :port =>@port) do |ssh|
46
- ssh.exec "sudo killall tcpdump"
46
+ ssh.exec "nohup sudo killall tcpdump 2>/dev/null"
47
47
  end
48
48
  end
49
49
 
50
50
  def stop_sniffer(pid)
51
51
  Net::SSH.start(@server, @user, :password => @pass, :port =>@port) do |ssh|
52
52
  ssh.exec "sudo kill -2 #{pid}"
53
- #LOGGER.info "[NAM]".yellow + "Tcpdump instance #{pid} stopped"
53
+ LOGGER.debug "NAM", "Tcpdump instance #{pid} stopped"
54
54
  end
55
55
  end
56
56
 
@@ -10,7 +10,8 @@ module Dorothy
10
10
  attr_reader :_settings
11
11
 
12
12
  def load!(filename, options = {})
13
- newsets = YAML::load_file(filename).deep_symbolize
13
+ t = YAML::load_file(filename).extend DeepSymbolizable
14
+ newsets = t.deep_symbolize
14
15
  newsets = newsets[options[:env].to_sym] if \
15
16
  options[:env] && \
16
17
  newsets[options[:env].to_sym]
@@ -106,7 +106,8 @@ module Dorothy
106
106
  @pp2
107
107
  end
108
108
 
109
- def get_new_procs(current_procs, original_procs=BASELINE_PROCS)
109
+ def get_new_procs(current_procs, original_procs_file)
110
+ original_procs = YAML.load_file(original_procs_file)
110
111
  @new_procs = Hash.new
111
112
  current_procs.each_key {|pid|
112
113
  @new_procs.merge!(Hash[pid, current_procs[pid]]) unless original_procs.has_key?(pid)
@@ -1,3 +1,4 @@
1
+ # From https://gist.github.com/morhekil/998709
1
2
  # Symbolizes all of hash's keys and subkeys.
2
3
  # Also allows for custom pre-processing of keys (e.g. downcasing, etc)
3
4
  # if the block is given:
@@ -13,10 +14,6 @@
13
14
 
14
15
  module DeepSymbolizable
15
16
 
16
- class Hash
17
- include DeepSymbolizable
18
- end
19
-
20
17
  def deep_symbolize(&block)
21
18
  method = self.class.to_s.downcase.to_sym
22
19
  syms = DeepSymbolizable::Symbolizers
@@ -62,6 +59,4 @@ module DeepSymbolizable
62
59
  end
63
60
  end
64
61
 
65
- end
66
-
67
- class Hash; include DeepSymbolizable; end
62
+ end
@@ -19,6 +19,7 @@ module Dorothy
19
19
  Dir.mkdir("#{home}/opt")
20
20
  Dir.mkdir("#{home}/opt/bins")
21
21
  Dir.mkdir("#{home}/opt/analyzed")
22
+ Dir.mkdir("#{home}/opt/analyzed/bins")
22
23
  end
23
24
  unless Util.exists?("#{home}/etc")
24
25
  Dir.mkdir("#{home}/etc")
@@ -50,6 +51,8 @@ module Dorothy
50
51
  conf["virustotal"] = Hash.new
51
52
  conf["esx"] = Hash.new
52
53
  conf["pcapr"] = Hash.new
54
+ conf["wgui"] = Hash.new
55
+ conf["bfm"] = Hash.new
53
56
 
54
57
 
55
58
  ################################################
@@ -64,14 +67,15 @@ module Dorothy
64
67
 
65
68
  puts "The Dorothy home directory is #{home}"
66
69
 
67
- conf["env"]["pidfile"] = "#{home}/var/dorothy.pid"
70
+ conf["env"]["pidfiles"] = "#{home}/var"
68
71
  conf["env"]["pidfile_parser"] = "#{home}/var/doroParser.pid"
69
72
  conf["env"]["analysis_dir"] = "#{home}/opt/analyzed"
73
+ conf["env"]["bins_repository"] = "#{home}/opt/analyzed/bins"
70
74
  conf["env"]["geoip"] = "#{home}/etc/geo/GeoLiteCity.dat"
71
75
  conf["env"]["geoasn"] = "#{home}/etc/geo/GeoIPASNum.dat"
72
76
  conf["env"]["geoisp"] = "#{home}/etc/geo/GeoIPISP.dat"
73
77
 
74
- conf["env"]["dtimeout"] = 3600
78
+ conf["env"]["sleeptime"] = 5
75
79
 
76
80
  conf["env"]["logfile"] = "#{home}/var/log/dorothy.log"
77
81
  conf["env"]["logfile_parser"] = "#{home}/var/log/parser.log"
@@ -120,19 +124,7 @@ module Dorothy
120
124
 
121
125
  puts "\n######### [" + " Sandbox configuration settings ".red + "] #########"
122
126
 
123
- puts "Insert the time (seconds) that the Sandbox should be run before it's reverted [60]"
124
- conf["sandbox"]["sleeptime"] = (t = gets.chop).empty? ? 60 : t
125
127
 
126
- puts "Insert how many screenshots do you want to take [1]"
127
- conf["sandbox"]["num_screenshots"] = (t = gets.chop).empty? ? 1 : t.to_i
128
-
129
- if conf["sandbox"]["num_screenshots"] > 1
130
- puts "Insert the time interval (seconds) between each screenshot [5] "
131
- conf["sandbox"]["screen2time"] = (t = gets.chop).empty? ? 5 : t
132
- end
133
-
134
- puts "After how many seconds do you want to take the first screenshot? [1]"
135
- conf["sandbox"]["screen1time"] = (t = gets.chop).empty? ? 1 : t
136
128
 
137
129
  puts "Which is the sandox's network? [10.10.10.0/0]"
138
130
  conf["sandbox"]["network"] = (t = gets.chop).empty? ? "10.10.10.0/0" : t
@@ -158,7 +150,7 @@ module Dorothy
158
150
  conf["nam"]["pass"] = gets.chop
159
151
 
160
152
  puts "SSH Port [22] :"
161
- conf["nam"]["port"] = (t = gets.chop).empty? ? 22 : t
153
+ conf["nam"]["port"] = (t = gets.chop).empty? ? 22 : t.to_i
162
154
 
163
155
  puts "Folder where to store PCAP files [/home/#{conf["nam"]["user"]}/pcaps]"
164
156
  conf["nam"]["pcaphome"] = (t = gets.chop).empty? ? "/home/#{conf["nam"]["user"]}/pcaps" : t
@@ -183,7 +175,30 @@ module Dorothy
183
175
  end
184
176
 
185
177
  puts "Pcapr HTTP Port [8080]:"
186
- conf["pcapr"]["port"] = (t = gets.chop).empty? ? 8080 : t
178
+ conf["pcapr"]["port"] = (t = gets.chop).empty? ? 8080 : t.to_i
179
+
180
+
181
+ ######################################################
182
+ ###WebGUI
183
+ ######################################################
184
+ puts "\n######### [" + " Web GUI configuration ".red + "] #########"
185
+
186
+ puts "IP Address used for listening. Use 0.0.0.0 to allow remote connections [localhost]:"
187
+ conf["wgui"]["host"] = (t = gets.chop).empty? ? 'localhost' : t.to_s
188
+
189
+ puts "TCP port [3435]:"
190
+ conf["wgui"]["port"] = (t = gets.chop).empty? ? 3435 : t.to_i
191
+
192
+ conf["wgui"]["environment"] = "production"
193
+ conf["wgui"]["logfile"] = "#{home}/var/log/webgui.log"
194
+
195
+ ######################################################
196
+ ###Binaries Fetcher Module
197
+ ######################################################
198
+ puts "\n######### [" + " Binaries Fetcher Module ".red + "] #########"
199
+
200
+ puts "How often the BFM should pool all the resources (sec)? [60]"
201
+ conf["bfm"]["sleeptime"] = (t = gets.chop).empty? ? 60 : t.to_i
187
202
 
188
203
 
189
204
  ######################################################
@@ -212,8 +227,6 @@ module Dorothy
212
227
  File.open("#{File.expand_path("~")}/.dorothy.yml", 'w+') {|f| f.write(conf.to_yaml) }
213
228
  FileUtils.ln_s("#{File.expand_path("~")}/.dorothy.yml", "#{home}/etc/dorothy.yml") unless Util.exists?("#{home}/etc/dorothy.yml")
214
229
 
215
- #copy the default extension file to the user-defined home
216
- FileUtils.cp("#{HOME}/etc/extensions.yml", "#{home}/etc/extensions.yml")
217
230
  correct = true
218
231
  puts "Configuration file has been saved in ~/.dorothy.conf and a symlink has been created in\n#{home}/etc/dorothy.yml for an easier edit."
219
232
  puts "\n######### [" + " Now you can restart dorothy, enjoy! ".yellow + "] #########"
@@ -231,6 +244,131 @@ module Dorothy
231
244
 
232
245
  end
233
246
 
247
+
248
+ def create_profiles(filename, sandbox=false, vtotal=nil)
249
+
250
+ correct = false
251
+ conf = Hash.new
252
+ if sandbox
253
+
254
+ conf['default'] = {}
255
+
256
+ conf['default']['sleeptime'] = 60
257
+ vtotal ? conf['default']['vtotal_query'] = true : conf['default']['vtotal_query'] = false
258
+
259
+
260
+ conf['default']['screenshots'] = {}
261
+ conf['default']['screenshots']['number'] = 2
262
+ conf['default']['screenshots']['delay_first'] = 1
263
+ conf['default']['screenshots']['delay_inbetween'] = 30
264
+
265
+
266
+
267
+ conf['default']['OS'] = {}
268
+ conf['default']['OS']['type'] = sandbox['os']
269
+ conf['default']['OS']['version'] = sandbox['version']
270
+ conf['default']['OS']['lang'] = sandbox['os_lang']
271
+
272
+
273
+
274
+ conf['default']['extensions'] = {}
275
+
276
+ %w(exe bat html rtf).each do |ext|
277
+ conf['default']['extensions'][ext] = Hash.new
278
+ conf['default']['extensions'][ext]['prog_name'] = 'Windows CMD.exe'
279
+ conf['default']['extensions'][ext]['prog_path'] = 'C:\windows\system32\cmd.exe'
280
+ conf['default']['extensions'][ext]['prog_args'] = '/C'
281
+ end
282
+
283
+
284
+ File.open(filename, 'w+') {|f| f.write(conf.to_yaml) }
285
+ puts "Profiles have been saved in #{filename}\nYou can either modify such file directly. Enjoy!"
286
+
287
+ else
288
+ until correct
289
+
290
+ finished = false
291
+
292
+ until finished
293
+
294
+ puts "\n######### [" + " Profiles configuration ".red + "] #########"
295
+
296
+ puts "Please insert the unique name for this profile"
297
+ pname = gets.chop
298
+
299
+ conf[pname] = {}
300
+ conf[pname]['OS'] = {}
301
+ conf[pname]['screenshots'] = {}
302
+ conf[pname]['extensions'] = {}
303
+
304
+ puts "Please insert the information on the OS you want to associate with this profile. This info must reflect the one inserted into the sandboxes.yml file"
305
+ puts "OS Type (Windows|Linux) [Windows] "
306
+ conf[pname]["OS"]['type'] = (t = gets.chop).empty? ? 'Windows' : t
307
+ puts "OS Version: (e.g. XP SP3) [XP SP3]"
308
+ conf[pname]["OS"]['version'] = (t = gets.chop).empty? ? 'XP SP3' : t
309
+ puts "OS Language: [eng]"
310
+ conf[pname]["OS"]['lang'] = (t = gets.chop).empty? ? 'eng' : t
311
+
312
+ puts "Sandbox parameters"
313
+ puts "Insert the time (seconds) that the Sandbox should be run before it's reverted [60]"
314
+ conf[pname]["sleeptime"] = (t = gets.chop).empty? ? 60 : t
315
+
316
+ puts "Insert how many screenshots do you want to take [1]"
317
+ conf[pname]['screenshots']["number"] = (t = gets.chop).empty? ? 1 : t.to_i
318
+
319
+ if conf[pname]["num_screenshots"] > 1
320
+ puts "Insert the time interval (seconds) between each screenshot [5] "
321
+ conf[pname]["screenshots"]['delay_inbetween'] = (t = gets.chop).empty? ? 5 : t.to_i
322
+ end
323
+
324
+ puts "After how many seconds do you want to take the first screenshot? [1]"
325
+ conf[pname]["screenshots"]['delay_first'] = (t = gets.chop).empty? ? 1 : t.to_i
326
+
327
+
328
+ puts "Enable Virus Total queries? VT API key must be in .dorothy.yml [y]"
329
+ t = gets.chop
330
+ (t.empty? || t == "y" || t == "yes") ? conf[pname]["vtotal_query"] = true : conf[pname]["vtotal_query"] = false
331
+
332
+ puts "Adding basic extensions (exe, bat, html, rtf)"
333
+
334
+ %w(exe bat html rtf).each do |ext|
335
+ conf[pname]['extensions'][ext] = Hash.new
336
+ conf[pname]['extensions'][ext]['prog_name'] = 'Windows CMD.exe'
337
+ conf[pname]['extensions'][ext]['prog_name'] = 'C:\windows\system32\cmd.exe'
338
+ conf[pname]['extensions'][ext]['prog_name'] = '/C'
339
+ end
340
+
341
+ puts "Profiles configured. Want you to configure another one? [n]"
342
+ t = gets.chop
343
+
344
+ if t == "y" || t == "yes"
345
+ finished = false
346
+ else
347
+ finished = true
348
+ end
349
+
350
+ end
351
+
352
+ puts "Configuration finished"
353
+ puts "Confirm? [y]"
354
+ t = gets.chop
355
+ puts t
356
+
357
+ if t.empty? || t == "y" || t == "yes"
358
+ File.open(filename, 'w+') {|f| f.write(conf.to_yaml) }
359
+ correct = true
360
+ puts "Profiles have been saved in #{filename}\nYou can either modify such file directly. Enjoy!"
361
+ else
362
+ puts "Please reinsert the info"
363
+ correct = false
364
+ end
365
+ end
366
+ end
367
+ end
368
+
369
+
370
+
371
+
234
372
  #Creates the sandbox configuration file
235
373
  def create_sandbox(sboxfile)
236
374
 
@@ -305,6 +443,135 @@ module Dorothy
305
443
  end
306
444
  end
307
445
 
446
+
447
+
448
+ #Creates the Source configuration file
449
+ def create_sources(sourcesfile = DoroSettings.env[:home] + '/etc/sources.yml')
450
+
451
+ correct = false
452
+
453
+ until correct
454
+
455
+ conf = Hash.new
456
+
457
+ #Add WGUI as default source
458
+
459
+ conf['webgui'] = Hash.new
460
+ conf['webgui']["type"] = 'web'
461
+ conf['webgui']["typeid"] = 1
462
+ conf['webgui']["localdir"] = DoroSettings.env[:home] + '/opt/bins/webgui'
463
+ conf['webgui']["priority"] = 3
464
+ conf['webgui']["profile"] = 'default'
465
+
466
+ finished = false
467
+
468
+ until finished
469
+ puts "Please insert a unique name for the binary source you want to add"
470
+ sname = gets.chop
471
+
472
+ conf[sname] = Hash.new
473
+
474
+ puts "Please specify the binary source type (system|ssh|mail) [system]"
475
+ conf[sname]["type"] = (t = gets.chop).empty? ? "system" : t
476
+ puts ">" + conf[sname]["type"]
477
+
478
+ case conf[sname]["type"]
479
+ when "system" then
480
+ puts "Please specify the system folder where are located the binaries [#{DoroSettings.env[:home]}/opt/bins/#{sname}]"
481
+ conf[sname]["localdir"] = (t = gets.chop).empty? ? "#{DoroSettings.env[:home]}/opt/bins/#{sname}" : t
482
+ when "mail" then
483
+ puts "Please specify the IP address/hostname of the mail server (e.g. pop-mail.outlook.com)"
484
+ conf[sname]["address"] = gets.chop
485
+
486
+ puts "Please specify the username used for the authentication"
487
+ conf[sname]["username"] = gets.chop
488
+
489
+ puts "Please specify the password used for the authentication"
490
+ conf[sname]["password"] = gets.chop
491
+
492
+ puts "Please specify the TCP port used by the mailserver [993]"
493
+ conf[sname]["port"] = (t = gets.chop).empty? ? 993 : t.to_i
494
+ puts ">" + conf[sname]["port"].to_s
495
+
496
+ puts "Is SSL required for this mailbox (true|false)? [true]"
497
+ t = (gets.chop == "false" ? false : true)
498
+ conf[sname]["enable_ssl"] = t
499
+ puts ">" + conf[sname]["enable_ssl"].to_s
500
+
501
+ puts "How many emails do you want to retreive during every request? [3]"
502
+ conf[sname]["n_emails"] = (t = gets.chop).empty? ? 3 : t.to_i
503
+ puts ">" + conf[sname]["n_emails"].to_s
504
+
505
+ puts "Do you want to delete the emails from the server once downloaded? [true] (Warning, if false, Dorothy wont understand which email is new. Put false only for development/testing)"
506
+ t = (gets.chop == "false" ? false : true)
507
+ conf[sname]["delete_once_downloaded"] = t
508
+ puts ">" + conf[sname]["delete_once_downloaded"].to_s
509
+
510
+ puts "Please specify the system folder where the attachments will be temporaly copied into [#{DoroSettings.env[:home]}/opt/bins/#{sname}]"
511
+ conf[sname]["localdir"] = (t = gets.chop).empty? ? "#{DoroSettings.env[:home]}/opt/bins/#{sname}" : t
512
+
513
+ when "ssh" then
514
+ puts "Please specify the IP address/hostname of the remote server"
515
+ conf[sname]["host"] = gets.chop
516
+
517
+ puts "Please specify the ssh TCP port of the remote server [22]"
518
+ conf[sname]["port"] = (t = gets.chop).empty? ? 22 : t.to_i
519
+ puts ">" + conf[sname]["port"].to_s
520
+
521
+ puts "Please specify the username used for the authentication"
522
+ conf[sname]["username"] = gets.chop
523
+
524
+ puts "Please specify the password used for the authentication"
525
+ conf[sname]["password"] = gets.chop
526
+
527
+ puts "Please specify the remote path where the binaries are"
528
+ conf[sname]["remotedir"] = gets.chop
529
+
530
+ puts "Please specify the system folder where the binaries will be temporaly copied into [#{DoroSettings.env[:home]}/opt/bins/#{sname}]"
531
+ conf[sname]["localdir"] = (t = gets.chop).empty? ? "#{DoroSettings.env[:home]}/opt/bins/#{sname}" : t
532
+ end
533
+
534
+
535
+ puts "Please specify the priority of this source. 1 is the lowest [1]"
536
+ conf[sname]["priority"] = (t = gets.chop).empty? ? 1 : t.to_i
537
+ puts ">" + conf[sname]["priority"].to_s
538
+
539
+ puts "Please specify which analysis profile you want to associate with this source. [default]"
540
+ conf[sname]["profile"] = (t = gets.chop).empty? ? "default" : t
541
+ puts ">" + conf[sname]["profile"]
542
+
543
+
544
+ puts "Binary source added. Do you want to add another one? [n]"
545
+ t = gets.chop
546
+
547
+ if t == "y" || t == "yes"
548
+ finished = false
549
+ else
550
+ finished = true
551
+ end
552
+
553
+
554
+ end
555
+
556
+ puts "Configuration finished"
557
+ puts "Confirm? [y]"
558
+ t = gets.chop
559
+ puts t
560
+
561
+ if t.empty? || t == "y" || t == "yes"
562
+ File.open(sourcesfile, 'w+') {|f| f.write(conf.to_yaml) }
563
+ correct = true
564
+ puts "Configuration file has been saved in #{sourcesfile}\nYou can either modify such file directly. Enjoy!"
565
+ else
566
+ puts "Please reinsert the info"
567
+ correct = false
568
+ end
569
+
570
+ end
571
+ end
572
+
573
+
574
+
308
575
  #This method will populate the dorothive table sandboxes
309
576
  def init_sandbox(file="../etc/sandboxes.yml")
310
577
  conf = YAML.load_file(file)
@@ -312,7 +579,7 @@ module Dorothy
312
579
  db = Insertdb.new
313
580
  db.begin_t
314
581
 
315
- LOGGER.warn "INIT", "Waring, the SandBox table is gonna be flushed, and updated with the new file"
582
+ LOGGER.warn "INIT", "Warning, the SandBox table is gonna be flushed, and updated with the new file"
316
583
  db.flush_table("sandboxes")
317
584
 
318
585
  conf.each_key do |sbox|