# ---- iso9660recover.pl - Win32 version
# Written by bitshiftleft for perlmonks.org
# Automate recovery of an entire data cdrom
# using Kris Kaspersky's RAW_TOC_READ.exe and ISO9660.dir.exe utility.
# Written for personal use and to answer the challenge on page 399 of
+the
# book "CD Cracking Uncovered", ISBN:1-931769-33-8
# BUGS: 1)Some recovered files belong to to parent directory - might c
+ross ref Joliet with iso9660 to verify
# 2)Extra character on subdirectory names
# ------- -----
use File::Path;
my @TOC;
my @TOCJoliet;
my $NS =0;
my %fileexists;
open(RAW_TOC,"RAW_TOC_READ.exe \\\\.\\D: 0|") || die "RAW_TOC_READ.exe
+ $!";
@TOC = <RAW_TOC>;
close RAW_TOC;
for ($i = 0; $i < 2; ++$i){ shift @TOC }; # trim header info
print " ------ TOC ------\n";
print @TOC;
foreach $session (@TOC){
last if $session eq "\n";
(undef, undef, $track,undef,$LBA1,$LBA2,$LBA3,$LBA4)=split(" ",$sessi
+on);
$StartLBA = hex($LBA1 .$LBA2 . $LBA3 .$LBA4);
chomp $StartLBA;
printf "Reading track %02X",hex($track);
open(ISODIR,"ISO9660.dir.exe \\\\.\\D: $StartLBA -Joliet|") || die "I
+SO9660.dir.exe $StartLBA -Joliet \n$!";
my @filenames = <ISODIR>;
for ($i = 0; $i < 6; ++$i){$l = shift @filenames; if ($l =~ /NOT/){ $
+NS = 1;} }; # trim header info
push @TOCJoliet, \@filenames;
close ISODIR;
print " Dirs/Files found: ",scalar(@filenames),":$NS\n";
if($NS){$NS = 0;};
# print @filenames;
# last if hex($track) == 3; for debugging this code
}
print "Retreiving files and directories....\n\n";
# ------- first reconstruct the directory tree ---
foreach $index (0 .. $#TOCJoliet){
my @files = @{$TOCJoliet[$index]};
next if $#files == -1;
foreach $ii (0 .. $#files){
($lba1,$size1,$name1 ) = split(" ", $files[$ii]);
$name1 = substr ($files[$ii],22); # in case there are spaces in th
+e subdir name
chomp $name1;
if ($ii == 0){
($lba2,$size2,$name2 ) = split(" ", $files[$ii+1]);
$name2 = substr ($files[$ii+1],22); # in case there are spaces in
+the subdir name
chomp $name2;
if ($lba1 == $lba2 && $name1 eq '.' && $name2 eq '..'){$dirtree{$l
+ba1} = 'root/'};
$activedir = $dirtree{$lba1};
if (! -d "$activedir"){mkpath($activedir,0,0777) ;}
}
next if ($name1 eq '.' or $name1 eq '..');
($lba2,$size2,$name2 ) = split(" ", $files[$ii+1]);
$name2 = substr ($files[$ii+1],22,); # in case there are spaces in
+the subdir name
chomp $name2;
if($name2 eq '.') { # ----- we have a subdirectory
($lba3,$size3,$name3 ) = split(" ", $files[$ii+2]); # get parent di
+r
# ---- now remove filename special characters, - needed for wprintf bu
+g ----
$name1 =~ s/(\=|\/|\[|\]|\"|\:|\;|\,|\?|\*|\<|\>|\|)$//g;
$dirtree{$lba1} = $dirtree{$lba3} . $name1 . '/';
$activedir = $dirtree{$lba1};
if (! -d "$activedir"){ mkpath("$activedir",0,0777) ;}
substr $files[$ii],22,0,$dirtree{$lba3}
} else { # ----- we have a file
substr $files[$ii],22,0,$activedir; # prepend full path
$files[$ii] =~ s/\;.*$//; # trim the filename ending
+s
}
}
push @cddirtree, \@files;
# print @files;
}
@TOCJoliet = (); # memory management - cleanup
foreach $index (0 .. $#cddirtree){
# next unless $index > 0x26;
my @files = @{$cddirtree[$index]};
foreach $ii (0 .. $#files){
($lba1,$size1,$name1 ) = split(" ", $files[$ii]);
($lba2,$size2,$name2 ) = split(" ", $files[$ii+1]);
next if $name2 eq '|.';
next if ($name1 eq '|.' or $name1 eq '|..');
$f = substr ($files[$ii],22);
chomp $f;
$size = substr($size1,1);
if (! exists($filexists{$lba1})){ # no need to recover same file
+from previous session
++$filexists{$lba1};
print "Recovering: \"$f\" \n";
# might need line continuations here very for long command lines
+(xargs for windows?)
system("ISO9660.dir.exe \\\\.\\D: \"$f\" $lba1 $size") && die "IS
+O9660.dir.exe: $!";
}
}
}
|