Il codice più corto per lanciare SIGILL


76

sfondo

Abbiamo già una sfida nel lanciare SIGSEGV , quindi perché non una sfida a lanciare SIGILL?

Che cos'è SIGILL?

SIGILL è il segnale per un'istruzione illegale nel processore, che accade molto raramente. L'azione predefinita dopo aver ricevuto SIGILL sta terminando il programma e scrivendo un core dump. L'ID del segnale di SIGILL è 4. Riscontri SIGILL molto raramente e non ho assolutamente idea di come generarlo nel tuo codice se non tramitesudo kill -s 4 <pid> .

Regole

Avrai root nei tuoi programmi, ma se non lo vuoi per nessun motivo, puoi anche usare un utente normale. Sono su un computer Linux con impostazioni locali tedesche e non conosco il testo inglese che viene visualizzato dopo aver catturato SIGILL, ma penso che sia qualcosa come "istruzioni illegali". Vince il programma più corto che lancia SIGILL.


6
Potresti voler chiarire se l'istruzione deve essere generata dal kernel o meno. In particolare, vuoi consentire al programma di generarlo direttamente usando la chiamata libc raise(SIGILL)?

1
Lo dice davvero Illegal instruction (core dumped).
Erik the Outgolfer,

@ ais523 Tutto è permesso.
Mega Man,

5
Per qualsiasi hardware che può aumentare SIGILL, la risposta sarà la stessa della lunghezza dell'istruzione. Metti semplicemente un'istruzione illegale da qualche parte e prova a eseguirla. L'unica cosa interessante sarà la complicata toolchain coinvolta.
Smetti di fare del male a Monica il

3
* le persone che pubblicano vecchi programmi che non hanno funzionato *
RudolfJelin,

Risposte:


112

Assemblatore PDP-11 (UNIX Sixth Edition), 1 byte

9

L'istruzione 9 non è un'istruzione valida sul PDP-11 (in ottale, sarebbe 000011, che non appare nell'elenco delle istruzioni (PDF)). L'assemblatore PDP-11 fornito con UNIX Sixth Edition sembra fare eco a tutto ciò che non capisce direttamente nel file; in questo caso, 9 è un numero, quindi genera un'istruzione letterale 9. Ha anche la proprietà dispari (al giorno d'oggi insolita nei linguaggi di assemblaggio) che i file iniziano a funzionare dall'inizio, quindi non abbiamo bisogno di dichiarazioni per rendere il programma lavoro.

Puoi testare il programma usando questo emulatore , anche se dovrai lottare con esso per inserire il programma.

Ecco come vanno le cose una volta che hai capito come usare il filesystem, l'editor, il terminale e cose simili che pensavi di sapere già come usare:

% a.out
Illegal instruction -- Core dumped

Ho confermato con la documentazione che si tratta di un SIGILLsegnale autentico (e aveva persino lo stesso numero di segnale, 4, fino a quel momento!)


1
Aveva lo stesso numero di segnale perché POSIX, UNIX e SUS sono strettamente correlati :)
cat

