james28909 has asked for the wisdom of the Perl Monks concerning the following question:

UPDATE: FIXED, and it will extract based off of offsets.


I should add MD5 verification to this. Should be easy enough to do!

i have figured it out. i had to change the until loop to stop at =~ "file25", then change the cursor position in the until loop to "0". Now it works great. :) Here is the updated code:
use File::Path qw(make_path); open (my $infile, '<', 'file') or die "cannot open file: $!"; binmode ($infile); make_path ('./extracted');#or die "Failed to create Direcotry: $!"; my $curpos = ''; my $fileLocation = ''; my $fileSize = ''; my $fileName = ''; my $file =''; my $chunk = ''; seek ($infile, 0x10, 0); #GET File Location, File Size, File Name and write to file until ($curpos =~ 0x04c0){ $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileLocation, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileSize, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileName, 0x20); $curpos = tell $infile; $fileLocation =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileSize =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileName =~ s/\0+$//; open($file, '>', "extracted/$fileName") or die "Cannot open $fileName + $!"; binmode($file); sysseek ($infile, hex($fileLocation), 0); sysread ($infile, $chunk, hex($fileSize)); syswrite ($file, $chunk); $fileLocation = ''; $fileSize = ''; };

you can download the file and run the script to try it out if you want. its extracting 25 files based off references in TOC and in 45-50 lines of AS perl. :P
You could possibly extract alot more data with this as long as the references are static. this is very very VERY useful LOL
the actual function is ironically 25 lines lol.

But you could extract a huge amount of data with this, just change the offsets to YOUR OWN references in YOUR OWN FILES TOC.

Wow 9 rep point lol, thanks guys/gals for checking this out :)

Replies are listed 'Best First'.
Re: problem with sysseek in loop
by Laurent_R (Canon) on May 05, 2014 at 17:47 UTC
    Is there any specific reason for using these low level IO functions (such as sysseek and sysread) where it seems to me that read would be simpler to use for what you want to do?

    Update: changed the links to more recent Perl documentation. Thanks to kennethk.

      If i dont use sysseek and sysread, I will get even more errors while trying to name the file. The script almost works i worked on it all morning and now my brain is tired ;(
      it is now working, thanks
      i changed all to seek and read and still getting same problems.
Re: problem with sysseek in loop
by james28909 (Deacon) on May 05, 2014 at 16:19 UTC
      I got it working correctly. I will update OP in a little while :)
      And yes it is faster than my other script lol
      If i can get this to work it will GREATLY reduce the size of my script and possibly speed it up as well ;)
      Otherwise i have to copy and paste the script over and over from the "dynamic extractor" thread.
      no rep love for me ;(
Re: problem with sysseek in loop
by Laurent_R (Canon) on May 06, 2014 at 19:02 UTC
    I would be happy to see what you eventually came up with. Can you show your last code in a new post within this thread (rather than changing your OP)?

      Here you go, its a working script that gets md5 and puts it in a file in "C:\md5.txt"



      use Digest::MD5; use File::Path qw(make_path); open (my $infile, '<', 'file') or die "cannot open file: $!"; binmode ($infile); make_path ('./extracted'); my $curpos = ''; my $fileLocation = ''; my $fileSize = ''; my $fileName = ''; my $file =''; my $chunk = ''; my $exit = ''; #GET File Location, File Size, File Name and write to file seek ($infile, 0x10, 0); until ($exit){ $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileLocation, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileSize, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileName, 0x20); $curpos = tell $infile; if ($fileLocation =~ 'unformatted characters'){ last; } $fileLocation =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileSize =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileName =~ s/\0+$//; if ($fileLocation =~ 'formatted characters'){ last; } #THIS PART ACTUALLY EXTRACTS THE DATA BASED OFF OF OFFSETS open($file, '>', "extracted/$fileName") or die "Cannot open $fileName +$!"; binmode($file); sysseek ($infile, hex($fileLocation), 0); sysread ($infile, $chunk, hex($fileSize)); syswrite ($file, $chunk); $fileLocation = ''; $fileSize = ''; }; #GET MD5 my $dirname = "extracted"; foreach my $file (<$dirname/*>) { next if -d $file; open( my $FILE, $file ); binmode($FILE); open (my $md5, "+>>", "C:/md5") or die "cant open md5.txt: $!"; binmode($md5); $file =~ s{.*/}{}; syswrite $md5, Digest::MD5->new->addfile($FILE)->hexdigest; syswrite $md5, " $file\n"; };


      seeing how $fileLocation is the first check, you can also exit with that if you have many many files to extract. but this will extract those files and it will also get the md5 of them in a split sec lol
      yall have a good one :)
      Any Questions?
        Hi,

        If I understand correctly what you are doing, you don't need the long series of:

        $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileLocation, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileSize, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileName, 0x20);
        This would probably be sufficient:
        read ($infile, $fileLocation, 0x08); read ($infile, $fileSize, 0x08); read ($infile, $fileName, 0x20);
        since the read function knows which byte it has last read and which one to read next, so that the calls to seek and tell are most probably not required.

      this is the final revised working code:

      use File::Path qw(make_path); open (my $infile, '<', 'file') or die "cannot open file: $!"; binmode ($infile); make_path ('./extracted'); my $curpos = ''; my $fileLocation = ''; my $fileSize = ''; my $fileName = ''; my $file =''; my $chunk = ''; my $empty = ''; #GET File Location, File Size, File Name and write to file seek ($infile, 0x10, 0); until ($curpos =~ 0x04c0){ $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileLocation, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileSize, 0x08); $curpos = tell $infile; seek ($infile, $curpos, 0); read ($infile, $fileName, 0x20); $curpos = tell $infile; $fileLocation =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileSize =~ s/(.)/sprintf("%02x",ord($1))/eg; $fileName =~ s/\0+$//; open($file, '>', "extracted/$fileName") or die "Cannot open $fileName + $!"; binmode($file); sysseek ($infile, hex($fileLocation), 0); sysread ($infile, $chunk, hex($fileSize)); syswrite ($file, $chunk); $fileLocation = ''; $fileSize = ''; };
        or do you mean with get md5 too?