Kode terpendek untuk melempar SIGILL


76

Latar Belakang

Kami sudah memiliki tantangan tentang melempar SIGSEGV , jadi mengapa bukan tantangan tentang melempar SIGILL?

Apa itu SIGILL?

SIGILL adalah sinyal untuk instruksi ilegal di prosesor, yang jarang terjadi. Tindakan default setelah menerima SIGILL adalah menghentikan program dan menulis dump inti. ID sinyal SIGILL adalah 4. Anda jarang menemukan SIGILL, dan saya sama sekali tidak tahu cara membuatnya dalam kode Anda kecuali melalui sudo kill -s 4 <pid>.

Aturan

Anda akan memiliki root di program Anda, tetapi jika Anda tidak mau karena alasan apa pun, Anda juga dapat menggunakan pengguna normal. Saya menggunakan komputer Linux dengan lokal Jerman dan saya tidak tahu teks bahasa Inggris yang ditampilkan setelah menangkap SIGILL, tapi saya pikir itu sesuatu seperti 'Instruksi ilegal'. Program terpendek yang melempar SIGILL menang.


6
Anda mungkin ingin mengklarifikasi apakah instruksi harus dihasilkan oleh kernel atau tidak. Secara khusus, apakah Anda ingin mengizinkan program hanya menghasilkan secara langsung menggunakan panggilan libc raise(SIGILL)?

1
Benar-benar dikatakan Illegal instruction (core dumped).
Erik the Outgolfer

@ ais523 Semuanya diizinkan.
Mega Man

5
Untuk perangkat keras apa pun yang dapat meningkatkan SIGILL, jawabannya akan sama dengan panjang instruksi. Cukup letakkan instruksi ilegal di suatu tempat dan coba jalankan. Satu-satunya hal yang menarik adalah toolchain yang terlibat.
OrangeDog

3
* orang yang memposting program lama yang tidak berhasil *
RudolfJelin

Jawaban:


112

Assembler PDP-11 (Edisi Keenam UNIX), 1 byte

9

Instruksi 9 bukan instruksi yang valid pada PDP-11 (dalam oktal, itu akan menjadi 000011, yang tidak muncul pada daftar instruksi (PDF)). Assembler PDP-11 yang dikirimkan bersama UNIX Sixth Edition ternyata menggemakan semua yang tidak dimengerti ke dalam file secara langsung; dalam hal ini, 9 adalah angka, sehingga menghasilkan instruksi literal 9. Ini juga memiliki properti aneh (tidak biasa dalam bahasa assembly saat ini) bahwa file mulai berjalan dari awal, jadi kita tidak perlu deklarasi untuk membuat program kerja.

Anda dapat menguji program menggunakan emulator ini , meskipun Anda harus berjuang sedikit untuk memasukkan program.

Inilah cara akhirnya setelah Anda menemukan cara menggunakan sistem file, editor, terminal, dan hal-hal serupa yang Anda pikir sudah Anda ketahui cara menggunakannya:

% a.out
Illegal instruction -- Core dumped

Saya telah mengkonfirmasi dengan dokumentasi bahwa ini adalah SIGILLsinyal asli (dan bahkan memiliki nomor sinyal yang sama, 4, sejak saat itu!)


1
Itu memiliki nomor sinyal yang sama karena POSIX dan UNIX dan SUS terkait erat :)
cat

4
Hampir semua nomor sinyal di V6 masih memiliki arti yang sama saat ini; mnemonik sebenarnya kurang stabil dari pada angka. Bandingkan minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/sys/param.h dengan github.com/freebsd/freebsd/blob/master/sys/sys/signal.h - semantik identik untuk 1 hingga 13, tetapi hanya 1, 2, dan 13 yang memiliki nama yang persis sama. (SIGALRM / 14 dan SIGTERM / 15 hanya ditambahkan dalam V7.) (Silsilah Sistem V memiliki beberapa perubahan, terutama memindahkan SIGBUS dari 10 ke 7 (mengganti SIGEMT yang tidak berguna) dan SIGSYS di atas 15, untuk memberikan ruang bagi SIGUSR1 dan SIGUSR2.)
zwol

4
@cat POSIX dan SUS tidak benar-benar menentukan nilai-nilai sinyal - mereka benar-benar menentukan arti beberapa angka ketika diteruskan sebagai argumen untuk perintah kill, tetapi SIGILL tidak termasuk.
Random832

7
a.outmemiliki banyak byte di dalamnya, memang ( 9instruksi dikompilasi menjadi dua byte, dan assembler juga menambahkan header dan footer untuk membuat program dapat dieksekusi). Itu sebabnya saya menulis program dalam bahasa assembly, bukan dalam kode mesin. Program bahasa assembly hanya memiliki satu byte, dan mengkompilasi ke program dengan byte lebih banyak di; ini adalah masalah kode-golf (meminimalkan ukuran sumber), bukan masalah pembuatan kode (meminimalkan ukuran yang dapat dieksekusi), jadi ukuran 1-byte dari sumber yang penting.

2
Penyalahgunaan sangat pintar dari sistem yang lama tapi mengagumkan.
Mast

81

C (x86_64, tcc ), 7 byte

main=6;

Terinspirasi oleh jawaban ini .

Cobalah online!

Bagaimana itu bekerja

Perakitan yang dihasilkan terlihat seperti ini.

    .globl  main
main:
    .long 6

Perhatikan bahwa TCC tidak menempatkan "fungsi" yang ditentukan di segmen data .

Setelah dikompilasi, _start akan mengarah ke main seperti biasa. Ketika program yang dihasilkan dijalankan, ia mengharapkan kode di main dan menemukan integer 6 bit-endian (!) 6 , yang dikodekan sebagai 0x06 0x00 0x00 0x00 . Byte pertama - 0x06 - adalah opcode yang tidak valid, sehingga program berakhir dengan SIGILL .


C (x86_64, gcc ), 13 byte

const main=6;

Cobalah online!

Bagaimana itu bekerja

Tanpa pengubah const , rakitan yang dihasilkan terlihat seperti ini.

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

Linker GCC memperlakukan baris terakhir sebagai petunjuk bahwa objek yang dihasilkan tidak memerlukan stack yang dapat dieksekusi. Karena main secara eksplisit ditempatkan di bagian data , opcode yang dikandungnya tidak dapat dieksekusi, sehingga program akan berhenti SIGSEGV (kesalahan segmentasi).

Menghapus baris kedua atau terakhir akan membuat pekerjaan yang dapat dieksekusi seperti yang dimaksudkan. Baris terakhir dapat diabaikan dengan flag compiler -zexecstack( Coba online! ), Tetapi ini biayanya 12 byte .

Alternatif yang lebih pendek adalah mendeklarasikan main dengan const modifier, menghasilkan perakitan berikut.

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

Ini berfungsi tanpa flag kompiler. Catatan yang main=6;akan menulis "fungsi" yang didefinisikan dalam data , tetapi pengubah const membuat GCC menulisnya di rodata , yang (setidaknya pada platform saya) diizinkan berisi kode.


Suka penghindaran lengkap bahkan menggunakan fungsi :) Bagaimana cara kerjanya dalam istilah C? Apakah kompiler melihat bahwa mainangka 6 dan mencoba menyebutnya (yang saya kira akan membuatnya menyerah dan mencoba instruksinya)?
Mia yun Ruse

11
@JackDobson itu adalah perilaku yang tidak terdefinisi, sehingga tidak berfungsi dalam hal C; Anda berada di tangan kompiler. Dentang bahkan memiliki peringatan untuk ini karena beberapa alasan: "variabel bernama 'utama' dengan tautan eksternal memiliki perilaku yang tidak jelas".
Bobby Sacamano

2
GCC akan mengeluh tentang maintidak menjadi fungsi tetapi hanya jika Anda menghidupkan peringatan (salah satu -Wallatau -pedanticakan melakukannya).
zwol