4
Quasi tutti i numeri di segnale in V6 hanno ancora gli stessi significati oggi; i mnemonici sono stati in realtà meno stabili dei numeri. Confronta minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/sys/param.h con github.com/freebsd/freebsd/blob/master/sys/sys/signal.h - semantica identica per Da 1 a 13, ma solo 1, 2 e 13 hanno esattamente gli stessi nomi. (SIGALRM / 14 e SIGTERM / 15 sono stati aggiunti solo in V7.) (Il lignaggio System V ha un paio di modifiche, in particolare spostando SIGBUS da 10 a 7 (sostituendo l'inutile SIGEMT) e SIGSYS sopra 15, per fare spazio a SIGUSR1 e SIGUSR2.)
zwol,

4
@cat POSIX e SUS in realtà non specificano i valori dei segnali, ma specificano il significato di alcuni numeri quando vengono passati come argomenti al comando kill, ma SIGILL non è incluso.
Casuale 832,

7
a.outcontiene più byte, infatti (l' 9istruzione viene compilata in due byte e l'assemblatore aggiunge anche un'intestazione e un piè di pagina per rendere eseguibile il programma). Ecco perché ho scritto il programma in linguaggio assembly, non in codice macchina. Il programma di linguaggio assembly ha solo un byte in e si compila in un programma con più byte in; questo è un problema di code-golf (minimizza le dimensioni della sorgente), non un problema di codifica (minimizza le dimensioni dell'eseguibile), quindi è la dimensione di 1 byte della sorgente che conta.

2
Abuso molto intelligente di un vecchio ma fantastico sistema.
Albero

81

C (x86_64, tcc ), 7 byte

main=6;

Ispirato da questa risposta .

Provalo online!

Come funziona

L'assembly generato è simile al seguente.

    .globl  main
main:
    .long 6

Si noti che TCC non inserisce la "funzione" definita in un segmento di dati .

Dopo la compilazione, _start indicherà main come al solito. Quando viene eseguito il programma risultante, si aspetta il codice in main e trova il numero intero 6 a 32 bit little-endian (!) , Che è codificato come 0x06 0x00 0x00 0x00 . Il primo byte - 0x06 - è un codice operativo non valido, quindi il programma termina con SIGILL .


C (x86_64, gcc ), 13 byte

const main=6;

Provalo online!

Come funziona

Senza il modificatore const , l'assembly generato è simile al seguente.

    .globl  main
    .data
main:
    .long   6
    .section    .note.GNU-stack,"",@progbits

Il linker di GCC considera l'ultima riga come un suggerimento che l'oggetto generato non richiede uno stack eseguibile. Poiché main è esplicitamente inserito in una sezione di dati , il codice operativo che contiene non è eseguibile, quindi il programma termina SIGSEGV (errore di segmentazione).

La rimozione della seconda o dell'ultima riga farà funzionare l'eseguibile generato come previsto. L'ultima riga potrebbe essere ignorata con il flag del compilatore -zexecstack( provalo online! ), Ma questo costa 12 byte .

Un'alternativa più breve è dichiarare main con il modificatore const , risultante nel seguente assemblaggio.

        .globl  main
        .section    .rodata
main:
        .long   6
        .section    .note.GNU-stack,"",@progbits

Funziona senza flag di compilazione. Si noti che main=6;scriverebbe la "funzione" definita nei dati , ma il modificatore const fa invece scrivere a GCC in rodata , che (almeno sulla mia piattaforma) può contenere codice.


Adoro evitare completamente di usare anche una funzione :) Ma come funziona in termini di C? Il compilatore vede che mainè un 6 e prova a chiamarlo (che immagino lo farebbe rinunciare e provare le istruzioni)?
Mia yun Ruse,

11
@JackDobson è un comportamento indefinito, quindi non funziona in termini di C; sei in balia del compilatore. Clang ha anche un avvertimento per questo per qualche motivo: "la variabile denominata 'main' con collegamento esterno ha un comportamento indefinito".
Bobby Sacamano,

2
GCC si lamenterà di mainnon essere una funzione, ma solo se si attivano gli avvisi ( -Wallo -pedanticlo faranno).
zwol,

Penso che sia abbastanza standard per gli eseguibili per sistemi simili a Unix avere segmenti di testo / dati / bss . Il linker inserisce la .rodata sezione all'interno del segmento di testo dell'eseguibile e mi aspetto che ciò accada praticamente su qualsiasi piattaforma. (Il programma di caricamento del kernel si preoccupa solo dei segmenti, non delle sezioni).
Peter Cordes,

3
Si noti inoltre che 06è solo un'istruzione non valida in x86-64. In modalità a 32 bit, lo è PUSH ES, quindi questa risposta funziona solo con compilatori predefiniti -m64. Vedi ref.x86asm.net/coder.html#x06 . L'unica sequenza di byte che è garantito per decodificare come un'istruzione non valida su tutte le CPU x86 future è il 2 byte di UD2 : 0F 0B. Qualsiasi altra cosa potrebbe essere un prefisso futuro o una codifica delle istruzioni. Tuttavia, è stato votato per un ottimo modo per ottenere un compilatore C per incollare mainun'etichetta su alcuni byte!
Peter Cordes,

39

Rapido, 5 byte

[][0]

Indice di accesso 0 di un array vuoto. Questo chiama fatalError(), che stampa un messaggio di errore e si blocca con un SIGILL. Puoi provarlo qui .


Questo è uno dei più difficili;)
Mega Man

