Come posso eseguire shell in questo esercizio CTF?

2

Sto giocando a un wargame CTF e sfortunatamente sono rimasto bloccato a questo livello, quindi voglio "crowdsourcing". Non c'è bisogno di una risposta completa, ma i suggerimenti sarebbero sufficienti.

Come posso:

  1. Rendi strcmp da 0 (valuta se a false)
  2. In qualche modo surprima i cantanti?

Voglio che la shell sia eseguita:

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

Qualche idea?

Binary è setuid e /levels/level08.pass è leggibile solo a livello superiore.

-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

Il codice del programma per level08.c è riportato di seguito.

#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); }
    
posta android_dev 25.05.2016 - 14:58
fonte

3 risposte

3

La chiamata strcmp e ciò che la porta è corretta. La tua seconda impressione, per sopprimere un po 'il segnale, è quella giusta.

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

La chiamata a raise genera un segnale la cui azione predefinita è quella di uccidere il programma. La chiamata precedente a signal garantisce che venga eseguita l'azione predefinita. Quando un processo segnala se stesso, questo è sincrono: il segnale viene ricevuto prima che la funzione raise ritorni.

Qual è il trucco? Oltre a ignorati , i segnali possono essere bloccati . Quando viene consegnato un segnale ignorato, non succede nulla. Quando viene ricevuto un segnale bloccato, il kernel si limita a prenderne nota, ma non lo consegna, quindi il programma continua a funzionare normalmente. Quando il segnale viene sbloccato, viene consegnato e viene eseguita l'azione associata al segnale al momento della consegna.

I segnali bloccati superano i confini di execve . Ne è disponibile una nota nella POSIX razionale per execve . La funzione per gestire il blocco del segnale è sigprocmask .

Quindi richiamare il programma con SIGABRT bloccato e ignorerai il controllo della password.

perl -MPOSIX -we 'sigprocmask(SIG_BLOCK, POSIX::SigSet->new(SIGABRT), POSIX::SigSet->new()); exec "level08", ""'
    
risposta data 25.05.2016 - 20:16
fonte
2
  1. Make strcmp to be 0

Supponendo una corretta implementazione di strcmp, significa che argv[1] deve corrispondere esattamente al contenuto di level08.pass per 63 byte o fino al primo byte newline / null.

Poiché non conosciamo il contenuto del file, la nostra unica opzione sarebbe manipolare argv[1] per puntare a un indirizzo in memoria contenente la stringa corretta (ad esempio buf ). L'assenza di qualsiasi controllo di argc mi ha fatto riflettere su questo, ma non è possibile il modo in cui viene gestito argv .

  1. Somehow suppress signals

Dai un'occhiata alla maschera del segnale di processo.

Ci sono un paio di punti chiave in questo paragrafo da i documenti :

The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.

    
risposta data 25.05.2016 - 17:47
fonte
0

Sembra che esegua la shell se inserisci la prima riga di /levels/level08.pass . Forse puoi utilizzare un attacco a tempo per controllare dove esce strcmp e usarlo per indovinare un personaggio alla volta.

    
risposta data 25.05.2016 - 15:30
fonte

Leggi altre domande sui tag