Saya pikir itu cukup standar untuk executable untuk sistem seperti Unix untuk memiliki segmen teks / data / bss . Linker menempatkan .rodata bagian di dalam segmen teks yang dapat dieksekusi, dan saya berharap ini akan menjadi kasus pada hampir semua platform. (Program-loader kernel hanya peduli pada segmen, bukan bagian).
Peter Cordes

3
Perhatikan juga bahwa 06ini hanya instruksi yang tidak valid di x86-64. Dalam mode 32-bit, itu PUSH ES, jadi jawaban ini hanya berfungsi dengan kompiler yang defaultnya -m64. Lihat ref.x86asm.net/coder.html#x06 . Satu-satunya urutan byte yang dijamin untuk memecahkan kode sebagai instruksi ilegal di semua CPU x86 masa depan adalah 2 byte UD2 : 0F 0B. Yang lain bisa berupa awalan atau pengkodean instruksi di masa depan. Namun, dipilih untuk cara yang keren untuk mendapatkan kompiler C untuk menempelkan mainlabel pada beberapa byte!
Peter Cordes

39

Swift, 5 byte

[][0]

Indeks akses 0 dari array kosong. Panggilan ini fatalError(), yang mencetak pesan kesalahan dan lumpuh dengan SIGILL. Anda bisa mencobanya di sini .


Ini adalah salah satu yang lebih sulit;)
Mega Man

26
... kenapa bisa menabrak SIGILL? Siapa yang mengira itu adalah sinyal yang tepat?
Hipster

4
@Asu Tidak; fatalError()sengaja crash dengan menjalankan ud2. Mengapa mereka memilih untuk melakukan itu saya tidak tahu, tetapi mungkin mereka berpikir pesan kesalahan "Instruksi ilegal" masuk akal karena program melakukan sesuatu yang ilegal.
NobodyNada

2
Cemerlang. Saya berani bertaruh ini juga merupakan kode Swift terpendek yang menyebabkan crash.
JAL

3
@ JAL Ya; Saya tidak bisa memikirkan yang lebih pendek. Saya mencoba nil!, tetapi kompiler tidak dapat menyimpulkan tipe hasil. (Juga, hai JAL!)
NobodyNada

23

GNU C, 25 byte

main(){__builtin_trap();}

GNU C (dialek khusus C dengan ekstensi) berisi instruksi untuk menghentikan program secara sengaja. Implementasi yang tepat bervariasi dari versi ke versi, tetapi seringkali pengembang berusaha untuk mengimplementasikan crash semurah mungkin, yang biasanya melibatkan penggunaan instruksi ilegal.

Versi spesifik yang saya gunakan untuk menguji adalah gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0; Namun, program ini menyebabkan SIGILL pada berbagai platfom yang cukup luas, dan karenanya cukup portabel. Selain itu, ia melakukannya dengan benar-benar menjalankan instruksi ilegal. Berikut kode perakitan yang dikompilasi di atas dengan pengaturan optimalisasi default:

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

ud2 adalah instruksi yang dijamin oleh Intel akan selalu tidak terdefinisi.


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

Juga, saya tidak tahu bagaimana kita menghitung byte untuk perakitan mentah, tetapi 00 00 0f 0bapakah bahasa mesin untuk ud2...
wchargin

5
@wchargin: itu jawaban x86 + GNU C. Yang ini portabel untuk semua sistem GNU. Perhatikan juga bahwa UD2 hanya 2 byte . IDK di mana Anda mendapatkan 00byte tersebut; mereka bukan bagian dari kode mesin untuk UD2. BTW, seperti yang saya komentari pada jawaban Dennis , ada instruksi ilegal satu byte di x86-64 untuk saat ini, tetapi mereka tidak dijamin akan tetap seperti itu.
Peter Cordes

@wchargin: Kami menghitung byte untuk fungsi / program kode mesin seperti yang Anda harapkan. Lihat beberapa jawaban saya, seperti Adler32 dalam 32 byte kode mesin x86-64 , atau GCD dalam 8 byte kode mesin x86-32 .
Peter Cordes

