Кратчайший код, чтобы бросить SIGILL


76

Фон

У нас уже есть проблема броска SIGSEGV , так почему бы не бросить вызов SIGILL?

Что такое SIGILL?

SIGILL - сигнал о недопустимой инструкции на процессоре, что происходит очень редко. Действие по умолчанию после получения SIGILL - завершение программы и запись дампа ядра. Идентификатор сигнала SIGILL равен 4. Вы встречаетесь с SIGILL очень редко, и я абсолютно не знаю, как сгенерировать его в вашем коде, кроме как через sudo kill -s 4 <pid>.

правила

Вы будете иметь root в своих программах, но если вы не хотите по каким-либо причинам, вы также можете использовать обычного пользователя. Я на компьютере Linux с немецким языком, и я не знаю английский текст, который отображается после перехвата SIGILL, но я думаю, что это что-то вроде «Недопустимая инструкция». Самая короткая программа, которая бросает SIGILL, побеждает.


6
Вы можете уточнить, должна ли инструкция генерироваться ядром или нет. В частности, хотите ли вы, чтобы программа просто генерировала ее напрямую с помощью вызова libc raise(SIGILL)?

1
Это действительно говорит Illegal instruction (core dumped).
Эрик Outgolfer

@ ais523 Все разрешено.
Mega Man

5
Для любого оборудования, которое может вызвать SIGILL, ответ будет таким же, как длина инструкции. Просто поместите незаконную инструкцию куда-нибудь и попробуйте выполнить ее. Единственной интересной вещью будет запутанная цепочка инструментов.
Стоп Harm Monica

3
* Люди публикуют старые программы, которые у них были, но они не работали *
RudolfJelin

Ответы:


112

Ассемблер PDP-11 (UNIX Sixth Edition), 1 байт

9

Инструкция 9 не является действительной инструкцией для PDP-11 (в восьмеричном виде она будет 000011отсутствовать в списке инструкций (PDF)). Ассемблер PDP-11, поставляемый с шестым выпуском UNIX, по-видимому, выводит все, что он не понимает, непосредственно в файл; в этом случае 9 - это число, поэтому он генерирует буквальную инструкцию 9. Он также имеет свойство odd (необычное в настоящее время на языках ассемблера), что файлы запускаются с самого начала, поэтому нам не нужны никакие объявления для создания программы. работай.

Вы можете протестировать программу с помощью этого эмулятора , хотя вам придется несколько бороться с ним, чтобы ввести программу.

Вот как все закончится, когда вы поймете, как использовать файловую систему, редактор, терминал и тому подобные вещи, которые, как вы думали, вы уже знаете, как использовать:

% a.out
Illegal instruction -- Core dumped

В документации я подтвердил, что это подлинный SIGILLсигнал (и он даже имел тот же номер сигнала, 4, тогда!)


1
У него был один и тот же номер сигнала, потому что POSIX, UNIX и SUS тесно связаны :)
кошка,

4
Почти все номера сигналов в V6 имеют сегодня те же значения; Мнемоника на самом деле была менее стабильной, чем цифры. Сравните minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/sys/param.h с github.com/freebsd/freebsd/blob/master/sys/sys/signal.h - идентичная семантика для С 1 по 13, но только 1, 2 и 13 имеют абсолютно одинаковые имена. (SIGALRM / 14 и SIGTERM / 15 были добавлены только в V7.) (Линия System V имеет несколько изменений, в частности, перемещение SIGBUS с 10 на 7 (замена бесполезного SIGEMT) и SIGSYS выше 15, чтобы освободить место для SIGUSR1 и SIGUSR2.)
zwol

4
@cat POSIX и SUS на самом деле не определяют значения сигналов - они определяют значение некоторых чисел, когда они передаются в качестве аргументов в команду kill, но SIGILL не включается.
Random832

