Restore files from a Windows Restore Point
From KnowWiki
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; }