1
@Ruslan: Mereka tidak; 00 00mendekode yang sama dalam x86-64 (as add [rax], al). 00 00 0f 0bbiasanya SIGSEGV sebelum SIGILL, kecuali jika Anda memiliki pointer yang dapat ditulis rax.
Peter Cordes

22

C (x86_64), 11, 30, 34, atau 34 + 15 = 49 byte

main[]="/";
c=6;main(){((void(*)())&c)();}
main(){int c=6;((void(*)())&c)();}

Saya telah mengajukan beberapa solusi yang menggunakan fungsi pustaka untuk melempar SIGILLmelalui berbagai cara, tetapi bisa dibilang itu curang, karena fungsi pustaka menyelesaikan masalah. Berikut sejumlah solusi yang tidak menggunakan fungsi pustaka, dan membuat berbagai asumsi tentang di mana sistem operasi bersedia membiarkan Anda mengeksekusi kode yang tidak dapat dieksekusi. (Konstanta di sini dipilih untuk x86_64, tetapi Anda bisa mengubahnya untuk mendapatkan solusi yang berfungsi untuk sebagian besar prosesor lain yang memiliki instruksi ilegal.)

06adalah byte terendah dari kode mesin yang tidak sesuai dengan instruksi yang ditentukan pada prosesor x86_64. Jadi yang harus kita lakukan adalah menjalankannya. (Atau, 2Fjuga tidak terdefinisi, dan sesuai dengan satu karakter ASCII yang dapat dicetak.) Tidak satu pun dari ini dijamin akan selalu tidak terdefinisi, tetapi mereka tidak didefinisikan pada hari ini.

Program pertama di sini dijalankan 2Fdari segmen data read-only. Sebagian besar penghubung tidak mampu menghasilkan lompatan kerja dari .textke .rodata(atau yang setara dengan OS mereka) karena itu bukan sesuatu yang akan berguna dalam program yang tersegmentasi dengan benar; Saya belum menemukan sistem operasi yang berfungsi. Anda juga harus membiarkan fakta bahwa banyak kompiler menginginkan string tersebut menjadi string lebar, yang akan membutuhkan tambahanL; Saya berasumsi bahwa sistem operasi apa pun yang berfungsi memiliki pandangan yang cukup usang, dan dengan demikian sedang membangun untuk standar pra-C94 secara default. Mungkin saja tidak ada tempat di mana program ini bekerja, tetapi ada juga kemungkinan bahwa ada suatu tempat di mana program ini bekerja, dan dengan demikian saya daftar di dalam kumpulan jawaban potensial yang lebih meragukan ke kurang meragukan. (Setelah saya memposting jawaban ini, Dennis juga menyebutkan kemungkinan main[]={6}dalam obrolan, yang panjangnya sama, dan yang tidak mengalami masalah dengan lebar karakter, dan bahkan mengisyaratkan potensi untuk main=6, saya tidak bisa mengklaim jawaban ini sebagai jawaban yang masuk akal. punyaku, karena aku sendiri tidak memikirkannya.)

Program kedua di sini dijalankan 06dari segmen data baca-tulis. Pada sebagian besar sistem operasi, ini akan menyebabkan kesalahan segmentasi, karena segmen data yang dapat ditulis dianggap sebagai cacat desain yang buruk yang membuat kemungkinan eksploitasi. Ini tidak selalu terjadi, jadi, mungkin ini bekerja pada versi Linux yang cukup lama, tetapi saya tidak dapat dengan mudah mengujinya.

Program ketiga dijalankan 06dari stack. Sekali lagi, ini menyebabkan kesalahan segmentasi saat ini, karena stack biasanya diklasifikasikan sebagai tidak dapat ditulis untuk alasan keamanan. Dokumentasi linker yang saya lihat sangat menyiratkan bahwa dulu legal untuk dieksekusi dari stack (tidak seperti dua kasus sebelumnya, melakukannya kadang-kadang berguna), jadi meskipun saya tidak bisa mengujinya, saya cukup yakin ada beberapa versi Linux (dan mungkin sistem operasi lain) tempat ini bekerja.