7
a.outдействительно, содержит несколько байтов ( 9инструкция компилируется в два байта, и ассемблер также добавляет верхний и нижний колонтитулы, чтобы сделать программу исполняемой). Вот почему я написал программу на ассемблере, а не в машинном коде. Программа на языке ассемблера имеет только один байт и компилируется в программу с большим количеством байтов; это проблема кода-гольфа (минимизировать размер источника), а не проблема кодирования размера (минимизировать размер исполняемого файла), поэтому имеет значение размер источника в 1 байт.

2
Очень умное злоупотребление старой, но удивительной системой.
Мачта

81

C (x86_64, tcc ), 7 байтов

main=6;

Вдохновлен этим ответом .

Попробуйте онлайн!

Как это устроено

Сгенерированная сборка выглядит следующим образом.

    .globl  main
main:
    .long 6

Обратите внимание, что TCC не помещает определенную «функцию» в сегмент данных .

После компиляции _start будет указывать на main как обычно. Когда получающаяся в результате программа выполняется, она ожидает код main и находит 32-разрядное целое число с прямым порядком байтов (!) 6 , которое кодируется как 0x06 0x00 0x00 0x00 . Первый байт - 0x06 - недопустимый код операции, поэтому программа завершается с SIGILL .


C (x86_64, гкц ), 13 байтов

const main=6;

Попробуйте онлайн!

Как это устроено

Без модификатора const сгенерированная сборка выглядит следующим образом.

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

Линкер GCC обрабатывает последнюю строку как подсказку о том, что сгенерированный объект не требует исполняемого стека. Поскольку main явно размещается в разделе данных , содержащийся в нем код операции не является исполняемым, поэтому программа завершит работу SIGSEGV (ошибка сегментации).

Удаление второй или последней строки заставит сгенерированный исполняемый файл работать так, как задумано. Последняя строка может быть проигнорирована с флагом компилятора -zexecstack( попробуйте онлайн! ), Но это стоит 12 байтов .

Более короткая альтернатива - объявить main с модификатором const , что приведет к следующей сборке.

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

Это работает без каких-либо флагов компилятора. Обратите внимание, что main=6;в данные будет записана определенная «функция» , но модификатор const вместо этого заставит GCC записать его в родату , которая (по крайней мере, на моей платформе) может содержать код.


Люблю полное избегание даже использования функции :) Как это работает в терминах C, хотя? Компилятор видит, что mainэто 6, и пытается вызвать его (что, я думаю, заставило бы его сдаться и попробовать инструкцию)?
Миа Юн Русе

11
@JackDobson - это неопределенное поведение, поэтому оно не работает с точки зрения C; Вы в милости компилятора. У Clang даже есть предупреждение по этой причине: «переменная с именем main с внешней связью имеет неопределенное поведение».
Бобби Сакамано

2
GCC будет жаловаться mainне является функцией , но только если вы включите предупреждения (либо -Wallили -pedanticбудет делать это).
Звол

Я думаю, что для исполняемых файлов Unix-подобных систем довольно стандартно иметь сегменты text / data / bss . Компоновщик размещает .rodata раздел внутри текстового сегмента исполняемого файла, и я ожидаю, что это будет иметь место практически на любой платформе. (Загрузчик программ ядра заботится только о сегментах, а не о разделах).
Питер Кордес

3
Также обратите внимание, что 06это только недопустимая инструкция в x86-64. В 32-битном режиме это так PUSH ES, поэтому этот ответ работает только с компиляторами по умолчанию -m64. См. Ref.x86asm.net/coder.html#x06 . Единственный байт последовательность , которая гарантированно декодировать как недопустимую инструкцию на всех будущих процессоров x86 является 2 байта UD2 : 0F 0B. Все остальное может быть каким-то будущим префиксом или кодировкой инструкций. Тем не менее, проголосовал за классный способ заставить компилятор C прикрепить mainметку на несколько байтов!
Питер Кордес

39

Swift, 5 байт

[][0]

Доступ к индексу 0 пустого массива. Это вызывает fatalError(), который печатает сообщение об ошибке и падает с SIGILL. Вы можете попробовать это здесь .


Это один из самых хитрых;)
Mega Man

