resilience 0.0.2 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/axe.rb +18 -0
- data/bin/fcomp.rb +15 -0
- data/bin/pex.rb +16 -0
- data/bin/rarser.rb +15 -0
- data/bin/reach.rb +16 -0
- data/bin/rex.rb +7 -66
- data/bin/rinfo.rb +19 -0
- data/lib/resilience.rb +5 -0
- data/lib/resilience/attribute.rb +21 -4
- data/lib/resilience/cli/all.rb +14 -0
- data/lib/resilience/cli/bin/axe.rb +34 -0
- data/lib/resilience/cli/bin/fcomp.rb +28 -0
- data/lib/resilience/cli/bin/pex.rb +43 -0
- data/lib/resilience/cli/bin/rarser.rb +72 -0
- data/lib/resilience/cli/bin/reach.rb +34 -0
- data/lib/resilience/cli/bin/rex.rb +33 -0
- data/lib/resilience/cli/bin/rinfo.rb +19 -0
- data/lib/resilience/cli/conf.rb +14 -0
- data/lib/resilience/cli/default.rb +17 -0
- data/lib/resilience/cli/disk.rb +40 -0
- data/lib/resilience/cli/file.rb +23 -0
- data/lib/resilience/cli/image.rb +45 -0
- data/lib/resilience/cli/metadata.rb +24 -0
- data/lib/resilience/cli/output.rb +84 -0
- data/lib/resilience/collections/dirs.rb +8 -0
- data/lib/resilience/collections/files.rb +41 -0
- data/lib/resilience/collections/pages.rb +16 -0
- data/lib/resilience/conf.rb +28 -0
- data/lib/resilience/constants.rb +31 -7
- data/lib/resilience/core_ext.rb +39 -0
- data/lib/resilience/fs_dir.rb +3 -0
- data/lib/resilience/fs_dir/dir_base.rb +16 -6
- data/lib/resilience/fs_dir/dir_entry.rb +33 -0
- data/lib/resilience/fs_dir/file_entry.rb +53 -0
- data/lib/resilience/image.rb +33 -0
- data/lib/resilience/mixins/on_image.rb +25 -0
- data/lib/resilience/page.rb +104 -0
- data/lib/resilience/tables.rb +1 -0
- data/lib/resilience/tables/boot.rb +89 -0
- data/lib/resilience/tables/object.rb +6 -2
- data/lib/resilience/tables/system.rb +5 -2
- data/lib/resilience/trees.rb +5 -0
- data/lib/resilience/trees/object_tree.rb +45 -0
- metadata +55 -15
- data/bin/cle.rb +0 -24
- data/bin/clum.py +0 -28
- data/bin/fs.rb +0 -21
- data/bin/ref.rb +0 -49
- data/bin/rels.rb +0 -269
- data/bin/resilience.rb +0 -351
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c196b5ebd4046ddcc6cd0298b62639063cd9a42
|
4
|
+
data.tar.gz: b70a64738927837777702e75b6a6ff087babc9f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3383922ed92c83ec17c7478c7053135897efe55effa28f29e908c01707e077b30d1a312aa67f933ee6eed1c1d81b90c3a17b61c042b7dbe2a3e22166cdcaefdf
|
7
|
+
data.tar.gz: f1828e8c195862117c8369c655b3788972edf65c07586f47cc687bf3267d230944b96c8949e8d49a5feaee916270076adeac8e51913da81399c4c6d1e15a74d8
|
data/bin/axe.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS File Attribute Extractor
|
3
|
+
# Copyright (C) 2015 Red Hat Inc.
|
4
|
+
|
5
|
+
require 'resilience'
|
6
|
+
|
7
|
+
require 'resilience/cli/all'
|
8
|
+
require 'resilience/cli/bin/axe'
|
9
|
+
|
10
|
+
include Resilience::CLI
|
11
|
+
|
12
|
+
optparse = axe_option_parser
|
13
|
+
optparse.parse!
|
14
|
+
|
15
|
+
verify_image!
|
16
|
+
verify_file!
|
17
|
+
parse_image
|
18
|
+
write_results
|
data/bin/fcomp.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS File Metadata Comparer
|
3
|
+
# Copyright (C) 2015 Red Hat Inc.
|
4
|
+
|
5
|
+
require 'resilience'
|
6
|
+
require 'resilience/cli/all'
|
7
|
+
require 'resilience/cli/bin/fcomp'
|
8
|
+
|
9
|
+
include Resilience::CLI
|
10
|
+
|
11
|
+
optparse = fcomp_option_parser
|
12
|
+
optparse.parse!
|
13
|
+
|
14
|
+
verify_image!
|
15
|
+
write_results parse_image
|
data/bin/pex.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS 0x4000 Page Extractor
|
3
|
+
# By mmorsi - 2014-07-14
|
4
|
+
|
5
|
+
require 'resilience'
|
6
|
+
require 'resilience/cli/all'
|
7
|
+
require 'resilience/cli/bin/pex'
|
8
|
+
|
9
|
+
include Resilience::CLI
|
10
|
+
|
11
|
+
optparse = pex_option_parser
|
12
|
+
optparse.parse!
|
13
|
+
|
14
|
+
verify_image!
|
15
|
+
verify_output_dir!
|
16
|
+
extract
|
data/bin/rarser.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# rarser.rb - Ruby ReFS Parser
|
3
|
+
# Copyright (C) 2015 Red Hat Inc.
|
4
|
+
|
5
|
+
require 'resilience'
|
6
|
+
require 'resilience/cli/all'
|
7
|
+
require 'resilience/cli/bin/rarser'
|
8
|
+
|
9
|
+
include Resilience::CLI
|
10
|
+
|
11
|
+
optparse = rarser_option_parser
|
12
|
+
optparse.parse!
|
13
|
+
|
14
|
+
verify_image!
|
15
|
+
write_results parse_image
|
data/bin/reach.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS file searcher
|
3
|
+
# Copyright (C) 2015 Red Hat Inc.
|
4
|
+
|
5
|
+
require 'resilience'
|
6
|
+
require 'resilience/cli/all'
|
7
|
+
require 'resilience/cli/bin/reach'
|
8
|
+
|
9
|
+
include Resilience::CLI
|
10
|
+
|
11
|
+
optparse = reach_option_parser
|
12
|
+
optparse.parse!
|
13
|
+
|
14
|
+
verify_image!
|
15
|
+
setup_image
|
16
|
+
run_search
|
data/bin/rex.rb
CHANGED
@@ -2,73 +2,14 @@
|
|
2
2
|
# ReFS File Extractor
|
3
3
|
# Copyright (C) 2015 Red Hat Inc.
|
4
4
|
|
5
|
-
require 'optparse'
|
6
5
|
require 'resilience'
|
6
|
+
require 'resilience/cli/all'
|
7
|
+
require 'resilience/cli/bin/rex'
|
7
8
|
|
8
|
-
|
9
|
-
cli_opts = parse_cli(ARGV)
|
10
|
-
results = parse_image cli_opts
|
11
|
-
write_results cli_opts, results
|
12
|
-
end
|
9
|
+
include Resilience::CLI
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
Dir.mkdir(dir) unless File.directory?(dir)
|
11
|
+
optparse = rex_option_parser
|
12
|
+
optparse.parse!
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
path = "#{dir}/#{name}".delete("\0")
|
21
|
-
File.write(path, contents)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def parse_image(opts)
|
26
|
-
file = File.open(opts[:image], 'rb')
|
27
|
-
image = Resilience::OnImage.image
|
28
|
-
image.file = file
|
29
|
-
image.offset = opts[:offset]
|
30
|
-
image.opts = opts
|
31
|
-
|
32
|
-
image.parse
|
33
|
-
files = image.root_dir.files
|
34
|
-
dirs = image.root_dir.dirs
|
35
|
-
{:files => files, :dirs => dirs}
|
36
|
-
end
|
37
|
-
|
38
|
-
def parse_cli(cli)
|
39
|
-
opts = {}
|
40
|
-
parser = OptionParser.new do |popts|
|
41
|
-
popts.on("-h", "--help", "Print help message") do
|
42
|
-
puts parser
|
43
|
-
exit
|
44
|
-
end
|
45
|
-
|
46
|
-
popts.on("-i", "--image path", "Path to the disk image to parse") do |path|
|
47
|
-
opts[:image] = path
|
48
|
-
end
|
49
|
-
|
50
|
-
popts.on("-o", "--offset bytes", "Start of volume with ReFS filesystem") do |offset|
|
51
|
-
opts[:offset] = offset.to_i
|
52
|
-
end
|
53
|
-
|
54
|
-
popts.on("-d", "--dir dir", "Output directory") do |dir|
|
55
|
-
opts[:dir] = dir
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
begin
|
60
|
-
parser.parse!(cli)
|
61
|
-
rescue OptionParser::InvalidOption
|
62
|
-
puts parser
|
63
|
-
exit
|
64
|
-
end
|
65
|
-
|
66
|
-
if !opts[:image] || !opts[:offset] || !opts[:dir]
|
67
|
-
puts "--image, --offset, and --dir params are needed"
|
68
|
-
exit 1
|
69
|
-
end
|
70
|
-
|
71
|
-
opts
|
72
|
-
end
|
73
|
-
|
74
|
-
main if __FILE__ == $0
|
14
|
+
verify_image!
|
15
|
+
write_results parse_image
|
data/bin/rinfo.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# ReFS Filesystem Info
|
4
|
+
# Copyright (C) 2015 Red Hat Inc.
|
5
|
+
###########################################################
|
6
|
+
|
7
|
+
require 'resilience'
|
8
|
+
require 'resilience/cli/all'
|
9
|
+
require 'resilience/cli/bin/rinfo'
|
10
|
+
|
11
|
+
include Resilience::CLI
|
12
|
+
|
13
|
+
optparse = rinfo_option_parser
|
14
|
+
optparse.parse!
|
15
|
+
|
16
|
+
boot2offset
|
17
|
+
verify_image!
|
18
|
+
parse_image
|
19
|
+
dump_info
|
data/lib/resilience.rb
CHANGED
@@ -2,12 +2,17 @@
|
|
2
2
|
# ReFS Parser (expiremental)
|
3
3
|
# Copyright (C) 2015 Red Hat Inc.
|
4
4
|
|
5
|
+
require 'resilience/core_ext'
|
6
|
+
|
5
7
|
require 'resilience/mixins'
|
6
8
|
require 'resilience/constants'
|
7
9
|
|
10
|
+
require 'resilience/conf'
|
8
11
|
require 'resilience/fs_dir'
|
9
12
|
require 'resilience/attribute'
|
13
|
+
require 'resilience/page'
|
10
14
|
require 'resilience/image'
|
11
15
|
|
12
16
|
require 'resilience/dirs'
|
13
17
|
require 'resilience/tables'
|
18
|
+
require 'resilience/trees'
|
data/lib/resilience/attribute.rb
CHANGED
@@ -6,23 +6,40 @@ module Resilience
|
|
6
6
|
class Attribute
|
7
7
|
include OnImage
|
8
8
|
|
9
|
+
attr_accessor :pos
|
9
10
|
attr_accessor :bytes
|
10
11
|
|
11
12
|
def initialize(args={})
|
12
|
-
@
|
13
|
+
@pos = args[:pos]
|
14
|
+
@bytes = args[:bytes]
|
15
|
+
end
|
16
|
+
|
17
|
+
def empty?
|
18
|
+
bytes.nil? || bytes.empty?
|
13
19
|
end
|
14
20
|
|
15
21
|
def self.read
|
16
|
-
pos
|
17
|
-
|
22
|
+
pos = image.pos
|
23
|
+
packed = image.read(4)
|
24
|
+
return new if packed.nil?
|
25
|
+
attr_len = packed.unpack('L').first
|
18
26
|
return new if attr_len == 0
|
19
27
|
|
20
28
|
image.seek pos
|
21
|
-
|
29
|
+
value = image.read(attr_len)
|
30
|
+
new(:pos => pos, :bytes => value)
|
22
31
|
end
|
23
32
|
|
24
33
|
def unpack(format)
|
25
34
|
bytes.unpack(format)
|
26
35
|
end
|
36
|
+
|
37
|
+
def [](key)
|
38
|
+
return bytes[key]
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
bytes.collect { |a| a.to_s(16) }.join(' ')
|
43
|
+
end
|
27
44
|
end
|
28
45
|
end # module Resilience
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Resilience CLI
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
require 'resilience/cli/default'
|
9
|
+
require 'resilience/cli/image'
|
10
|
+
require 'resilience/cli/output'
|
11
|
+
require 'resilience/cli/metadata'
|
12
|
+
require 'resilience/cli/file'
|
13
|
+
require 'resilience/cli/disk'
|
14
|
+
require 'resilience/cli/conf'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Resilience axe cli util
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
5
|
+
###########################################################
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
def axe_option_parser
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
default_options opts
|
12
|
+
image_options opts
|
13
|
+
file_select_options opts
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_file!(file)
|
18
|
+
if file.nil?
|
19
|
+
puts "File #{conf.file} not found"
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def write_results
|
25
|
+
file = image.root_dir.files.at(conf.file)
|
26
|
+
validate_file!(file)
|
27
|
+
puts "File: #{file.fullname} attributes: "
|
28
|
+
file.metadata_attrs.each_index { |attr_index|
|
29
|
+
attr = file.metadata_attrs[attr_index]
|
30
|
+
print "Attribute #{attr_index}: "
|
31
|
+
print attr.collect { |b| b.to_s(16) }.join(' ')
|
32
|
+
puts "\n\n"
|
33
|
+
}
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Resilience rcomp cli util
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
5
|
+
###########################################################
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
def fcomp_option_parser
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
default_options opts
|
12
|
+
image_options opts
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def write_results(image)
|
17
|
+
puts "Analyzed:"
|
18
|
+
puts "#{image.root_dir.files.collect { |f| f.fullname }.join("\n")}"
|
19
|
+
different_bytes = image.root_dir.files.bytes_diff
|
20
|
+
0.upto(different_bytes.size-1) do |byte_index|
|
21
|
+
next if different_bytes[byte_index].nil?
|
22
|
+
puts "Byte 0x#{byte_index.to_s(16)} differs".red.bold
|
23
|
+
different_bytes[byte_index].each do |file, byte|
|
24
|
+
print " 0x#{byte.unpack('C*').first.to_s(16)}".blue
|
25
|
+
end
|
26
|
+
puts
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Resilience pex cli util
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
5
|
+
###########################################################
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
def pex_option_parser
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
default_options opts
|
12
|
+
image_options opts
|
13
|
+
output_fs_options opts
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def target_clusters
|
18
|
+
@target_clusters ||= [0x1e, 0x20, 0x21, 0x22, 0x28, 0x29,
|
19
|
+
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
20
|
+
0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
|
21
|
+
0x36, 0x37, 0x38,
|
22
|
+
0x2c0, 0x2c1, 0x2c2, 0x2c3, 0x2c4,
|
23
|
+
0x2c5, 0x2c6, 0x2c7, 0x2c8, 0x2cc,
|
24
|
+
0x2cd, 0x2ce, 0x2cf]
|
25
|
+
end
|
26
|
+
|
27
|
+
def extract
|
28
|
+
create_output_dir!
|
29
|
+
setup_image
|
30
|
+
|
31
|
+
target_clusters.each do |cluster|
|
32
|
+
extract_cluster cluster
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def extract_cluster(cluster)
|
37
|
+
out = File.open("#{conf.dir}/#{cluster.to_s(16)}", 'wb')
|
38
|
+
offset = cluster * PAGE_SIZE
|
39
|
+
image.seek(offset)
|
40
|
+
contents = image.read(PAGE_SIZE)
|
41
|
+
out.write contents
|
42
|
+
out.close
|
43
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Resilience rarser cli util
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
5
|
+
###########################################################
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
def rarser_option_parser
|
10
|
+
conf.pages = true
|
11
|
+
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
default_options opts
|
14
|
+
image_options opts
|
15
|
+
metadata_options opts
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def page_attribute_output(page)
|
21
|
+
output = page.attributes.collect { |attribute|
|
22
|
+
" #{attribute.to_s[0...10]}...\n"
|
23
|
+
}.join
|
24
|
+
|
25
|
+
" Attributes:\n" + output
|
26
|
+
end
|
27
|
+
|
28
|
+
def page_output(page)
|
29
|
+
page_out = "Page #{page.id.indented(4).blue.bold}: " \
|
30
|
+
"number #{page.virtual_page_number.indented(3).blue.bold} - " \
|
31
|
+
"sequence #{page.sequence.indented(2).blue.bold} - " \
|
32
|
+
"object id #{page.object_id.indented(2).blue.bold} - " \
|
33
|
+
"records #{page.entries.indented(2).blue.bold}\n"
|
34
|
+
|
35
|
+
page_out += page_attribute_output(page) if conf.attributes? && page.has_attributes?
|
36
|
+
page_out
|
37
|
+
end
|
38
|
+
|
39
|
+
def pages_output
|
40
|
+
image.pages.collect { |page_id, page| page_output(page) }.join
|
41
|
+
end
|
42
|
+
|
43
|
+
def object_table_output
|
44
|
+
return "" unless conf.object_table?
|
45
|
+
|
46
|
+
output = image.object_table.pages.collect { |obj_id, cluster|
|
47
|
+
"#{obj_id.big_endian_str[0..4]} | #{cluster.big_endian_str}\n"
|
48
|
+
}.join
|
49
|
+
|
50
|
+
"\nObject table:\n" \
|
51
|
+
"Obj | Cluster\n" \
|
52
|
+
"-------------\n#{output}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def object_tree_output
|
56
|
+
return "" unless conf.object_tree?
|
57
|
+
|
58
|
+
output = image.object_tree.map.collect { |obj, refs|
|
59
|
+
references = refs.collect { |ref| ref[0..4] }.join(', ')
|
60
|
+
"#{obj[0..4]} -> #{references}\n"
|
61
|
+
}.join
|
62
|
+
|
63
|
+
"\nObject tree:\n" \
|
64
|
+
"-------------\n#{output}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_results(image)
|
68
|
+
puts header_output
|
69
|
+
puts pages_output
|
70
|
+
puts object_table_output
|
71
|
+
puts object_tree_output
|
72
|
+
end
|