Anrokku, un videojuego tipo puzzle

Anrokku es un juego de puzles que he programado estas semanas. Las reglas son simples, somos una ambulancia y tenemos que salir del parking debido a una emergencia. Desafortunadamente el parking es un caos y los coches bloquean la salida. Tu labor es ir moviendo los coches para lograr que la ambulancia salga del parking. Y cuantos menos movimientos hagas mejor.

En el menú principal podremos seleccionar a cuál de los 20 niveles queremos jugar. No podremos jugar a todos a la vez, es necesario habernos pasado los niveles anteriores para desbloquear el siguiente.

Ya en el juego tenemos que ir arrastrando los coches con el ratón para que la ambulancia pueda irse por la derecha. El juego está programando en Python 2.7 usando GTK. El renderizado está hecho en un GtkDrawingArea donde he usado Cairo. ¿Quiéres jugar? El juego completo es gratuito y open source bajo la liencia MIT en GitHub. No obstante, puedes descargar el archivo ZIP con el juego desde este enlace.

Descargar Anrokku

Después de descargar y descomprimir el archivo. Ejecuta el fichero main.py haciendo doble click o desde la terminal:

python2 main.py

¡Quiero ver muchas pantallas como esta!

 El juego almacena los récords obtenidos en cada nivel. Puede ser interesante repetir los niveles para hacerlo en el menor número posible de movimientos. En el primer nivel he conseguido ganar en 32 movimientos, ¿alguien se atreve a superarme?

loading...

Mandando paquetes ICMP ECHO personalizados con Python

Estos días he estado experimentando un poco con una característica de las redes. En concreto he intentando ver si era posible lanzar un paquete a la red cuyo origen es una dirección broadcast y el receptor, al mandar la respuesta, lo hiciera sin darse cuenta a todos los equipos de la red. Esto en efecto podría usarse para inutilizar una red por Denial of Service.

ICMP ECHO

La prueba la he hecho con un ICMP ECHO pero podría hacerse con otros protocolos también, como DHCP.

Un ICMP ECHO es lo que hace el famoso comando pingping6 (en IPv6). Se trata de un protocolo de la capa de red (capa 3 en TCP/IP). ICMP dispone de varias operaciones para funcionar correctamente (Internet Control Message Protocol, controlar la red) pero la mayoría de ellas no se utilizan. Una que sí se usa es el ECHO, que permite mandar una información a un host y el host nos tiene que devolver lo mismo.

¿Cómo sabe a donde tiene que enviar la respuesta? A la IP de origen del primer paquete claro, pero ¿y si mentimos? ¿Y si le ponemos que la IP de origen es la IP de broadcast? Supuestamente, enviaría la respuesta a todos los demás hosts de la subred.

Script en Python

Para poder hacer los datagramas IP personalizados y poder mentir, usé raw sockets. Estos solo me han funcionado en Linux. El código es muy simple, la parte que más me costó fue el checksum pues las operaciones con bytes en Python son un poco curiosas, no existiendo el tipo byte pero si bytes.

import socket
import struct
import random
import binascii
import sys
import functools

ICMP_CODE = socket.getprotobyname("icmp")
ICMP_ECHO = 8
IP_SRC = "192.168.0.255"
IP_DST = "192.168.0.255"

def main():
    s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)
    s.setsockopt(socket.SOL_IP,socket.IP_HDRINCL,1)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    packet_id = int((100000* random.random()) % 65535)
    packet = create_packet(packet_id)
    #print ("Size of packet: "+str(sys.getsizeof(packet)))
    s.sendto(packet,(IP_DST,0))