26
... perché mai si schianta con un SIGILL? Chi pensava che fosse un segnale appropriato?
Pantaloni a vita bassa

4
@Asu No; fatalError()si arresta intenzionalmente eseguendo ud2. Perché abbiano scelto di farlo non lo so, ma forse hanno pensato che il messaggio di errore "Istruzioni illegali" avesse senso perché il programma ha fatto qualcosa di illegale.
Nessuno Nada,

2
Brillante. Scommetto che questo è anche il codice Swift più breve per causare un arresto anomalo.
JAL

3
@JAL Sì; Non riesco a pensare a niente di più corto. Ho provato nil!, ma il compilatore non è riuscito a inferire il tipo di risultato. (Inoltre, ciao JAL!)
NobodyNada,

23

GNU C, 25 byte

main(){__builtin_trap();}

GNU C (un dialetto specifico di C con estensioni) contiene un'istruzione per arrestare intenzionalmente il programma. L'implementazione esatta varia da versione a versione, ma spesso gli sviluppatori tentano di implementare il crash nel modo più economico possibile, il che comporta normalmente l'uso di un'istruzione illegale.

La versione specifica che ho usato per testare è gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0; tuttavia, questo programma provoca un SIGILL su una gamma abbastanza ampia di piattaforme, e quindi è abbastanza portatile. Inoltre, lo fa eseguendo effettivamente un'istruzione illegale. Ecco il codice assembly che compila sopra con le impostazioni di ottimizzazione predefinite:

main:
    pushq %rbp
    movq %rsp, %rbp
    ud2

ud2 è un'istruzione che Intel garantisce che rimarrà sempre indefinita.


11
−6:main(){asm("ud2");}
wchargin,

Inoltre, non so come contiamo i byte per l'assemblaggio non 00 00 0f 0bud2
elaborato

5
@wchargin: questa è una risposta x86 + GNU C. Questo è portatile per tutti i sistemi GNU. Si noti inoltre che UD2 è solo 2 byte . IDK dove hai preso quei 00byte; non fanno parte del codice macchina per UD2. A proposito, come ho commentato la risposta di Dennis , per ora ci sono istruzioni illegali a un byte in x86-64, ma non è garantito che rimangano tali.
Peter Cordes,

@wchargin: contiamo i byte per funzioni / programmi con codice macchina come ti aspetteresti. Guarda alcune delle mie risposte, come Adler32 in 32 byte di codice macchina x86-64 o GCD in 8 byte di codice macchina x86-32 .
Peter Cordes,

1
@Ruslan: Non lo sono; 00 00decodifica lo stesso in x86-64 (as add [rax], al). 00 00 0f 0bdi solito SIGSEGV prima di SIGILL, a meno che tu non abbia un puntatore scrivibile dentro rax.
Peter Cordes,

22

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).


Su x86-64 / linux con gcc6 nella sua modalità predefinita (indulgente), const main=6;funziona, così come diverse varianti. Questo linker (che sospetto sia anche il tuo linker) è in grado di generare un salto da .texta .rodata; il problema che hai riscontrato è che, senza const, stai saltando nel segmento di dati scrivibili ( .data), che non è eseguibile su hardware moderno. Avrebbe funzionato su vecchi x86, in cui l'hardware di protezione della memoria non poteva contrassegnare le pagine come leggibili ma non eseguibili.
zwol,

Si noti che anche in C89, maindeve essere una funzione (§5.1.2.2.1) - Non so perché gcc consideri la dichiarazione maincome oggetto dati meritare solo un avvertimento, e solo con -pedanticsulla riga di comando. Qualcuno nei primi anni '90 forse pensava che nessuno lo avrebbe fatto per caso, ma non è che sia una cosa utile da fare apposta se non per questo tipo di gioco.
zwol,

