dorothy2 0.0.3 → 1.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.
data/README.md CHANGED
@@ -13,7 +13,7 @@ Dorothy2 is a continuation of my Bachelor degree's final project ([Dorothy: insi
13
13
  The main framework's structure remained almost the same, and it has been fully detailed in my degree's final project or in this short [paper](http://www.honeynet.it/wp-content/uploads/Dorothy/EC2ND-Dorothy.pdf). More information about the whole project can be found on the Italian Honeyproject [website](http://www.honeynet.it).
14
14
 
15
15
 
16
- The framework is manly composed by four big elements that can be even executed separately:
16
+ The framework is mainly composed by four big elements that can be even executed separately:
17
17
 
18
18
  * The Dorothy analysis engine (included in this gem)
19
19
 
@@ -33,7 +33,7 @@ The framework is manly composed by four big elements that can be even executed s
33
33
 
34
34
  The first three modules are (or will be soon) publicly released under GPL 2/3 license as tribute to the the [Honeynet Project Alliance](http://www.honeynet.org).
35
35
  All the information generated by the framework - i.e. binary info, timestamps, dissected network analysis - are stored into a postgres DB (Dorothive) in order to be used for further analysis.
36
- A no-SQL database (CouchDB) is also used to mass strore all the traffic dumps thanks to the [pcapr/xtractr](https://code.google.com/p/pcapr/wiki/Xtractr) technology.
36
+ A no-SQL database (CouchDB) is also used to mass store all the traffic dumps thanks to the [pcapr/xtractr](https://code.google.com/p/pcapr/wiki/Xtractr) technology.
37
37
 
38
38
  I started to code this project in late 2009 while learning Ruby at the same time. Since then, I´ve been changing/improving it as long as my Ruby coding skills were improving. Because of that, you may find some parts of code not-really-tidy :)
39
39
 
@@ -55,6 +55,11 @@ Dorothy needs the following software (not expressly in the same host) in order t
55
55
  * [pcapr-local](https://github.com/mudynamics/pcapr-local ) (only used by doroParser)
56
56
  * MaxMind libraries (only used by doroParser)
57
57
 
58
+ Regarding the Operating System
59
+
60
+ * Dorothy has been designed to run on any *nix system. So far it was successfully tested on OSX and Linux.
61
+ * The virtual machines used as sandboxes are meant to be Windows based (successfully tested on XP)
62
+ * Only pcapr-local strictly requires Linux, if you want to use a Mac for executing this gem (like I do), install it into the NAM (as this guide suggests)
58
63
 
59
64
  ## Installation
60
65
 
@@ -116,7 +121,7 @@ It is recommended to follow this step2step process:
116
121
 
117
122
  #gem install pcapr-local
118
123
 
119
- * Start pcapr-local by using the dorothy's account and configure it. When prompted, insert the folder path used to store the network dumps
124
+ * Start pcapr-local by using the dorothy's system account and configure it. When prompted, insert the folder path used to store the network dumps
120
125
 
121
126
  $startpcapr
122
127
  ....
@@ -164,7 +169,7 @@ or
164
169
  2. Configure a dedicated postgres user for Dorothy (or use the default postgres user instead, up to you :)
165
170
 
166
171
  > Note:
167
- > If you want to use Postgres "as is", and then configure Dorothy to use "postgres" degault the user, configure a password for this user at least (by default it comes with no password)
172
+ > If you want to use Postgres "as is", and then configure Dorothy to use "postgres" default the user, configure a password for this user at least (by default it comes with no password)
168
173
 
169
174
  3. Install the following packages
170
175
 
@@ -222,8 +227,8 @@ The first time you execute Dorothy, it will ask you to fill those information in
222
227
  --infoflow, -i: Print the analysis flow
223
228
  --source, -s <s>: Choose a source (from the ones defined in etc/sources.yml)
224
229
  --daemon, -d: Stay in the background, by constantly pooling datasources
225
- --SandboxUpdate, -S: Update Dorothive with the new Sandbox file
226
- --DorothiveInit, -D: (RE)Install the Dorothy Database (Dorothive)
230
+ --SandboxUpdate, -S: Update Dorothive with the new Sandbox file
231
+ --DorothiveInit, -D: (RE)Install the Dorothy Database (Dorothive)
227
232
  --help, -h: Show this message
228
233
 
229
234
 
@@ -231,6 +236,10 @@ The first time you execute Dorothy, it will ask you to fill those information in
231
236
  >
232
237
  $dorothy_start -v -s malwarefolder
233
238
 
239
+ After the execution, if everything went fine, you will find the analysis output (screens/pcap/bin) into the analysis folder that you have configured e.g. dorothy/opt/analyzed/[:digit:]/
240
+ Other information will be stored into Dorothive.
241
+ If executed in daemon mode, Dorothy2 will poll the datasources every X seconds (where X is defined by the "dtimeout:" field in the configuration file) looking for new binaries.
242
+
234
243
  ### DoroParser usage:
235
244
 
236
245
  $dparser_start [options]
@@ -245,6 +254,9 @@ The first time you execute Dorothy, it will ask you to fill those information in
245
254
  $dparser_start -d start
246
255
  $dparser_stop
247
256
 
257
+
258
+ After the execution, if everything went fine, doroParser will store all the donwloaded files into the binary's analysis folder e.g. dorothy/opt/analyzed/[:digit:]/downloads
259
+ Other information -i.e. Network data- will be stored into Dorothive.
248
260
  If executed in daemon mode, DoroParser will poll the database every X seconds (where X is defined by the "dtimeout:" field in the configuration file) looking for new pcaps that has been inserted.
249
261
 
250
262
  ###6. Debugging problems
@@ -268,6 +280,18 @@ Below there are some tips about how understand the root-cause of your crash.
268
280
 
269
281
  ------------------------------------------
270
282
 
283
+ ## Acknowledgements
284
+
285
+ Thanks to all the people who have contributed in making the Dorothy2 project up&running:
286
+
287
+ * Marco C. (research)
288
+ * Davide C. (Dorothive)
289
+ * Andrea V. (WGUI)
290
+ * Domenico C. - Patrizia P. (Dorothive/JDrone)
291
+ * [All](https://www.honeynet.it/research) the graduating students from [UniMI](http://cdlonline.di.unimi.it/) who have contributed.
292
+ * Sabrina P. (our students "headhunter" :)
293
+ * Jorge C. and Nelson M. (betatesting/first release feedbacks)
294
+
271
295
  ## Contributing
272
296
 
273
297
  1. Fork it
data/TODO ADDED
@@ -0,0 +1,21 @@
1
+ ##############
2
+ #DOROTHY-TODO#
3
+ ##############
4
+
5
+ -PORT TO Ruby 2.0
6
+ -WGUI
7
+
8
+ -BINARY STATIC ANALYSIS
9
+ -ANALYZE SYSTEM CHANGES
10
+ -SYSTEM ANALYSIS -VMWARE API: QueryChangedDiskAreas
11
+ -LIST PROCESSES-> pm.ListProcessesInGuest(:vm => vm, :auth => auth).inspect
12
+
13
+ -CODE- CATCH CTRL-C AND EXIT GRACEFULLY
14
+ -INTERACTIVE CONSOLE FOR NETWORK ANALYSIS
15
+
16
+ -REVIEW DOROTHIVE (binary fullpath?)
17
+
18
+ -ADD EMAIL AS SOURCETYPE (use ruby mail gem for retreiving the emails, and parse them)
19
+
20
+ -REPORT PLUGIN
21
+ -REPORT - MAEC
data/bin/dorothy_start CHANGED
@@ -37,7 +37,7 @@ opts = Trollop.options do
37
37
  opt :source, "Choose a source (from the ones defined in etc/sources.yml)", :type => :string
38
38
  opt :daemon, "Stay in the backround, by constantly pooling datasources"
39
39
  opt :SandboxUpdate, "Update Dorothive with the new Sandbox file"
40
- opt :DorothiveInit, "(RE)Install the Dorothy Database (Dorothive)"
40
+ opt :DorothiveInit, "(RE)Install the Dorothy Database (Dorothive)", :type => :string
41
41
 
42
42
  end
43
43
 
@@ -103,6 +103,12 @@ end
103
103
  sfile = home + '/etc/sources.yml'
104
104
  sboxfile = home + '/etc/sandboxes.yml'
105
105
 
106
+ if opts[:DorothiveInit]
107
+ Util.init_db(opts[:DorothiveInit])
108
+ puts "[Dorothy]".yellow + " Database loaded, now you can restart Dorothy!"
109
+ exit(0)
110
+ end
111
+
106
112
  #INIT DB Connector
107
113
  begin
108
114
  db = Insertdb.new
@@ -120,11 +126,6 @@ rescue => e
120
126
  end
121
127
 
122
128
 
123
- if opts[:DorothiveInit]
124
- Util.init_db
125
- exit(0)
126
- end
127
-
128
129
  if opts[:SandboxUpdate]
129
130
  puts "[Dorothy]".yellow + " Loading #{sboxfile} into Dorothive"
130
131
  DoroConfig.init_sandbox(sboxfile)
data/bin/dparser_start CHANGED
@@ -63,11 +63,23 @@ LOGGER_PARSER.sev_threshold = DoroSettings.env[:loglevel]
63
63
  LOGGER = DoroLogger.new(logout, DoroSettings.env[:logage])
64
64
  LOGGER.sev_threshold = DoroSettings.env[:loglevel]
65
65
 
66
+ begin
67
+
68
+ rescue
69
+ exit(1)
70
+
71
+ end
72
+
73
+
74
+
66
75
  begin
67
76
  DoroParser.start(daemon)
68
77
  rescue => e
69
78
  puts "[PARSER]".yellow + " An error occurred: ".red + $!
70
- puts "[PARSER]".yellow + " For more information check the logfile" + $! if daemon
79
+ if daemon
80
+ puts "[PARSER]".yellow + " For more information check the logfile" + $!
81
+ puts "[PARSER]".yellow + "Dorothy-Parser has been stopped"
82
+ end
71
83
  LOGGER_PARSER.error "Parser", "An error occurred: " + $!
72
84
  LOGGER_PARSER.debug "Parser", "#{e.inspect} --BACKTRACE: #{e.backtrace}"
73
85
  LOGGER_PARSER.info "Parser", "Dorothy-Parser has been stopped"
@@ -128,26 +128,6 @@ CREATE TYPE layer7_protocols AS ENUM (
128
128
 
129
129
  ALTER TYPE dorothy.layer7_protocols OWNER TO postgres;
130
130
 
131
- --
132
- -- Name: sample_type; Type: TYPE; Schema: dorothy; Owner: postgres
133
- --
134
-
135
- CREATE TYPE sample_type AS ENUM (
136
- 'mz',
137
- 'pe',
138
- 'elf'
139
- );
140
-
141
-
142
- ALTER TYPE dorothy.sample_type OWNER TO postgres;
143
-
144
- --
145
- -- Name: TYPE sample_type; Type: COMMENT; Schema: dorothy; Owner: postgres
146
- --
147
-
148
- COMMENT ON TYPE sample_type IS 'Sample file type';
149
-
150
-
151
131
  --
152
132
  -- Name: sanbox_type; Type: TYPE; Schema: dorothy; Owner: postgres
153
133
  --
@@ -245,7 +225,6 @@ SELECT pg_catalog.setval('analyses_id_seq', 1, true);
245
225
  CREATE TABLE samples (
246
226
  hash character(64) NOT NULL,
247
227
  size integer NOT NULL,
248
- type sample_type,
249
228
  path character(256),
250
229
  filename character(256),
251
230
  md5 character(64),
@@ -276,14 +255,6 @@ COMMENT ON COLUMN samples.hash IS 'SHA256 checksum hash';
276
255
 
277
256
  COMMENT ON COLUMN samples.size IS 'Sample size';
278
257
 
279
-
280
- --
281
- -- Name: COLUMN samples.type; Type: COMMENT; Schema: dorothy; Owner: postgres
282
- --
283
-
284
- COMMENT ON COLUMN samples.type IS 'Sample type';
285
-
286
-
287
258
  --
288
259
  -- Name: CONSTRAINT size_notneg ON samples; Type: COMMENT; Schema: dorothy; Owner: postgres
289
260
  --
@@ -298,7 +269,7 @@ COMMENT ON CONSTRAINT size_notneg ON samples IS 'Sample size must not be negativ
298
269
  CREATE TABLE traffic_dumps (
299
270
  hash character(64) NOT NULL,
300
271
  size integer NOT NULL,
301
- pcapr_id character(64),
272
+ pcapr_id character(32),
302
273
  "binary" character varying,
303
274
  parsed boolean
304
275
  );
@@ -1323,7 +1294,7 @@ COPY roles (id, type, comment) FROM stdin;
1323
1294
  -- Data for Name: samples; Type: TABLE DATA; Schema: dorothy; Owner: postgres
1324
1295
  --
1325
1296
 
1326
- COPY samples (hash, size, type, path, filename, md5, long_type) FROM stdin;
1297
+ COPY samples (hash, size, path, filename, md5, long_type) FROM stdin;
1327
1298
  \.
1328
1299
 
1329
1300
 
data/lib/doroParser.rb CHANGED
@@ -17,7 +17,6 @@
17
17
 
18
18
 
19
19
  require 'rubygems'
20
- require 'mu/xtractr'
21
20
  require 'md5'
22
21
  require 'rbvmomi'
23
22
  require 'rest_client'
@@ -32,15 +31,17 @@ require 'pg'
32
31
  require 'iconv'
33
32
  require 'tmail'
34
33
  require 'ipaddr'
34
+ require 'net/http'
35
+ require 'json'
35
36
 
36
37
  require File.dirname(__FILE__) + '/dorothy2/environment'
38
+ require File.dirname(__FILE__) + '/mu/xtractr'
37
39
  require File.dirname(__FILE__) + '/dorothy2/DEM'
38
40
  require File.dirname(__FILE__) + '/dorothy2/do-utils'
39
41
  require File.dirname(__FILE__) + '/dorothy2/do-logger'
40
42
  require File.dirname(__FILE__) + '/dorothy2/deep_symbolize'
41
43
 
42
44
 
43
-
44
45
  module DoroParser
45
46
  #Host roles
46
47
 
@@ -85,12 +86,34 @@ module DoroParser
85
86
 
86
87
 
87
88
  begin
88
- xtractr = Doroxtractr.create "http://#{DoroSettings.pcapr[:host]}:#{DoroSettings.pcapr[:port]}/pcaps/1/pcap/#{dump['pcapr_id'].gsub(/\s+/, "")}"
89
+
90
+ #check if the pcap has been correctly indexed by pcapr
91
+ xtractr = Doroxtractr.create "http://#{DoroSettings.pcapr[:host]}:#{DoroSettings.pcapr[:port]}/pcaps/1/pcap/#{dump['pcapr_id'].rstrip}"
89
92
 
90
93
  rescue => e
91
- LOGGER_PARSER.fatal "PARSER", "Can't create a XTRACTR instance, try with nextone"
94
+ LOGGER_PARSER.fatal "PARSER", "Can't connect to the PCAPR server."
92
95
  LOGGER_PARSER.debug "PARSER", "#{$!}"
93
- LOGGER_PARSER.debug "PARSER", e
96
+ LOGGER_PARSER.debug "PARSER", e.backtrace if VERBOSE
97
+ return false
98
+ end
99
+
100
+ #it may happen that Pcapr has created an instance, but it is still indexing the pcap.
101
+ #The following section is to avoid a crash while quering such (still-empty instance)
102
+ #In addition, an added check is inserted, to see if the pcapr instance really match the pcap filename
103
+ begin
104
+ pcapr_query = URI.parse "http://#{DoroSettings.pcapr[:host]}:#{DoroSettings.pcapr[:port]}/pcaps/1/about/#{dump['pcapr_id'].rstrip}"
105
+ pcapr_response = Net::HTTP.get_response(pcapr_query)
106
+ pcapname = File.basename(JSON.parse(pcapr_response.body)["filename"], ".pcap")
107
+
108
+ t ||= $1 if pcapname =~ /[0-9]*\-(.*)$/
109
+ raise NameError.new if t != dump['sample'].rstrip
110
+
111
+ rescue NameError
112
+ LOGGER_PARSER.error "PARSER", "The pcapr filename mismatchs the one present in Dorothive!. Skipping."
113
+ next
114
+
115
+ rescue
116
+ LOGGER_PARSER.error "PARSER", "Can't find the PCAP into Pcapr, maybe it has not been indexed yet. Skipping."
94
117
  next
95
118
  end
96
119
 
@@ -103,18 +126,14 @@ module DoroParser
103
126
 
104
127
  flowdeep = xtractr.flows("flow.id:#{flow.id}")
105
128
 
106
-
107
-
108
129
  #Skipping if NETBIOS spreading activity:
109
130
  if flow.dport == 135 or flow.dport == 445
110
131
  LOGGER_PARSER.info "PARSER", "Netbios connections, skipping flow" unless NONETBIOS
111
132
  next
112
133
  end
113
134
 
114
-
115
135
  title = flow.title[0..200].gsub(/'/,"") #xtool bug ->')
116
136
 
117
-
118
137
  #insert hosts (geo) info into db
119
138
  #TODO: check if is a localaddress
120
139
  localip = xtractr.flows.first.src.address
@@ -258,10 +277,6 @@ module DoroParser
258
277
 
259
278
  end
260
279
 
261
-
262
-
263
-
264
-
265
280
  end
266
281
 
267
282
  #case MAIL
@@ -269,8 +284,6 @@ module DoroParser
269
284
  LOGGER_PARSER.info "SMTP", "FOUND an SMTP request..".white
270
285
  #insert mail
271
286
  #by from to subject data id time connection
272
-
273
-
274
287
  streamdata.each do |m|
275
288
  mailfrom = 'null'
276
289
  mailto = 'null'
@@ -303,8 +316,6 @@ module DoroParser
303
316
  @insertdb.insert("emails", mailvalues )
304
317
  end
305
318
 
306
-
307
-
308
319
  #case FTP
309
320
  when "FTP" then
310
321
  LOGGER_PARSER.info "FTP", "FOUND an FTP request".white
@@ -324,9 +335,7 @@ module DoroParser
324
335
  end
325
336
  end
326
337
 
327
-
328
338
  else
329
-
330
339
  LOGGER_PARSER.info "PARSER", "Unknown traffic, try see if it is IRC traffic"
331
340
 
332
341
  if Parser.guess(streamdata.inspect).class.inspect =~ /IRC/
@@ -358,14 +367,12 @@ module DoroParser
358
367
  end
359
368
  end
360
369
 
361
-
362
370
  @p.each do |d|
363
371
 
364
372
  begin
365
373
 
366
374
  dns = DoroDNS.new(d)
367
375
 
368
-
369
376
  dnsvalues = ["default", dns.name, dns.cls_i.inspect, dns.qry?, dns.ttl, flowid, dns.address.to_s, dns.data, dns.type_i.inspect]
370
377
 
371
378
  LOGGER_PARSER.debug "DB", " Inserting DNS data from #{flow.dst.address.to_s}".blue if VERBOSE
@@ -404,8 +411,8 @@ module DoroParser
404
411
 
405
412
  rescue => e
406
413
 
407
- LOGGER_PARSER.error "PARSER", "Error while analyzing flow #{flow.id}"
408
- LOGGER_PARSER.debug "PARSER", "#{e.inspect} BACKTRACE: #{e.backtrace}"
414
+ LOGGER_PARSER.error "PARSER", "Error while analyzing flow #{flow.id}: #{e.inspect}"
415
+ LOGGER_PARSER.debug "PARSER", "#{e.backtrace}" if VERBOSE
409
416
  LOGGER_PARSER.info "PARSER", "Flow #{flow.id} will be skipped"
410
417
  next
411
418
  end
data/lib/dorothy2/BFM.rb CHANGED
@@ -7,15 +7,15 @@
7
7
  ###BINARY FETCHER MODULE###
8
8
  ### ###
9
9
  ###########################
10
-
10
+ #The BFM module is in charge of retreiving the binary from the sources configured in the sources.yml file.
11
+ #It receive the source hash, and return the downloaded binaries objects.
11
12
  module Dorothy
12
13
 
13
-
14
14
  class DorothyFetcher
15
15
  attr_reader :bins
16
16
 
17
-
18
- def initialize(source) #source struct: Hash, {:dir => "#{HOME}/bins/honeypot", :typeid=> 0 ..}
17
+ #Source struct: Hash, {:dir => "#{HOME}/bins/honeypot", :typeid=> 0 ..}
18
+ def initialize(source)
19
19
  ndownloaded = 0
20
20
 
21
21
  @bins = []
@@ -26,7 +26,6 @@ module Dorothy
26
26
  when "ssh" then
27
27
  LOGGER.info "BFM", " Fetching trojan from > Honeypot"
28
28
  #file = "/opt/dionaea/var/dionaea/binaries/"
29
-
30
29
  #puts "Start to download malware"
31
30
 
32
31
  files = []
@@ -37,7 +36,6 @@ module Dorothy
37
36
  unless files.include? "#{source["localdir"]}/" + File.basename(name)
38
37
  ndownloaded += 1
39
38
  files.push "#{source["localdir"]}/" + File.basename(name)
40
- # puts ""
41
39
  end
42
40
  # print "#{File.basename(name)}: #{sent}/#{total}\r"
43
41
  # $stdout.flush
@@ -45,26 +43,22 @@ module Dorothy
45
43
  LOGGER.info "BFM", "#{ndownloaded} files downloaded"
46
44
  end
47
45
 
48
-
49
46
  rescue => e
50
47
  LOGGER.error "BFM", "An error occurred while downloading malwares from honeypot sensor: " + $!
51
48
  LOGGER.error "BFM", "Error: #{$!}, #{e.inspect}, #{e.backtrace}"
52
49
  end
53
50
 
54
51
  #DIRTY WORKAROUND for scp-ing only files without directory
55
-
56
52
  FileUtils.mv(Dir.glob(source["localdir"] + "/binaries/*"), source["localdir"])
57
53
  Dir.rmdir(source["localdir"] + "/binaries")
58
54
 
59
55
 
60
56
  begin
61
-
62
57
  unless DoroSettings.env[:testmode]
63
58
  Net::SSH.start(source["ip"], source["user"], :password => source["pass"], :port => source["port"]) do |ssh|
64
59
  ssh.exec "mv #{source["remotedir"]}/* #{source["remotedir"]}/../analyzed "
65
60
  end
66
61
  end
67
-
68
62
  rescue
69
63
  LOGGER.error "BFM", "An error occurred while erasing parsed malwares in the honeypot sensor: " + $!
70
64
  end
@@ -87,8 +81,6 @@ module Dorothy
87
81
  end
88
82
  end
89
83
 
90
-
91
-
92
84
  private
93
85
  def load_malw(f, typeid, sourceinfo = nil)
94
86
 
@@ -100,7 +92,7 @@ module Dorothy
100
92
  return false
101
93
  end
102
94
 
103
- samplevalues = [bin.sha, bin.size, bin.dbtype, bin.dir_bin, filename, bin.md5, bin.type ]
95
+ samplevalues = [bin.sha, bin.size, bin.dir_bin, filename, bin.md5, bin.type ]
104
96
  sighvalues = [bin.sha, typeid, bin.ctime, "null"]
105
97
 
106
98
  begin
@@ -16,16 +16,16 @@ module Dorothy
16
16
  File.exist?(file)
17
17
  end
18
18
 
19
- def init_db(force=false)
20
- LOGGER.warn "DB", "The database is going to be initialized, all the data present will be lost. Continue?(write yes)"
19
+ def init_db(ddl=DoroSettings.dorothive[:ddl], force=false)
20
+ LOGGER.warn "DB", "The database is going to be initialized with the file #{ddl}. If the Dorothive is already present, " + "all the its data will be lost".red + ". Continue?(write yes)"
21
21
  answ = "yes"
22
22
  answ = gets.chop unless force
23
23
 
24
24
  if answ == "yes"
25
25
  begin
26
26
  #ugly, I know, but couldn't find a better and easier way..
27
- raise 'An error occurred' unless system "psql -h #{DoroSettings.dorothive[:dbhost]} -U #{DoroSettings.dorothive[:dbuser]} -f #{DoroSettings.dorothive[:ddl]}"
28
- LOGGER.info "DB", "Database correctly initialized."
27
+ raise 'An error occurred' unless system "psql -h #{DoroSettings.dorothive[:dbhost]} -U #{DoroSettings.dorothive[:dbuser]} -f #{ddl} 1> /dev/null"
28
+ LOGGER.info "DB", "Database correctly initialized. Now you can restart Dorothy!"
29
29
  rescue => e
30
30
  LOGGER.error "DB", $!
31
31
  LOGGER.debug "DB", e.inspect
@@ -248,7 +248,6 @@ module Dorothy
248
248
  @binpath = file
249
249
  @filename = File.basename file
250
250
  @extension = File.extname file
251
- @dbtype = "null" #TODO: remove type column in sample table
252
251
 
253
252
  File.open(file, 'rb') do |fh1|
254
253
  while buffer1 = fh1.read(1024)
@@ -1,3 +1,3 @@
1
1
  module Dorothy2
2
- VERSION = "0.0.3"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/dorothy2.rb CHANGED
@@ -5,7 +5,6 @@
5
5
  ##for irb debug:
6
6
  ##from $home, irb and :
7
7
  ##load 'lib/dorothy2.rb'; include Dorothy; LOGGER = DoroLogger.new(STDOUT, "weekly"); DoroSettings.load!('etc/dorothy.yml')
8
- #$LOAD_PATH.unshift '/opt/local/lib/ruby/gems/1.8/gems/ruby-filemagic-0.4.2/lib'
9
8
 
10
9
  require 'net/ssh'
11
10
  require 'net/scp'
@@ -152,8 +151,8 @@ module Dorothy
152
151
  vsm.copy_file("#{bin.md5}#{bin.extension}",filecontent)
153
152
 
154
153
  #Start Sniffer
155
- dumpname = bin.md5
156
- pid = @nam.start_sniffer(guestvm[2],DoroSettings.nam[:interface], dumpname, DoroSettings.nam[:pcaphome]) #dumpname = vmfile.pcap
154
+ dumpname = anal_id.to_s + "-" + bin.md5
155
+ pid = @nam.start_sniffer(guestvm[2],DoroSettings.nam[:interface], dumpname, DoroSettings.nam[:pcaphome])
157
156
  LOGGER.info "NAM","VM#{guestvm[0]} ".yellow + "Start sniffing module"
158
157
  LOGGER.debug "NAM","VM#{guestvm[0]} ".yellow + "Tcpdump instance #{pid} started" if VERBOSE
159
158
 
@@ -216,8 +215,7 @@ module Dorothy
216
215
 
217
216
  #Downloading PCAP
218
217
  LOGGER.info "NAM", "VM#{guestvm[0]} ".yellow + "Downloading #{dumpname}.pcap to #{bin.dir_pcap}"
219
- #t = DoroSettings.nam[:pcaphome] + "/" + dumpname + ".pcap"
220
- Ssh.download(DoroSettings.nam[:host], DoroSettings.nam[:user],DoroSettings.nam[:pass], DoroSettings.nam[:pcaphome] + "/" + dumpname + ".pcap", bin.dir_pcap)
218
+ Ssh.download(DoroSettings.nam[:host], DoroSettings.nam[:user],DoroSettings.nam[:pass], DoroSettings.nam[:pcaphome] + "/#{dumpname}.pcap", bin.dir_pcap)
221
219
 
222
220
  #Downloading Screenshots from esx
223
221
  LOGGER.info "NAM", "VM#{guestvm[0]} ".yellow + "Downloading Screenshots"
@@ -231,11 +229,10 @@ module Dorothy
231
229
  #UPDATE DOROTHIBE DB#
232
230
  #####################
233
231
 
234
- pcapfile = bin.dir_pcap + dumpname + ".pcap"
235
- dump = Loadmalw.new(pcapfile)
232
+ dump = Loadmalw.new(bin.dir_pcap + dumpname + ".pcap")
236
233
 
237
234
  #pcaprpath = bin.md5 + "/pcap/" + dump.filename
238
- pcaprid = Loadmalw.calc_pcaprid(dump.filename, dump.size)
235
+ pcaprid = Loadmalw.calc_pcaprid(dump.filename, dump.size).rstrip
239
236
 
240
237
  LOGGER.debug "NAM", "VM#{guestvm[0]} ".yellow + "Pcaprid: " + pcaprid if VERBOSE
241
238
 
@@ -0,0 +1,57 @@
1
+ # "THE BEER-WARE LICENSE" (Revision 42):
2
+ # Mu[http://www.mudynamics.com] wrote this file. As long as you retain this
3
+ # notice you can do whatever you want with this stuff. If we meet some day,
4
+ # and you think this stuff is worth it, you can buy us a beer in return.
5
+ #
6
+ # All about pcapr
7
+ # * http://www.pcapr.net
8
+ # * http://groups.google.com/group/pcapr-forum
9
+ # * http://twitter.com/pcapr
10
+ #
11
+ # Mu Dynamics
12
+ # * http://www.mudynamics.com
13
+ # * http://labs.mudynamics.com
14
+
15
+ module Mu
16
+ class Xtractr
17
+ # = About
18
+ # Contains the meta data about the index including the number of packets,
19
+ # flows, hosts, services and also the duration (in seconds) of the indexed
20
+ # pcaps.
21
+ #
22
+ # xtractr.about.duration
23
+ # xtractr.about.packets
24
+ class About
25
+ # Returns the version of the xtractr server
26
+ attr_reader :version
27
+
28
+ # Returns the ##packets in the index
29
+ attr_reader :packets
30
+
31
+ # Returns the ##flows in the index
32
+ attr_reader :flows
33
+
34
+ # Returns the ##hosts in the index
35
+ attr_reader :hosts
36
+
37
+ # Returns the ##services in the index
38
+ attr_reader :services
39
+
40
+ # Returns the total duration of all the pcaps in the index
41
+ attr_reader :duration
42
+
43
+ def initialize json # :nodoc:
44
+ @version = json['version']
45
+ @packets = json['packets']
46
+ @flows = json['flows']
47
+ @hosts = json['hosts']
48
+ @services = json['services']
49
+ @duration = json['duration']
50
+ end
51
+
52
+ def inspect # :nodoc:
53
+ "#<about \##{flows} flows, \##{packets} packets>"
54
+ end
55
+ end
56
+ end # Xtractr
57
+ end # Mu
@@ -0,0 +1,68 @@
1
+ # "THE BEER-WARE LICENSE" (Revision 42):
2
+ # Mu[http://www.mudynamics.com] wrote this file. As long as you retain this
3
+ # notice you can do whatever you want with this stuff. If we meet some day,
4
+ # and you think this stuff is worth it, you can buy us a beer in return.
5
+ #
6
+ # All about pcapr
7
+ # * http://www.pcapr.net
8
+ # * http://groups.google.com/group/pcapr-forum
9
+ # * http://twitter.com/pcapr
10
+ #
11
+ # Mu Dynamics
12
+ # * http://www.mudynamics.com
13
+ # * http://labs.mudynamics.com
14
+
15
+ module Mu
16
+ class Xtractr
17
+ # = Content
18
+ # Content is the next level of abstraction beyond Message. When a stream is
19
+ # fetched from xtractr, all registered stream processors are invoked on the
20
+ # various messages. For example, the HTTP content processor, pulls out the
21
+ # response body from HTTP requests and responses, dechunks them and potentially
22
+ # unzips the content. The resulting content represents the HTML file or a JPEG
23
+ # image that can be saved off.
24
+ #
25
+ # xtractr.packets('http.content.type:gif').first.flow.stream.contents.each do |c|
26
+ # c.save
27
+ # end
28
+ class Content
29
+ # The name of the content (like a jpeg or pdf file).
30
+ attr_accessor :name
31
+
32
+ # The encoding (base64, gzip, deflate, etc) of this content.
33
+ attr_accessor :encoding
34
+
35
+ # The mime type of this content.
36
+ attr_accessor :type
37
+
38
+ # The message from which this content was extracted.
39
+ attr_reader :message
40
+
41
+ # The actual body of the content (gunzip'd PDF file, for example)
42
+ attr_accessor :body
43
+
44
+ def initialize message # :nodoc:
45
+ @name = "content.#{message.stream.flow.id}.#{message.index}"
46
+ @type = 'application/unknown'
47
+ @body = nil
48
+ @message = message
49
+ end
50
+
51
+ # Save the content to a file. If the filename is not provided then the
52
+ # content name is used instead. This is a convenience method used for
53
+ # method chaining.
54
+ # flow.stream.contents.first.save
55
+ def save filename=nil
56
+ open(filename || name, "w") do |ios|
57
+ ios.write body
58
+ end
59
+ return self
60
+ end
61
+
62
+ def inspect # :nodoc:
63
+ preview = body[0..32].inspect
64
+ "#<content #{name} #{type} #{encoding} #{preview}>"
65
+ end
66
+ end
67
+ end # Xtractr
68
+ end # Mu