| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Parse::Win32Registry::WinNT::Value; |
|
2
|
|
|
|
|
|
|
|
|
3
|
13
|
|
|
13
|
|
90
|
use strict; |
|
|
13
|
|
|
|
|
31
|
|
|
|
13
|
|
|
|
|
371
|
|
|
4
|
13
|
|
|
13
|
|
67
|
use warnings; |
|
|
13
|
|
|
|
|
36
|
|
|
|
13
|
|
|
|
|
345
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
13
|
|
|
13
|
|
68
|
use base qw(Parse::Win32Registry::Value); |
|
|
13
|
|
|
|
|
23
|
|
|
|
13
|
|
|
|
|
1295
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
13
|
|
|
13
|
|
90
|
use Carp; |
|
|
13
|
|
|
|
|
45
|
|
|
|
13
|
|
|
|
|
814
|
|
|
9
|
13
|
|
|
13
|
|
111
|
use Encode; |
|
|
13
|
|
|
|
|
29
|
|
|
|
13
|
|
|
|
|
1021
|
|
|
10
|
13
|
|
|
13
|
|
145
|
use Parse::Win32Registry::Base qw(:all); |
|
|
13
|
|
|
|
|
28
|
|
|
|
13
|
|
|
|
|
2842
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
13
|
|
|
13
|
|
97
|
use constant VK_HEADER_LENGTH => 0x18; |
|
|
13
|
|
|
|
|
27
|
|
|
|
13
|
|
|
|
|
902
|
|
|
13
|
13
|
|
|
13
|
|
92
|
use constant OFFSET_TO_FIRST_HBIN => 0x1000; |
|
|
13
|
|
|
|
|
34
|
|
|
|
13
|
|
|
|
|
20642
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub new { |
|
16
|
6124
|
|
|
6124
|
0
|
9592
|
my $class = shift; |
|
17
|
6124
|
|
|
|
|
8734
|
my $regfile = shift; |
|
18
|
6124
|
|
|
|
|
8795
|
my $offset = shift; # offset to vk record relative to first hbin |
|
19
|
|
|
|
|
|
|
|
|
20
|
6124
|
50
|
|
|
|
11314
|
croak 'Missing registry file' if !defined $regfile; |
|
21
|
6124
|
50
|
|
|
|
9933
|
croak 'Missing offset' if !defined $offset; |
|
22
|
|
|
|
|
|
|
|
|
23
|
6124
|
|
|
|
|
15843
|
my $fh = $regfile->get_filehandle; |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# 0x00 dword = value length (negative = allocated) |
|
26
|
|
|
|
|
|
|
# 0x04 word = 'vk' signature |
|
27
|
|
|
|
|
|
|
# 0x06 word = value name length |
|
28
|
|
|
|
|
|
|
# 0x08 dword = value data length (bit 31 set => data stored inline) |
|
29
|
|
|
|
|
|
|
# 0x0c dword = offset to data/inline data |
|
30
|
|
|
|
|
|
|
# 0x10 dword = value type |
|
31
|
|
|
|
|
|
|
# 0x14 word = flags (bit 1 set => compressed name) |
|
32
|
|
|
|
|
|
|
# 0x16 word |
|
33
|
|
|
|
|
|
|
# 0x18 = value name [for value name length bytes] |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# Extracted offsets are always relative to first hbin |
|
36
|
|
|
|
|
|
|
|
|
37
|
6124
|
|
|
|
|
35542
|
sysseek($fh, $offset, 0); |
|
38
|
6124
|
|
|
|
|
45547
|
my $bytes_read = sysread($fh, my $vk_header, VK_HEADER_LENGTH); |
|
39
|
6124
|
100
|
|
|
|
16370
|
if ($bytes_read != VK_HEADER_LENGTH) { |
|
40
|
1
|
|
|
|
|
5
|
warnf('Could not read value at 0x%x', $offset); |
|
41
|
1
|
|
|
|
|
16
|
return; |
|
42
|
|
|
|
|
|
|
} |
|
43
|
|
|
|
|
|
|
|
|
44
|
6123
|
|
|
|
|
27958
|
my ($length, |
|
45
|
|
|
|
|
|
|
$sig, |
|
46
|
|
|
|
|
|
|
$name_length, |
|
47
|
|
|
|
|
|
|
$data_length, |
|
48
|
|
|
|
|
|
|
$offset_to_data, |
|
49
|
|
|
|
|
|
|
$type, |
|
50
|
|
|
|
|
|
|
$flags, |
|
51
|
|
|
|
|
|
|
) = unpack('Va2vVVVv', $vk_header); |
|
52
|
|
|
|
|
|
|
|
|
53
|
6123
|
|
|
|
|
11846
|
my $allocated = 0; |
|
54
|
6123
|
50
|
|
|
|
11198
|
if ($length > 0x7fffffff) { |
|
55
|
6123
|
|
|
|
|
9121
|
$allocated = 1; |
|
56
|
6123
|
|
|
|
|
10046
|
$length = (0xffffffff - $length) + 1; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
# allocated should be true |
|
59
|
|
|
|
|
|
|
|
|
60
|
6123
|
50
|
|
|
|
10978
|
if ($length < VK_HEADER_LENGTH) { |
|
61
|
0
|
|
|
|
|
0
|
warnf('Invalid value entry length at 0x%x', $offset); |
|
62
|
0
|
|
|
|
|
0
|
return; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
|
|
65
|
6123
|
100
|
|
|
|
12430
|
if ($sig ne 'vk') { |
|
66
|
1
|
|
|
|
|
6
|
warnf('Invalid signature for value at 0x%x', $offset); |
|
67
|
1
|
|
|
|
|
16
|
return; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
6122
|
|
|
|
|
37085
|
$bytes_read = sysread($fh, my $name, $name_length); |
|
71
|
6122
|
100
|
|
|
|
16932
|
if ($bytes_read != $name_length) { |
|
72
|
1
|
|
|
|
|
5
|
warnf('Could not read name for value at 0x%x', $offset); |
|
73
|
1
|
|
|
|
|
26
|
return; |
|
74
|
|
|
|
|
|
|
} |
|
75
|
|
|
|
|
|
|
|
|
76
|
6121
|
100
|
|
|
|
11745
|
if ($flags & 1) { |
|
77
|
6015
|
|
|
|
|
18274
|
$name = decode($Parse::Win32Registry::Base::CODEPAGE, $name); |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
else { |
|
80
|
106
|
|
|
|
|
342
|
$name = decode('UCS-2LE', $name); |
|
81
|
|
|
|
|
|
|
}; |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# If the top bit of the data_length is set, then |
|
84
|
|
|
|
|
|
|
# the value is inline and stored in the offset to data field (at 0xc). |
|
85
|
6121
|
|
|
|
|
181863
|
my $data; |
|
86
|
6121
|
|
|
|
|
10932
|
my $data_inline = $data_length >> 31; |
|
87
|
6121
|
100
|
|
|
|
10549
|
if ($data_inline) { |
|
88
|
|
|
|
|
|
|
# REG_DWORDs are always inline, but I've also seen |
|
89
|
|
|
|
|
|
|
# REG_SZ, REG_BINARY, REG_EXPAND_SZ, and REG_NONE inline |
|
90
|
3194
|
|
|
|
|
4863
|
$data_length &= 0x7fffffff; |
|
91
|
3194
|
100
|
|
|
|
5478
|
if ($data_length > 4) { |
|
92
|
425
|
|
|
|
|
1230
|
warnf("Invalid inline data length for value '%s' at 0x%x", |
|
93
|
|
|
|
|
|
|
$name, $offset); |
|
94
|
425
|
|
|
|
|
653
|
$data = undef; |
|
95
|
|
|
|
|
|
|
} |
|
96
|
|
|
|
|
|
|
else { |
|
97
|
|
|
|
|
|
|
# unpack inline data from header |
|
98
|
2769
|
|
|
|
|
5751
|
$data = substr($vk_header, 0xc, $data_length); |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
else { |
|
102
|
2927
|
50
|
33
|
|
|
10118
|
if ($offset_to_data != 0 && $offset_to_data != 0xffffffff) { |
|
103
|
2927
|
|
|
|
|
4372
|
$offset_to_data += OFFSET_TO_FIRST_HBIN; |
|
104
|
2927
|
100
|
|
|
|
8616
|
if ($offset_to_data < ($regfile->get_length - $data_length)) { |
|
105
|
2926
|
|
|
|
|
5774
|
$data = _extract_data($fh, $offset_to_data, $data_length); |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
else { |
|
108
|
1
|
|
|
|
|
4
|
warnf("Invalid offset to data for value '%s' at 0x%x", |
|
109
|
|
|
|
|
|
|
$name, $offset); |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
|
|
114
|
6121
|
|
|
|
|
11148
|
my $self = {}; |
|
115
|
6121
|
|
|
|
|
13365
|
$self->{_regfile} = $regfile; |
|
116
|
6121
|
|
|
|
|
9997
|
$self->{_offset} = $offset; |
|
117
|
6121
|
|
|
|
|
9834
|
$self->{_length} = $length; |
|
118
|
6121
|
|
|
|
|
9471
|
$self->{_allocated} = $allocated; |
|
119
|
6121
|
|
|
|
|
10674
|
$self->{_tag} = $sig; |
|
120
|
6121
|
|
|
|
|
9791
|
$self->{_name} = $name; |
|
121
|
6121
|
|
|
|
|
9075
|
$self->{_name_length} = $name_length; |
|
122
|
6121
|
|
|
|
|
13770
|
$self->{_type} = $type; |
|
123
|
6121
|
|
|
|
|
10157
|
$self->{_data} = $data; |
|
124
|
6121
|
|
|
|
|
9132
|
$self->{_data_length} = $data_length; |
|
125
|
6121
|
|
|
|
|
9427
|
$self->{_data_inline} = $data_inline; |
|
126
|
6121
|
|
|
|
|
9410
|
$self->{_offset_to_data} = $offset_to_data; |
|
127
|
6121
|
|
|
|
|
9686
|
$self->{_flags} = $flags; |
|
128
|
6121
|
|
|
|
|
10039
|
bless $self, $class; |
|
129
|
|
|
|
|
|
|
|
|
130
|
6121
|
|
|
|
|
17047
|
return $self; |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub _extract_data { |
|
134
|
2926
|
|
|
2926
|
|
4083
|
my $fh = shift; |
|
135
|
2926
|
|
|
|
|
4361
|
my $offset_to_data = shift; |
|
136
|
2926
|
|
|
|
|
4023
|
my $data_length = shift; |
|
137
|
|
|
|
|
|
|
|
|
138
|
2926
|
50
|
33
|
|
|
8991
|
if ($offset_to_data == 0 || $offset_to_data == 0xffffffff) { |
|
139
|
0
|
|
|
|
|
0
|
return undef; |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
2926
|
|
|
|
|
16452
|
sysseek($fh, $offset_to_data, 0); |
|
143
|
2926
|
|
|
|
|
21653
|
my $bytes_read = sysread($fh, my $data_header, 4); |
|
144
|
2926
|
50
|
|
|
|
7567
|
if ($bytes_read != 4) { |
|
145
|
0
|
|
|
|
|
0
|
warnf('Could not read data at 0x%x', $offset_to_data); |
|
146
|
0
|
|
|
|
|
0
|
return undef; |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
2926
|
|
|
|
|
8017
|
my ($max_data_length) = unpack('V', $data_header); |
|
150
|
|
|
|
|
|
|
|
|
151
|
2926
|
|
|
|
|
4755
|
my $data_allocated = 0; |
|
152
|
2926
|
50
|
|
|
|
5642
|
if ($max_data_length > 0x7fffffff) { |
|
153
|
2926
|
|
|
|
|
4700
|
$data_allocated = 1; |
|
154
|
2926
|
|
|
|
|
4996
|
$max_data_length = (0xffffffff - $max_data_length) + 1; |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
# data_allocated should be true |
|
157
|
|
|
|
|
|
|
|
|
158
|
2926
|
|
|
|
|
4135
|
my $data; |
|
159
|
|
|
|
|
|
|
|
|
160
|
2926
|
50
|
|
|
|
5050
|
if ($data_length > $max_data_length) { |
|
161
|
0
|
|
|
|
|
0
|
$bytes_read = sysread($fh, my $db_entry, 8); |
|
162
|
0
|
0
|
|
|
|
0
|
if ($bytes_read != 8) { |
|
163
|
0
|
|
|
|
|
0
|
warnf('Could not read data at 0x%x', $offset_to_data); |
|
164
|
0
|
|
|
|
|
0
|
return undef; |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
|
|
167
|
0
|
|
|
|
|
0
|
my ($sig, $num_data_blocks, $offset_to_data_block_list) |
|
168
|
|
|
|
|
|
|
= unpack('a2vV', $db_entry); |
|
169
|
0
|
0
|
|
|
|
0
|
if ($sig ne 'db') { |
|
170
|
0
|
|
|
|
|
0
|
warnf('Invalid signature for big data at 0x%x', $offset_to_data); |
|
171
|
0
|
|
|
|
|
0
|
return undef; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
0
|
|
|
|
|
0
|
$offset_to_data_block_list += OFFSET_TO_FIRST_HBIN; |
|
174
|
|
|
|
|
|
|
|
|
175
|
0
|
|
|
|
|
0
|
sysseek($fh, $offset_to_data_block_list + 4, 0); |
|
176
|
0
|
|
|
|
|
0
|
$bytes_read = sysread($fh, my $data_block_list, $num_data_blocks * 4); |
|
177
|
0
|
0
|
|
|
|
0
|
if ($bytes_read != $num_data_blocks * 4) { |
|
178
|
0
|
|
|
|
|
0
|
warnf('Could not read data block list at 0x%x', |
|
179
|
|
|
|
|
|
|
$offset_to_data_block_list); |
|
180
|
0
|
|
|
|
|
0
|
return undef; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
|
|
183
|
0
|
|
|
|
|
0
|
$data = ""; |
|
184
|
0
|
|
|
|
|
0
|
my @offsets = map { OFFSET_TO_FIRST_HBIN + $_ } |
|
|
0
|
|
|
|
|
0
|
|
|
185
|
|
|
|
|
|
|
unpack("V$num_data_blocks", $data_block_list); |
|
186
|
0
|
|
|
|
|
0
|
foreach my $offset (@offsets) { |
|
187
|
0
|
|
|
|
|
0
|
sysseek($fh, $offset, 0); |
|
188
|
0
|
|
|
|
|
0
|
$bytes_read = sysread($fh, my $block_header, 4); |
|
189
|
0
|
0
|
|
|
|
0
|
if ($bytes_read != 4) { |
|
190
|
0
|
|
|
|
|
0
|
warnf('Could not read data block at 0x%x', $offset); |
|
191
|
0
|
|
|
|
|
0
|
return undef; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
0
|
|
|
|
|
0
|
my ($block_length) = unpack('V', $block_header); |
|
194
|
0
|
0
|
|
|
|
0
|
if ($block_length > 0x7fffffff) { |
|
195
|
0
|
|
|
|
|
0
|
$block_length = (0xffffffff - $block_length) + 1; |
|
196
|
|
|
|
|
|
|
} |
|
197
|
0
|
|
|
|
|
0
|
$bytes_read = sysread($fh, my $block_data, $block_length - 8); |
|
198
|
0
|
0
|
|
|
|
0
|
if ($bytes_read != $block_length - 8) { |
|
199
|
0
|
|
|
|
|
0
|
warnf('Could not read data block at 0x%x', $offset); |
|
200
|
0
|
|
|
|
|
0
|
return undef; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
0
|
|
|
|
|
0
|
$data .= $block_data; |
|
203
|
|
|
|
|
|
|
} |
|
204
|
0
|
0
|
|
|
|
0
|
if (length($data) < $data_length) { |
|
205
|
0
|
|
|
|
|
0
|
warnf("Insufficient data blocks for data at 0x%x", $offset_to_data); |
|
206
|
0
|
|
|
|
|
0
|
return undef; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
0
|
|
|
|
|
0
|
$data = substr($data, 0, $data_length); |
|
209
|
0
|
|
|
|
|
0
|
return $data; |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
else { |
|
212
|
2926
|
|
|
|
|
18202
|
$bytes_read = sysread($fh, $data, $data_length); |
|
213
|
2926
|
50
|
|
|
|
8123
|
if ($bytes_read != $data_length) { |
|
214
|
0
|
|
|
|
|
0
|
warnf("Could not read data at 0x%x", $offset_to_data); |
|
215
|
0
|
|
|
|
|
0
|
return undef; |
|
216
|
|
|
|
|
|
|
} |
|
217
|
|
|
|
|
|
|
} |
|
218
|
2926
|
|
|
|
|
8079
|
return $data; |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub get_data { |
|
222
|
292
|
|
|
292
|
0
|
1729
|
my $self = shift; |
|
223
|
|
|
|
|
|
|
|
|
224
|
292
|
|
|
|
|
813
|
my $type = $self->get_type; |
|
225
|
|
|
|
|
|
|
|
|
226
|
292
|
|
|
|
|
551
|
my $data = $self->{_data}; |
|
227
|
292
|
100
|
|
|
|
775
|
return if !defined $data; |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# apply decoding to appropriate data types |
|
230
|
281
|
100
|
66
|
|
|
1441
|
if ($type == REG_DWORD) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
231
|
89
|
100
|
|
|
|
210
|
if (length($data) == 4) { |
|
232
|
64
|
|
|
|
|
210
|
$data = unpack('V', $data); |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
else { |
|
235
|
|
|
|
|
|
|
# incorrect length for dword data |
|
236
|
25
|
|
|
|
|
44
|
$data = undef; |
|
237
|
|
|
|
|
|
|
} |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
elsif ($type == REG_DWORD_BIG_ENDIAN) { |
|
240
|
44
|
100
|
|
|
|
111
|
if (length($data) == 4) { |
|
241
|
24
|
|
|
|
|
77
|
$data = unpack('N', $data); |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
else { |
|
244
|
|
|
|
|
|
|
# incorrect length for dword data |
|
245
|
20
|
|
|
|
|
38
|
$data = undef; |
|
246
|
|
|
|
|
|
|
} |
|
247
|
|
|
|
|
|
|
} |
|
248
|
|
|
|
|
|
|
elsif ($type == REG_SZ || $type == REG_EXPAND_SZ) { |
|
249
|
42
|
|
|
|
|
130
|
$data = decode('UCS-2LE', $data); |
|
250
|
|
|
|
|
|
|
# snip off any terminating null |
|
251
|
42
|
100
|
|
|
|
2022
|
chop $data if substr($data, -1, 1) eq "\0"; |
|
252
|
|
|
|
|
|
|
} |
|
253
|
|
|
|
|
|
|
elsif ($type == REG_MULTI_SZ) { |
|
254
|
82
|
|
|
|
|
246
|
$data = decode('UCS-2LE', $data); |
|
255
|
|
|
|
|
|
|
# snip off any terminating nulls |
|
256
|
82
|
100
|
|
|
|
3783
|
chop $data if substr($data, -1, 1) eq "\0"; |
|
257
|
82
|
100
|
|
|
|
229
|
chop $data if substr($data, -1, 1) eq "\0"; |
|
258
|
82
|
|
|
|
|
297
|
my @multi_sz = split("\0", $data, -1); |
|
259
|
|
|
|
|
|
|
# make sure there is at least one empty string |
|
260
|
82
|
100
|
|
|
|
218
|
@multi_sz = ('') if @multi_sz == 0; |
|
261
|
82
|
100
|
|
|
|
930
|
return wantarray ? @multi_sz : join($", @multi_sz); |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
199
|
|
|
|
|
1412
|
return $data; |
|
265
|
|
|
|
|
|
|
} |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub as_regedit_export { |
|
268
|
53
|
|
|
53
|
0
|
135
|
my $self = shift; |
|
269
|
53
|
|
50
|
|
|
228
|
my $version = shift || 5; |
|
270
|
|
|
|
|
|
|
|
|
271
|
53
|
|
|
|
|
171
|
my $name = $self->get_name; |
|
272
|
53
|
100
|
|
|
|
244
|
my $export = $name eq '' ? '@=' : '"' . $name . '"='; |
|
273
|
|
|
|
|
|
|
|
|
274
|
53
|
|
|
|
|
145
|
my $type = $self->get_type; |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
# XXX |
|
277
|
|
|
|
|
|
|
# if (!defined $self->{_data}) { |
|
278
|
|
|
|
|
|
|
# $name = $name eq '' ? '@' : qq{"$name"}; |
|
279
|
|
|
|
|
|
|
# return qq{; $name=(invalid data)\n}; |
|
280
|
|
|
|
|
|
|
# } |
|
281
|
|
|
|
|
|
|
|
|
282
|
53
|
100
|
66
|
|
|
372
|
if ($type == REG_SZ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
283
|
8
|
|
|
|
|
19
|
my $data = $self->get_data; |
|
284
|
8
|
50
|
|
|
|
26
|
$data = '' if !defined($data); |
|
285
|
8
|
|
|
|
|
27
|
$export .= '"' . $data . '"'; |
|
286
|
8
|
|
|
|
|
21
|
$export .= "\n"; |
|
287
|
|
|
|
|
|
|
} |
|
288
|
|
|
|
|
|
|
elsif ($type == REG_BINARY) { |
|
289
|
4
|
|
|
|
|
12
|
$export .= "hex:"; |
|
290
|
4
|
|
|
|
|
22
|
$export .= format_octets($self->{_data}, length($export)); |
|
291
|
|
|
|
|
|
|
} |
|
292
|
|
|
|
|
|
|
elsif ($type == REG_DWORD) { |
|
293
|
16
|
|
|
|
|
45
|
my $data = $self->get_data; |
|
294
|
16
|
100
|
|
|
|
82
|
$export .= defined($data) |
|
295
|
|
|
|
|
|
|
? sprintf("dword:%08x", $data) |
|
296
|
|
|
|
|
|
|
: "dword:"; |
|
297
|
16
|
|
|
|
|
43
|
$export .= "\n"; |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
elsif ($type == REG_EXPAND_SZ || $type == REG_MULTI_SZ) { |
|
300
|
|
|
|
|
|
|
my $data = $version == 4 |
|
301
|
|
|
|
|
|
|
? encode("ascii", $self->{_data}) # unicode->ascii |
|
302
|
12
|
50
|
|
|
|
37
|
: $self->{_data}; # raw data |
|
303
|
12
|
|
|
|
|
64
|
$export .= sprintf("hex(%x):", $type); |
|
304
|
12
|
|
|
|
|
65
|
$export .= format_octets($data, length($export)); |
|
305
|
|
|
|
|
|
|
} |
|
306
|
|
|
|
|
|
|
else { |
|
307
|
13
|
|
|
|
|
76
|
$export .= sprintf("hex(%x):", $type); |
|
308
|
13
|
|
|
|
|
82
|
$export .= format_octets($self->{_data}, length($export)); |
|
309
|
|
|
|
|
|
|
} |
|
310
|
53
|
|
|
|
|
245
|
return $export; |
|
311
|
|
|
|
|
|
|
} |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
sub parse_info { |
|
314
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
my $info = sprintf '0x%x vk len=0x%x alloc=%d "%s" type=%d', |
|
317
|
|
|
|
|
|
|
$self->{_offset}, |
|
318
|
|
|
|
|
|
|
$self->{_length}, |
|
319
|
|
|
|
|
|
|
$self->{_allocated}, |
|
320
|
|
|
|
|
|
|
$self->{_name}, |
|
321
|
0
|
|
|
|
|
|
$self->{_type}; |
|
322
|
0
|
0
|
|
|
|
|
if ($self->{_data_inline}) { |
|
323
|
|
|
|
|
|
|
$info .= sprintf ' data=inline,len=0x%x', |
|
324
|
0
|
|
|
|
|
|
$self->{_data_length}; |
|
325
|
|
|
|
|
|
|
} |
|
326
|
|
|
|
|
|
|
else { |
|
327
|
|
|
|
|
|
|
$info .= sprintf ' data=0x%x,len=0x%x', |
|
328
|
|
|
|
|
|
|
$self->{_offset_to_data}, |
|
329
|
0
|
|
|
|
|
|
$self->{_data_length}; |
|
330
|
|
|
|
|
|
|
} |
|
331
|
0
|
|
|
|
|
|
return $info; |
|
332
|
|
|
|
|
|
|
} |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
1; |