Akhirnya, jika Anda memberikan -Wl,-z,execstack(15 byte penalti) untuk gcc(jika menggunakan GNU ldsebagai bagian dari backend), itu akan secara eksplisit mematikan perlindungan stack yang dapat dieksekusi, memungkinkan program ketiga untuk bekerja dan memberikan sinyal operasi ilegal seperti yang diharapkan. Saya telah menguji dan memverifikasi versi 49-byte ini agar berfungsi. (Dennis menyebutkan dalam obrolan bahwa opsi ini tampaknya bekerja dengan baik main=6, yang akan memberikan skor 6 + 15. Saya cukup terkejut bahwa ini berhasil, mengingat bahwa 6 secara terang-terangan tidak ada di stack; opsi tautan tampaknya melakukan lebih dari sekadar namanya menyarankan.)


Pada x86-64 / linux dengan gcc6 dalam mode default (ringan), const main=6;berfungsi, seperti halnya beberapa variasi. Linker ini (yang saya duga adalah juga linker Anda) adalah mampu menghasilkan melompat dari .textke .rodata; masalah yang Anda hadapi adalah, tanpa const, Anda masuk ke segmen data yang dapat ditulis ( .data), yang tidak dapat dieksekusi pada perangkat keras modern. Ini akan bekerja pada x86 yang lebih lama, di mana perangkat keras perlindungan memori tidak dapat menandai halaman sebagai dapat dibaca-tetapi-tidak-dapat dieksekusi.
zwol

Perhatikan bahwa bahkan dalam C89, maindiperlukan suatu fungsi (§5.1.2.2.1) - Saya tidak tahu mengapa gcc menganggap menyatakan mainsebagai objek data hanya layak mendapat peringatan, dan hanya dengan -pedanticpada baris perintah. Seseorang di awal 1990-an mungkin berpikir bahwa tidak ada orang yang akan melakukan itu secara tidak sengaja, tetapi itu tidak seperti hal yang berguna untuk dilakukan dengan sengaja kecuali untuk permainan semacam ini.
zwol

1
... Membaca ulang lagi, sepertinya Anda diharapkan main[]="/"untuk melompat ke segmen data read-only, karena literal string masuk dalam rodata. Anda telah terperangkap oleh perbedaan antara char *foo = "..."dan char foo[] = "...". char *foo = "..."adalah gula sintaksis untuk const char __inaccessible1[] = "..."; char *foo = (char *)&__inaccessible1[0];, jadi string literal memang masuk dalam rodata, dan foomerupakan variabel global terpisah yang dapat ditulis yang menunjuk padanya. Dengan char foo[] = "...", bagaimanapun, seluruh array masuk di segmen data yang dapat ditulis.
zwol

19

