C (x86_64), 11, 30, 34 або 34 + 15 = 49 байт
main[]="/";
c=6;main(){((void(*)())&c)();}
main(){int c=6;((void(*)())&c)();}
Я подав пару рішень, які використовують функції бібліотеки для перекидання SIGILLрізними засобами, але, мабуть, це обман, оскільки функція бібліотеки вирішує проблему. Ось низка рішень, які не використовують функцій бібліотеки, і роблять різні припущення щодо того, де операційна система готова дозволити вам виконувати невиконаний код. (Константи тут вибрані для x86_64, але ви можете змінити їх, щоб отримати робочі рішення для більшості інших процесорів, які мають незаконні інструкції.)
06це найменший байт машинного коду, який не відповідає визначеній інструкції на процесорі x86_64. Отже, все, що нам потрібно зробити, - це виконати. (Крім того, 2Fвін також не визначений і відповідає одному друкованому символу ASCII.) Жоден з них не гарантовано завжди бути невизначеним, але вони не визначені на сьогодні.
Перша програма тут виконується 2Fз сегмента даних, доступних лише для читання. Більшість лінкери не здатні виробляти робочий стрибок від .textдо .rodata(або еквівалент їх ОС) , оскільки це не те , що коли - небудь буде корисно в правильно сегментированной програмі; Я ще не знайшов операційну систему, на якій це працює. Ви також повинні мати на увазі те, що багато компіляторів хочуть, щоб розглянутий рядок був широким рядком, що вимагало б додатковоїL; Я припускаю, що будь-яка операційна система, над якою працює, має досить застаріле уявлення про речі, і, таким чином, будує стандарт за попереднім C94 за замовчуванням. Можливо, що ніде ця програма не працює, але також можливо, що десь ця програма працює, і тому я перераховую її у цій збірці більш сумнівних, менш менш сумнівних потенційних відповідей. (Після того як я опублікував цю відповідь, Денніс також згадав про можливість main[]={6}спілкування в чаті, що має однакову довжину, і який не стикається з проблемами з шириною символів, і навіть натякнув на потенціал main=6; моє, як я про них не думав.)
Друга програма тут виконується 06з сегмента даних для читання-запису. У більшості операційних систем це призведе до помилки сегментації, тому що сегменти даних, що записуються, вважаються поганим недоліком дизайну, що робить експлуатацію ймовірною. Це не завжди так, тому, ймовірно, це працює на досить старій версії Linux, але я не можу її легко перевірити.
Третя програма виконується 06зі стека. Знову ж таки, це спричиняє помилку сегментації в даний час, тому що стек, як правило, класифікується як ненаписаний з міркувань безпеки. Документація на лінкер, яку я бачив, вказує на те, що вона була легальною для виконання зі стека (на відміну від попередніх двох випадків, це робиться іноді корисно), тому хоча я не можу це перевірити, я впевнений, що є деякі версія Linux (і, мабуть, інших операційних систем), на якій це працює.
Нарешті, якщо ви дасте -Wl,-z,execstack(15 байт штрафу) до gcc(якщо ви використовуєте GNU ldяк частину бекенда), це явно вимкне захист виконуваного стека, що дозволить третій програмі працювати і подавати сигнал незаконної роботи, як очікувалося. Я вже випробувано і перевірено це 49-байтовий версія для роботи. (Денніс згадує в чаті, що цей варіант, мабуть, працює з цим main=6, що дасть оцінку 6 + 15. Я дуже здивований, що це працює, враховуючи, що 6 очевидно не знаходиться в стеці; варіант посилання, очевидно, робить більше, ніж його назва підказує.)
raise(SIGILL)?