martes, 22 de marzo de 2011

Humo y espejos con el terminal y `cat`

Cross-posteado en el blog de HackXCrack

Si alguna vez se te ocurrió lanzar un cat a un archivo que no fuera de texto, como una imágen o un ejecutable hay ciertas posibilidades de que notaras que había pasado algo raro cuando el comando volvió, el terminal "pensó" que habías escrito algunos caracteres... es más, si pulsaste [enter] para pasar a una línea limpia pensando que solo es basura que dejó el archivo, el terminal había intentado ejecutar el comando!

Me atreveré a decir que lo que pasó fue que en algún momento el cat mostró el par de caracteres \x1b Z  ( \x1b es ESC ), mostrando algo como "62;9;c", hay más combinaciones que producen estos eventos pero esta, por ser la más corta, es la que tiene más probabilidades de darse por casualidad.

Todo esto viene porque el terminal emula un procolo antiguo, que acepta ciertas combinaciones de datos como caracteres de control (algo similar era en lo que se basaba el phreaking analógico :P ), aprovechando esto y esperando que el usuario también pulse instintivamente [enter] para pasar a una línea en blanco intentaremos que el usuario que lea un archivo ejecute un comando :), aunque la verdad sea dicha, estamos muy limitados.

Nota: aquí hablo del comando cat, pero pasa lo mismo con cualquiera que muestre algo directamente por pantalla, head, tail, un echo preparado o el programa que muestra un archivo que escribiste cuando aprendías.

Nota2: realmente todo esto tiene un motivo, pero si hay que profundizar en el protocolo el día de hoy se nos queda corto, si quieres hecharle un vistazo a sus entrañas revisa los links del final.

Pero empezemos por algo más sencillo, supongamos que queremos que el terminal deje de responder cuando lea un archivo, desde el terminal escribe esto:

echo -e "\x1bP" > danger

Se generará un archivo "danger", si lo intentamos leer con cat el terminal se detendrá ( aunque la interfaz gráfica siga funcionanado sin problemas ).

 Realmente lo que ha pasado es que ese código ( llamado "Device control" ) le indica al terminal que se ponga en modo "Graphics String Format" y intentará leer los datos que vienen detrás como pertenecientes a ese formato, hasta que encuentre otro código, ESC \ ("\x1b\\"), que hará que salga de ese modo, así que si no lo incluimos, no será capaz de interpretar lo que muestre el cat después ni lo que el usuario teclee.

Bien, volvamos a lo nuestro, estas son las combinaciones interesantes que encontré hasta ahora:

ESC: \x1b 

ESC c: borra la terminal

ESC [ t: amplia hasta esas filas la terminal

ESC Z ó ESC [c ó ESC [0c : el usuario teclea
          "62;9;c" en gnome-terminal
          "1;2c" en xterm

ESC [5n : el usuario teclea
          "n" en xterm y gnome-terminal

ESC [6n : el usuario teclea
          "1R" ó ";1R" si es a partir de la sexta línea

ESC [?9h : convierte los clicks en el terminal en cadenas de caracteres
           que teclea el usuario

ESC [13t : el usuario teclea
          "261;79t"

ESC [14t : el usuario teclea
          "136;640t"

ESC [18t : el usuario teclea
          ";;80t"

ESC [19t : el usuario teclea
          ";52;180t"

ESC [20t : el usuario teclea
          "LTerminal"
ESC [21t : el usuario teclea
          "lTerminal"

ESC [x : el usuario teclea
          "x"

ESC P : corta el flujo datos hasta ESC \


Si nos olvidamos de los números, que no nos sirven para nada, nos quedamos con esto:

ESC [5n : el usuario teclea
          "n" en xterm y gnome-terminal
ESC [x : el usuario teclea
          "x"
ESC [20t : el usuario teclea
          "LTerminal"
ESC [21t : el usuario teclea
          "lTerminal"


Es decir, que si queremos que el usuario "teclee" nx, le pasaremos un archivo generado con esto:

echo -e "\x1b[5n\x1b[0x" > danger


Como truco de magia está pasable, pero con solo las letras "n", "x" y las palabras "lTerminal" y "LTerminal" no podemos lograr gran cosa, como mucho ejecutar "nn", un lector de noticias.

Pero aquí no acaba todo, aún nos queda un truco bajo la manga, hay un código que nos permite leer los clicks en el terminal, y a que no adivinais como los muestra ? Sí, interpreta que los escribió el usuario :D

El código es:

ESC [?9h


Lo podemos activar con

echo -e "\x1b[?9h"


Con esto solo podremos conseguir que ejecute comandos de dos letras ( después del código de cada posición el terminal añade un espacio. En fin, hechandole imaginación podemos intentar que ejecute el servidor X

echo -e "\x1b[30t\x1bc\x1b[27;45fPulsa aqui[\x1b[7mX\x1b[0m]\x1b[?9h"

  • \x1b[30t : Para obtener suficientes filas y poder conseguir el código X;
  • \x1bc : Se deja la terminal en blanco
  • \x1b[27;45f : Saltamos a la fila 27, columna 45
  • Pulsa aqui[ : Se muestra al usuario
  • \x1b[7m : Invierte el esquema de colores
  • X : Algo donde pulsar :P
  • \x1b[0m : Restaura el esquema de colores
  • ] : Se muestra por pantalla
  • \x1b[?9h : Para que convierta los clicks en las posiciones en códigos


Y eso es todo, a portarse bien ;)

[Recursos]
http://www.vt100.net/
http://www.windred.dk/avr/info/ascii-tabel_vt-codes.htm
http://ascii-table.com/ansi-escape-sequences-vt-100.php

2 comentarios: