Impossibile sovrascrivere il registro EIP

7

Codice sorgente per entrambi i programmi alla fine del post

Quindi, ho lavorato con Hacking: The Art Of Exploitation, e finora tutto bene. Sono riuscito a controllare EIP nel programma vulnerabile notesearch.c.

gdb-peda$ run $(perl -e 'print "a"x112 . "bbbb"')
Starting program: /root/hacking/booksrc/notesearch $(perl -e 'print "a"x112 . "bbbb"')
[DEBUG] found a 5 byte note for user id 0
[DEBUG] found a 7 byte note for user id 0
-------[ end of note data ]-------

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers----------------------------------    -]
EAX: 0x0 
EBX: 0x0 
ECX: 0xbffff300 ('a' <repeats 36 times>, "
gdb-peda$ run
Starting program: /root/vulnerable 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbb

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0x41414141 ('AAAA')
EDX: 0xb7fb687c --> 0x0 
ESI: 0x1 
EDI: 0xb7fb5000 --> 0x1b3db0 
EBP: 0x41414141 ('AAAA')
ESP: 0x4141413d ('=AAA')
EIP: 0x804841d (<main+50>:  ret)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]
   0x8048419 <main+46>: leave  
   0x804841a <main+47>: lea    esp,[ecx-0x4]
=> 0x804841d <main+50>: ret    
   0x804841e:   xchg   ax,ax
   0x8048420 <__libc_csu_init>: push   ebp
   0x8048421 <__libc_csu_init+1>:   push   edi
   0x8048422 <__libc_csu_init+2>:   push   esi
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x4141413d
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0804841d in main ()
gdb-peda$ p/x $eip
$1 = 0x804841d
gdb-peda$ 
3") EDX: 0x0 ESI: 0x2 EDI: 0xb7fb5000 --> 0x1b3db0 EBP: 0x0 ESP: 0xbffff300 ('a' <repeats 36 times>, "
#include <stdio.h>

int main(){
    char *buffer[64];
    gets(buffer);
    return 0;
}
3") EIP: 0x61616161 ('aaaa') EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code------------------------------------ -] Invalid $PC address: 0x61616161 [------------------------------------stack------------------------------------ -] 0000| 0xbffff300 ('a' <repeats 36 times>, "
gdb-peda$ run $(perl -e 'print "a"x112 . "bbbb"')
Starting program: /root/hacking/booksrc/notesearch $(perl -e 'print "a"x112 . "bbbb"')
[DEBUG] found a 5 byte note for user id 0
[DEBUG] found a 7 byte note for user id 0
-------[ end of note data ]-------

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers----------------------------------    -]
EAX: 0x0 
EBX: 0x0 
ECX: 0xbffff300 ('a' <repeats 36 times>, "
gdb-peda$ run
Starting program: /root/vulnerable 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbb

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0x41414141 ('AAAA')
EDX: 0xb7fb687c --> 0x0 
ESI: 0x1 
EDI: 0xb7fb5000 --> 0x1b3db0 
EBP: 0x41414141 ('AAAA')
ESP: 0x4141413d ('=AAA')
EIP: 0x804841d (<main+50>:  ret)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]
   0x8048419 <main+46>: leave  
   0x804841a <main+47>: lea    esp,[ecx-0x4]
=> 0x804841d <main+50>: ret    
   0x804841e:   xchg   ax,ax
   0x8048420 <__libc_csu_init>: push   ebp
   0x8048421 <__libc_csu_init+1>:   push   edi
   0x8048422 <__libc_csu_init+2>:   push   esi
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x4141413d
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0804841d in main ()
gdb-peda$ p/x $eip
$1 = 0x804841d
gdb-peda$ 
3") EDX: 0x0 ESI: 0x2 EDI: 0xb7fb5000 --> 0x1b3db0 EBP: 0x0 ESP: 0xbffff300 ('a' <repeats 36 times>, "
#include <stdio.h>

int main(){
    char *buffer[64];
    gets(buffer);
    return 0;
}
3") EIP: 0x61616161 ('aaaa') EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code------------------------------------ -] Invalid $PC address: 0x61616161 [------------------------------------stack------------------------------------ -] 0000| 0xbffff300 ('a' <repeats 36 times>, "%pre%3") 0004| 0xbffff304 ('a' <repeats 32 times>, "%pre%3") 0008| 0xbffff308 ('a' <repeats 28 times>, "%pre%3") 0012| 0xbffff30c ('a' <repeats 24 times>, "%pre%3") 0016| 0xbffff310 ('a' <repeats 20 times>, "%pre%3") 0020| 0xbffff314 ('a' <repeats 16 times>, "%pre%3") 0024| 0xbffff318 ('a' <repeats 12 times>, "%pre%3") 0028| 0xbffff31c ("aaaaaaaa%pre%3") [----------------------------------------------------------------------------- -] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x61616161 in ?? () gdb-peda$
3") 0004| 0xbffff304 ('a' <repeats 32 times>, "%pre%3") 0008| 0xbffff308 ('a' <repeats 28 times>, "%pre%3") 0012| 0xbffff30c ('a' <repeats 24 times>, "%pre%3") 0016| 0xbffff310 ('a' <repeats 20 times>, "%pre%3") 0020| 0xbffff314 ('a' <repeats 16 times>, "%pre%3") 0024| 0xbffff318 ('a' <repeats 12 times>, "%pre%3") 0028| 0xbffff31c ("aaaaaaaa%pre%3") [----------------------------------------------------------------------------- -] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x61616161 in ?? () gdb-peda$

Tuttavia, una volta che scrivo il mio codice buggy molto semplice e provo a controllare l'EIP, ciò accade

%pre%

Non ottengo nulla, l'ESP non dovrebbe rimanere invariato (dato che non è memorizzato nello stack) e EIP viene sovrascritto?

Puoi trovare notesearch.c @ link Di seguito è riportato il mio programma "sfruttabile".

Inutile dire che ho ASLR disabilitato e i programmi sono compilati con flag -fno-stack-protector e -zexecstack. Se hai bisogno di maggiori informazioni, lascia un commento.

%pre%     
posta user3006498 22.04.2016 - 18:57
fonte

1 risposta

6

Il tuo codice è sbagliato:

#include <stdio.h>

int main(){
    char *buffer[64];
    gets(buffer);
    return 0;
}

Il char *buffer[64] crea una serie di puntatori ai caratteri.

Riprova con questo:

#include <stdio.h>

int main(){
    char buffer[64];
    gets(buffer);
    return 0;
}

Esegui su IDEone .

In realtà, posso vedere alcuni motivi per cui questo non ha funzionato. Seguiamo il tuo assemblaggio:

   0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]

Poiché ebp-0x4 è una posizione all'interno del tuo buffer di input, ecx è caricato con 0x41414141 .

   0x8048419 <main+46>: leave  

Questo cancella il frame dello stack corrente, impostando fondamentalmente esp su ebp , quindi apre il valore superiore dallo stack in ebp per ripristinare il precedente puntatore del frame. Puoi nuovamente vedere che ebp è stato impostato su 0x41414141 , perché l'elemento in cima allo stack faceva ancora parte del tuo buffer.

   0x804841a <main+47>: lea    esp,[ecx-0x4]

Carica l'indirizzo effettivo di ecx-0x4 in esp . Pensa a lea come una comoda istruzione matematica del puntatore. In questo caso sta letteralmente facendo solo esp = ecx - 0x4 . Questo è il motivo per cui il tuo valore esp è 0x4141413d .

=> 0x804841d <main+50>: ret    

Un'istruzione ret imposta eip sul valore superiore nello stack. Il problema qui è che il puntatore dello stack è impostato su una memoria non valida. Lo hai sovrascritto con 0x4141413d .

Perché è successo? Il tuo carico utile è quasi certamente troppo lungo, tanto per cominciare, ma c'è una differenza nell'assemblaggio tra ciò che fa il tuo codice e ciò che il codice di esempio ha fatto. Tuttavia, c'è un rivestimento argentato: hai il controllo del puntatore dello stack immediatamente prima di un'istruzione ret . Ciò significa che devi solo puntare esp in una determinata memoria che controlli e ottieni il controllo di eip .

Quello che vuoi fare è eseguire il codice fino a raggiungere <main+43> , quindi calcolare l'offset nel tuo payload è stato collocato a ebp+0x4 . Puoi renderlo un po 'più semplice usando uno strumento come il file pattern_create.rb di Metasploit, ma solo osservare i valori nello stack dovrebbe essere sufficiente per risolverlo manualmente.

Quindi immaginiamo che 80 byte nel tuo payload siano dove l'applicazione legge questo valore. Il tuo payload ora vuole iniziare con 'A' * 80 . Dopo questo, codifica l'indirizzo dello stack meno 8 byte nel payload. Quindi, se il puntatore dello stack a quel punto era 0x4120EC40, sottrarre 8 per ottenere 0x4120EC38, quindi posizionare \x41\x20\xEC\x38 nel tuo payload dopo tutti i valori di A .

Al prossimo avvio del programma, ciò che dovrebbe accadere è questo:

0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]
; [ebp-0x4] contains an address slightly further up the stack (0x4120EC38)
; all the memory around this address contains 0x41414141
0x8048419 <main+46>: leave  
; leave the stack frame, setting esp and popping ebp
; both registers are trashed but it doesn't matter
0x804841a <main+47>: lea    esp,[ecx-0x4]
; subtract 4 from 0x4120EC38, giving us 0x4120EC34
; then set esp to this value - [esp] is now 0x41414141
0x804841d <main+50>: ret    
; pop the top value off the stack and set eip to it
; eip is now 0x41414141

Vinci.

Come appendice, potresti incontrare il problema che non puoi codificare l'indirizzo dello stack nel tuo payload perché contiene un byte null. È possibile aggirare questo accorciando il carico utile in modo che sovrascriva solo parzialmente il puntatore del frame dello stack, in modo da poter modificare il byte meno significativo (o due byte) consentendo il controllo parziale su esp per puntarlo più in alto sullo stack, piuttosto che totalmente sovrascrivendolo.

    
risposta data 22.04.2016 - 19:30
fonte

Leggi altre domande sui tag