Blame SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch

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