sábado, diciembre 18, 2010

Fuera de servicio


Después de 10 años de uso era tiempo de cambiarlo. El viejo sigue funcionando igual que el primer día, solo que a veces tengo que limpiarle el polvo y tierra de la ruedita porque se atasca.

sábado, noviembre 27, 2010

Se me corrio la plancha

El metodo de la planchita

Esto es lo que pasa cuando se presiona muy fuerte una plancha caliente sobre el PCB, corrés el riesgo que se te corra la tinta.

lunes, noviembre 01, 2010

Quizes


Les dejo cinco Quiz de criptografía y algoritmos que publique en un par de listas de correo:

1. Descifrar la/s palabra/s:

[103, 67, 68, 68, 79, 75, 90, 69, 70, 67, 89]

2. Hallar el valor de a:

>>> map(lambda x: f(ord(x)), a)
[234, 166, 4, 34, 166, 182, 134, 118, 38, 4, 134, 4, 202, 22, 78, 174,
70, 70, 166, 78, 158, 132]

3. Descifrar la/s palabra/s:

[1, 2, 3, 4, 5, 6, 7, 4, 8, 2, 3, 5]

4. Descifrar la/s palabra/s:

[1, 2, 1, 2, 3, 1]

5. Usando el diccionario estandar de GNU/Linux (/usr/share/dict/american-english), encontrar la única palabra que solo tiene las letras: 'bilmopsty'. Las letras en la palabra pueden estar repetidas.

viernes, octubre 22, 2010

Antena UHF para TV Digital

DSC00322

(esta es una copia de un mensaje que mandé hacia el grupo Yahoo Ciencia Amateur, si les interesa la ciencia amateur no dejen de entrar.)

Hace unos meses compre en La Plata un dongle USB para ver TV Digital en la PC, pero la antenita que trae el equipo no tiene suficiente ganancia como para recibir la señal desde la Ciudad de Buenos Aires.

Hace poco levantaron una antena en La Plata. Aún así, me quedé con ganas de hacerme una Yagi direccional UHF para 550 Mhz. Hoy aproveché que tenia la tarde libre e hice una.

Usé la calculadora de K7MEM para Yagis VHF/UHF e hice una de 10 elementos ajustada en 550 Mhz, (casi) la frecuencia de Canal 7 en TV Digital. El boom central tiene 1,70 metros de largo y como materia prima aproveché una vieja antena de TV de aire analógica que bajé para instalar la Right VHF.

No la pude terminar ya que el elemento Director no esta en las medidas correctas. Usé un dipolo ajustado a 550 Mhz y tendria que acortarlo 1cm de cada lado.

Algo que noté fue que, si bien tengo una antena de TV Digital a menos de 1 Km de mi casa (antes estaba a 100 Km) apuntando hacia Buenos Aires se recibian imágenes, mientras que apuntando a 90° no se recibia nada. Eso me da una idea de que la Yagi esta funcionando mas o menos bien.

La calculadora que usé es:

 http://www.k7mem.150m.com/Electronic_Notebook/antennas/yagi_vhf.html

Acá pueden ver algunas fotos mientras fui armado la antena:

 http://www.flickr.com/photos/alejolp/sets/72157625095857543/

Entre las fotos se colaron imágenes de la Ringo y el dipolo de 14.1Mhz, aunque está bastante sordo. Al final de todo pueden ver par a par la Yagi UHF contra la omni que trae el aparato.

73's, LU4EXT.

lunes, octubre 11, 2010

Problemas con Speedy


Al igual que Javier, tengo problemas con Speedy: navegando por paginas Web aparece un error aleatorio que me obliga a apretar F5 cada cierto tiempo.

Es bastante molesto hacer eso a mano, asi que hice un mini script para automatizar la tarea. Les presento a Hammer of Thor, un Proxy SOCKS que cuando detecta el error puntual de desconexion de Speedy sigue insistiendo hasta que logra cargar la página.