def create_header(data):
    version = 4 # IP version
    ihl = 5 # Numero de Bytes
    DF = 0
    Tlen = sys.getsizeof(data) + 20 # Longitud del datagrama
    ID = 1774 # ID de paquete
    Flag = 0 # Opciones
    Fragment = 0 # Numero de fragmento
    TTL = 128 # Tiempo de vida
    Proto = socket.IPPROTO_ICMP # Protocolo de los datos
    ip_checksum = checksum(data) # Checksum de los datos
    SIP = socket.inet_aton(IP_SRC) # Source IP address
    DIP = socket.inet_aton(IP_DST) # Destination IP address
    ver_ihl = (version << 4) + ihl
    f_f = (Flag << 13) + Fragment
    ip_hdr =  struct.pack("!BBHHHBBH4s4s", ver_ihl,DF,Tlen,ID,f_f,TTL,Proto,ip_checksum,SIP,DIP)
    return ip_hdr

def checksum(msg):
    flag = False
    suma = 0
    for byte in msg:
        if not flag:
            suma += (byte << 8)
        else:
            suma += byte
        flag = not flag
    resto = suma & 0xFFFF0000
    resto = resto >> 8
    suma += resto
    check = (~suma) & 0x0000FFFF
    return check

def create_data(id):
    header = struct.pack("bbHHh", ICMP_ECHO, 0, 0, id, 1)
    data = b"42"
    header = struct.pack("bbHHh", ICMP_ECHO, 0, socket.htons(checksum(header+data)), id, 1)
    return header + data

def create_packet(packet_id):
    data = create_data(packet_id)
    header = create_header(data)
    return header+data
while True:
    main()

Espero que a alguien le resulte interesante el código. Es un ejemplo de como generar datagramas sin la ayuda del sistema operativo. Además es importante saber que este tipo de programas solo pueden ejecutarse como root. Yo, por las pruebas que pude hacer, creo que los sistemas operativos actuales no son tontos y este tipo de ataques ya son conocidos. No pude capturar con Wireshark ninguno que fuese respuesta a broadcast, mientras que si la IP, aun siendo falsa, parecía real, sí que podía capturarla.
 

¡Haz scripts!

¡Haz scripts! ¡Escribe scripts! ¡Programa scripts! ¡Ejecuta scripts! ¡Automatiza! Escribir scripts tiene muchas ventajas. Escribir scripts es la mejor manera de ser productivo, mantener el entorno actualizado y evitar el error humano. ¡Automatiza!

Automation

Se es más productivo

Escribir scripts es la mejor manera de ser productivo. Perdemos parte de nuestro tiempo inicialmente para posteriormente recuperarlo en el futuro. Escribir un script es una inversión.

Estan siempre actualizados

Puede que hoy sepas el procedimiento exacto a realizar para una determinada tarea pero en el futuro puede que no lo sepas. El script siempre está actualizado, pues en cuanto deja de funcionar se debe reparar para seguir usándose. La documentación por ejemplo

bash

Menos errores

Tener un script reduce la posibilidad de error humano. Piensa que cada vez que hacemos algo de memoria podemos fallar. ¡Y puede que no sepamos cuando ha pasado eso!

Fáciles de compartir

Hoy día es muy fácil compartir scripts con el mundo. Cualquier programa de ‘paste’ funciona y sirve. Pastebin, BitBin.it, DesdeLinux Paste, GitHub Gist, BitBucket Snippets, Mozilla Paste, Ubuntu Paste, CryptoBin, Pasted, …

Algunos incluso te pagan por las visitas

Son TUS herramientas

Eres programador. Usas herramientas diseñadas por otros programadores. ¿Por qué no hacer tú alguna de tus herramientas? Agilizan tu entorno de trabajo como solo tu sabes. El verdadero maestro conoce sus herramientas al dedillo, si las diseñas todo ya tendrás mucho trecho hecho.

powershell

¿A qué esperas?

Creo que se ha quedado demostrado que quiero que hagas scripts; que automatices. Da igual el lenguaje que uses, pero usa tus propios scripts. Puedes usar Perl, Python, JavaScript, Ruby, Tcl, Bash, Fish, PowerShell, Lua y muchos más.