1
... Rileggendo ancora, sembra che ti aspetti main[]="/"di passare al segmento di dati di sola lettura, perché i valori letterali delle stringhe vanno in rodata. Sei stato colto dalla differenza tra char *foo = "..."e char foo[] = "...". char *foo = "..."è zucchero sintattico per const char __inaccessible1[] = "..."; char *foo = (char *)&__inaccessible1[0];, quindi la stringa letterale va in rodata ed fooè una variabile globale separata e scrivibile che punta ad essa. Con char foo[] = "...", tuttavia, l'intero array va nel segmento di dati scrivibili.
zwol,

19

GNU come (x86_64), 3 byte

ud2

$ xxd sigill.S

00000000: 7564 32                                  ud2

$ as --64 sigill.S -o sigill.o; ld -S sigill.o -o sigill

sigill.S: Assembler messages:
sigill.S: Warning: end of file not at end of a line; newline inserted
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400078

$ ./sigill

Illegal instruction

$ objdump -d sigill

sigill:     file format elf64-x86-64

Disassembly of section .text:

0000000000400078 <__bss_start-0x200002>:>
  400078:       0f 0b                   ud2

Deve esserci un modo per esprimerlo in una "sorgente" a due byte ...
Stop Harming Monica,

Oh, intelligente. Mi chiedevo se ci fosse un modo per costruire questo che avrebbe messo il punto di ingresso all'inizio del file (senza dichiarazioni) e che non avrebbe comportato penalità per un'insolita configurazione del sistema di compilazione. Non riuscivo a trovarne uno, ma sembra che tu l'abbia fatto.

@ ais523: sì, il mio solito build-script NASM / YASM ( asm-link) per programmi giocattolo a file singolo avrebbe creato un eseguibile da questa fonte allo stesso modo, poiché per ldimpostazione predefinita il punto di ingresso all'inizio del segmento di testo o qualcosa del genere. Semplicemente non pensavo di scegliere la dimensione della fonte per questo: P
Peter Cordes,

18

Bash su Raspbian su QEMU, 4 (1?) Byte

Non è il mio lavoro. Riferisco semplicemente il lavoro di un altro. Non sono nemmeno in grado di testare il reclamo. Poiché una parte cruciale di questa sfida sembra essere la ricerca di un ambiente in cui questo segnale verrà raccolto e catturato, non includo le dimensioni di QEMU, Raspbian o bash.

Il 27 febbraio 2013 alle 20:49 , l'utente emlhalac ha riferito " Ottenere" istruzioni illegali "quando tenta di chroot " sul forum di Raspberry Pi.

ping

produzione

qemu: uncaught target signal 4 (Illegal instruction) - core dumped
Illegal instruction (core dumped)

Immagino che comandi molto più brevi produrranno questo output, ad esempio tr.

EDIT: basato sul commento di @ fluffy , ha ridotto il limite inferiore ipotizzato sulla lunghezza dell'input a "1?".


5
Penserei che il [comando avrebbe vinto. :)
soffice

17

File COM MS-DOS x86, 2 byte

EDIT: Come sottolineato nei commenti, DOS stesso non intrappolerà l'eccezione della CPU e si bloccherà (non solo l'app, l'intero sistema operativo). L'esecuzione su un sistema operativo basato su NT a 32 bit come Windows XP, infatti, innescherà un segnale di istruzione illegale.

0F 0B

Dalla documentazione :

Genera un codice operativo non valido. Questa istruzione viene fornita per i test del software per generare esplicitamente un codice operativo non valido.

Il che è piuttosto autoesplicativo. Salvare come file .com ed eseguirlo in qualsiasi emulatore DOS Gli emulatori DOS si arrestano in modo anomalo. Esegui su Windows XP, Vista o 7 a 32 bit.

SIGILL su Windows XP


1
Tecnicamente, il processore genera un'eccezione di istruzione illegale. Tuttavia, DOS ha una protezione della memoria molto limitata e capacità di gestione delle eccezioni, e non sarei sorpreso se solo causasse un comportamento indefinito / crash del sistema operativo. L'OP non ha detto che il kernel ha dovuto rilevare l'errore e stampare "Illegal Instruction" sulla console.
Maservant,