26
... с какой стати он падает с SIGILL? Кто думал, что это подходящий сигнал? Кровавые хипстеры: D
Музер

4
@ Асу Нет; fatalError()намеренно вылетает при беге ud2. Почему они решили сделать это, я не знаю, но, возможно, они думали, что сообщение об ошибке «Недопустимая инструкция» имело смысл, потому что программа сделала что-то нелегальное.
NobodyNada

2
Brilliant. Держу пари, что это также самый короткий код Swift, вызывающий сбой.
JAL

3
@JAL Да; Я не могу думать ни о чем короче. Я пытался nil!, но компилятор не мог определить тип результата. (Кроме того, привет JAL!)
NobodyNada

23

GNU C, 25 байт

main(){__builtin_trap();}

GNU C (определенный диалект C с расширениями) содержит инструкцию преднамеренного сбоя программы. Точная реализация варьируется от версии к версии, но часто разработчики пытаются реализовать сбой настолько дешево, насколько это возможно, что обычно включает использование недопустимой инструкции.

Конкретная версия , которую я использовал , чтобы проверить это gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0; однако, эта программа вызывает SIGILL на довольно широком диапазоне платформ, и, таким образом, является довольно переносимой. Кроме того, он делает это посредством фактического выполнения недопустимой инструкции. Вот код сборки, который компилируется выше с настройками оптимизации по умолчанию:

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

ud2 это инструкция, которую Intel гарантирует, всегда будет оставаться неопределенным.


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

Кроме того, я не знаю, как мы считаем байты для необработанной сборки, но 00 00 0f 0bэто машинный язык для ud2...
wchargin

5
@wchargin: это x86 + GNU C ответ. Этот портативный для всех систем GNU. Также обратите внимание, что UD2 составляет всего 2 байта . ИДК, где вы получили эти 00байты; они не являются частью машинного кода для UD2. Кстати, как я прокомментировал ответ Денниса, на данный момент в x86-64 есть однобайтовые недопустимые инструкции, но они не гарантируют того, что так и останется.
Питер Кордес

@wchargin: мы рассчитываем байты для функций / программ машинного кода, как и следовало ожидать. См. Некоторые из моих ответов, например, Adler32 в 32 байтах машинного кода x86-64 или GCD в 8 байтах машинного кода x86-32 .
Питер Кордес

1
@ Руслан: они не; 00 00декодирует то же самое в x86-64 (как add [rax], al). 00 00 0f 0bобычно SIGSEGV до SIGILL, если только у вас не было записываемого указателя rax.
Питер Кордес

22

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 явно не в стеке; опция ссылки, очевидно, делает больше, чем его название подсказывает.)


На x86-64 / linux с gcc6 в режиме по умолчанию (снисходительном) const main=6;работает, как и несколько вариантов. Этот линкер (я подозреваю , тоже ваш компоновщик) является способным генерировать скачок от .textдо .rodata; проблема, с которой вы столкнулись, заключается в том, что без constэтого вы попадаете в доступный для записи сегмент данных ( .data), который не может быть выполнен на современном оборудовании. Это работало бы на более старых x86, где аппаратное обеспечение защиты памяти не могло маркировать страницы как читаемые, но не исполняемые.
zwol

Обратите внимание, что даже в C89 mainобязательно должна быть функция (§5.1.2.2.1) - я не знаю, почему gcc рассматривает объявление mainв качестве объекта данных только для того, чтобы заслужить только предупреждение, и только -pedanticв командной строке. Кто-то в начале 1990-х, возможно, думал, что никто не сделает это случайно, но это не так, как будто это полезно делать специально, за исключением игры такого рода.
zwol

1
... Перечитав еще раз, кажется, вы ожидаете main[]="/"перейти к сегменту данных только для чтения, потому что строковые литералы идут в родате. Вы были пойманы разницей между char *foo = "..."и char foo[] = "...". char *foo = "..."является синтаксическим сахаром для const char __inaccessible1[] = "..."; char *foo = (char *)&__inaccessible1[0];, поэтому строковый литерал идет в родате и fooявляется отдельной доступной для записи глобальной переменной, указывающей на него. При char foo[] = "..."этом весь массив помещается в сегмент данных для записи.
Звол

