«Se te dan bien las expresiones regulares, ¿no? ;)» Así empieza el enunciado del level 6. Un level (IMHO) jodido al que mis compañeros Joserra y Beñat estuvieron, durante unas cuantas horas, dándole vueltas, mientras el resto nos devanábamos los sesos con el level de la calculadora polaca inversa (RPN)…
Nos pasan el siguiente churro:
#!/bin/sed -rnuf s/.*/Password:/;p;n;s/[^a-zA-Z0-9]/_/g;s/./ /g;s/[0-9] /0 /g;s/[a-p] /1 /g;s/[q-z] /2 /g;s/[A-P] /3 /g;s/[Q-Z] /4 /g;y/abcdefghijklmnopqrstuvwxyz/0123456789abcdef0123456789/;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/0123456789abcdef0123456789/;s/_/50/g;s/(.)(.) /21/g;x;s/$/-----/g;s/-/---/g;s/-/----/g;s/-/---/g;x;:x;y/072b346d18a9f5ce/143c527e9ab0d6f8/;ta;:a;s/[^0x]/x /g;y/fedcba987654321/edcba9876543210/;ta;s/(x*)0(x*)0/12020/g;s/x{16}//g;s/x{15}0/f/g;s/x{14}0/e/g;s/x{13}0/d/g;s/x{12}0/c/g;s/x{11}0/b/g;s/x{10}0/a/g;s/x{9}0/9/g;s/x{8}0/8/g;s/x{7}0/7/g;s/x{6}0/6/g;s/x{5}0/5/g;s/x{4}0/4/g;s/x{3}0/3/g;s/x{2}0/2/g;s/x{1}0/1/g;s/^(0)(.{3})(.*)/132/;s/^(1)(.{8})(.*)/132/;s/^(2)(.{7})(.*)/132/;s/^(4)(.{2})(.*)/132/;s/^(6)(.{10})(.*)/132/;s/^(8)(.{9})(.*)/132/;s/^(a)(.{11})(.*)/132/;s/^(c)(.{5})(.*)/132/;s/^(e)(.{16})(.*)/132/;s/(...)(.*)/21/;tz;:z;x;s/-//;x;tx;s/^017c43a81ddb8b638fb3a32c51f4$/Win!/;Tf;p;q;:f;s/.*/You Fail It!/;p;q |
Precioso, ¿eh?. Bien, antes de llegar a este nivel creía que controlaba algo del editor de flujos de texto sed («sed – stream editor for filtering and transforming text»), pero cuando ví este script me dí cuenta que aún me faltaban «algunos» conocimientos al respecto. En fin, vayamos por partes.
Sed nos permite manipular texto desde la línea de comandos con scripts concisos y la ayuda de expresiones regulares (mmmh… no me meteré a explicar qué son las expresiones regulares, hay libros completos para ello, bastante tengo con sed 🙂
Por ejemplo, para pasar de «esto es una prueba» a «esto una prueba es», podríamos ejecutar lo siguiente:
echo "esto es una prueba" | sed -re 's/(.*) es(.*)/12 es/' |
-r = expresiones regulares extendidas
-e = editar en línea (en lugar de meter el script sed en un fichero)
La primera línea del script que nos pasan es:
#!/bin/sed -rnuf |
El shebang y la ruta al ejecutable de sed, con los parámetros -rnuf.
-n = quiet (que no escriba automáticamente el resultado de ejecutar cada línea del script sed, como hace por defecto. Si dentro del script se quisiera imprimir, habría que ejecutar el comando ‘p’ de sed)
-u = unbuffered (no tengo clara esta opción… se supone que ésto hace que sed lea cantidades mínimas de la entrada estándar y escriba por salida estándar los resultados ‘más frecuentemente’, sin almacenar resultados en buffers, pero no sé exactamente cómo afecta al script)
-f = el script viene a continuación, en este mismo fichero
Lo primero que hay que hacer es formatear y comentar el script, para ver qué demonios hace. Por ejemplo, las primeras líneas:
s/.*/Password:/; # lee la primera línea que le pasemos y la sustituye por 'Password:' p; # escribe el resultado de la sustitución (es decir, escribe 'Password:') n; # salta a la siguiente línea de entrada estándar |
¿Te animas a seguir descifrando el script? Una vez que lo hagas, comenzarás a entender qué es lo que se supone que hay que hacer…
Nosotros encontramos un script de python, sedsed, que permite hacer un debug de todo el script de sed. La verdad es que es util, porque muestra en cada paso de script el buffer de pattern, y el buffer de hold. Basta hacer un volcado del debug a un archivo txt, y ver después qué hace cada comando en el script. Por cierto, muy curioso el método para sumar en hexadecimal 😉