Restore files from a Windows Restore Point

This script allows you to restore arbitrary files from a Windows restore point. Mount a drive with the restore point in question from a failed machine to a working machine and run the following perl script.

Here is it's counterpart: Analyze and Display Windows restore point information

#!/bin/perl
# this code will parse up the Windows Restore point information and roll back the files
# it will not roll back the registry - you have to do it manually
use warnings;
use Switch;
use IO::Seekable qw(SEEK_SET SEEK_CUR SEEK_END);
use File::Copy;

$dir=shift;
defined ($dir) || die "Just give me a folder like C:\\System Volume Information\\_restore{...}\\RP28 as a parameter and I will do the rest\n";
$|=1; # autoflush stdio

opendir(DIR, "$dir") || die "cant open $dir";
mkdir "$dir/rollback";
open (R,">>$dir/rollback/rollback.sh")|| die "can't create rollback";
print R "#!/bin/bash\n";
my @entities=grep(/change\.log.*/i, readdir DIR);
foreach my $entity (@entities) {
print "Processing $entity...\n";
open (F,"$dir/$entity") || die "$dir/$entity";

$i=0;
while (sysread(F,$temp,4) != 0){
  $len=unpack("l",$temp);
  sysread(F,$temp,4);
  $type=unpack("l",$temp);
  sysread(F,$temp,4);
  $sig=unpack("h8",$temp);
  if ($sig ne "21fedcba"){
    print "invalid signature $sig\n";
    exit 1;
  }
  sysread(F,$payload,$len-16);
  sysseek(F,4,1);
  if ($type == 1){ # file name
    $changetype=unpack("l",substr($payload,0,4));
    $changename="!unknown";
    switch ($changetype){
        case 0x00000001 {$changename= "Modify File      "}
        case 0x00000002 {$changename= "Update ACL       "}
        case 0x00000004 {$changename= "Update Attributes"}
        case 0x00000010 {$changename= "Delete File      "}
        case 0x00000020 {$changename= "Create File      "}
        case 0x00000040 {$changename= "Rename File      "}
        case 0x00000080 {$changename= "Create directory "}
        case 0x00000100 {$changename= "Rename directory "}
        case 0x00000200 {$changename= "Delete directory "}
        case 0x00000400 {$changename= "MNT-CREATE"}
    }
#   $flags=unpack("h8",substr($payload,4,4));
#   $attributes=unpack("h8",substr($payload,8,4));
#   $eventid=unpack("l",substr($payload,12,4));
    if ($changetype == 0x00000001 || $changetype==0x00000010){
    $offset=52;
    $j=0;
    $orig="";
    $back="";
    while ($offset < $len-16){
        $fieldlen=unpack("l",substr($payload,$offset,4));
        if ($fieldlen==0) {
            print "fieldlength is 0";
            exit 1;
        }
        $fieldtype=unpack("l",substr($payload,$offset+4,4));
        $field=substr($payload,$offset+8,$fieldlen-8);
        $orig=unidecode($field) if ($fieldtype == 0x00000003);
        $back=unidecode($field) if ($fieldtype == 0x00000005);
#           switch ($fieldtype){
#               case 0x00000003 {print "long original filename"}
#               case 0x00000004 {print "long new filename     "}
#               case 0x00000005 {print "backup filename       "}
#               case 0x00000006 {print "ACL                   "}
#               case 0x00000009 {print "short orig filename   "}
#               case 0x0000000A {print "short new filename    "}
#           }
        $offset+=$fieldlen;
        $j++;
    }
    if ($orig =~ /^\\WINDOWS/){ # filter only needed stuff
        if ($orig ne "" && $back ne ""){
            $orig =~ s/\\/\//g;
            $orig = "/media/sda1".$orig;
            if (-e $orig) { # if file exists
                print "Replacing $orig with $dir/$back...\n";
                if (-e "$dir/rollback/$back"){
                    print "Backup $dir/rollback/$back already exists, refuse to overwrite\n";
                    print R "cp \"$dir/rollback/$back\" \"$orig\"\n";
                } else {
                    copy("$orig","$dir/rollback/$back");#|| print "Cant copy $orig to $dir/rollback/$back";
                    copy("$dir/$back","$orig");# || print "Cant copy $dir/$back to $orig";
                    print R "cp \"$dir/rollback/$back\" \"$orig\"\n";
                }
            } else {
                print "Restoring $orig from $dir/$back...\n";
                copy("$dir/$back","$orig");# || print "Cant copy $dir/$back to $orig";
                print R "rm \"$orig\"\n";
            }
        } else {
            print "Missing information: op:$changename orig=$orig, back=$back\n";
        }
    } else {
        print "Skipping nonessential: op:$changename orig=$orig, back=$back\n";
    }
    }
}
$i++;
}
close (F);
}
close (R);

sub unidecode {
    $data=shift;
    $off=0;
    $result="";
    while ($off < length($data) && (substr($data,$off,1) ne "\0")){
        $result.=substr($data,$off,1);
        $off+=2;
#       print substr($data,$offset,1)."-".$offset."\n";
    }
    $result;
}

@Tools @Windows




Backlinks: iamhow.com:Tools and Scripts:Analyze and Display Windows restore point information