19

GNU as (x86_64), 3 байта

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

Должен быть способ выразить это в двухбайтовом «источнике» ...
Остановить Harming Monica

Ох, умный Мне было интересно, есть ли способ построить это, который поместил бы точку входа в начало файла (без объявлений) и который не повлек бы за собой штрафы за необычную конфигурацию системы сборки. Я не мог найти один, но похоже, что вы нашли.

@ ais523: да, мой обычный сценарий сборки NASM / YASM ( asm-link) для однофайловых игрушечных программ будет создавать исполняемый файл из этого источника таким же образом, поскольку по ldумолчанию точка входа находится в начале текстового сегмента или что-то в этом роде. Я просто не думал о том, чтобы выбрать размер исходного кода asm: P
Питер Кордес

18

Bash на Raspbian на QEMU, 4 (1?) Байта

Не моя работа. Я просто сообщаю о работе другого. Я даже не в состоянии проверить претензию. Поскольку важной частью этой проблемы, похоже, является нахождение среды, в которой этот сигнал будет поднят и пойман, я не учитываю размер QEMU, Raspbian или bash.

27 февраля 2013 г. в 20:49 пользователь emlhalac сообщил на форуме « Raspberry Pi » « Получение« недопустимых инструкций при попытке выполнить chroot ».

ping

производства

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

Я полагаю , гораздо более короткие команды будут производить этот вывод, например, tr.

РЕДАКТИРОВАТЬ: На основе комментария @ fluffy , уменьшил предполагаемую нижнюю границу длины ввода до «1?».


5
Я думаю, что [команда победит. :)
пушистый

17

COM-файл x86 MS-DOS, 2 байта

РЕДАКТИРОВАТЬ: Как указано в комментариях, сама DOS не будет перехватывать исключение процессора и будет просто зависать (не только приложение, вся ОС). Работа в 32-битной операционной системе на базе NT, такой как Windows XP, действительно вызовет недопустимый сигнал инструкции.

0F 0B

Из документации :

Создает недопустимый код операции. Эта инструкция предназначена для тестирования программного обеспечения для явного генерирования недействительного кода операции.

Что довольно очевидно. Сохраните как файл .com и запустите в любом эмуляторе DOS. Эмуляторы DOS просто рухнут. Работать на Windows XP, Vista или 7 32-разрядных.

SIGILL на Windows XP


1
Технически это заставляет процессор генерировать недопустимое исключение команды. Тем не менее, DOS имеет очень ограниченные возможности защиты памяти и обработки исключений, и я не удивлюсь, если это просто приведет к неопределенному поведению / падению ОС. ОП не сказал, что ядро ​​должно было отловить ошибку и вывести «Illegal Instruction» на консоль.
служитель

4
Я думал об этом решении, но я не верю, что оно действительно. Вопрос требует недопустимого сигнала инструкции , а не просто ловушки недопустимого процессора команд , поэтому цель состояла в том, чтобы найти операционную систему, которая фактически генерировала бы сигнал в ответ на #UDловушку. (Кроме того, я решил протестировать его, и он, похоже, бросил мой эмулятор DOS в бесконечный цикл.)

2
Я проверял это на реальных MS-DOS на AMD K6-II. При его запуске просто зависает система, как с EMM386, так и без него. (EMM386 перехватывает некоторые ошибки и останавливает систему с помощью сообщения, поэтому стоило проверить, имеет ли это значение.)
Отметить

2
Да, окна на основе DOS должны быть в состоянии действительно поймать ловушку и, по крайней мере, вывести приложение из строя.
Асу

2
@Asu Я могу подтвердить, что это работает в 32-разрядной версии XP и, вероятно, будет работать во всех других 32-разрядных системах Windows. Я согласен, что это не решение для самой DOS, так как он просто падает.
слуга

13

C (32-битная Windows), 34 байта

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

