resilience 0.0.2 → 0.1.1
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.
- 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
data/lib/resilience/constants.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
# ReFS Constants
|
3
3
|
# Copyright (C) 2015 Red Hat Inc.
|
4
4
|
|
5
|
-
|
5
|
+
FS_SIGNATURE = [0x00, 0x00, 0x00, 0x52, 0x65, 0x46, 0x53, 0x00] # ...ReFS.
|
6
|
+
|
6
7
|
PAGE_SIZE = 0x4000
|
7
|
-
FIRST_PAGE_ADDRESS = FIRST_PAGE_ID * PAGE_SIZE
|
8
8
|
|
9
9
|
ROOT_DIR_ID = [0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0]
|
10
10
|
DIR_ENTRY = 0x20030
|
@@ -14,19 +14,43 @@ DIR_TREE = 0x301
|
|
14
14
|
DIR_LIST = 0x200
|
15
15
|
#DIR_BRANCH = 0x000 ?
|
16
16
|
|
17
|
+
PAGES = {
|
18
|
+
# page id's:
|
19
|
+
:first => 0x1e,
|
20
|
+
|
21
|
+
# virtual page numbers:
|
22
|
+
:root => 0x00,
|
23
|
+
:object_table => 0x02,
|
24
|
+
:object_tree => 0x03
|
25
|
+
}
|
26
|
+
|
17
27
|
ADDRESSES = {
|
28
|
+
# size / bounds
|
29
|
+
:bytes_per_sector => 0x20,
|
30
|
+
:sectors_per_cluster => 0x24,
|
31
|
+
|
18
32
|
# page
|
33
|
+
:page_sequence => 0x08, # shadow pages share the same virtual page number
|
19
34
|
:virtual_page_number => 0x18,
|
20
35
|
:first_attr => 0x30,
|
21
36
|
|
22
|
-
# page 0x1e
|
37
|
+
# on page 0x1e:
|
23
38
|
:system_table_page => 0xA0,
|
24
39
|
|
25
|
-
# system table
|
40
|
+
# on system table:
|
26
41
|
:system_pages => 0x58,
|
27
42
|
|
28
|
-
# generic table
|
29
|
-
|
43
|
+
# generic table:
|
44
|
+
# referenced from start of first attr
|
45
|
+
:object_id => 0x0C,
|
46
|
+
:num_objects => 0x20,
|
47
|
+
|
48
|
+
# referenced from start of table header
|
49
|
+
:table_length => 0x04,
|
30
50
|
|
31
|
-
|
51
|
+
# object tree:
|
52
|
+
:object_tree_start1 => 0x10,
|
53
|
+
:object_tree_end1 => 0x1F,
|
54
|
+
:object_tree_start2 => 0x20,
|
55
|
+
:object_tree_end2 => 0x2F
|
32
56
|
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Resilience Core Ruby Extensions
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2015 Red Hat, Inc.
|
5
|
+
|
6
|
+
class String
|
7
|
+
def indented(places=1)
|
8
|
+
rjust(places, '0').upcase
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Fixnum
|
13
|
+
def indented(places=1)
|
14
|
+
'0x' + to_s(16).rjust(places, '0').upcase
|
15
|
+
end
|
16
|
+
|
17
|
+
def big_endian_str
|
18
|
+
[self].big_endian_str
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class NilClass
|
23
|
+
def indented(places=1)
|
24
|
+
'0x' + ('0' * places)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Array
|
29
|
+
def big_endian_str
|
30
|
+
str = '0x'
|
31
|
+
value = false
|
32
|
+
reverse_each { |b|
|
33
|
+
next if b == 0 && !value
|
34
|
+
value = true
|
35
|
+
str += b.to_s(16)
|
36
|
+
}
|
37
|
+
str
|
38
|
+
end
|
39
|
+
end
|
data/lib/resilience/fs_dir.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
# Copyright (C) 2014-2015 Red Hat Inc.
|
4
4
|
|
5
5
|
require 'fileutils'
|
6
|
+
require 'resilience/collections/dirs'
|
7
|
+
require 'resilience/collections/files'
|
6
8
|
|
7
9
|
module Resilience
|
8
10
|
module FSDir
|
@@ -14,8 +16,8 @@ module Resilience
|
|
14
16
|
|
15
17
|
def parse_dir_obj(object_id, prefix)
|
16
18
|
object_table = image.object_table
|
17
|
-
@dirs ||=
|
18
|
-
@files ||=
|
19
|
+
@dirs ||= Dirs.new
|
20
|
+
@files ||= Files.new
|
19
21
|
|
20
22
|
page_id = object_table.pages[object_id]
|
21
23
|
page_address = page_id * PAGE_SIZE
|
@@ -90,15 +92,23 @@ module Resilience
|
|
90
92
|
if entry_type == DIR_ENTRY
|
91
93
|
dir_name = key_bytes[4..-1].pack('L*')
|
92
94
|
dir_obj = value.unpack('C*')[0...8]
|
93
|
-
dirs
|
95
|
+
dirs << DirEntry.new(:prefix => prefix,
|
96
|
+
:name => dir_name,
|
97
|
+
:metadata => dir_obj,
|
98
|
+
:record => record)
|
94
99
|
|
95
100
|
dir_obj = [0, 0, 0, 0, 0, 0, 0, 0].concat(dir_obj)
|
96
101
|
parse_dir_obj(dir_obj, "#{prefix}\\#{dir_name}")
|
97
102
|
|
98
103
|
elsif entry_type == FILE_ENTRY
|
99
|
-
|
100
|
-
|
101
|
-
|
104
|
+
filename = key_bytes[4..-1]
|
105
|
+
filename.delete(0)
|
106
|
+
filename = filename.pack('C*')
|
107
|
+
|
108
|
+
files << FileEntry.new(:prefix => prefix,
|
109
|
+
:name => filename,
|
110
|
+
:metadata => value,
|
111
|
+
:record => record)
|
102
112
|
end
|
103
113
|
end
|
104
114
|
end # class DirBase
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS Directory Dir Entry
|
3
|
+
# Copyright (C) 2014-2015 Red Hat Inc.
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module Resilience
|
8
|
+
module FSDir
|
9
|
+
class DirEntry
|
10
|
+
attr_accessor :prefix
|
11
|
+
attr_accessor :name
|
12
|
+
attr_accessor :metadata
|
13
|
+
|
14
|
+
# metadata record
|
15
|
+
attr_accessor :record
|
16
|
+
|
17
|
+
def initialize(args={})
|
18
|
+
@prefix = args[:prefix]
|
19
|
+
@name = args[:name]
|
20
|
+
@metadata = args[:metadata]
|
21
|
+
@record = args[:record]
|
22
|
+
end
|
23
|
+
|
24
|
+
def fullname
|
25
|
+
"#{prefix}\\#{name}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def disk_offset
|
29
|
+
image.offset + dir.record.attribute.pos
|
30
|
+
end
|
31
|
+
end # class DirEntry
|
32
|
+
end # module FSDir
|
33
|
+
end # module Resilience
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS Directory File Entry
|
3
|
+
# Copyright (C) 2014-2015 Red Hat Inc.
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module Resilience
|
8
|
+
module FSDir
|
9
|
+
class FileEntry
|
10
|
+
attr_accessor :prefix
|
11
|
+
attr_accessor :name
|
12
|
+
attr_accessor :metadata
|
13
|
+
|
14
|
+
# metadata record
|
15
|
+
attr_accessor :record
|
16
|
+
|
17
|
+
# known metadata attributes
|
18
|
+
attr_accessor :metadata_attrs
|
19
|
+
|
20
|
+
def initialize(args={})
|
21
|
+
@prefix = args[:prefix]
|
22
|
+
@name = args[:name]
|
23
|
+
@metadata = args[:metadata]
|
24
|
+
@record = args[:record]
|
25
|
+
parse_attrs
|
26
|
+
end
|
27
|
+
|
28
|
+
def fullname
|
29
|
+
"#{prefix}\\#{name}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def total_offset
|
33
|
+
image.offset + record.attribute.pos
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_attrs
|
37
|
+
metadata_bytes = @metadata.unpack('C*')
|
38
|
+
metadata_dwords = @metadata.unpack('L*')
|
39
|
+
attr1_length = metadata_dwords[0]
|
40
|
+
attr1_dwords = attr1_length/4
|
41
|
+
attr2_length = metadata_dwords[attr1_dwords]
|
42
|
+
attr2_dwords = attr2_length/4
|
43
|
+
attr3_length = metadata_dwords[attr1_dwords + attr2_dwords]
|
44
|
+
# there may be other attrs after this point...
|
45
|
+
|
46
|
+
attr1 = metadata_bytes[0..attr1_length]
|
47
|
+
attr2 = metadata_bytes[attr1_length..attr1_length+attr2_length]
|
48
|
+
attr3 = metadata_bytes[attr1_length+attr2_length..attr1_length+attr2_length+attr3_length]
|
49
|
+
@metadata_attrs = [attr1, attr2, attr3]
|
50
|
+
end
|
51
|
+
end # class FileEntry
|
52
|
+
end # module FSDir
|
53
|
+
end # module Resilience
|
data/lib/resilience/image.rb
CHANGED
@@ -4,22 +4,41 @@
|
|
4
4
|
|
5
5
|
module Resilience
|
6
6
|
class Image
|
7
|
+
include Conf
|
8
|
+
|
7
9
|
attr_accessor :file
|
8
10
|
attr_accessor :offset
|
9
11
|
attr_accessor :opts
|
10
12
|
|
13
|
+
attr_accessor :bytes_per_sector
|
14
|
+
attr_accessor :sectors_per_cluster
|
15
|
+
|
16
|
+
def cluster_size
|
17
|
+
@cluster_size ||= bytes_per_sector * sectors_per_cluster
|
18
|
+
end
|
19
|
+
|
11
20
|
attr_accessor :root_dir
|
12
21
|
attr_accessor :system_table
|
13
22
|
attr_accessor :object_table
|
23
|
+
attr_accessor :object_tree
|
24
|
+
|
25
|
+
# all pages including shadow pages
|
26
|
+
attr_accessor :pages
|
14
27
|
|
15
28
|
def initialize(args={})
|
16
29
|
@file = args[:file] || []
|
17
30
|
end
|
18
31
|
|
19
32
|
def parse
|
33
|
+
parse_bounds
|
34
|
+
|
35
|
+
# each of these is a seperate parsing process,
|
36
|
+
# though later ones may depend on former
|
37
|
+
@pages = Resilience::Page.extract_all if conf.pages?
|
20
38
|
@system_table = Resilience::SystemTable.parse
|
21
39
|
@object_table = Resilience::ObjectTable.parse
|
22
40
|
@root_dir = Resilience::RootDir.parse
|
41
|
+
@object_tree = Resilience::ObjectTree.parse if conf.object_tree?
|
23
42
|
end
|
24
43
|
|
25
44
|
def seek(position)
|
@@ -30,8 +49,22 @@ module Resilience
|
|
30
49
|
@file.pos - offset
|
31
50
|
end
|
32
51
|
|
52
|
+
def total_pos
|
53
|
+
@file.pos
|
54
|
+
end
|
55
|
+
|
33
56
|
def read(len)
|
34
57
|
@file.read(len)
|
35
58
|
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def parse_bounds
|
63
|
+
seek(ADDRESSES[:bytes_per_sector])
|
64
|
+
@bytes_per_sector = read(4).unpack('L').first
|
65
|
+
|
66
|
+
seek(ADDRESSES[:sectors_per_cluster])
|
67
|
+
@sectors_per_cluster = read(4).unpack('L').first
|
68
|
+
end
|
36
69
|
end
|
37
70
|
end # module Resilience
|
@@ -12,14 +12,39 @@ module Resilience
|
|
12
12
|
@image ||= Resilience::Image.new
|
13
13
|
end
|
14
14
|
|
15
|
+
def self.store_pos
|
16
|
+
@image_pos ||= []
|
17
|
+
@image_pos.unshift image.pos
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.restore_pos
|
21
|
+
image.seek @image_pos.shift
|
22
|
+
end
|
23
|
+
|
15
24
|
def image
|
16
25
|
OnImage.image
|
17
26
|
end
|
18
27
|
|
28
|
+
def store_pos
|
29
|
+
OnImage.store_pos
|
30
|
+
end
|
31
|
+
|
32
|
+
def restore_pos
|
33
|
+
OnImage.restore_pos
|
34
|
+
end
|
35
|
+
|
19
36
|
module ClassMethods
|
20
37
|
def image
|
21
38
|
OnImage.image
|
22
39
|
end
|
40
|
+
|
41
|
+
def store_pos
|
42
|
+
OnImage.store_pos
|
43
|
+
end
|
44
|
+
|
45
|
+
def restore_pos
|
46
|
+
OnImage.restore_pos
|
47
|
+
end
|
23
48
|
end
|
24
49
|
end # module OnImage
|
25
50
|
end # module Resilience
|
@@ -0,0 +1,104 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# ReFS Page Representation
|
3
|
+
# Copyright (C) 2015 Red Hat Inc.
|
4
|
+
|
5
|
+
require 'resilience/collections/pages'
|
6
|
+
|
7
|
+
module Resilience
|
8
|
+
class Page
|
9
|
+
include OnImage
|
10
|
+
|
11
|
+
attr_accessor :id
|
12
|
+
attr_accessor :contents
|
13
|
+
|
14
|
+
attr_accessor :sequence
|
15
|
+
attr_accessor :virtual_page_number
|
16
|
+
|
17
|
+
attr_accessor :attributes
|
18
|
+
|
19
|
+
attr_accessor :object_id
|
20
|
+
attr_accessor :entries
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@attributes ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.extract_all
|
27
|
+
page_id = PAGES[:first]
|
28
|
+
pages = Pages.new
|
29
|
+
|
30
|
+
image.seek(page_id * PAGE_SIZE)
|
31
|
+
while contents = image.read(PAGE_SIZE)
|
32
|
+
# only pull out metadata pages currently
|
33
|
+
extracted_id = id_from_contents(contents)
|
34
|
+
is_metadata = extracted_id == page_id
|
35
|
+
pages[page_id] = Page.parse(page_id, contents) if is_metadata
|
36
|
+
page_id += 1
|
37
|
+
end
|
38
|
+
|
39
|
+
pages
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.id_from_contents(contents)
|
43
|
+
contents.unpack('S').first
|
44
|
+
end
|
45
|
+
|
46
|
+
def offset
|
47
|
+
id * PAGE_SIZE
|
48
|
+
end
|
49
|
+
|
50
|
+
def attr_start
|
51
|
+
offset + ADDRESSES[:first_attr]
|
52
|
+
end
|
53
|
+
|
54
|
+
def root?
|
55
|
+
virtual_page_number == PAGES[:root]
|
56
|
+
end
|
57
|
+
|
58
|
+
def object_table?
|
59
|
+
virtual_page_number == PAGES[:object_table]
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.parse(id, contents)
|
63
|
+
store_pos
|
64
|
+
|
65
|
+
page = new
|
66
|
+
page.id = id
|
67
|
+
page.contents = contents
|
68
|
+
|
69
|
+
image.seek(page.offset + ADDRESSES[:page_sequence])
|
70
|
+
page.sequence = image.read(4).unpack('L').first
|
71
|
+
|
72
|
+
image.seek(page.offset + ADDRESSES[:virtual_page_number])
|
73
|
+
page.virtual_page_number = image.read(4).unpack('L').first
|
74
|
+
|
75
|
+
unless page.root? || page.object_table?
|
76
|
+
# TODO:
|
77
|
+
#page.parse_attributes
|
78
|
+
#page.parse_metadata
|
79
|
+
end
|
80
|
+
|
81
|
+
restore_pos
|
82
|
+
|
83
|
+
page
|
84
|
+
end
|
85
|
+
|
86
|
+
def has_attributes?
|
87
|
+
!@attributes.nil? && !@attributes.empty?
|
88
|
+
end
|
89
|
+
|
90
|
+
def parse_attributes
|
91
|
+
image.seek(attr_start)
|
92
|
+
while true
|
93
|
+
attr = Attribute.read
|
94
|
+
break if attr.empty?
|
95
|
+
@attributes << attr
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def parse_metadata
|
100
|
+
@object_id = @attributes.first.unpack("C*")[ADDRESSES[:object_id]]
|
101
|
+
@entries = @attributes.first.unpack("C*")[ADDRESSES[:num_objects]]
|
102
|
+
end
|
103
|
+
end # class Page
|
104
|
+
end # module Resilience
|