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
@@ -0,0 +1,34 @@
|
|
1
|
+
# Resilience reach cli util
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
5
|
+
###########################################################
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
def reach_option_parser
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
default_options opts
|
12
|
+
image_options opts
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def check_sequence
|
17
|
+
@check_sequence ||= 0xe010002800000038 # inverted due to endian ordering
|
18
|
+
end
|
19
|
+
|
20
|
+
def sequence_length
|
21
|
+
@sequence_length ||= 8
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_search
|
25
|
+
while check = image.read(sequence_length)
|
26
|
+
unpacked = check.unpack('Q').first
|
27
|
+
write_match if unpacked == check_sequence
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def write_match
|
32
|
+
puts 'File at: 0x' + image.total_pos.to_s(16) +
|
33
|
+
' cluster ' + (image.pos / 0x4000).to_s(16)
|
34
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Resilience rex cli util
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
5
|
+
###########################################################
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
def rex_option_parser
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
default_options opts
|
12
|
+
image_options opts
|
13
|
+
output_fs_options opts
|
14
|
+
stdout_options opts
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def write_results(image)
|
19
|
+
create_output_dir!
|
20
|
+
|
21
|
+
dirs = image.root_dir.dirs
|
22
|
+
dirs.each do |dir|
|
23
|
+
puts "Dir: #{dir.fullname} at #{dir.total_offset}" if conf.dirs?
|
24
|
+
end
|
25
|
+
|
26
|
+
files = image.root_dir.files
|
27
|
+
files.each do |file|
|
28
|
+
puts "File: #{file.fullname} at #{file.total_offset}" if conf.files?
|
29
|
+
|
30
|
+
path = "#{output_dir}/#{file.fullname}".delete("\0")
|
31
|
+
File.write(path, file.metadata) if write_to_output_dir?
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Resilience rinfo cli util
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
5
|
+
###########################################################
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
|
9
|
+
def rinfo_option_parser
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
default_options opts
|
12
|
+
image_options opts
|
13
|
+
disk_options opts
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def dump_info
|
18
|
+
puts header_output
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Reslience CLI Conf
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
module Resilience
|
9
|
+
module CLI
|
10
|
+
def conf
|
11
|
+
Conf
|
12
|
+
end
|
13
|
+
end # mdoule CLI
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Reslience CLI Default Options
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
module Resilience
|
9
|
+
module CLI
|
10
|
+
def default_options(option_parser)
|
11
|
+
option_parser.on('-h', '--help', 'Print help message') do
|
12
|
+
puts option_parser
|
13
|
+
exit
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end # module CLI
|
17
|
+
end # module Resilience
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Resilience Disk Options
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
module Resilience
|
9
|
+
module CLI
|
10
|
+
def disk_options(option_parser)
|
11
|
+
option_parser.on("-m", "--mbr", "Extract FS Info From MBR") do
|
12
|
+
conf.mbr = true
|
13
|
+
end
|
14
|
+
|
15
|
+
option_parser.on("-g", "--gpt", "Extract FS Info From GUID Partition Table") do
|
16
|
+
conf.gpt = true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def mbr2offset
|
21
|
+
return unless conf.mbr
|
22
|
+
image.offset = 0
|
23
|
+
offset = MBR.new.refs_offset
|
24
|
+
conf[:offset] = offset unless offset.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def gpt2offset
|
28
|
+
return unless conf.gpt
|
29
|
+
image.offset = 0
|
30
|
+
image.offset = MBR.new.gpt_offset
|
31
|
+
image.offset = conf.offset = GPT.new.refs_offset
|
32
|
+
end
|
33
|
+
|
34
|
+
def boot2offset
|
35
|
+
setup_image
|
36
|
+
mbr2offset if conf.mbr
|
37
|
+
gpt2offset if conf.gpt
|
38
|
+
end
|
39
|
+
end # module CLI
|
40
|
+
end # module Resilience
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Reslience File Options
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
module Resilience
|
9
|
+
module CLI
|
10
|
+
def file_select_options(option_parser)
|
11
|
+
option_parser.on("-f", "--file [file]", "File to analyze") do |file|
|
12
|
+
conf.file = file
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def verify_file!
|
17
|
+
unless conf.file
|
18
|
+
puts "--file param needed"
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end # module CLI
|
23
|
+
end # module Resilience
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Reslience CLI Image Options
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
module Resilience
|
9
|
+
module CLI
|
10
|
+
def image_options(option_parser)
|
11
|
+
option_parser.on("-i", "--image path", "Path to the disk image to parse") do |path|
|
12
|
+
conf.image_file = path
|
13
|
+
end
|
14
|
+
|
15
|
+
option_parser.on("-o", "--offset bytes", "Start of volume with ReFS filesystem") do |offset|
|
16
|
+
conf.offset = offset.to_i
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def verify_image!
|
21
|
+
unless conf.image && conf.offset
|
22
|
+
puts "--image and --offset params needed"
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup_image
|
28
|
+
file = File.open(conf.image_file, 'rb')
|
29
|
+
image.file = file
|
30
|
+
image.offset = conf.offset
|
31
|
+
image.opts = conf
|
32
|
+
image
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_image
|
36
|
+
setup_image
|
37
|
+
image.parse
|
38
|
+
image
|
39
|
+
end
|
40
|
+
|
41
|
+
def image
|
42
|
+
Resilience::OnImage.image
|
43
|
+
end
|
44
|
+
end # module CLI
|
45
|
+
end # module Resilience
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Reslience Metadata Default Options
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
module Resilience
|
9
|
+
module CLI
|
10
|
+
def metadata_options(option_parser)
|
11
|
+
option_parser.on("-a", "--attributes", "Include attribute analysis in output") do
|
12
|
+
conf.attributes = true
|
13
|
+
end
|
14
|
+
|
15
|
+
option_parser.on("--table", "Include object table analysis in output") do
|
16
|
+
conf.object_table = true
|
17
|
+
end
|
18
|
+
|
19
|
+
option_parser.on("--tree", "Include object tree analysis in output") do
|
20
|
+
conf.object_tree = true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end # module CLI
|
24
|
+
end # module Resilience
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Reslience CLI Output Options
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
require 'colored'
|
9
|
+
|
10
|
+
module Resilience
|
11
|
+
module CLI
|
12
|
+
OUTPUT_LABELS = {
|
13
|
+
:bps => "(bytes per sector)",
|
14
|
+
:spc => "(sectors per cluster)",
|
15
|
+
:bpc => "(bytes per cluster)",
|
16
|
+
:vbr => "VBR",
|
17
|
+
:image => "Analyzed ReFS filesystem on",
|
18
|
+
:offset => "starting at"
|
19
|
+
}
|
20
|
+
|
21
|
+
def output_fs_options(option_parser)
|
22
|
+
option_parser.on("--write dir", "Write output to directory") do |dir|
|
23
|
+
conf.dir = dir
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def stdout_options(option_parser)
|
28
|
+
option_parser.on("-f", "--files", "List files in output") do
|
29
|
+
conf.files = true
|
30
|
+
end
|
31
|
+
|
32
|
+
option_parser.on("-d", "--dirs", "List dirs in output") do
|
33
|
+
conf.dirs = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def verify_output_dir!
|
38
|
+
unless conf.dir
|
39
|
+
puts "--write param needed"
|
40
|
+
exit 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def output_dir
|
45
|
+
conf.dir
|
46
|
+
end
|
47
|
+
|
48
|
+
def write_to_output_dir?
|
49
|
+
!!output_dir
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_output_dir!
|
53
|
+
return unless write_to_output_dir?
|
54
|
+
Dir.mkdir(output_dir) unless File.directory?(output_dir)
|
55
|
+
end
|
56
|
+
|
57
|
+
def image_output
|
58
|
+
"#{OUTPUT_LABELS[:image]} #{conf.image_file.green.bold} "\
|
59
|
+
"#{OUTPUT_LABELS[:offset]} #{conf.offset.to_s.green.bold}\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
def header_output
|
63
|
+
image_output + vbr_output
|
64
|
+
end
|
65
|
+
|
66
|
+
def bytes_per_sector_output
|
67
|
+
"#{image.bytes_per_sector.indented.yellow.bold} (#{OUTPUT_LABELS[:bps]})"
|
68
|
+
end
|
69
|
+
|
70
|
+
def sectors_per_cluster_output
|
71
|
+
"#{image.sectors_per_cluster.indented.yellow.bold} (#{OUTPUT_LABELS[:spc]})"
|
72
|
+
end
|
73
|
+
|
74
|
+
def cluster_size_output
|
75
|
+
"#{image.cluster_size.indented.yellow.bold} (#{OUTPUT_LABELS[:bpc]})\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
def vbr_output
|
79
|
+
"#{OUTPUT_LABELS[:vbr]}: #{bytes_per_sector_output} * " \
|
80
|
+
"#{sectors_per_cluster_output} = " \
|
81
|
+
"#{cluster_size_output}"
|
82
|
+
end
|
83
|
+
end # module CLI
|
84
|
+
end # module Resilience
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS Files Collection
|
3
|
+
# Copyright (C) 2015 Red Hat Inc.
|
4
|
+
|
5
|
+
module Resilience
|
6
|
+
class Files < Array
|
7
|
+
def names
|
8
|
+
collect { |f| f.name }
|
9
|
+
end
|
10
|
+
|
11
|
+
def fullnames
|
12
|
+
collect { |f| f.fullname }
|
13
|
+
end
|
14
|
+
|
15
|
+
def at(path)
|
16
|
+
find { |f| f.fullname == path }
|
17
|
+
end
|
18
|
+
|
19
|
+
def byte_map
|
20
|
+
bytes = []
|
21
|
+
each do |file|
|
22
|
+
0.upto(file.metadata.size-1) do |byte_index|
|
23
|
+
bytes[byte_index] ||= {}
|
24
|
+
bytes[byte_index][file] = file.metadata[byte_index]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
bytes
|
28
|
+
end
|
29
|
+
|
30
|
+
def bytes_diff
|
31
|
+
map = byte_map
|
32
|
+
different_bytes = []
|
33
|
+
0.upto(map.size-1).each do |byte_index|
|
34
|
+
bytes = map[byte_index].values
|
35
|
+
different = bytes.uniq.size != 1 || bytes.size != size
|
36
|
+
different_bytes << (different ? map[byte_index] : nil)
|
37
|
+
end
|
38
|
+
different_bytes
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS Pages Collection
|
3
|
+
# Copyright (C) 2015 Red Hat Inc.
|
4
|
+
|
5
|
+
module Resilience
|
6
|
+
class Pages < Hash
|
7
|
+
def with_number(virtual_page_number)
|
8
|
+
select { |page_id, page| page.virtual_page_number == virtual_page_number }
|
9
|
+
end
|
10
|
+
|
11
|
+
def newest_for(virtual_page_number)
|
12
|
+
pages = with_number(virtual_page_number)
|
13
|
+
pages.values.sort { |p1, p2| p2.sequence <=> p1.sequence }.first
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# Reslience Conf
|
3
|
+
#
|
4
|
+
# Licensed under the MIT license
|
5
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
6
|
+
###########################################################
|
7
|
+
|
8
|
+
module Resilience
|
9
|
+
module Conf
|
10
|
+
def self.conf
|
11
|
+
@conf ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.method_missing(method, *args)
|
15
|
+
if method.to_s =~ /=$/
|
16
|
+
conf[method.to_s.match(/^(.*)=$/)[1].to_sym] = args.first
|
17
|
+
elsif method.to_s =~ /\?$/
|
18
|
+
!!conf[method.to_s.match(/^(.*)\?$/)[1].to_sym]
|
19
|
+
else
|
20
|
+
conf[method]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def conf
|
25
|
+
Conf
|
26
|
+
end
|
27
|
+
end # module Conf
|
28
|
+
end
|