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