Skip to content

Instantly share code, notes, and snippets.

@CirKu17
Created October 26, 2011 09:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save CirKu17/1315864 to your computer and use it in GitHub Desktop.
Save CirKu17/1315864 to your computer and use it in GitHub Desktop.
File Carving script
## Originally coded by Trenton (http://www.hackyeah.com/?p=36)
## Amended by CirKu17 ( http://short-circuit.x10.mx )
#!/usr/bin/env perl
use warnings;
use strict;
@ARGV || die "Missing filename argument $!\n";
my $infile = $ARGV[0]; #Get our image name from the command line argument
open INFILE, "<", $infile or die "Can't find file $infile\n"; #Open the file up in read only mode
binmode INFILE; #Set it to binmode
my $n = 0; #This will keep track of our current location in INFILE
my $data; # This will hold our data from any read()
my $search_block_size = 512; #This will be how many characters we will search at a time
my $fflag = 0; # Inizialize a flag var, so we can check if some header is found
while(!eof(INFILE)){
seek(INFILE,$n,0); #Set INFILE to $n characters from the start (note n++ at the end of this while loop)
read(INFILE, $data, $search_block_size); #Read a block of information from INFILE and place it into $data.
if ($data =~ m/(\xFF\xD8\xFF(\xE0|\xE1|\xE8){1}..(\x45|\x4A|\x53){1}(\x46|\x78|\x50){1}(\x49|\x69){1}(\x46|\x66){1}(\x46|\x00){1}\x00?)/s){ #If $data contains our file signature, we have probably found the start of a file.
print "\n[*]JPG header found\n";
$fflag = 1;
&get_jpg; #Go to our get_jpg sub function.
}
if ($data =~ m/(\x25\x50\x44\x46)/) {
print "\n[*]PDF header found\n";
$fflag = 1;
&get_pdf;
}
if ($data =~ m/(\x47\x49\x46\x38(\x37|\x39){1}\x61)/) {
print "\n[*]GIF header found\n";
$fflag = 1;
&get_gif;
}
if ($data =~ m/(\x89\x50\x4E\x47\x0D\x0A\x1A\x0A)/) {
print "\n[*]PNG header found\n";
$fflag = 1;
&get_png;
}
$n += ($search_block_size -15); #Increment INFILE location while looking for a new file ( the -15 is just in case our signature is crossing the border between two reads
}
if ( $fflag == 0 ) { print "\n[!] No header found\n"; }
close INFILE;
sub get_jpg {
my $file_start = ($n + $-[0]); #Let's not forget the start of the found header.
my $n = $file_start; #Set our location value back to the start of the header
print "\tHeader (", unpack("H*", $1), ") Found at location: ", $file_start , "\n"; #Print some output to show that we found something.
my $file_end; #Define what we hope will hold the locaiton of the trailing signature;
while(!eof(INFILE)){
seek(INFILE, $n, 0); #Set INFILE to $n characters from the start of the file
read(INFILE, $data, $search_block_size); #Read a block of infromation from INFILE and place it into $data.
if($data =~ m/(\xFF\xD9)/s){ #Like above - we are checking for our footer
$file_end = ($n + $-[0]); #Set $file_end to the start location of our buffer plus the length between the start of our buffer and our match
print "\t\tFooter (", unpack("H*", $1), ") Found at location: ", $n + $-[0], "\n"; #Print more output for our users
#Open the file we are going to write to
open OUTFILE, ">", $file_start . ".jpg";
binmode OUTFILE;
#Reset our INFILE location to the start (out File Signature);
$n=$file_start;
#Print everything to OUTFILE file one character at a time;
while($n < ($file_end + 2)){
seek(INFILE,$n,0);
read(INFILE, $data, 1);
print OUTFILE $data;
$n++;
}
}
if($file_end) {last};
$n += ($search_block_size -15); #Increment INFILE location while looking for a new file
}
if(!$file_end) {
die "\tNo footer found for file. Quitting...\n\n"; #If there are no more footers in the file, we don't want to keep looking for more headers
}
}
sub get_pdf {
my $file_start = ($n + $-[0]);
my $n = $file_start;
print "\tHeader (", unpack("H*", $1), ") Found at location: ", $file_start , "\n";
my $file_end;
while(!eof(INFILE)){
seek(INFILE, $n, 0);
read(INFILE, $data, $search_block_size);
if($data =~ m/((\x0A|\x0D){1}(\x25|x0A){1}\x25(\x45|\x25){1}(\x45|\x4F){1}(\x46|\x4F){1}(\x0A|\x46|\x0D){1}(\x0D\x0A)?)/){
$file_end = ($n + $-[0]);
print "\t\tFooter (", unpack("H*", $1), ") Found at location: ", $n + $-[0], "\n";
open OUTFILE, ">", $file_start . ".pdf";
binmode OUTFILE;
$n=$file_start;
while($n < ($file_end + 2)){
seek(INFILE,$n,0);
read(INFILE, $data, 1);
print OUTFILE $data;
$n++;
}
}
if($file_end) {last};
$n += ($search_block_size -15);
}
if(!$file_end) {
die "\tNo footer found for file. Quitting...\n\n";
}
}
sub get_gif {
my $file_start = ($n + $-[0]);
my $n = $file_start;
print "\tHeader (", unpack("H*", $1), ") Found at location: ", $file_start , "\n";
my $file_end;
while(!eof(INFILE)){
seek(INFILE, $n, 0);
read(INFILE, $data, $search_block_size);
if($data =~ m/(\x00\x3B)/) {
$file_end = ($n + $-[0]);
print "\t\tFooter (", unpack("H*", $1), ") Found at location: ", $n + $-[0], "\n";
open OUTFILE, ">", $file_start . ".gif";
binmode OUTFILE;
$n=$file_start;
while($n < ($file_end + 2)){
seek(INFILE,$n,0);
read(INFILE, $data, 1);
print OUTFILE $data;
$n++;
}
}
if($file_end) {last};
$n += ($search_block_size -15);
}
if(!$file_end) {
die "\tNo footer found for file. Quitting...\n\n";
}
}
sub get_png {
my $file_start = ($n + $-[0]);
my $n = $file_start;
print "\tHeader (", unpack("H*", $1), ") Found at location: ", $file_start , "\n";
my $file_end;
while(!eof(INFILE)){
seek(INFILE, $n, 0);
read(INFILE, $data, $search_block_size);
if($data =~ m/(\x49\x45\x4E\x44\xAE\x42\x60\x82)/) {
$file_end = ($n + $-[0]);
print "\t\tFooter (", unpack("H*", $1), ") Found at location: ", $n + $-[0], "\n";
open OUTFILE, ">", $file_start . ".png";
binmode OUTFILE;
$n=$file_start;
while($n < ($file_end + 2)){
seek(INFILE,$n,0);
read(INFILE, $data, 1);
print OUTFILE $data;
$n++;
}
}
if($file_end) {last};
$n += ($search_block_size -15);
}
if(!$file_end) {
die "\tNo footer found for file. Quitting...\n\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment