Indirizzi cablati e relativi nello shellcode

3

Questa domanda è principalmente nel contesto dell'esecuzione di comandi arbitrari in un overflow del buffer (ad es. stack).

Recentemente ho letto da qualche parte che gli indirizzi (assoluti) cablati sono non buoni per lo shellcode, ad es. ad esempio usando / bin / sh . Il problema è che significa che il codice non è indipendente dalla posizione.

Tuttavia, non capisco perché gli indirizzi cablati non siano preferibili a quelli relativi. Gli indirizzi cablati non significherebbero che le librerie / chiamate desiderate utilizzate nell'attacco sono accessibili ovunque il codice (cioè è indipendente dalla posizione) dove gli indirizzi relativi indicano che il codice deve essere nella posizione corretta rispetto alla chiamata?

    
posta Sean Frötkék 18.05.2017 - 11:58
fonte

2 risposte

1

Gli indirizzi relativi avranno sempre un vantaggio rispetto a quelli codificati, perché? lasciami spiegare:

  • Supponiamo che tu esegua nuovamente l'applicazione dopo l'uscita o un riavvio potrebbe non essere caricato sugli stessi indirizzi in memoria
  • ASLR: randomizzazione del layout dello spazio degli indirizzi, una funzionalità di sicurezza in Sistemi operativi che non caricheranno mai l'eseguibile nello stesso spazio ... questo significherà che gli indirizzi saranno diversi ogni volta, quindi gli indirizzi hard codificati non funzioneranno e dovrai cambiarli ogni volta che è veramente zoppo e funziona solo.
  • Dire, vuoi passare a un indirizzo specifico, invece di jmp [indirizzo] sarebbe sempre bene essere relativi ad alcuni registri come jmp ecx + 8 e questo non cambierà anche se cambiano gli indirizzi.
risposta data 18.05.2017 - 12:27
fonte
1

Ci sono due tipi di problemi che penso tu stia confondendo. Uno è l'indirizzo delle funzioni chiamate dal tuo shellcode fornite dall'applicazione vulnerabile o dalle librerie caricate, e l'altro è salti assoluti o relativi all'interno del tuo shellcode.

Chiamate di libreria

Supponiamo, per un secondo, che tu stia tentando un exploit return-to-libc su un semplice binario. Quindi vuoi l'indirizzo di system per molti di questi exploit. Costruiamo un piccolo binario che stampa l'indirizzo di system .

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  printf("system @%p\n", system);
  return 0;
}

Compila ed esegui alcune volte:

% gcc -o getsystem getsystem.c
% ./getsystem
system @0x7fdc54419d40
% ./getsystem
system @0x7fbc15b61d40
% ./getsystem
system @0x7fbeacfb6d40

Si noti che ogni volta che viene eseguito, l'indirizzo di system è cambiato. Ciò è dovuto a una moderna mitigazione della sicurezza chiamata ASLR: la libreria C viene caricata su un indirizzo di base diverso, quindi system verrà caricato in un indirizzo diverso. Di conseguenza, lo shellcode deve prima individuare libc, quindi chiamare system a un indirizzo relativo all'inizio della libreria. (Chiamato "indirizzo base".)

Salta

In uno shellcode più complesso, potrebbe essere necessario creare un jmp o call all'interno del payload stesso. In questi casi, devi avere salti e chiamate relativi, perché non conosci l'indirizzo esatto in cui verrà caricato il codice shell. Invece di dire "salta a 0x0804abcd ", dovresti "saltare 5 byte avanti". Questo è il significato di "Position-Independent Code": può funzionare quando caricato in qualsiasi posizione, e non solo ad un indirizzo di partenza fisso.

Poiché lo shellcode di solito viene caricato nello stack o nell'heap, entrambi sono soggetti a varie manipolazioni (ASLR, altri dati che utilizzano lo stack / heap, threading, ecc.), è impossibile prevedere un indirizzo assoluto in cui lo shellcode terreni.

    
risposta data 13.01.2018 - 23:07
fonte

Leggi altre domande sui tag