GNU as (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

Pasti ada cara untuk menyatakan bahwa dalam "sumber" dua byte ...
OrangeDog

Oh, pintar. Saya bertanya-tanya apakah ada cara untuk membangun ini yang akan menempatkan titik masuk di awal file (tanpa deklarasi) dan yang tidak akan dikenakan penalti untuk konfigurasi sistem build yang tidak biasa. Saya tidak dapat menemukannya, tetapi sepertinya Anda menemukannya.

@ ais523: yeah, script-build NASM / YASM ( asm-link) saya yang biasa ( ) untuk program-program mainan file tunggal akan membangun executable dari sumber ini dengan cara yang sama, karena lddefault titik masuk ke awal segmen teks atau sesuatu seperti itu. Saya hanya tidak berpikir untuk pergi untuk ukuran sumber ASM yang satu ini: P
Peter Cordes

18

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

Bukan pekerjaanku. Saya hanya melaporkan karya orang lain. Saya bahkan tidak dalam posisi untuk menguji klaim. Karena bagian penting dari tantangan ini tampaknya menemukan lingkungan di mana sinyal ini akan dinaikkan dan ditangkap, saya tidak termasuk ukuran QEMU, Raspbian, atau bash.

Pada 27 Februari 2013 8:49 malam, pengguna emlhalac melaporkan " Mendapatkan 'instruksi ilegal' ketika mencoba melakukan chroot " di forum Raspberry Pi.

ping

memproduksi

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

Saya membayangkan perintah yang jauh lebih pendek akan menghasilkan output ini, misalnya tr,.

EDIT: Berdasarkan komentar @ fluffy , mengurangi batas bawah dugaan pada panjang input menjadi "1?".


5
Saya pikir [perintah itu akan menang. :)
fluffy

17

File MS-DOS COM x86, 2 byte

EDIT: Seperti yang ditunjukkan dalam komentar, DOS itu sendiri tidak akan menjebak pengecualian CPU dan hanya akan menggantung (bukan hanya aplikasi, seluruh OS). Menjalankan OS 32-bit berbasis NT seperti Windows XP, memang akan memicu sinyal instruksi ilegal.

0F 0B

Dari dokumentasi :

Menghasilkan opcode yang tidak valid. Instruksi ini disediakan untuk pengujian perangkat lunak untuk secara eksplisit menghasilkan opcode yang tidak valid.

Yang cukup jelas. Simpan sebagai file .com, dan jalankan di emulator DOS. Emulator DOS akan macet. Jalankan pada Windows XP, Vista, atau 7 32-bit.

SIGILL pada Windows XP


1
Secara teknis memang menyebabkan prosesor menghasilkan pengecualian instruksi ilegal. Namun, DOS memiliki perlindungan memori yang sangat terbatas dan kemampuan penanganan pengecualian, dan saya tidak akan terkejut jika itu hanya menyebabkan perilaku yang tidak jelas / OS crash. OP tidak mengatakan kernel harus menangkap kesalahan dan mencetak "Instruksi Ilegal" ke konsol.
Maservant

4
Saya memikirkan solusi ini, tetapi saya tidak percaya itu valid. Pertanyaannya memerlukan sinyal instruksi ilegal , bukan hanya perangkap prosesor instruksi ilegal , jadi tujuannya adalah untuk menemukan sistem operasi yang benar-benar akan menghasilkan sinyal dalam menanggapi #UDperangkap. (Juga, saya memutuskan untuk benar-benar mengujinya, dan tampaknya emulator DOS saya dibuang ke loop yang tak terbatas.)

2
Saya menguji ini pada MS-DOS aktual pada AMD K6-II. Menjalankannya hanya menggantung sistem, baik dengan dan tanpa EMM386 berjalan. (EMM386 menjebak beberapa kesalahan dan menghentikan sistem dengan pesan, jadi layak untuk diuji untuk melihat apakah itu membuat perbedaan.)
Mark

2
Ya, windows berbasis DOS harus dapat benar-benar menangkap jebakan dan setidaknya crash aplikasi.
Asu

2
@Asu, saya dapat mengkonfirmasi bahwa ini berfungsi pada XP 32-bit, dan mungkin akan bekerja pada semua sistem Windows 32-bit lainnya. Saya setuju bahwa ini bukan solusi pada DOS itu sendiri, karena hanya crash.
Maservant

13

C (Windows 32-bit), 34 byte

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

Ini hanya berfungsi jika kompilasi tanpa optimasi (selain itu, kode ilegal dalam ffungsi "dioptimalkan").

Pembongkaran mainfungsi terlihat seperti ini:

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

Kita dapat melihat bahwa ia menggunakan pushinstruksi dengan nilai literal 0b0f(little-endian, sehingga byte-bytenya di-swap). The callinstruksi mendorong alamat pengirim (dari ...instruksi), yang terletak di tumpukan dekat parameter fungsi. Dengan menggunakan [-1]perpindahan, fungsi menimpa alamat pengirim sehingga menunjuk 9 byte lebih awal, di mana byte 0f 0bberada.

Bytes ini menyebabkan pengecualian "instruksi tidak terdefinisi", seperti yang dirancang.


12

Java, 50 43 24 byte

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

Ini adalah java.util.function.Consumer<Runtime>1 yang perintahnya dicuri dari jawaban Fluffy . Ini berfungsi karena Anda harus menyebutnya sebagai whateverNameYouGiveIt.accept(Runtime.getRuntime())!

Perhatikan bahwa ini akan membuat proses baru dan membuatnya melempar SIGILL daripada melemparkan SIGILL itu sendiri.

1 - Secara teknis, ini juga bisa menjadi java.util.function.Function<Runtime, Process>karena Runtime#exec(String)mengembalikan java.lang.Processyang dapat digunakan untuk mengontrol proses yang baru saja Anda buat dengan mengeksekusi perintah shell.


Demi melakukan sesuatu yang lebih mengesankan dalam bahasa lisan, inilah bonus 72 60 48-byte:

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

Yang satu ini adalah Consumer<Runtime>yang melewati SEMUA proses (termasuk dirinya sendiri), membuat masing-masing dari mereka melemparkan SIGILL. Penjepit yang lebih baik untuk kecelakaan hebat.


Dan bonus lain (a Consumer<ANYTHING_GOES>), yang setidaknya berpura - pura melempar SIGILL dalam 20 byte:

a->System.exit(132);

8

Perl, 9 byte

kill+4,$$

Cukup panggil fungsi pustaka yang sesuai untuk memberi sinyal suatu proses, dan dapatkan program untuk memberi sinyal sendiri SIGILL. Tidak ada instruksi ilegal yang terlibat di sini, tetapi itu menghasilkan hasil yang sesuai. (Saya pikir ini membuat tantangannya cukup murah, tetapi jika ada yang diizinkan, ini adalah celah yang akan Anda gunakan ...)


Datang ke sini untuk memposting yang sama, dengan spasi alih-alih +. :)
simbabque

