Skip to main content

Descargando el manual 'La guía definitiva de PNG' con bash

Pues eso, hoy va a ser algo corto, el "problema" es simple, tenemos estos ingredientes: - Un manual sobre el formato PNG [ http://www.libpng.org/pub/png/book/toc.html ] - Una conexión a Internet intermitente, así que no es una posibilidad leerlo online - Pereza suficiente para no ponerse a descargarlo a mano - Ganas de trastear con bash

Y la receta, comentadita [ vacuum.sh ] o coloreado:

===============================================================================

!/usr/bin/env bash

nxt="$1"

base="$2"

Se comprueban los argumentos

if [ -z "$nxt" ] || [ -z "$base" ]; then

echo "$0 "

exit 0

fi

Mientras queden páginas

while [ ! -z "$nxt" ];do

# Se descarga

wget "$nxt"

# Se lee el nombre del archivo

for i in $(echo $nxt|sed "s/\// /g");do

   fname=$i

done

nxt=""

# Se lee el archivo en busca del link al siguiente

# ( la línea contiene align="right" y al principio está el <a href )

echo "Parsing..."

for o in $(cat $fname|sed "s/\ /%/g");do

   i=`echo "$o"|sed "s/%/\ /g"`

   l1=`echo "$i"|grep 'align="right"'`

   l2=`echo "$i"|cut -d\" -f1|grep 'href'`



   # Si se encuentran las dos cosas

   if [ ! -z "$l1" ] &amp;&amp; [ ! -z "$l2" ];then



       # Se extrae lo que está entre las comillas

       nxt="$base"`echo "$i"|cut -d\" -f2`

       echo "Next: $nxt"

       break # Ya está, pasamos a la siguiente

   fi

done

# Se comprueba que no se volvió al principio

if [ "$nxt" == "$1" ];then

   break

fi

done

Para lanzarlo contra la web de antes, habría que hacer: ./vacuum.sh "http://www.libpng.org/pub/png/book/title.html" "http:// www.libpng.org/pub/png/book/"

Sí, es bastante cutre, pero no se me ocurrió nada mejor :P.

Saludos

Introducción a NetKit ( IV ): Un puente a Internet

Introducción_a_NetKit(III):switches_y_enrutado Introducción_a_NetKit(_II):creando_redes Introducción_a_Netkit(_I):_Instalación

Pues llegamos a la última parte de esta introducción a NetKit, donde simplemente veremos como hacer un laboratorio con una máquina que se conecte a el anfitrión ( y con ello a Internet ), queda como ejercicio para el lector añadir y configurar otras máquinas a la red que aprovechen esa conexión.

Lo único que hay que hacer es añadir una interfaz Point-To-Point, en el archivo "lab.conf": []=tap,, Nota: esto requiere permisos de root

Por ejemplo, si el laboratorio tiene una máquina llamada door, se añadiría esta línea para conectarse con la IP 10.1.1.2 al anfitrión, que recibiría la IP 10.1.1.1: door[0]=tap,10.1.1.1,10.1.1.2

Con esto ya se puede realizar una conexión con internet, para ser completamente usable habría que configurar DNS y tal, pero lo dicho, queda como ejercicio para el lector

Y hasta aquí esta serie, saludos

[Cheatsheet] de variables inseguras en PHP

Hoy algo de carne, una chuleta sobre las variables superglobales (woh!) no fiables, donde el cliente puede meter mano:

Leyenda:

===============================================================================

$_SERVER: PHP_SELF I argv I argc S GATEWAY_INTERFACE S SERVER_ADDR S SERVER_NAME S SERVER_SOFTWARE S SERVER_PROTOCOL I REQUEST_METHOD I REQUEST_TIME S QUERY_STRING S: Sin comprobar DOCUMENT_ROOT S HTTP_ACCEPT I HTTP_ACCEPT* I HTTP_CONNECTION I HTTP_HOST D: Inseguro para el host por defecto si hace fallback HTTP_REFERER I HTTP_USER_AGENT I HTTPS S: Sin comprobar REMOTE_ADDR S REMOTE_HOST D: Inseguro si el atacante tiene acceso al servidor DNS REMOTE_PORT S SCRIPT_FILENAME S SERVER_ADMIN S SERVER_PORT S SERVER_SIGNATURE S PATH_TRANSLATED I SCRIPT_NAME S REQUEST_URI S PHP_AUTH_DIGEST I PHP_AUTH_USER I PHP_AUTH_PW I AUTH_TYPE I: No he podido comprobarlo PATH_INFO I ORIG_PATH_INFO I: No he podido comprobarlo

$_GET / $_POST / $_REQUEST / $_COOKIE / $argv / $_HTTP_RAW_POST_DATA I

Pero muy mucho, eh!

Notas: $_GET se pasa por urldecode() antes de llegar al script

$argc S

$_FILES: name I type I tmp_name S error S size S

===============================================================================

Como filtrar Si es un entero: $clean = intval($dirty);

Si es un flotante: $clean = floatval($dirty);

Si es una cadena: Antes de meter en la base de datos:

http://php.net/manual/en/function.mysql-real-escape-string.php

$clean = mysql_real_escape_string($dirty);

Antes de mostrar al usuario:

http://es.php.net/manual/en/function.htmlentities.php

$clean = html_entities($dirty);

Alternativamente se puede utilizar una función que elimine los caracteres peligrosos ( como base64 ), pero hay que recordar que volverán a ser dañinos si se devuelve a la forma original. Así, una contraseña que se almacene como un hash, una vez se le pasó la función ( y dado que la forma original se descarta ) es fiable.

===============================================================================

Lógicamente no es mano de santo, y no es que yo sepa demasiado de PHP, así que cualquier corrección se agradece.

Añadiendo el Wiimote a los scripts de PyGame

Pues eso, veamos como podemos hacer para añadir de forma fácil la posibilidad de usar el Wiimote en los scripts que usan PyGame modificando mínimamente el código.

La idea es muy simple, el sistema de eventos de PyGame permite añadir eventos desde fuera, mezclando eso con el sistema de callbacks de cwiid ( la librería para manejar el Wiimote ) podemos hacer como si se pulsasen teclas del teclado desde el Wiimote, los eventos se pueden crear así:

ev = pygame.event.Event( , { "key": } )

Y después solo hay que añadirlos con:

pygame.event.post( ev )

Entonces el script quedaría algo como esto [ wii4pygame.py ], solo hay que hacer bind_wiimote(), opcionalmente mandando el número del led a activar ( 1 por defecto ), por ejemplo:

import wii4pygame

print "Pulsa [1] y [2]"

wmote = wii4pygame.bind_wiimote( ) # Salvar el wiimote del recolector de basura

Y ya se puede usar el wiimote, pygame capturará los eventos

for event in pygame.event.get():

...

Genera eventos de tipo KEYDOWN o KEYUP según se pulsen o liberen botones Las teclas pulsadas se "mapean" así ( wiimote: evento ) :

* A : 'A'

* B : 'B'

* 1 : '1'

* 2 : '2'

* +: '+'

* - : '-'

* Home: K_HOME

* ↑ :K_UP

* ↓ :K_DOWN

* ← :K_LEFT
*
* → :K_RIGHT
*

Y yastá, hale

Controlando el reproductor Totem desde el Wiimote

Al principio la idea no era exactamente esa, de hecho era sobre rhythmbox... pero empecemos desde el principio.

Hablando con un colega sobre nosequé salió la idea de controlar el Rhythmbox ( reproductor de música de gnome bastante usado ). Al volver sobre la idea días ¿ semanas ? más tarde, leyendo la documentación sobre como hacer un plugin llegue a esta web: http://redjunasun.blogspot.com/2010/11/wiimote-for- controlling-rhythmbox.html a ver... compila perfectamente con "gcc archivo.c - o loquesea -lcwiid" y funciona bien.

Y no es un plugin, hmmm... parece ser que lo que usa para controlarlo es el DBus y uno pensando que solo servía para cosas de bajo nivel, mola controlar el reproductor así, enfin, eso ya está hecho, habrá que buscar otra cosa, probemos con el Totem.

Al parecer no hay nada por el estilo para el reproductor de video, así después de pasarse un buen rato a cabezazos contra DBus ( a ver si hago un tutorial que en cuanto se entiende es interesante ) aquí teneis el resultado: [ totemote.py ]

Necesita la librería cwiid con los bindings para python "apt-get install python-cwiid" y activar el plugin DBus para Totem ( se puede conseguir con "apt-get install totem-plugins" )

Y nada, el script no tiene ningún misterio, solo hay que ejecutarlo con el Totem iniciado y ya está, los botones son:

* A : Play/Pause

* ↑ : Avanza 60 segundos

* ↓ : Retrocede 10 segundos

* ← : Pasa al video anterior

* → : Pasa al video siguiente

* + : Sube el volumen un 5%
*
* - : Baja el volumen un 5%
*

Y dándole al botón de apagar cierra también el programa.

Hasta otra

Montando un sistema de descargas oculto ( 2 ): cifrando y pensando a lo grande

[ Montando_un_sistema_de_descargas_oculto_(1):_las_bases ]

Seguimos avanzando, está claro que aunque los datos se ocultan dentro de una imágen, si tiras de esteganografía para esto, dejar los datos simplement así es casi como que vayan en *, si alguien busca datos ocultos en una imágen LSB es lo primero que se probaría, hay  que reforzarlo con un cifrado, con un simple ARC4 con una clave segura y suficiente padding basta para darle en los morros a los cotillas y para desalentar a algun bot que analice la red en busca de algo sospechoso, este_cifrado_ya_se_explico_anteriormente, así que vamos con lo siguiente.

Una sola imágen está bien para cosas pequeñas, pero hasta una relativamente grande no puede soportar más de 1 mega, hay que buscar una forma de dividir el archivo y mantener una lista de las ubicaciones de las partes, digamos por ejemplo que queremos dividir el archivo cifrado entre las imágenes y subir estas a un hosting de imágenes como Imageshack.us, habría que guardar las URL donde quedan las imágenes, ya puestos la clave se podría sacar de "/dev/ urandom" para que sea lo suficientemente cerca y de paso guardar el tamaño del archivo original, en esta implementación, el formato usado es este:

===============================================================================

  • Tamaño del archivo original: 8 bytes
  • Clave en hexadecimal, string acabada en \0
  • Las URL, en el orden en que se codifico el archivo, terminada cada una por \0

===============================================================================

Todo comprimido con GZip.

Los scripts: el primero, que divide un archivo entre varias imágenes y genera el gzip con "la hoja de ruta" [ stego_split.py ] ( utiliza esto_para_las peticiones_POST ), el segundo, que descarga las imágenes y descifra el archivo usando el archivo GZip [ stego_join.py ]. Nota: al dividir el archivo, para de subir imágenes cuando puede haber metido todo el archivo. Nota2: al dividirlo, el mayor cuello de botella es la subida por eso se hace con multiples hilos, al final cuando pone "Online: ...", esos son los hilos que están subiendo imágenes.

Argumentos del que divide y sube: ./stego_split.py [[ ... ]]

Argumentos del que lo vuelve a juntar: ./stego_join.py

Capturas subiendo un archivo de 2Megas:

Escogí el formato GZip  porque aunque no comprime mucho, es suficiente para datos sobre todo alfabéticos, además soporta "basura" al final del archivo, entonces se pueden utilizar los scripts de la_parte_anterior para añadirlo a una imágen, por ejemplo, una imágen como esta ( obra del gran "Bichero") puede contener el GZip que permite recuperar las otras imágenes y el archivo final ( solo un video de colorines ) :

===============================================================================

$ ./stego_extract.py piratas.png path.gz $ ./stego_join.py path.gz video.avi Tamaño del archivo: 2758500 Clave:  fccf9b4969c1feaec8faeb4ca70e11cdd9484018 Descargando http://img192.imageshack.us/img192/4793/upanddown0sp.png Leyendo upanddown0sp.png Descargando http://img511.imageshack.us/img511/2542/upanddown1sp.png Leyendo upanddown1sp.png Descargando http://img6.imageshack.us/img6/9034/upanddown2sp.png Leyendo upanddown2sp.png Descargando http://img13.imageshack.us/img13/404/upanddown3sp.png Leyendo upanddown3sp.png Descargando http://img534.imageshack.us/img534/3374/upanddown4sp.png Leyendo upanddown4sp.png Descargando http://img843.imageshack.us/img843/6019/upanddown5sp.png Leyendo upanddown5sp.png Descargando http://img17.imageshack.us/img17/2379/upanddown6sp.png Leyendo upanddown6sp.png Descargando http://img836.imageshack.us/img836/7600/upanddown7sp.png Leyendo upanddown7sp.png $ md5sum video.avi para_prueba.avi 6e604af1761085c9104b8141c01d47e8  video.avi 6e604af1761085c9104b8141c01d47e8  para_prueba.avi $

===============================================================================

El problema: hay que subir más o menos 4 veces más datos de los necesarios, probado con un archivo de ~ 50 megas, resulta en 200, ... y dá gracias de que PNG esté comprimido.

Y hasta aquí esto de montar un mini sistema de descargas oculto, nos leemos.

Cambiando seriesyonkis por Twitter

Después de ver cosas como este_post_en_Freesoftwareando uno no puede menos que intentar estirar un poco más la goma, si ellos consiguieron subir tantos enlaces a twitter, aquí presento un programa que permite acceder a ellos directamente... vaaale, solo una excusa para probar el twitter4j.

Por partes, si quieres compilar tu mismo el programa, vas a necesitar el mentado twitter4j, aquí ya se explicó como hacerlo ( y sin compilarlo tampoco estoy seguro que se pueda prescindir de el, así que va también en el paquete ) . El programa se puede descargar aquí [ twlinks.zip ] y estas son las fuentes [ TwLinks_src.zip ] Para ejecutarlo hay que descomprimirlo y ejecutar el jar.

El funcionamiento del programa no tiene ningún misterio, introduce los términos de búsqueda en la entrada de texto ( el hashtag #enlazareslegal se añade por defecto ) y pulsa buscar:

Esto mostará la lista de resultados ( limitada a los 10 primeros, creo )

Solo queda elegir el que queremos, y pulsando en "Descargar" nos abre una ventana de navegador en la página de descarga

ps: está poco probada, así que menos explotar puede pasarle de todo :P

Y no hay más, nos vemos

Instalando twitter4j en Gnu/Linux

Twitter4j es un envoltorio (wrapper) del API de twitter para Java, veamos como instalarlo rápidamente:

Lo primero es instalar maven, esto se puede hacer con

sudo apt-get install maven2

Descargamos la última versión desde Twitter4j_-_GitHub

Ahora hay que descomprimirlo y ejecutar el package.sh

bash package.sh

Y por último copiar los .jar que se generaron en el directorio "twitter4j- core/target/" al directorio de librerías de java, en mi caso ( openjdk-6 ) sería:

sudo cp *.jar  /usr/lib/jvm/java-6-openjdk/jre/lib/ext/

Y dar permisos de lectura ( no vaya a ser )

sudo chmod +r /usr/lib/jvm/java-6-openjdk/jre/lib/ext/twitter4j*.jar

Ya podemos usar esta librería tan completa en nuestro código.

Montando un sistema de descargas oculto ( 1 ): las bases

La idea era mostrar primero un posible escenario de control total de internet, pero se volvió demasiado post-apocalíptico. Na' , imaginaos simplemente que queremos distribuir eh...código fuente, pero sin que nadie se dé cuenta de que su servidor lo aloja. Una opción es utilizar algo conocido como esteganografía, como dice en la Wikipedia:
La esteganografía es la disciplina en la que se estudian y aplican
técnicas que permiten el ocultamiento de mensajes u objetos, dentro
de otros, llamados portadores, de modo que no se perciba su
existencia. Es una mezcla de artes y técnicas que se combinan para
conformar la práctica de ocultar y enviar información sensible en
un portador que pueda pasar desapercibido.

Vamos, que así como la criptografía intenta que los datos no sean recuperables sin una contraseña, la esteganografía apunta a pasar mensajes sin que se interpreten como tales.

Por ejemplo, hay imágenes en casi cualquier página de Internet, podemos introducir nuestros datos en una imágen y después subirla a un foro, un host de imágenes o donde nos de la gana.

La técnica de esteganografía probablemente más utilizada con las imágenes es la llamada LSB ( "Least Significant Bit", el Bit Menos Significativo ), que se basa en lo siguiente:

Las imágenes típicas ( BMP, PNG, GIF, JPEG ... ) son gráficos_raster, es decir, que un archivo se reduce a un conjunto de valores de píxeles ( con cabeceras y quizá algún tipo de compresión ), y por cada pixel un número para cada color, por ejemplo BMP, PNG y JPEG usan un esquema llamado RGB o RGBA si hay transparencia, donde un pixel se codifica como tres números, uno que representa la cantidad de rojo ( "R" ), otro para el verde ( "G" ) y otro para el azul ( "B" ), y uno más para la transparencia, si la hay ( alpha "A" ), normalmente cada uno puede ir de 0 a 255, un byte, o 8 bits.

La técnica LSB substituye el bit menos significativo de cada pixel por uno del archivo a incluir, si cada pixel tiene 8 bits, cambiar el bit menos significativo hace que el color cambie en 1/256 en el peor de los casos, cambio que el ojo no es capaz de apreciar, decidme, sin tener que buscar cambios en una imágen compleja, encontrais la diferencia entre:

y:

Indistinguibles verdad?, pues ese esa es la mayor diferencia que puede haber.

A la hora de escribir el código, si utilizamos python, Python_Imaging_Library allana el camino permitiendonos ver la imágen como un array bidimensional de pixeles, solo hay que abrirla from PIL import Image

img = Image.open( archivo de imágen )

Ahora si vamos a manipular mucho los pixels lo más eficiente es cargarlos en memoria fst_img = img.load( )

Y podemos acceder a ellos como si fuera un array de tuplas pixel = fst_img[ x, y ]

Otra propiedad muy útil es el ancho y alto de la imágen, están en el atributo size de la imágen dim = img.size# Poniendo todos los pixels a negro

for x in xrange( dim[ 0 ] ):

for y in xrange( dim[ 1 ] ):

   fst_img[ x, y ] = ( 0, 0, 0 )

Solo queda guardar la imágen: img.save( nombre del archivo guardado )

El resto está en manos del programador, este es el que añade el archivo [ stego_add.py ] y este el que lo extrae [ stego_extract.py ], el que extrae, extrae todos los bits, lo que hace que el archivo acabe con ruido, con compresiones como gzip esto no es un problema ya que simplemente lo ignora, si el formato que piensas usar tiene problemas con estas cosas puedes simplemente añadir unos cuantos bytes al principio que indique el tamaño del archivo para solo leer lo necesario.

Nota: obviamente no se pueden cambiar alegremente los pixeles de una imagen JPEG ( que comprime con pérdidas ) y esperar que funcione, ya que al codificarla se pierde la información, para este formato hay que usar otros métodos.

Por ejemplo:

===============================================================================

$ ./stego_add.py llcat2.jpg freenet07.tar.gz test.png Tamaño del archivo: 40879 bytes Imágen: 500 x 374 70125 bytes 68.4814453125 Kb $

===============================================================================

Imágen original:

Imágen con el tar.gz de freenet en los bits menos significativos:

( El formato pasó de ser JPEG a PNG por lo dicho antes. )

===============================================================================

$ ./stego_extract.py test.png fnet.tar.gz $ gunzip fnet.tar.gz

gzip: fnet.tar.gz: decompression OK, trailing garbage ignored $

===============================================================================

Se puede abrir el archivo tar y comprobar que los archivos siguen intactos

En la siguiente más y mejor ...

[ Montando_un_sistema_de_descargas_oculto_(2):_cifrando_y_pensando_a_lo grande ]

Resolviendo dominios .42 en un servidor BIND9 casero (DNS)

Pues nada, veamos como hacer que nuestro DNS casero resuelva direcciones con el TLD .42, si no sabes que es esto, mejor hechale un vistazo al proyecto https:// www.42registry.org/faq-es.php
"42 Registry es, principalmente, una experiencia como otras tantas de
las que abundan en Internet hoy en día. Es una organización sin
ánimo de lucro, orientada a proponer un TLD_(Dominio_de_Primer
Nivel) para agrupar a una comunidad concreta."

Voy a suponer una distro basada en Debian ( Ubuntu, Trisquel ... Debian... ), pero la idea es la misma para todos, solo hay que cambiar un par de cosas (que avisaré cuando se tercie).

Primero instalamos el servidor DNS en la máquina que queremos sudo apt-get install bind9

( Aceptamos lo que sea, y sinó usamos una distro "Debian-based", buscamos el paquete en el repositorio correspondiente )

( Esto se puede leer en el FAQ de 42 ) Abrimos el archivo "/etc/bind/ named.conf" sudo nano /etc/bind/named.conf

( Puedes cambiar nano por gedit, joe, emacs, vi, kwrite, o el que sea ) y añadimos esto al final:

===============================================================================

zone "42" IN { type forward;

forwarders {91.191.147.246; 91.191.147.243; 79.143.244.68;};

};

===============================================================================

Hay que reiniciar el servidor DNS para que lea la configuración sudo /etc/init.d/bind9 restart

(Puede cambiar según la distro)

Y añadir la maquina como servidor DNS, abrimos "/etc/resolv.conf" sudo nano  /etc/resolv.conf

(Lo dicho, no tiene porque ser nano) y añadimos

===============================================================================

nameserver aquí_la_ip_del_servidor_dns

===============================================================================

Ya se puede comprobar que funciona

===============================================================================

$ nslookup 4.irc.42

Server:        127.0.0.1

Address:    127.0.0.1#53

Non-authoritative answer:

4.irc.42    canonical name = irc.geeknode.org.

Name:    irc.geeknode.org

Address: 91.208.40.24

Name:    irc.geeknode.org

Address: 193.200.42.54

Name:    irc.geeknode.org

Address: 80.67.169.17

Name:    irc.geeknode.org

Address: 81.93.247.132

$

===============================================================================

Y ya está, solo queda insistir en que quién no haya leído el FAQ, lo haga.