Técnicamente hablando, de forma aleatoria se genera un paquete IP con el flag RST activado, generando que efectivamente se cierre la conexión. Lo extraño es que ese paquete llega unos pocos milisegundos más tarde del saludo de tres vias. Cosa 'e mandinga dirá alguno.

El programa está hecho en Python usando Twisted, e implementa de forma casera el protocolo SOCKS v5 siguiendo la RFC. Espero poder sacar una nueva version que entienda tambien v4 y Proxy HTTP, pero mi tiempo libre es poco. Se aceptan contribuciones :)

Actualización 12 de Octubre: Parece que la causa de fondo es en realidad un "TCP reset attack"; para mas detalles mirar el thread de la lista de Ubuntu. Una alternativa al Martillo de Thor es filtrar los paquetes RST; por ejemplo con iptables para Linux se puede hacer:
iptables -A OUTPUT -p tcp --dport 80 -m state --state NEW -m recent --set --name thor --rdest -j ACCEPT
iptables -A INPUT -p tcp -m tcp --tcp-flag RST RST -m state --state ESTABLISHED -m recent --name thor --rcheck --rsource --seconds 1 -j DROP
La idea es muy similar al Martillo de Thor: si llega un RST antes de que se cumpla 1 segundo desde que se inició la conexion, descartarlo. Este es un problema que seguro habrá que escalarlo a la CNC, ¿no?.

sábado, octubre 02, 2010

Ejecutando código Python de forma segura con eval()

Respuesta corta


Eval es maligno, no lo intentes.

Respuesta larga


Hace unos días publicaron en la lista de Python Argentina la pregunta de qué tan peligroso era usar la función eval para ejecutar código:

code = raw_input('Ingrese una entrada: ')
eval(code)

Sucede que si el usuario ingresa una expresion similar a:

Ingrese una entrada: __import__('os').system('ls /')

Pueden ocurrir cosas malas; en este ejemplo se esta listando los archivos del directorio raíz, pero ingresando: "rm -rf ~" se van a borrar todos los archivos de la carpeta personal del usuario.

Entonces, eval() parece bastante malo.

Una primera mejora a la fución eval() es asignarle dos parámetros adicionales para anular las funciones de importacion de módulos. Haciendo:

eval(code, {'__import__': None}, {})

El anterior ejemplo ya no funciona:

>>> eval('__import__("os")', {'__import__': None}, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
TypeError: 'NoneType' object is not callable

Pero hay otra forma de pasar por arriba la limitacion de __import__:

>>> eval('__builtins__["__import__"]("os")', {'__import__': None}, {})
<module 'os' from '/usr/lib/python2.6/os.pyc'>

Ya tenemos de vuelta la referencia a __import__. Entonces como bien comentaron en la lista, una solución sería anular la referencia a __builtins__:

>>> eval('__builtins__["__import__"]("os")', {'__import__': None, '__builtins__': None}, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
TypeError: 'NoneType' object is unsubscriptable

Y si queremos abrir un arhivo tampoco se puede:

>>> eval('open("/tmp/aa", "w")', {'__import__': None, '__builtins__': None}, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'open' is not defined

Con la función 'file' tampoco funciona. El módulo __builtins__ es el módulo donde residen todas las funciones predefinidas de Python: file, open, list, dir, etc. Si queremos construir una lista tampoco se puede:

>>> eval('list()', {'__import__': None, '__builtins__': None}, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'list' is not defined

Pero hay otras formas de pasar por arriba las limitaciones de no tener __builtins__. Solo se necesita tener una referencia a un objeto que referencie a una función que nos permita hacer cosas no permitidas.

Una forma es usar las operaciones de 'introspection' de Python. Dada una instancia de un objeto podemos saber su clase, la clase padre y las subclases. Por ejemplo:

>>> (1).__class__.__bases__[0].__subclasses__()
[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, <type 'weakproxy'>, <type 'int'>, <type 'basestring'>, <type 'bytearray'>, ...]

En este caso estamos tomando la instancia del objeto int(1), preguntando su clase, luego la clase padre (object), y luego las subclases de ésta (¡un montón!).

Mirando atentamente la lista encontramos dos referencias interesantes:

  • <type 'file'>
  • <type 'zipimport.zipimporter'>

La primera es el tipo file(), la misma que se usa para leer y escribir archivos. La segunda es la clase zipimporter, que permite importar módulos dentro de un zip.

Lo interesante es que aún anulando la referencia al módulo __builtins__, las anteriores operaciones siguen funcionando:

>>> eval("""[x for x in (1).__class__.__bases__[0].__subclasses__() if x.__name__=='file'][0]("/proc/version")""", {'__import__': None, '__builtins__': None, }, {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
IOError: file() constructor not accessible in restricted mode

Intentando usar la referencia a 'file' tenemos un problema: el IOError.

El mensaje de error IOError aparece porque dentro de la función file() hay un bloque de código que verifica que __builtins__ no sea None.

Años atrás, el equipo de Python intentó agregarle al lenguaje la funcionalidad de ejecución restringida de código, que permita ejecutar código no seguro de forma segura.

Luego de varios intentos desistieron, justamente porque no era posible contemplar todos los casos. Hoy en día esas funciones están deprecated y en Python 3 fueron completamente removidas del código fuente.

Entonces, en Python 3 es posible importar cualquier módulo y ejectar codigo malicioso fácilmente, aún anulando __builtins__:

>>> (eval('[x for x in (1).__class__.__bases__[0].__subclasses__() if x.__name__ == "ImpImporter"][0]().find_module("os").load_module("os").system("id")', {'__import__': None, '__builtins__': None}, {}))
uid=1000(alejo) gid=1000(alejo) groups=1000(alejo),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),44(video),46(plugdev)

En este caso, la clase ImpImporter es una subclase de object que abstrae todo el comportamiento de importación de módulos. Acceder a esa clase es algo que no se puede evitar usando las opciones de eval().

Quedó pendiente la instancia de zipimporter.

Importar modulos con esa clase no imposible, la única complicación es conocer la ruta de algún egg o zip dentro del sistema que nos ofrezca alguna referencia a __builtins__, __import__, al módulo 'os' o a otro módulo que nos interese.

Por ejemplo, hacer un zip que tenga dentro un modulo que importe el módulo 'os' es bastante trivial:

>>> eval("""[x for x in (1).__class__.__bases__[0].__subclasses__() if x.__name__=='zipimporter'][0]("/tmp/modulo1.zip").find_module("modulo1").load_module("modulo1").os.system("id")""", {'__import__': None, '__builtins__': None, }, {})
uid=1000(alejo) gid=1000(alejo) groups=1000(alejo),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),44(video),46(plugdev)

En resumen, no se confíen de eval() para ejecutar código potencialmente inseguro. En la wiki de Python.org hay una sección dedicada exclusivamente a la seguridad, aquellos que estén interesados no dejen de leerla.

domingo, septiembre 12, 2010

The Knights who say Ni

''.join(reduce(lambda a,b:[a[0]/13,a[1]+[" aeghiknostwy"[a[0]%13]]],' '*22,[0x1220cc0bb8b8a537ca145,[]])[1])

update: reducida la cantidad de caracteres y corregido el error del espacio

martes, junio 29, 2010

Mac Pan


Mac Pan es una versión alternativa del Pac Man hecha en Python con Pygame. Los gráficos son de Emiliano Luciani y se puede bajar desde:

http://code.google.com/p/macpan/

Espero les guste :)

sábado, junio 26, 2010

Usando Pastebin desde la linea de comandos

En Debian y Ubuntu hay un paquete llamado "pastebinit" que permite enviar pegajosos a pastebin.com directamente:
aptitude install pastebinit

Y usarlo es muy facil:

pastebinit archivo.py

Tambien puede tomar el texto desde la entrada estandar en caso de querer enviar la salida de un comando:
comando | pastebinit

jueves, junio 24, 2010

Manejo de LVM en GNU/Linux

Acabo de ver que Leo en su blog publicó una serie de notas sobre como manejar LVM en sistemas GNU/Linux. ¡Imepecable Leo!

http://www.netstorming.com.ar/tag/lvm/

martes, junio 01, 2010

El comic perdido de XKCD


Dibujado por el mismo Randall Munroe, creador de XKCD. Acá está el post original de donde lo saqué.

jueves, abril 22, 2010

acelerando firefox/iceweasel

Despues de un tiempo firefox/iceweasel empiezan a andar muy lento. Ejecutando este comando vuelvo todo a la normalidad:

for f in $(find ~/.mozilla -iname '*.sqlite' -print); do sqlite3 $f "vacuum;"; done

Solo funciona en Linux teniendo instalado el paquete sqlite3. No se como hacerlo en Windows ya que no tengo uno a mano ahora.

viernes, abril 09, 2010

python: 70's

Para cerrarlo apretar Control-C en la terminal.

import pygame,math,itertools,random
for x in itertools.chain(itertools.islice(itertools.imap(lambda x: x(), [lambda: pygame.init(), lambda: pygame.display.set_mode((320,240))]),2,2), itertools.count()): (pygame.draw.circle(pygame.display.get_surface(),(random.randint(0,255),random.randint(0,255),random.randint(0,255)),(160,120),x%200+2,1), [pygame.display.get_surface().set_at((random.randint(0,319),random.randint(0,239)), (random.randint(0,255),random.randint(0,255),random.randint(0,255))) for y in xrange(1000)], pygame.display.flip()) and None

jueves, abril 08, 2010

creativo

Si no estas dispuesto a equivocarte, nunca vas a ser creativo.
Ken Robinson

python: wave or wave

import itertools, math, time
for x in itertools.count(0): print "".join([time.sleep(0.003)][0:0] + [y in [int(math.cos(x*3.14/(50 + 25*math.cos((x/50.0)*3.14/50)))*37 + 37), int(math.sin(x*3.14/(50 + 25*math.sin((x/50.0)*3.14/50)))*37 + 37)] and '#' or ' ' for y in xrange(75)])

miércoles, abril 07, 2010

python: wave

import itertools, math, time
for x in itertools.count(0): print "".join([time.sleep(0.005)][0:0] + [int(math.sin(x*3.14/(50))*37 + 37) == y and '#' or ' ' for y in xrange(75)])

martes, abril 06, 2010

python: 60's

import itertools,math,time
for z,w in itertools.imap(lambda x: (x % 12, (x / 12) % 5), itertools.count(0)): print ''.join(map(lambda x: x, ["\n".join([''.join([(math.hypot(x-10,y-10) < z and (math.hypot(x-10,y-10) > z/2 and '#$%&!'[w] or ' @'[(z/2)%2]) or ('.,:;+'[z%5])) for x in xrange(21)]) for y in xrange(21)]), time.sleep(0.05) or '']))

lunes, abril 05, 2010

python: ping pong

[actualizado] en una sola linea:

while 1: print str('d' not in globals() and globals().__setitem__('d', [__import__('random').randint(1,8),6,1,1]))[0:0] + "\n".join(['-'*12] + ['|' + ''.join([((x,y) == (d[0], d[1])) and '#' or ' ' for x in xrange(10)]) + '|' for y in xrange(10)] + ['-'*12]) + str((lambda: (d.__setitem__(0, d[0]+d[2]), d.__setitem__(1, d[1]+d[3]), d[0] not in range(1,9) and d.__setitem__(2, d[2] * -1), d[1] not in range(1,9) and d.__setitem__(3, d[3] * -1)))())[0:0] + str(__import__('time').sleep(0.2))[0:0]

domingo, abril 04, 2010

python: otra silueta

print "\n".join(["|" + "".join([int(10*(((x-10)**2)/float(10**2) + ((y-10)**2)/float(10**2))) in [10,11] and '#' or (((y == 10) and (x in range(3,18))) and '66656c696365732070617363756173'.decode('hex')[x-3] or ' ') for x in xrange(21)]) + "|" for y in xrange(21)])

python: silueta

import math;print "\n".join([''.join([int(math.cos(x * 3.14 / 19) * 5 + 2) == (y -2) and (abs(math.sin(x * 3.14 / 19)) < 0.05 and '*' or '#') or ' ' for x in xrange(78)]) for y in xrange(11)])

domingo, enero 17, 2010

Haití - Información recibida

Una conversación telefónica de Ramón Santoyo, XE1KK, con Hugo Ramón HI8VRS, confirmó que el team del RC Dominicano HI8RCD, compuesto por 8 radioaficionados, ha regresado a la ciudad fronteriza de Jimani en República Dominicana.

El convoy que los trasladaba, y que incluía a otras personas, fue asaltado recibiendo disparos que causaron varios heridos y 1 persona perdió la vida.

El grupo de radioaficionados salió ileso del ataque, debiendo volver a la frontera sin escolta reportando que la situación era extremadamente insegura.

Pudieron dejar instalada una repetidora de VHF que cubre ambas capitales, HI y HH, que está siendo usada por la Cruz Roja y la Defensa Civil ya que no hay comunicaciones viables en la zona.

Fuente: Lista de mails opinion-lu.

miércoles, enero 13, 2010

Software con nombre de frutas y verduras




En un día de inspiración extrema (???) se me ocurrió ver qué nombres de frutas y verduras habían sido usados en relación a programas de computadoras:
Y en SourceForge solamente:
  • Carrot2: clustering engine (Open Source).
  • Small Potato: juego de ajedrez (Open Source).
  • PotatoVM: máquina virtual de Squeak hecha en Java (Open Source).
  • Hot Potato: juego open source.
  • Tomato IDE: Entorno de desarrollo experimental (Open Source).
  • Tomato Firmware: firmware alternativo para routers WRT54G y otros basados en chipset Broadcom (Open Source).
  • libonion: Librería en C++ para el manejo de WebDAV (Open Source).
  • Strawberry: librería para el manejo de tags ID3 en archivos MP3 (Open Source).
  • Grape: software para el estudio de demostraciónes lógicas (Open Source).
  • Orange HRM: software de manejo de recursos humanos (Open Source).
 Hay más, pero me cansé de buscar.

    viernes, enero 08, 2010

    Forks

    El año pasado Sun compró MySQL y Oracle compró a Sun, dejando en un futuro incierto a MySQL: nadie sabe bien qué es lo que Oracle quiere hacer con MySQL.

    Lo que a mi me preocupa no es lo que Oracle haga con MySQL, sino lo que está ocurriendo ahora: ya hay varios forks (ramificaciones) del proyecto. Un fork consiste en tomar el código GPL de un proyecto y marcarle un nuevo rumbo, dividiendo esfuerzos.

    Eso nunca es bueno.

    Como dice Jeff Atwood en: Oh yeah? Fork you!:

    Los forks se diferencian en la intención. En un fork las personas creando un fork intentan que el fork reemplace o compita con el proyecto original.

    [...]

    Es muy difícil lograr que un fork triunfe. Es una dolorosa pero necesaria parte de la evolución del software de código abierto. Tal como en la evolución normal de la vida, sospecho que la mayoría de los forks mueren en grandes e innumerables cantidades antes de convertirse en suficientemente fuertes como para engendrar un nuevo proyecto por si mismos.

    Un fork es la piedra fundamental de cualquier proyecto de software open source, pero es un camino que no hay que tomar a la ligera.

    Hace unos años hice mi propio fork de un proyecto open source. Fracasó miserablemente ya que el poco apoyo que tuve con el proyecto murió por diferencias creativas. Hizo falta mucho esfuerzo, más del que le pude dedicar.

    La idea de un proyecto de software --cualquier proyecto de software-- es que todos se muevan para el mismo lado y entre todos lleven adelante el proyecto. Dividir esfuerzos va a hacer que el o los proyectos mueran.