Это работает только при компиляции без оптимизации (в противном случае недопустимый код в fфункции «оптимизирован»).

Разборка mainфункции выглядит так:

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

Мы можем видеть, что он использует pushинструкцию с буквальным значением 0b0f(little-endian, поэтому его байты меняются местами). callИнструкция выталкивает адрес возврата (в ...инструкции), который находится в стеке около параметра функции. Используя [-1]смещение, функция переопределяет адрес возврата, поэтому она указывает на 9 байтов раньше, где байты 0f 0bнаходятся.

Эти байты вызывают исключение «неопределенная инструкция», как и было задумано.


12

Java, 50 43 24 байта

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

Это java.util.function.Consumer<Runtime>1, чья команда украдена из ответа Пушистика . Это работает, потому что вы должны называть это как whateverNameYouGiveIt.accept(Runtime.getRuntime())!

Обратите внимание, что это создаст новый процесс и заставит его бросать SIGILL, а не сам SIGILL.

1 - Технически это также может быть java.util.function.Function<Runtime, Process>потому, что Runtime#exec(String)возвращает a, java.lang.Processкоторый можно использовать для управления процессом, который вы только что создали, выполнив команду оболочки.


Ради делать что - то более впечатляющее таким многословным языком, вот 72 60 бонус 48 байт:

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

Этот - другой, Consumer<Runtime>который проходит ВСЕ процессы (включая себя), заставляя каждый из них бросать SIGILL. Лучше подготовиться к насильственной аварии.


И еще один бонус (а Consumer<ANYTHING_GOES>), который, по крайней мере, претендует на то, чтобы бросить SIGILL в 20 байтов:

a->System.exit(132);

8

Perl, 9 байт

kill+4,$$

Просто вызывает соответствующую библиотечную функцию для сигнализации процесса и заставляет программу сигнализировать себя SIGILL. Здесь нет никаких фактических незаконных инструкций, но это дает соответствующий результат. (Я думаю, что это делает задачу довольно дешевой, но если что-то разрешено, это лазейка, которую вы бы использовали ...)


Пришел сюда, чтобы опубликовать то же самое, с пробелом вместо +. :)
simbabque

2
Когда люди изучают Perl для программирования не в гольф, они изучают его с помощью +. После игры в гольф они время от +времени выпендриваются. В конце концов, они написали достаточно программ, где им нужно было по каким-либо причинам избегать пробелов, которые +становятся привычкой. (Он также анализирует менее двусмысленно, потому что он работает вокруг запуска особого случая в синтаксическом анализаторе для скобок.)

8

ARM Unified Assembler Language (UAL), 3 байта

nop

Например:

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

После выполнения nopпроцессор интерпретирует .ARM.attributesраздел как код и встречает где-то недопустимую инструкцию:

$ 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

Проверено на Raspberry Pi 3.


Как-то это не работает на Pi 2.
Mega Man

7

Microsoft C (Visual Studio 2005 и выше), 16 байт

main(){__ud2();}

Я не могу легко это проверить, но в соответствии с документацией он должен создать недопустимую инструкцию, намеренно пытаясь выполнить инструкцию только для ядра из программы пользовательского режима. (Обратите внимание, что из-за того, что недопустимая инструкция приводит к сбою программы, нам не нужно пытаться вернуться из mainнее, что означает, что эта mainфункция в стиле K & R действительна. Visual Studio, никогда не переходившая из C89, обычно плохая вещь, но она пришла полезно здесь.)


Можете ли вы скомпилировать для Linux с VS2015? Потому что я не думаю, что SIGILL определяется в Windows, не так ли?
Андрей Савиных

7

Рубин, 13 байт

`kill -4 #$$`

Я думаю, можно с уверенностью предположить, что мы запускаем это из оболочки * nix. Литералы backtick запускают данную команду оболочки. $$это запущенный процесс Ruby, а #для интерполяции строк.


Не вызывая оболочку напрямую:

Рубин, 17 байт

Process.kill 4,$$

6