4
Ho pensato a questa soluzione, ma non credo sia valida. La domanda richiede un segnale di istruzione illegale , non solo una trappola del processore di istruzioni illegale , quindi l'obiettivo era trovare un sistema operativo che avrebbe effettivamente generato un segnale in risposta alla #UDtrappola. (Inoltre, ho deciso di testarlo, e sembrava lanciare il mio emulatore DOS in un ciclo infinito.)

2
Ho provato questo su MS-DOS reale su un AMD K6-II. Eseguendolo si blocca semplicemente il sistema, con e senza EMM386 in esecuzione. (EMM386 intrappola alcuni errori e arresta il sistema con un messaggio, quindi vale la pena testarlo per vedere se ha fatto la differenza.)
Marco

2
Sì, le finestre basate su DOS dovrebbero essere in grado di catturare davvero la trappola e almeno arrestare l'app.
Asu,

2
@Asu Posso confermare che funziona su XP a 32 bit e probabilmente funzionerà su tutti gli altri sistemi Windows a 32 bit. Sono d'accordo che questa non è una soluzione su DOS stesso, in quanto si blocca.
Maservant,

13

C (Windows a 32 bit), 34 byte

f(i){(&i)[-1]-=9;}main(){f(2831);}

Funziona solo se si compila senza ottimizzazioni (altrimenti, il codice illegale nella ffunzione è "ottimizzato").

Lo smontaggio della mainfunzione è simile al seguente:

68 0f 0b 00 00    push 0b0f
e8 a1 d3 ff ff    call _f
...

Possiamo vedere che utilizza pushun'istruzione con un valore letterale 0b0f(little-endian, quindi i suoi byte vengono scambiati). L' callistruzione invia un indirizzo di ritorno ( ...dell'istruzione), che si trova sullo stack vicino al parametro della funzione. Usando uno [-1]spostamento, la funzione sovrascrive l'indirizzo di ritorno in modo che punti 9 byte prima, dove si trovano i byte 0f 0b.

Questi byte causano un'eccezione "istruzione non definita", come previsto.


12

Java, 50 43 24 byte

a->a.exec("kill -4 $$");

Questo è un java.util.function.Consumer<Runtime>1 il cui comando viene rubato dalla risposta di Fluffy . Funziona perché devi chiamarlo come whateverNameYouGiveIt.accept(Runtime.getRuntime())!

Si noti che ciò creerà un nuovo processo e lo farà lanciare un SIGILL piuttosto che lanciare un SIGILL stesso.

1 - Tecnicamente, può anche essere un java.util.function.Function<Runtime, Process>perché Runtime#exec(String)restituisce un java.lang.Processche può essere usato per controllare il processo appena creato eseguendo un comando shell.


Per fare qualcosa di più impressionante in un linguaggio così dettagliato, ecco un bonus di 72 60 a 48 byte:

a->for(int b=0;;b++)a.exec("sudo kill -s 4 "+b);

Questo è un altro Consumer<Runtime>che attraversa TUTTI i processi (incluso se stesso), facendo sì che ognuno di essi lanci un SIGILL. Meglio prepararsi per un incidente violento.


E un altro bonus (a Consumer<ANYTHING_GOES>), che almeno finge di lanciare un SIGILL in 20 byte:

a->System.exit(132);

8

Perl, 9 byte

kill+4,$$

Chiama semplicemente la funzione di libreria appropriata per segnalare un processo e fa in modo che il programma segnali con se stesso SIGILL. Qui non sono coinvolte istruzioni illegali effettive, ma produce il risultato appropriato. (Penso che questo renda la sfida abbastanza economica, ma se qualcosa è permesso, questa è la scappatoia che useresti ...)


Sono venuto qui per pubblicare lo stesso, con uno spazio anziché il +. :)
simbabque il

2
Quando le persone imparano il Perl per la programmazione non golfistica, lo imparano con a +. Dopo aver giocato a golf per un po ', ogni +tanto lo fanno per mettersi in mostra. Alla fine, hanno scritto abbastanza programmi in cui avevano bisogno di evitare gli spazi bianchi per qualche motivo o per +diventare un'abitudine. (Analizza anche in modo meno ambiguo, perché si aggira innescando il caso speciale nel parser per le parentesi.)

