# FHTTP Kit by Xianur0 # Copyright (C) 2011 Oscar García López (http://hackingtelevision.blogspot.com) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # xianur0.null@gmail.com # http://hackingtelevision.blogspot.com/ package http; use Switch; my $cantidad = 0; my @encabezados = (); my $ignorarerroresestructura = 0; my @contador = (); my @contadorfinal = (); my $paquetest = 0; my @almacen = (); my $contenedor :shared; my $terminado :shared; my $EOL :shared = "\r\n"; sub new { $cantidad = 0; @encabezados = (); $ignorarerroresestructura = 0; @contador = (); @contadorfinal = (); $paquetest = 0; @almacen = (); $contenedor = ""; $terminado = ""; my ($class,$metodo,$url,$version,$modo) = @_; $ignorarerroresestructura = 1 if($modo == 1); my $paquete = {}; bless $paquete,$class; $version = $paquete->version($version); $url = $paquete->formatourl($url); my ($scheme, $host, $path) = $paquete->comprobarurl($url); $paquete->{encabezados}[0][0] = "Host: ".$host if($host ne ""); $contador[$npaquete] = 1; $paquete->{version}[0] = $version; $url =~ s/^https?:\/\/([^\/]+)//g; if($version eq "HTTP/0.9") { $paquete->{paquetes}[0] = join "",$metodo," ",$url,"\r\n"; } else { $paquete->{paquetes}[0] = join "",$metodo," ",$url," ",$version,"\r\n"; } $paquete->{versioninicial} = $version; $cantidad++; return $paquete; } sub comprobarurl { my ($paquete,$url) = @_; my ($scheme,$host,$path); if($url =~ /^(https?):\/\/(.*?)\/(.*)/) { ($scheme, $host, $path) = ($1,$2,$3); } else { ($scheme, $host) = ($url =~ /^(https?):\/\/(.*)/ && $ignorarerroresestructura == 0) or die("Warning: URL Invalida!\n"); } return ($scheme, $host, $path); } sub version { my ($paquete,$version) = @_; switch($version) { case "1.0" { $version = "HTTP/1.0"} case "1.1" { $version = "HTTP/1.1"} case "0.9" { $version = "HTTP/0.9"} else { die("Warning: Version de HTTP invalida! (".$version.")") if($ignorarerroresestructura != 1)} } return $version; } sub formatourl { my ($paquete, $url) = @_; my ($scheme, $host, $path,$parametros); $url =~ s/(\r\n|\n|\r)/%0d%0a/g; $url =~ s/\s/%20/g; return $url; } sub estructurar { my $paquete = shift; my $contenidon = ""; my $contenido = ""; my $contentlengthestablecido = 0; for($contenidon=0;$contenidon<=$paquetest;$contenidon++) { $contenido .= $paquete->{paquetes}[$contenidon]; for($ubicacionencabezado = 0; $ubicacionencabezado < $contador[$contenidon]; $ubicacionencabezado++) { $contenido .= $paquete->{encabezados}[$contenidon][$ubicacionencabezado].$EOL if($paquete->{encabezados}[$contenidon][$ubicacionencabezado] ne ""); $contentlengthestablecido = 1 if($paquete->{encabezados}[$contenidon][$ubicacionencabezado] =~ /^Content-Length: /); } if($contenidon>=0 && $contenidon < $paquetest) { $contenido .= join "","Connection: Keep-Alive",$EOL,"Proxy-Connection: Keep-Alive",$EOL; } if($contenidon==$paquetest && $contenidon > 0) { $contenido .= join "","Connection: Close",$EOL,"Proxy-Connection: Close",$EOL; } if($paquete->{postdatas}[$contenidon] ne "") { $contenido .= join "","Content-Length: ",length($paquete->{postdatas}[$contenidon]),$EOL,$EOL,$paquete->{postdatas}[$contenidon] if($contentlengthestablecido == 0); } for($ubicacionencabezado = 0; $ubicacionencabezado < $contadorfinal[$contenidon];$ubicacionencabezado++) { $contenido .= $paquete->{encabezadosfinal}[$contenidon][$ubicacionencabezado].$EOL if($paquete->{encabezadosfinal}[$contenidon][$ubicacionencabezado] ne ""); } $contenido .= $EOL; } return $contenido; } sub print { my $paquete = shift; my $contenido = ""; if($paquete->{version}[0] eq "HTTP/0.9") { $contenido = $paquete->{paquetes}[0]."\r\n"; } else { $contenido = $paquete->estructurar; } print $red, "FHTTP -> Server:\n", $reset; print $contenido; } sub paquete { my $paquete = shift; $contenido = $paquete->estructurar; return $contenido; } sub agregarencabezados { my $npaquete = ""; my ($paquete,$npaquete,@nencabezados) = @_; die("Warning: Numero de paquete invalido!\n") if($npaquete !~ /^\d+$/ || $npaquete > $paquetest); foreach $cabeza (@nencabezados) { $paquete->{encabezados}[$npaquete][$contador[$npaquete]] = $cabeza; $contador[$npaquete]++; } } sub agregarencabezadosfinal { my ($paquete,$npaquete,@nencabezados) = @_; die("Warning: Numero de paquete invalido!\n") if($npaquete !~ /^\d+$/ || $npaquete > $paquetest); foreach $cabeza (@nencabezados) { $paquete->{encabezadosfinal}[$npaquete][$contadorfinal[$npaquete]] = $cabeza; $contadorfinal[$npaquete]++; } } sub modo { my $opcion = ""; my ($paquete,$opcion) = @_; switch($opcion) { case 1 { $ignorarerroresestructura = 1; } case 0 { $ignorarerroresestructura = 0;} } } sub siguiente { $paquetest++; my ($paquete,$metodo,$url,$version) = @_; $version = $paquete->version($version); die("Warning: Versiones HTTP de los paquetes no coinciden! (".$paquete->{versioninicial}."-".$version.")") if($ignorarerroresestructura != 1 && $version ne $paquete->{versioninicial}); $url = $paquete->formatourl($url); my ($scheme, $host, $path) = $paquete->comprobarurl($url); $paquete->{encabezados}[$paquetest][0] = "Host: ".$host if($host ne ""); $contador[$paquetest]++; $paquete->{version}[0] = $version; if($version eq "HTTP/0.9") { $paquete->{paquetes}[$paquetest] = join "",$metodo," ",$url,"\r\n"; } else { $paquete->{paquetes}[$paquetest] = join "",$metodo," ",$url," ",$version,"\r\n"; } } sub establecercontenido { my ($paquete,$npaquete, $postdata) = @_; die("Warning: ID Invalido!\n") if($npaquete eq "" || $paquete->{paquetes}[$npaquete] eq ""); die("Warning: Este metodo no usa esta clase de contenido\n") if($paquete->{paquetes}[$npaquete] !~ /^(POST|PUT)(\s|\t)/ && $ignorarerroresestructura == 0); $paquete->{postdatas}[$npaquete] = $postdata; } sub enviar { my ($paquete,$host,$puerto,$ssl) = @_; my $respuesta = ""; my $parser = parser->new(); my $byte = ""; my $tmp = ""; my $contenedor = ""; my @respuestas = (); my $envio = ""; die("Warning: Datos de envio invalidos!") if($host eq "" || $puerto eq ""); if($ssl == 0) { $servidor = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $puerto, Proto => 'tcp'); $servidor = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $puerto, Proto => 'tcp') or die("[x] Objetivo Invalido!\n") if(!$servidor); } else { if(&main::mods("IO::Socket::SSL") == 1) { $servidor = IO::Socket::SSL->new($host.":".$puerto) or die("[x] Houston, tenemos un problema de tipo https: ".$@."\n"); } else { die("\n[x]No se pueden iniciar conexiones SSL (no se encontro IO::Socket::SSL) - HTTP\n\n"); } } if($paquete->{version}[0] eq "HTTP/0.9") { $envio = $paquete->{paquetes}[0]."\r\n"; } else { $envio = $paquete->estructurar; } print $servidor $envio; my $terminado = 0; my $veces = 0; die("[x] Conexion cerrada!\n") if(!$servidor); while(read($servidor, $byte, 1)) { $contenedor .= $byte; } if($paquete->{version}[0] eq "HTTP/0.9") { $respuestas[0] = $contenedor; } else { # parseamos.... @respuestas = $parser->parsear($contenedor,()); } my $id = 0; my @tmp = (); my @tmp2 = (); my @encabezados = (); my @contenidos = (); my @estados = (); my %estructura = (); $estructura{total} = 0; my $res = ""; $estructura{respuesta} = $contenedor; foreach $res (@respuestas) { @tmp = split(/(\r?\n)/,$res); $estructura{estados}[$id] = $tmp[0]; @tmp = split(/(\r?\n\r?\n)/,$res); $tmp[0] =~ s/^(\r?\n|\s)+//g; $estructura{encabezado}[$id] = $tmp[0]; @tmp2 = split(/(\r?\n)/,$tmp[0]); foreach $cabe (@tmp2) { if(my ($nombre,$valor) = ($cabe =~ /(.*?):([^\r\n]*)/)) { $valor =~ s/^[\s\t]//; $valor =~ s/[\r\n]+//g; $estructura{encabezados}[$id]{$nombre} .= $valor; } } $contenidos[$id] = ""; my $contador = 0; foreach(@tmp) { $estructura{contenidos}[$id] .= $_."\r\n" if($contador > 0); $contador++; } $estructura{contenidos}[$id] = &tools::dechunk($estructura{contenidos}[$id]) if($estructura{encabezados}[$id]{'Transfer-Encoding'} eq "chunked"); $estructura{contenidos}[$id] = &tools::descomprimirgzip($estructura{contenidos}[$id]) if($estructura{encabezados}[$id]{'Content-Encoding'} eq "gzip"); $estructura{contenidos}[$id] = &tools::descomprimirdeflate($estructura{contenidos}[$id]) if($resp{encabezados}[$id]{'Content-Encoding'} eq "deflate"); $id++; $estructura{total}++; } return %estructura; } 1;