2
Ketika orang belajar Perl untuk pemrograman non-golf, mereka mempelajarinya dengan a +. Setelah bermain golf sebentar, mereka +sesekali melakukan pamer. Akhirnya, mereka telah menulis program yang cukup di mana mereka perlu menghindari ruang kosong untuk beberapa alasan atau lainnya yang +menjadi kebiasaan. (Ini juga mem-parsing kurang ambigu, karena bekerja di sekitar memicu kasus khusus di parser untuk kurung.)

8

ARM Unified Assembler Language (UAL), 3 byte

nop

Sebagai contoh:

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

Setelah dieksekusi nop, prosesor menafsirkan .ARM.attributesbagian tersebut sebagai kode dan menemukan instruksi ilegal di suatu tempat di sana:

$ 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

Diuji pada Raspberry Pi 3.


Entah bagaimana ini tidak bekerja pada Pi 2.
Mega Man

7

Microsoft C (Visual Studio 2005 dan seterusnya), 16 byte

main(){__ud2();}

Saya tidak dapat dengan mudah menguji ini, tetapi menurut dokumentasi itu harus menghasilkan instruksi ilegal dengan sengaja mencoba menjalankan instruksi hanya kernel dari program mode pengguna. (Perhatikan bahwa karena instruksi ilegal membuat crash program, kami tidak perlu mencoba untuk kembali dari main, yang berarti bahwa mainfungsi gaya K&R ini valid. Visual Studio tidak pernah pindah dari C89 biasanya merupakan hal yang buruk, tetapi itu datang pada berguna disini.)


Bisakah Anda mengkompilasi untuk linux dengan VS2015? Karena menurut saya SIGILL tidak didefinisikan di Windows, bukan?
Andrew Savinykh

7

Ruby, 13 byte

`kill -4 #$$`

Saya kira aman untuk menganggap bahwa kita menjalankan ini dari shell * nix. Literal backtick menjalankan perintah shell yang diberikan. $$adalah proses Ruby yang sedang berjalan, dan #untuk interpolasi string.


Tanpa memanggil shell secara langsung:

Ruby, 17 byte

Process.kill 4,$$

6

Semua shell (sh, bash, csh, dll.), POSIX (10 byte)

Jawaban sepele tapi saya belum melihat orang mempostingnya.

kill -4 $$

Cukup kirimkan SIGILL ke proses saat ini. Contoh output pada OSX:

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

Anda dapat melakukannya kill -4 1jika pertanyaannya tidak spesifik tentang program mana yang melempar SIGILL
Mark K Cowan

