C (x86_64), 11, 30, 34 o 34 + 15 = 49 byte
main[]="/";
c=6;main(){((void(*)())&c)();}
main(){int c=6;((void(*)())&c)();}
Ho presentato un paio di soluzioni che usano le funzioni di libreria per lanciare SIGILLcon vari mezzi, ma probabilmente è barare, in quanto la funzione di libreria risolve il problema. Ecco una gamma di soluzioni che non utilizzano funzioni di libreria e fanno ipotesi diverse su dove il sistema operativo è disposto a consentire l'esecuzione di codice non eseguibile. (Le costanti qui sono scelte per x86_64, ma è possibile modificarle per ottenere soluzioni funzionanti per la maggior parte degli altri processori che hanno istruzioni illegali.)
06è il byte con il numero più basso di codice macchina che non corrisponde a un'istruzione definita su un processore x86_64. Quindi tutto ciò che dobbiamo fare è eseguirlo. (In alternativa, 2Fè anche indefinito e corrisponde a un singolo carattere ASCII stampabile.) Nessuno di questi è garantito per essere sempre indefinito, ma non sono definiti al giorno d'oggi.
Il primo programma qui viene eseguito 2Fdal segmento di dati di sola lettura. La maggior parte dei linker non è in grado di produrre un salto funzionante da .texta.rodata (o l'equivalente del loro OS) come non è qualcosa che possa mai essere utile in un programma correttamente segmentato; Non ho ancora trovato un sistema operativo su cui funzioni. Dovresti anche tenere conto del fatto che molti compilatori vogliono che la stringa in questione sia una stringa larga, il che richiederebbe un ulterioreL; Suppongo che qualsiasi sistema operativo su cui funzioni abbia una visione abbastanza obsoleta delle cose, e quindi stia costruendo per impostazione predefinita uno standard pre-C94. È possibile che non funzioni da nessuna parte questo programma, ma è anche possibile che ci sia un posto in cui questo programma funziona, e quindi lo sto elencando in questa raccolta di potenziali risposte più dubbi o meno dubbi. (Dopo aver postato questa risposta, Dennis ha anche menzionato la possibilità main[]={6}nella chat, che è della stessa lunghezza e che non incontra problemi con la larghezza dei caratteri, e ha anche accennato al potenziale per main=6; Non posso ragionevolmente rivendicare queste risposte come il mio, dato che non li ho pensati io.)
Il secondo programma qui viene eseguito 06dal segmento di dati di lettura-scrittura. Nella maggior parte dei sistemi operativi ciò causerà un errore di segmentazione, poiché i segmenti di dati scrivibili sono considerati un difetto di progettazione errato che rende probabili gli exploit. Questo non è sempre stato il caso, quindi probabilmente funziona su una versione sufficientemente vecchia di Linux, ma non riesco facilmente a provarlo.
Il terzo programma viene eseguito 06dallo stack. Ancora una volta, ciò causa un errore di segmentazione al giorno d'oggi, poiché lo stack è normalmente classificato come non scrivibile per motivi di sicurezza. La documentazione del linker che ho visto implica fortemente che era legale eseguirla dallo stack (a differenza dei due casi precedenti, farlo occasionalmente è utile), quindi anche se non posso provarlo, sono abbastanza sicuro che ci siano alcuni versione di Linux (e probabilmente altri sistemi operativi) su cui funziona.
Infine, se si assegna -Wl,-z,execstack(penalità di 15 byte) a gcc(se si utilizza GNU ldcome parte del back-end), si spegne esplicitamente la protezione dello stack eseguibile, consentendo al terzo programma di funzionare e dando un segnale di funzionamento illegale come previsto. Io ho testato e verificato questa versione 49 byte per lavorare. (Dennis menziona in chat che questa opzione sembra funzionare main=6, il che darebbe un punteggio di 6 + 15. Sono abbastanza sorpreso che funzioni, dato che il 6 palesemente non è in pila; l'opzione di collegamento apparentemente fa più di il suo nome suggerisce).
raise(SIGILL)?