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 SIGILL
melalui 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.)
06
adalah byte terendah dari kode mesin yang tidak sesuai dengan instruksi yang ditentukan pada prosesor x86_64. Jadi yang harus kita lakukan adalah menjalankannya. (Atau, 2F
juga 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 2F
dari segmen data read-only. Sebagian besar penghubung tidak mampu menghasilkan lompatan kerja dari .text
ke .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 06
dari 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 06
dari 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 ld
sebagai 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.)
raise(SIGILL)
?