¿Cómo puedo ejecutar shell en este ejercicio CTF?

2

Estoy jugando un juego de guerra CTF y, por desgracia, me quedé atascado en este nivel, así que quiero "crowdsourcing". No hay necesidad de una respuesta completa, pero las sugerencias serían suficientes.

¿Cómo puedo:

  1. Haz que strcmp sea 0 (evalúa si es falso)
  2. ¿De alguna manera, suprimir las canciones?

Quiero que el shell sea ejecutado:

execl("/bin/sh", "sh", NULL);

¿Alguna idea?

Binary es setuid y /levels/level08.pass solo se puede leer en un nivel superior.

-r-sr-x---  1 level9  level8   7696 Apr 25  2015 level08
-r--------  1 level8  level8    412 Apr 25  2015 level08.c
-r--------  1 level9  level9     13 Apr 25  2015 level08.pass

El código del programa para el nivel08.c está debajo.

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
        char buf[64];
        FILE *fp;
    signal(SIGABRT, SIG_DFL);
    fp = fopen("/levels/level08.pass", "r");
        fgets(buf, 64, fp);
        buf[strcspn(buf, "\n")] = '
execl("/bin/sh", "sh", NULL);
'; if(strcmp(buf, argv[1])) raise(SIGABRT); execl("/bin/sh", "sh", NULL); }
    
pregunta android_dev 25.05.2016 - 14:58
fuente

3 respuestas

3

La llamada strcmp y lo que conduce a ella es correcta. Tu segundo presentimiento, para suprimir un poco la señal, es el correcto.

signal(SIGABRT, SIG_DFL);
…
raise(SIGABRT);

La llamada a raise genera una señal cuya acción predeterminada es eliminar el programa. La llamada previa a signal garantiza que se realice la acción predeterminada. Cuando un proceso señala por sí mismo, esto es síncrono: la señal se recibe antes de que regrese la función raise .

¿Cuál es el truco? Además de ser ignorado , las señales pueden bloquearse . Cuando se entrega una señal ignorada, no pasa nada. Cuando se recibe una señal bloqueada, el núcleo simplemente toma nota de ella, pero no la entrega, por lo que el programa sigue funcionando normalmente. Cuando la señal se desbloquea, se entrega y se realiza la acción asociada con la señal en el momento de la entrega.

Las señales bloqueadas cruzan execve de los límites. Hay una nota de eso en el justificación POSIX para execve . La función para gestionar el bloqueo de la señal es sigprocmask .

Así que invoca el programa con SIGABRT bloqueado y omitirás la verificación de contraseña.

perl -MPOSIX -we 'sigprocmask(SIG_BLOCK, POSIX::SigSet->new(SIGABRT), POSIX::SigSet->new()); exec "level08", ""'
    
respondido por el Gilles 25.05.2016 - 20:16
fuente
2
  
  1. Haz que strcmp sea 0
  2.   

Suponiendo una implementación correcta de strcmp, esto significa que argv[1] debe coincidir exactamente con el contenido de level08.pass para 63 bytes o hasta la primera línea nueva / byte nulo.

Como no conocemos el contenido del archivo, nuestra única opción sería manipular argv[1] para que apunte a una dirección en la memoria que contenga la cadena correcta (por ejemplo, buf ). La ausencia de cualquier argc cheques me hizo preguntarme acerca de esto, pero no es posible la forma en que se maneja argv .

  
  1. De alguna manera suprimir señales
  2.   

Eche un vistazo a la máscara de señal de proceso.

Hay un par de puntos clave en este párrafo de the docs :

  

La colección de señales que están actualmente bloqueadas se llama   máscara de señal. Cada proceso tiene su propia máscara de señal. Cuando creas un   proceso nuevo (ver Creación de un proceso), hereda la máscara de su padre.   Puede bloquear o desbloquear señales con total flexibilidad modificando   la máscara de la señal.

    
respondido por el grc 25.05.2016 - 17:47
fuente
0

Parece que ejecuta el shell si ingresas la primera línea de /levels/level08.pass . Tal vez puedas usar un ataque de tiempo para verificar dónde sale strcmp y usarlo para adivinar un personaje a la vez.

    
respondido por el Sjoerd 25.05.2016 - 15:30
fuente

Lea otras preguntas en las etiquetas