Académique Documents
Professionnel Documents
Culture Documents
4,5 EUROS
00030
8 414090 202756
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:
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...
Listado 1
Si no ha habido ningún problema,
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.
:-)
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
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.
Listado 15
10
Listado 16
11
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
13
Imagen 22
14
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
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
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
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 ;).
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
18
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.
19
20
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 (</table> 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
22
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
24
25
26
27
28
29
30
ESCRIBIENDO CONSIGUIENDO
ARTÍCULOS PUBLICIDAD
31
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
33
34
35
mov al, 1
dec ebx
int 0x80
ida:
call vuelta
db "Hola HxC!"
36
37
38
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 ;-).
39
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
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);
return 0;
Como os veo con ganas en esto de irle }
41
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
43
int main()
return 0;
{
}
44
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.
45
&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 = ℜ
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
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 = ℜ 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
PetitSuisse 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 PetitSuisse :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
48
#include<stdio.h>
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
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
51
Nota
52
53
54
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:
55
#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 */
56
precios desde
99 euros
57
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
59
60
61
** 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
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
63
64
65
66
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.