Любая оболочка (sh, bash, csh и т. Д.), Любой POSIX (10 байт).

Тривиальный ответ, но я не видел, чтобы кто-то опубликовал его.

kill -4 $$

Просто отправляет SIGILL в текущий процесс. Пример вывода на OSX:

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

Вы могли бы сделать, kill -4 1если вопрос не определен о том, какая программа выдает SIGILL
Марк К Коуэн

@MarkKCowan Хех, хорошая точка зрения, хотя это предполагает корень ...
пушистый

2
You will have root in your programs- отбросьте байт из своего ответа и одновременно слегка троллейте вопрос: D. БОНУС: Вы убиваетеinit
Марк К Коуэн

2
@MarkKCowan: На (современных версиях?) Linux initфактически невосприимчив к сигналам, которые он специально не запрашивал, даже с root. Возможно, вы могли бы обойти это, используя другую ОС POSIX.

2
kill -4 2тогда: D
Марк К Коуэн

6

Машинный код ELF + x86, 45 байт

Это должна быть самая маленькая исполняемая программа на Unix-машине, которая выдает SIGILL (из-за того, что Linux не распознает исполняемый файл, если он уменьшен).

Компилировать с nasm -f bin -o a.out tiny_sigill.asm, протестировано на виртуальной машине x64.

Фактический 45-байтовый двоичный файл:

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

Список сборок (см. Источник ниже):

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

Отказ от ответственности: код из следующего руководства по написанию самой маленькой программы сборки для возврата числа, но с использованием кода операции ud2 вместо mov: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html


2
Я собирался опубликовать модифицированный исполняемый файл именно этого урока, но вы меня опередили. Это заслуживает победы; Это настоящий минималист в смысле системных ресурсов (для него требуется не более 45 байт как в файле, так и в памяти, и он абсолютно одинаков в обоих), и нет раздутого интерпретатора, как в других решениях на ассемблере. Это просто то, что есть.
Iwillnotexist Idonotexist

5

AutoIt , 93 байта

Используя встроенную сборку flatassembler:

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

При запуске в интерактивном режиме SciTE он сразу вылетает. Отладчик Windows должен появиться на долю секунды. Вывод консоли будет примерно таким:

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

Где -1073741795находится неопределенный код ошибки, выдаваемый WinAPI. Это может быть любое отрицательное число.

Похоже, используя мой собственный ассемблер LASM :

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

5

NASM, 25 байт

Я не знаю, как это работает, просто это работает на моем компьютере (Linux x86_64).

global start
start:
jmp 0

Компилировать и запускать как:

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

Вероятно, вы можете сократить его до четырех байтов, какja 0
Марк К Коуэн

1
или три какud2
Марк К Коуэн

1
Возможно, потому что он пытается перейти к некоторым данным?
Асу

5

TI-83 Hex Assembly, 2 байта

PROGRAM:I
:AsmPrgmED77

Запустить как Asm(prgmI). Выполняет недопустимый код операции 0xed77. Я считаю каждую пару шестнадцатеричных цифр одним байтом.




1

Оболочка Linux, 9 байт

kill -4 0

Посылает SIGILLпроцессу с PID 0. Я не знаю, какой процесс имеет PID 0, но он всегда существует.

Попробуйте онлайн!


От man kill:0 All processes in the current process group are signaled.
Деннис

1

GNU C, 24 19 18 байт

-4 благодаря Деннису
-1 благодаря потолку

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

Попробуйте онлайн! Это предполагает ASCII и x86_64. Он пытается запустить машинный код 27, который ... является незаконным.


shortC , 10 5 4 байта

AV"'

Эквивалентен приведенному выше коду GNU C. Попробуйте онлайн!


L"\6"также незаконно, предполагая x86_64.
Деннис

@ Денис Какая инструкция 0x06? Кроме того, Lэто не обязательно.
MD XF

Это не назначено.
Деннис

Это не назначено; вот что делает его незаконным. Кроме того , 'есть 39 = 0x27 , не 0x39 .
Деннис

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.