@MarkKCowan Heh, poin bagus, meskipun itu mengasumsikan root ...
fluffy

2
You will have root in your programs- jatuhkan byte dari jawaban Anda dan putar pertanyaan sedikit pada saat yang sama: D. BONUS: Anda bisa membunuhinit
Mark K Cowan

2
@MarkKCowan: Aktif (versi modern?) Linux, initsebenarnya kebal terhadap sinyal yang belum secara khusus diminta untuk diterima, bahkan dengan root. Anda mungkin bisa mengatasinya dengan menggunakan OS POSIX yang berbeda.

2
kill -4 2kemudian: D
Mark K Cowan

6

Kode mesin ELF + x86, 45 byte

Ini harus menjadi program executable terkecil pada mesin Unix yang melempar SIGILL (karena Linux tidak mengenali executable jika dibuat lebih kecil).

Kompilasi dengan nasm -f bin -o a.out tiny_sigill.asm, diuji pada mesin virtual x64.

Biner 45 byte aktual:

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

Daftar majelis (lihat sumber di bawah):

;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     $ - $$

Penafian: kode dari tutorial berikut tentang penulisan program perakitan terkecil untuk mengembalikan nomor, tetapi menggunakan opcode ud2 alih-alih mov: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html


2
Saya akan memposting executable yang dimodifikasi dari tutorial yang tepat, tetapi Anda mengalahkan saya untuk itu. Ini pantas untuk menang; Ini benar-benar minimalis dalam arti sumber daya sistem (Tidak memerlukan lebih dari 45 byte baik di-file dan di-memori, dan persis sama di keduanya), dan tidak ada penerjemah bengkak seperti solusi assembler lainnya. Ini adalah apa adanya.
Iwillnotexist Idonotexist

5

Otomatis , 93 byte

Menggunakan perakitan inass flatassembler:

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

Ketika dijalankan dalam mode interaktif SciTE, itu akan langsung crash. Windows debugger harus muncul selama sepersekian detik. Output konsol akan menjadi seperti ini:

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

Di mana -1073741795kode kesalahan yang tidak ditentukan dilemparkan oleh WinAPI. Ini bisa berupa angka negatif.

Mirip menggunakan LASM assembler saya sendiri :

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

5

NASM, 25 byte

Saya tidak tahu bagaimana ini bekerja, hanya saja ia bekerja di komputer saya secara khusus (Linux x86_64).

global start
start:
jmp 0

Kompilasi & jalankan seperti:

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

Anda mungkin dapat mempersingkat menjadi empat byte, karenaja 0
Mark K Cowan

1
atau tiga sebagaiud2
Mark K Cowan

1
Mungkin karena mencoba melompat ke beberapa data?
Asu

5

TI-83 Hex Assembly, 2 byte

PROGRAM:I
:AsmPrgmED77

Jalankan sebagai Asm(prgmI). Menjalankan opcode 0xed77 ilegal. Saya menghitung setiap pasangan angka hex sebagai satu byte.



3

x86 .COM, 1 byte

c

ARPLmenyebabkan #UDdalam mode 16-bit


1

Linux shell, 9 byte

kill -4 0

Mengirim SIGILLke proses dengan PID 0. Saya tidak tahu proses apa yang memiliki PID 0, tetapi selalu ada.

Cobalah online!


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

1

GNU C, 24 19 18 byte

-4 Terima kasih kepada Dennis
-1 berkat ceilingcat

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

Cobalah online! Ini mengasumsikan ASCII dan x86_64. Mencoba menjalankan kode mesin 27, yang ... ilegal.


shortC , 10 5 4 byte

AV"'

Setara dengan kode GNU C di atas. Cobalah online!


L"\6"juga ilegal, dengan anggapan x86_64.
Dennis

@Dennis Instruksi apa 0x06? Juga, Litu tidak perlu.
MD XF

Itu belum ditetapkan.
Dennis

Itu belum ditetapkan; itulah yang membuatnya ilegal. Juga, 'adalah 39 = 0x27 , bukan 0x39 .
Dennis

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.