dorothy2 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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|