|
|
3d1215 |
From 362d5cd9b6527e4f9d3a3729afbe7cd90486c39d Mon Sep 17 00:00:00 2001
|
|
|
3d1215 |
From: Dawid Zamirski <dzamirski@datto.com>
|
|
|
3d1215 |
Date: Thu, 16 Feb 2017 18:17:26 -0500
|
|
|
3d1215 |
Subject: [PATCH 12/12] hivexregedit: allow to pass HIVEX_OPEN_UNSAFE
|
|
|
3d1215 |
|
|
|
3d1215 |
via new --unsafe flag. Also make --export catpure, log and skip over
|
|
|
3d1215 |
errors when reading subkeys/values so that export in unsafe mode does
|
|
|
3d1215 |
not abort at first sign of error.
|
|
|
3d1215 |
|
|
|
3d1215 |
(cherry picked from commit 2610b1e089fa84d294f9925342929e3d7408c35b)
|
|
|
3d1215 |
---
|
|
|
3d1215 |
perl/lib/Win/Hivex/Regedit.pm | 59 ++++++++++++++++++++++++++++++++++++++-----
|
|
|
3d1215 |
regedit/hivexregedit | 20 ++++++++++++---
|
|
|
3d1215 |
2 files changed, 70 insertions(+), 9 deletions(-)
|
|
|
3d1215 |
|
|
|
3d1215 |
diff --git a/perl/lib/Win/Hivex/Regedit.pm b/perl/lib/Win/Hivex/Regedit.pm
|
|
|
3d1215 |
index 8914f9e..355699e 100644
|
|
|
3d1215 |
--- a/perl/lib/Win/Hivex/Regedit.pm
|
|
|
3d1215 |
+++ b/perl/lib/Win/Hivex/Regedit.pm
|
|
|
3d1215 |
@@ -67,7 +67,7 @@ package Win::Hivex::Regedit;
|
|
|
3d1215 |
use strict;
|
|
|
3d1215 |
use warnings;
|
|
|
3d1215 |
|
|
|
3d1215 |
-use Carp qw(croak confess);
|
|
|
3d1215 |
+use Carp qw(croak carp confess);
|
|
|
3d1215 |
use Encode qw(encode decode);
|
|
|
3d1215 |
|
|
|
3d1215 |
require Exporter;
|
|
|
3d1215 |
@@ -528,19 +528,51 @@ sub reg_export_node
|
|
|
3d1215 |
print $fh "]\n";
|
|
|
3d1215 |
|
|
|
3d1215 |
my $unsafe_printable_strings = $params{unsafe_printable_strings};
|
|
|
3d1215 |
+ my $unsafe = $params{unsafe};
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+ my @values;
|
|
|
3d1215 |
+ my @safe_values;
|
|
|
3d1215 |
|
|
|
3d1215 |
# Get the values.
|
|
|
3d1215 |
- my @values = $h->node_values ($node);
|
|
|
3d1215 |
+ if ($unsafe) {
|
|
|
3d1215 |
+ my $have_vals = 0;
|
|
|
3d1215 |
+ eval {
|
|
|
3d1215 |
+ @values = $h->node_values ($node);
|
|
|
3d1215 |
+ $have_vals = 1;
|
|
|
3d1215 |
+ };
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+ if (!$have_vals) {
|
|
|
3d1215 |
+ carp "Failed to read node values at $path";
|
|
|
3d1215 |
+ }
|
|
|
3d1215 |
+ } else {
|
|
|
3d1215 |
+ @values = $h->node_values ($node);
|
|
|
3d1215 |
+ }
|
|
|
3d1215 |
|
|
|
3d1215 |
foreach (@values) {
|
|
|
3d1215 |
use bytes;
|
|
|
3d1215 |
|
|
|
3d1215 |
my $key = $h->value_key ($_);
|
|
|
3d1215 |
- my ($type, $data) = $h->value_value ($_);
|
|
|
3d1215 |
- $_ = { key => $key, type => $type, data => $data }
|
|
|
3d1215 |
+ my ($type, $data);
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+ if ($unsafe) {
|
|
|
3d1215 |
+ my $val_ok = 0;
|
|
|
3d1215 |
+ eval {
|
|
|
3d1215 |
+ ($type, $data) = $h->value_value ($_);
|
|
|
3d1215 |
+ $val_ok = 1;
|
|
|
3d1215 |
+ };
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+ if (!$val_ok) {
|
|
|
3d1215 |
+ carp "skipping unreadable value of key: $key in $path";
|
|
|
3d1215 |
+ next;
|
|
|
3d1215 |
+ }
|
|
|
3d1215 |
+ } else {
|
|
|
3d1215 |
+ ($type, $data) = $h->value_value ($_);
|
|
|
3d1215 |
+ }
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+ push @safe_values, { key => $key, type => $type, data => $data };
|
|
|
3d1215 |
}
|
|
|
3d1215 |
|
|
|
3d1215 |
- @values = sort { $a->{key} cmp $b->{key} } @values;
|
|
|
3d1215 |
+ @values = sort { $a->{key} cmp $b->{key} } @safe_values;
|
|
|
3d1215 |
|
|
|
3d1215 |
# Print the values.
|
|
|
3d1215 |
foreach (@values) {
|
|
|
3d1215 |
@@ -573,7 +605,22 @@ sub reg_export_node
|
|
|
3d1215 |
}
|
|
|
3d1215 |
print $fh "\n";
|
|
|
3d1215 |
|
|
|
3d1215 |
- my @children = $h->node_children ($node);
|
|
|
3d1215 |
+ my @children;
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+ if ($unsafe) {
|
|
|
3d1215 |
+ my $have_children = 0;
|
|
|
3d1215 |
+ eval {
|
|
|
3d1215 |
+ @children = $h->node_children ($node);
|
|
|
3d1215 |
+ $have_children = 1;
|
|
|
3d1215 |
+ };
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+ if (!$have_children) {
|
|
|
3d1215 |
+ carp "Could not get children of $path";
|
|
|
3d1215 |
+ }
|
|
|
3d1215 |
+ } else {
|
|
|
3d1215 |
+ @children = $h->node_children ($node);
|
|
|
3d1215 |
+ }
|
|
|
3d1215 |
+
|
|
|
3d1215 |
@children = sort { $h->node_name ($a) cmp $h->node_name ($b) } @children;
|
|
|
3d1215 |
reg_export_node ($h, $_, $fh, @_) foreach @children;
|
|
|
3d1215 |
}
|
|
|
3d1215 |
diff --git a/regedit/hivexregedit b/regedit/hivexregedit
|
|
|
3d1215 |
index 0e534de..aa0ee6e 100755
|
|
|
3d1215 |
--- a/regedit/hivexregedit
|
|
|
3d1215 |
+++ b/regedit/hivexregedit
|
|
|
3d1215 |
@@ -252,6 +252,17 @@ into another program or stored in another hive.
|
|
|
3d1215 |
|
|
|
3d1215 |
=cut
|
|
|
3d1215 |
|
|
|
3d1215 |
+my $unsafe;
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+=item B<--unsafe>
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+Use heuristics to tolerate certain levels of corruption within hives.
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+This is unsafe but may allow to export/merge valid keys/values in an
|
|
|
3d1215 |
+othewise corrupted hive.
|
|
|
3d1215 |
+
|
|
|
3d1215 |
+=cut
|
|
|
3d1215 |
+
|
|
|
3d1215 |
GetOptions ("help|?" => \$help,
|
|
|
3d1215 |
"debug" => \$debug,
|
|
|
3d1215 |
"merge|import" => \$merge,
|
|
|
3d1215 |
@@ -259,6 +270,7 @@ GetOptions ("help|?" => \$help,
|
|
|
3d1215 |
"prefix=s" => \$prefix,
|
|
|
3d1215 |
"encoding=s" => \$encoding,
|
|
|
3d1215 |
"unsafe-printable-strings" => \$unsafe_printable_strings,
|
|
|
3d1215 |
+ "unsafe" => \$unsafe,
|
|
|
3d1215 |
) or pod2usage (2);
|
|
|
3d1215 |
pod2usage (1) if $help;
|
|
|
3d1215 |
|
|
|
3d1215 |
@@ -281,7 +293,8 @@ if ($merge) { # --merge (reg_import)
|
|
|
3d1215 |
|
|
|
3d1215 |
my $hivefile = shift @ARGV;
|
|
|
3d1215 |
|
|
|
3d1215 |
- my $h = Win::Hivex->open ($hivefile, write => 1, debug => $debug);
|
|
|
3d1215 |
+ my $h = Win::Hivex->open ($hivefile, write => 1, debug => $debug,
|
|
|
3d1215 |
+ unsafe => $unsafe);
|
|
|
3d1215 |
|
|
|
3d1215 |
# Read from stdin unless other files have been specified.
|
|
|
3d1215 |
unshift (@ARGV, '-') unless @ARGV;
|
|
|
3d1215 |
@@ -312,13 +325,14 @@ if ($merge) { # --merge (reg_import)
|
|
|
3d1215 |
my $hivefile = shift @ARGV;
|
|
|
3d1215 |
my $key = shift @ARGV;
|
|
|
3d1215 |
|
|
|
3d1215 |
- my $h = Win::Hivex->open ($hivefile, debug => $debug);
|
|
|
3d1215 |
+ my $h = Win::Hivex->open ($hivefile, debug => $debug, unsafe => $unsafe);
|
|
|
3d1215 |
|
|
|
3d1215 |
print "Windows Registry Editor Version 5.00\n\n";
|
|
|
3d1215 |
|
|
|
3d1215 |
reg_export ($h, $key, \*STDOUT,
|
|
|
3d1215 |
prefix => $prefix,
|
|
|
3d1215 |
- unsafe_printable_strings => $unsafe_printable_strings);
|
|
|
3d1215 |
+ unsafe_printable_strings => $unsafe_printable_strings,
|
|
|
3d1215 |
+ unsafe => $unsafe);
|
|
|
3d1215 |
}
|
|
|
3d1215 |
|
|
|
3d1215 |
=head1 SEE ALSO
|
|
|
3d1215 |
--
|
|
|
3d1215 |
1.8.3.1
|
|
|
3d1215 |
|