#!/usr/bin/perl
use strict;

#----------------------------------------------------
# unchunk.pl - HTTP Chunked Response Decoder
# Created: 02MAY10 
# Programmer: dn1nj4 at shadowserver dot org
# Purpose: Takes reassembled Chunked Encoded HTTP
#	responses and decodes them
# Usage: perl unchunk.pl input_file output_file
#----------------------------------------------------
# REV:
#----------------------------------------------------
#
#----------------------------------------------------
# GLOBALS
#----------------------------------------------------

#----------------------------------------------------
# SUBS
#----------------------------------------------------

#----------------------------------------------------
# MAIN
#----------------------------------------------------
my $infile = shift;
my $outfile = shift;

my $byte = "";
my $last = "";
my $next_chunk = "";
my $final = "";

# Read the entire input file into memory
open(INFILE,"<$infile");
binmode(INFILE);
undef $/;
my $buffer = <INFILE>;

# Scan for the first \x0d0a0d0a, signifying the end of the HTTP headers.
my $prev_crlf = index($buffer,"\x0d\x0a\x0d\x0a") + 4;

# Starting from the end of the HTTP headers, find the next \x0d0a.
my $next_crlf = index($buffer,"\x0d\x0a",$prev_crlf)+2; 

# Through the rest of the file, get the chunk size, add that data to the 
#	reconstructed buffer.
while ($next_crlf > 1) {

	# The chunk size is going to be ASCII text representing the number of bytes
	#	in this particular chunk.  The chunk size is bound on either side by 
	#	\x0d0a.
	my $chunk_size = substr($buffer,$prev_crlf,$prev_crlf-$next_crlf-2);
	print "Reading " . hex($chunk_size) . " bytes from stream position $next_crlf.\n";
	
	# Cut $chunk_size of data from the stream and append it to the reassembled 
	#	data buffer.
	$final .= substr($buffer,$next_crlf,hex($chunk_size));
	
	# Calculate the starting point for the next chunk size.
	$prev_crlf = $next_crlf+2+hex($chunk_size);
	
	# Find the next \x0d\x0a.
	$next_crlf = index($buffer,"\x0d\x0a",$prev_crlf)+2;
}

open(OUTFILE,">$outfile");
binmode(OUTFILE);
print OUTFILE $final;
close(OUTFILE);