8

ARM Unified Assembler Language (UAL), 3 byte

nop

Per esempio:

$ as ill.s -o ill.o
$ ld ill.o -o ill
ld: warning: cannot find entry symbol _start; defaulting to 00010054
$ ./ill 
Illegal instruction

Dopo l'esecuzione nop, il processore interpreta la .ARM.attributessezione come codice e incontra da qualche parte un'istruzione illegale:

$ objdump -D ill

ill:     file format elf32-littlearm


Disassembly of section .text:

00010054 <__bss_end__-0x10004>:
   10054:       e1a00000        nop                     ; (mov r0, r0)

Disassembly of section .ARM.attributes:

00000000 <.ARM.attributes>:
   0:   00001341        andeq   r1, r0, r1, asr #6
   4:   61656100        cmnvs   r5, r0, lsl #2
   8:   01006962        tsteq   r0, r2, ror #18
   c:   00000009        andeq   r0, r0, r9
  10:   01080106        tsteq   r8, r6, lsl #2

Testato su un Raspberry Pi 3.


In qualche modo questo non funziona su un Pi 2.
Mega Man

7

Microsoft C (Visual Studio 2005 in poi), 16 byte

main(){__ud2();}

Non posso facilmente verificarlo, ma secondo la documentazione dovrebbe produrre un'istruzione illegale provando intenzionalmente a eseguire un'istruzione solo kernel da un programma in modalità utente. (Si noti che poiché l'istruzione illegale arresta in modo anomalo il programma, non è necessario provare a tornare indietro main, il che significa che questa mainfunzione in stile K & R è valida. Visual Studio non è mai passato da C89 di solito è una cosa negativa, ma è arrivato utile qui.)


Puoi compilare per Linux con VS2015? Perché non penso che SIGILL sia definito in Windows, vero?
Andrew Savinykh,

7

Rubino, 13 byte

`kill -4 #$$`

Immagino sia sicuro supporre che lo stiamo eseguendo da una shell * nix. I letterali backtick eseguono il comando shell specificato. $$è il processo Ruby in esecuzione e #è per l'interpolazione di stringhe.


Senza chiamare direttamente la shell:

Rubino, 17 byte

Process.kill 4,$$

6

Qualsiasi shell (sh, bash, csh, ecc.), Qualsiasi POSIX (10 byte)

Risposta fondamentale ma non avevo visto nessuno pubblicarlo.

kill -4 $$

Invia SIGILL al processo corrente. Esempio di output su OSX:

bash-3.2$ kill -4 $$
Illegal instruction: 4

Si potrebbe fare kill -4 1se la domanda non è specifica su quale programma genera SIGILL
Mark K Cowan,

@MarkKCowan Heh, buon punto, anche se questo presuppone radice ...
soffice

2
You will have root in your programs- cancella un byte dalla tua risposta e troll leggermente la domanda allo stesso tempo: D. BONUS: Devi uccidereinit
Mark K Cowan il

2
@MarkKCowan: Su (versioni moderne di?) Linux, in initrealtà è immune ai segnali che non ha specificamente richiesto di ricevere, anche con root. Tuttavia, potresti forse aggirare questo problema utilizzando un diverso sistema operativo POSIX.

2
kill -4 2quindi: D
Mark K Cowan,

6

ELF + codice macchina x86, 45 byte

Questo dovrebbe essere il più piccolo programma eseguibile su una macchina Unix che lancia SIGILL (a causa del fatto che Linux non riconosce l'eseguibile se reso più piccolo).

Compilare con nasm -f bin -o a.out tiny_sigill.asm, testato su una macchina virtuale x64.

Binario a 45 byte effettivi:

0000000 457f 464c 0001 0000 0000 0000 0000 0001

0000020 0002 0003 0020 0001 0020 0001 0004 0000

0000040 0b0f c031 cd40 0080 0034 0020 0001

Elenco degli assiemi (vedi fonte sotto):

;tiny_sigill.asm      
BITS 32


            org     0x00010000

            db      0x7F, "ELF"             ; e_ident
            dd      1                                       ; p_type
            dd      0                                       ; p_offset
            dd      $$                                      ; p_vaddr 
            dw      2                       ; e_type        ; p_paddr
            dw      3                       ; e_machine
            dd      _start                  ; e_version     ; p_filesz
            dd      _start                  ; e_entry       ; p_memsz
            dd      4                       ; e_phoff       ; p_flags


_start:
                ud2                             ; e_shoff       ; p_align
                xor     eax, eax
                inc     eax                     ; e_flags
                int     0x80
                db      0
                dw      0x34                    ; e_ehsize
                dw      0x20                    ; e_phentsize
                db      1                       ; e_phnum
                                                ; e_shentsize
                                                ; e_shnum
                                                ; e_shstrndx

  filesize      equ     $ - $$

Disclaimer: codice dal seguente tutorial sulla scrittura del programma di assemblaggio più piccolo per restituire un numero, ma utilizzando opcode ud2 invece di mov: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html


2
Avrei pubblicato un eseguibile modificato di quell'esatto tutorial, ma mi hai battuto. Questo merita di vincere; È un vero minimalista nel senso delle risorse di sistema (non richiede più di 45 byte sia in file che in memoria, ed è esattamente lo stesso in entrambi), e nessun interprete gonfio come le altre soluzioni assembler. È semplicemente quello che è.
Iwillnotexist Idonotexist,

5

AutoIt , 93 byte

Utilizzo dell'assemblaggio in linea del flatassembler:

#include<AssembleIt.au3>
Func W()
_("use32")
_("ud2")
_("ret")
EndFunc
_AssembleIt("int","W")

Quando eseguito in modalità interattiva SciTE, si bloccherà immediatamente. Il debugger di Windows dovrebbe apparire per una frazione di secondo. L'output della console sarà simile al seguente:

--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
0x0F0BC3
!>14:27:09 AutoIt3.exe ended.rc:-1073741795

Dove si -1073741795trova il codice di errore non definito generato da WinAPI. Questo può essere qualsiasi numero negativo.

Simile usando il mio assemblatore LASM :

#include<LASM.au3>
$_=LASM_ASMToMemory("ud2"&@CRLF&"ret 16")
LASM_CallMemory($_,0,0,0,0)

5

NASM, 25 byte

Non so come funzioni, solo che lo fa sul mio computer (Linux x86_64).

global start
start:
jmp 0

Compila ed esegui come:

$ nasm -f elf64 ill.asm && ld ill.o && ./a.out
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080
Illegal instruction

Probabilmente puoi accorciarlo a quattro byte, comeja 0
Mark K Cowan il

1
o tre comeud2
Mark K Cowan,

1
Probabilmente perché sta cercando di passare ad alcuni dati?
Asu,

5

Gruppo esadecimale TI-83, 2 byte

PROGRAM:I
:AsmPrgmED77

Esegui come Asm(prgmI). Esegue il codice operativo 0xed77 illegale. Conto ogni coppia di cifre esadecimali come un byte.



3

x86 .COM, 1 byte

c

ARPLcausa #UDin modalità 16 bit


1

Shell Linux, 9 byte

kill -4 0

Invia SIGILLal processo con PID 0. Non so quale processo abbia PID 0, ma esiste sempre.

Provalo online!


Da man kill:0 All processes in the current process group are signaled.
Dennis,

1

GNU C, 24 19 18 byte

-4 grazie a Dennis
-1 grazie a ceilingcat

main(){goto*&"'";}

Provalo online! Ciò presuppone ASCII e x86_64. Tenta di eseguire il codice macchina 27, che ... è illegale.


shortC , 10 5 4 byte

AV"'

Equivalente al codice GNU C sopra. Provalo online!


L"\6"è anche illegale, supponendo x86_64.
Dennis,

@Dennis Che istruzione è 0x06? Inoltre, Lnon è necessario.
MD XF,

Non è assegnato.
Dennis,

Non è assegnato; questo è ciò che lo rende illegale. Inoltre, 'è 39 = 0x27 , non 0x39 .
Dennis

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.