Código más corto para lanzar SIGILL

76

Antecedentes

Ya tenemos un desafío sobre lanzar SIGSEGV , entonces, ¿por qué no un desafío sobre lanzar SIGILL?

¿Qué es SIGILL?

SIGILL es la señal de una instrucción ilegal en el procesador, que ocurre muy raramente. La acción predeterminada después de recibir SIGILL es terminar el programa y escribir un volcado de memoria. La identificación de la señal de SIGILL es 4. Te encuentras con SIGILL muy raramente, y no tengo ni idea de cómo generarlo en tu código, excepto a través de sudo kill -s 4 <pid>.

Reglas

Tendrá root en sus programas, pero si no lo desea por algún motivo, también puede usar un usuario normal. Estoy en una computadora Linux con configuración regional alemana y no sé el texto en inglés que se muestra después de capturar SIGILL, pero creo que es algo así como 'Instrucción ilegal'. El programa más corto que arroja SIGILL gana.

Mega Man
fuente
66
Es posible que desee aclarar si la instrucción debe ser generada por el núcleo o no. En particular, ¿desea permitir que el programa solo lo genere directamente usando la llamada libc raise(SIGILL)?
1
Realmente lo dice Illegal instruction (core dumped).
Erik the Outgolfer
@ ais523 Todo está permitido.
Mega Man
55
Para cualquier hardware que pueda aumentar SIGILL, la respuesta será la misma que la longitud de la instrucción. Simplemente ponga una instrucción ilegal en alguna parte e intente ejecutarla. Lo único interesante será la complicada cadena de herramientas involucrada.
OrangeDog
3
* personas publicando programas antiguos que tenían que no funcionaban *
RudolfJelin el

Respuestas:

112

Ensamblador PDP-11 (Sexta edición de UNIX), 1 byte

9

La Instrucción 9 no es una instrucción válida en el PDP-11 (en octal, lo sería 000011, lo que no aparece en la lista de instrucciones (PDF)). El ensamblador PDP-11 que se entrega con UNIX Sixth Edition aparentemente hace eco de todo lo que no entiende en el archivo directamente; en este caso, 9 es un número, por lo que genera una instrucción literal 9. También tiene la propiedad impar (inusual en los lenguajes de ensamblaje hoy en día) de que los archivos comienzan a ejecutarse desde el principio, por lo que no necesitamos ninguna declaración para hacer el programa trabajo.

Puede probar el programa usando este emulador , aunque tendrá que luchar un poco con él para ingresar el programa.

Así es como terminan las cosas una vez que has descubierto cómo usar el sistema de archivos, el editor, el terminal y cosas similares que creías que ya sabías cómo usar:

% a.out
Illegal instruction -- Core dumped

He confirmado con la documentación que esta es una SIGILLseñal genuina (¡e incluso tenía el mismo número de señal, 4, en todo momento!)


fuente
1
Tenía el mismo número de señal porque POSIX y UNIX y el SUS están estrechamente relacionados :)
cat
44
Casi todos los números de señal en V6 todavía tienen los mismos significados hoy; La mnemotecnia en realidad ha sido menos estable que los números. Compare minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/sys/param.h con github.com/freebsd/freebsd/blob/master/sys/sys/signal.h - semántica idéntica para 1 a 13, pero solo 1, 2 y 13 tienen exactamente los mismos nombres. (SIGALRM / 14 y SIGTERM / 15 solo se agregaron en V7.) (El linaje System V tiene un par de cambios, notablemente mover SIGBUS de 10 a 7 (reemplazando el inútil SIGEMT) y SIGSYS por encima de 15, para dejar espacio para SIGUSR1 y SIGUSR2.)
zwol
44
@cat POSIX y SUS en realidad no especifican los valores de las señales; sí especifican el significado de algunos números cuando se pasan como argumentos al comando kill, pero SIGILL no está incluido.
Aleatorio832
77
a.outtiene múltiples bytes, de hecho (la 9instrucción se compila en dos bytes, y el ensamblador también agrega un encabezado y pie de página para hacer que el programa sea ejecutable). Es por eso que escribí el programa en lenguaje ensamblador, no en código máquina. El programa en lenguaje ensamblador tiene solo un byte y se compila en un programa con más bytes; Este es un problema de código de golf (minimizar el tamaño de la fuente), no un problema de codificación de tamaño (minimizar el tamaño del archivo ejecutable), por lo que es el tamaño de 1 byte de la fuente lo que importa.
2
Abuso muy inteligente de un sistema antiguo pero impresionante.
Mástil
81

C (x86_64, tcc ), 7 bytes

main=6;

Inspirado por esta respuesta .

Pruébalo en línea!

Cómo funciona

El conjunto generado se ve así.

    .globl  main
main:
    .long 6

Tenga en cuenta que TCC no coloca la "función" definida en un segmento de datos .

Después de la compilación, _start apuntará a main como de costumbre. Cuando se ejecuta el programa resultante, espera código en main y encuentra el entero 6 de 32 bits little-endian (!) , Que está codificado como 0x06 0x00 0x00 0x00 . El primer byte, 0x06 , es un código de operación no válido, por lo que el programa termina con SIGILL .


C (x86_64, gcc ), 13 bytes

const main=6;

Pruébalo en línea!

Cómo funciona

Sin el modificador const , el conjunto generado se ve así.

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

El enlazador de GCC trata la última línea como una pista de que el objeto generado no requiere una pila ejecutable. Dado que main se coloca explícitamente en una sección de datos , el código de operación que contiene no es ejecutable, por lo que el programa termina SIGSEGV (error de segmentación).

Al eliminar la segunda o la última línea, el ejecutable generado funcionará según lo previsto. La última línea podría ignorarse con el indicador del compilador -zexecstackPruébelo en línea! ), Pero esto cuesta 12 bytes .

Una alternativa más corta es declarar main con el modificador const , lo que resulta en el siguiente ensamblaje.

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

Esto funciona sin ningún indicador del compilador. Tenga en cuenta que main=6;escribiría la "función" definida en los datos , pero el modificador constante hace que GCC la escriba en rodata , que (al menos en mi plataforma) puede contener código.

Dennis
fuente
Me encanta evitar incluso usar una función :) ¿Cómo funciona esto en términos C? ¿El compilador ve que maines un 6 e intenta llamarlo (lo que supongo que haría que se rindiera e intentara la instrucción)?
Mia yun Ruse el
11
@JackDobson es un comportamiento indefinido, por lo que no funciona en términos de C; estás a merced del compilador. Clang incluso tiene una advertencia para esto por alguna razón: "la variable llamada 'main' con enlace externo tiene un comportamiento indefinido".
Bobby Sacamano
2
GCC se quejará de mainno ser una función, pero solo si activa las advertencias ( -Wallo -pedanticlo hará).
zwol
Creo que es bastante estándar que los ejecutables para sistemas tipo Unix tengan segmentos de texto / datos / bss . El vinculador coloca la .rodata sección dentro del segmento de texto del ejecutable, y espero que este sea el caso en casi cualquier plataforma. (El cargador de programas del núcleo solo se preocupa por los segmentos, no por las secciones).
Peter Cordes
3
También tenga en cuenta que 06solo es una instrucción no válida en x86-64. En el modo de 32 bits, es PUSH ES, por lo que esta respuesta solo funciona con compiladores predeterminados -m64. Ver ref.x86asm.net/coder.html#x06 . La única secuencia de bytes que está garantizado para decodificar como una instrucción ilegal en todas las CPU x86 futuros es el octeto 2 UD2 : 0F 0B. Cualquier otra cosa podría ser algún prefijo futuro o codificación de instrucciones. Aún así, ¡voté por una forma genial de hacer que un compilador de C pegue una mainetiqueta en algunos bytes!
Peter Cordes el
39

Rápido, 5 bytes

[][0]

Índice de acceso 0 de una matriz vacía. Esto llama fatalError(), que imprime un mensaje de error y se bloquea con un SIGILL. Puedes probarlo aquí .

NadieNada
fuente
Este es uno de los más complicados;)
Mega Man
26
... ¿por qué se estrella con un SIGILL? ¿Quién pensó que era una señal apropiada?
Hipsters
44
@Asu No; fatalError()se bloquea intencionalmente al correr ud2. No sé por qué decidieron hacer eso, pero tal vez pensaron que el mensaje de error "Instrucción ilegal" tenía sentido porque el programa hizo algo ilegal.
NadieNada
2
Brillante. Apuesto a que este también es el código Swift más corto para causar un bloqueo.
JAL
3
@JAL Sí; No se me ocurre nada más corto. Lo intenté nil!, pero el compilador no pudo inferir el tipo de resultado. (También, hola JAL!)
NobodyNada
23

GNU C, 25 bytes

main(){__builtin_trap();}

GNU C (un dialecto específico de C con extensiones) contiene una instrucción para bloquear el programa intencionalmente. La implementación exacta varía de una versión a otra, pero a menudo los desarrolladores intentan implementar el bloqueo lo más barato posible, lo que normalmente implica el uso de una instrucción ilegal.

La versión específica que solía probar es gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0; sin embargo, este programa causa una SIGILL en una gama bastante amplia de plataformas y, por lo tanto, es bastante portátil. Además, lo hace mediante la ejecución de una instrucción ilegal. Aquí está el código de ensamblaje en el que se compila lo anterior con la configuración de optimización predeterminada:

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

ud2 es una instrucción que Intel garantiza que siempre permanecerá indefinida.


fuente
11
−6:main(){asm("ud2");}
wchargin
Además, no sé cómo contamos bytes para el montaje en bruto, pero 00 00 0f 0bes el lenguaje de máquina para ud2...
wchargin
55
@wchargin: esa es una respuesta x86 + GNU C. Este es portátil para todos los sistemas GNU. También tenga en cuenta que UD2 tiene solo 2 bytes . IDK donde obtuviste esos 00bytes; no son parte del código de máquina para UD2. Por cierto, como comenté en la respuesta de Dennis , hay instrucciones ilegales de un byte en x86-64 por ahora, pero no se garantiza que permanezcan así.
Peter Cordes
@wchargin: contamos bytes para funciones / programas de código de máquina como es de esperar. Vea algunas de mis respuestas, como Adler32 en 32 bytes de código de máquina x86-64 , o GCD en 8 bytes de código de máquina x86-32 .
Peter Cordes el
1
@Ruslan: No lo son; 00 00decodifica lo mismo en x86-64 (como add [rax], al). 00 00 0f 0bgeneralmente SIGSEGV antes de SIGILL, a menos que tenga un puntero grabable rax.
Peter Cordes
22

C (x86_64), 11, 30, 34 o 34 + 15 = 49 bytes

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

He presentado un par de soluciones que usan funciones de biblioteca para lanzar a SIGILLtravés de varios medios, pero podría decirse que es trampa, ya que la función de biblioteca resuelve el problema. Aquí hay una gama de soluciones que no utilizan funciones de biblioteca y hacen suposiciones variables sobre dónde el sistema operativo está dispuesto a permitirle ejecutar código no ejecutable. (Las constantes aquí se eligen para x86_64, pero puede cambiarlas para obtener soluciones de trabajo para la mayoría de los otros procesadores que tienen instrucciones ilegales).

06es el byte de código máquina con el número más bajo que no corresponde a una instrucción definida en un procesador x86_64. Entonces, todo lo que tenemos que hacer es ejecutarlo. (Alternativamente, 2Ftambién está indefinido y corresponde a un único carácter ASCII imprimible). Ninguno de estos está garantizado que siempre esté indefinido, pero no están definidos a partir de hoy.

El primer programa aquí se ejecuta 2Fdesde el segmento de datos de solo lectura. La mayoría de los enlazadores no son capaces de producir un salto trabajando desde .texta .rodata(o el equivalente en su sistema operativo) ya que no es algo que nunca sería útil en un programa correctamente segmentada; Todavía no he encontrado un sistema operativo en el que esto funcione. También debería tener en cuenta el hecho de que muchos compiladores quieren que la cadena en cuestión sea una cadena ancha, lo que requeriría un adicionalL; Supongo que cualquier sistema operativo en el que funcione tiene una visión bastante desactualizada de las cosas y, por lo tanto, se está construyendo para un estándar anterior a C94 por defecto. Es posible que no haya ningún lugar donde funcione este programa, pero también es posible que haya algún lugar donde funcione este programa, y ​​por lo tanto lo estoy enumerando en esta colección de posibles respuestas más dudosas a menos dudosas. (Después de publicar esta respuesta, Dennis también mencionó la posibilidad main[]={6}en el chat, que tiene la misma longitud y que no tiene problemas con el ancho de los caracteres, e incluso insinuó el potencial para main=6; No puedo reclamar razonablemente estas respuestas como mía, ya que no pensé en ellos yo mismo).

El segundo programa aquí se ejecuta 06desde el segmento de datos de lectura-escritura. En la mayoría de los sistemas operativos, esto causará una falla de segmentación, ya que los segmentos de datos grabables se consideran un defecto de diseño incorrecto que hace que las vulnerabilidades sean probables. Sin embargo, este no siempre ha sido el caso, por lo que probablemente funcione en una versión suficientemente antigua de Linux, pero no puedo probarlo fácilmente.

El tercer programa se ejecuta 06desde la pila. Nuevamente, esto causa una falla de segmentación hoy en día, porque la pila normalmente se clasifica como no escribible por razones de seguridad. La documentación del enlazador que he visto implica en gran medida que solía ser legal ejecutarlo desde la pila (a diferencia de los dos casos anteriores, hacerlo ocasionalmente es útil), así que aunque no puedo probarlo, estoy bastante seguro de que hay algunos versión de Linux (y probablemente otros sistemas operativos) en la que esto funciona.

Finalmente, si le da -Wl,-z,execstack(penalización de 15 bytes) a gcc(si usa GNU ldcomo parte del backend), desactivará explícitamente la protección de la pila ejecutable, permitiendo que el tercer programa funcione y dé una señal de operación ilegal como se esperaba. Yo he probado y verificado esta versión 49 bytes para trabajar. (Dennis menciona en el chat que aparentemente esta opción funciona main=6, lo que daría un puntaje de 6 + 15. Estoy bastante sorprendido de que esto funcione, dado que el 6 descaradamente no está en la pila; la opción de enlace aparentemente hace más de su nombre lo sugiere.)


fuente
En x86-64 / linux con gcc6 en su modo predeterminado (indulgente), const main=6;funciona, al igual que varias variaciones. Este enlazador (que sospecho es también su enlazador) es capaz de generar un salto de .texta .rodata; El problema que tenía es que, sin consteso, está entrando en el segmento de datos de escritura ( .data), que no es ejecutable en el hardware moderno. Habría funcionado en versiones anteriores de x86, donde el hardware de protección de memoria no podía marcar las páginas como legibles pero no ejecutables.
zwol
Tenga en cuenta que incluso en C89, mainse requiere que sea una función (§5.1.2.2.1): no sé por qué gcc considera que declarar maincomo un objeto de datos solo merece una advertencia, y solo con -pedanticla línea de comando. Alguien a principios de la década de 1990 tal vez pensó que nadie lo haría por accidente, pero no es que sea algo útil a propósito, excepto para este tipo de juego.
zwol
1
... Volviendo main[]="/"a leer de nuevo, parece que esperaba saltar al segmento de datos de solo lectura, porque los literales de cadena van en rodata. Te ha sorprendido la diferencia entre char *foo = "..."y char foo[] = "...". char *foo = "..."es azúcar sintáctico para const char __inaccessible1[] = "..."; char *foo = (char *)&__inaccessible1[0];, por lo que el literal de cadena va en rodata, y fooes una variable global independiente y grabable que apunta a él. Sin char foo[] = "..."embargo, con toda la matriz va en el segmento de datos grabables.
zwol
19

GNU como (x86_64), 3 bytes

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
Torkel Bjørnson-Langen
fuente
Debe haber una manera de expresar eso en una "fuente" de dos bytes ...
OrangeDog
Oh, listo Me preguntaba si había una manera de construir esto que pondría el punto de entrada al comienzo del archivo (sin declaraciones) y que no incurriría en penalidades por una configuración de sistema de construcción inusual. No pude encontrar uno, pero parece que lo hiciste.
@ ais523: sí, mi habitual script de compilación NASM / YASM ( asm-link) para programas de juguete de un solo archivo compilaría un ejecutable desde esta fuente de la misma manera, ya que ldel punto de entrada predeterminado es el inicio del segmento de texto o algo así. Simplemente no pensé en buscar el tamaño de fuente asm en este: P
Peter Cordes
18

Bash en Raspbian en QEMU, 4 (1?) Bytes

No es mi trabajo Simplemente informo el trabajo de otro. Ni siquiera estoy en condiciones de probar el reclamo. Dado que una parte crucial de este desafío parece ser encontrar un entorno en el que se eleve y capture esta señal, no incluyo el tamaño de QEMU, Raspbian o bash.

El 27 de febrero de 2013, 8:49 pm, el usuario emlhalac informó " Obteniendo 'instrucciones ilegales' al intentar chroot " en el foro Raspberry Pi.

ping

productor

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

Imagino comandos mucho más cortos producirán esta salida, por ejemplo, tr.

EDITAR: Basado en el comentario de @ fluffy , redujo el límite inferior conjeturado en la longitud de entrada a "1?".

Eric Towers
fuente
55
Creo que el [comando ganaría. :)
esponjoso
17

Archivo COM x86 MS-DOS, 2 bytes

EDITAR: Como se señaló en los comentarios, el DOS en sí no atrapará la excepción de la CPU y simplemente se bloqueará (no solo la aplicación, todo el sistema operativo). Ejecutar en un sistema operativo basado en NT de 32 bits como Windows XP, de hecho, activará una señal de instrucción ilegal.

0F 0B

De la documentación :

Genera un código de operación no válido. Esta instrucción se proporciona para pruebas de software para generar explícitamente un código de operación no válido.

Lo cual se explica por sí mismo. Guardar como un archivo .com y ejecutar en cualquier emulador de DOS Los emuladores de DOS simplemente se bloquean. Ejecutar en Windows XP, Vista o 7 de 32 bits.

SIGILL en Windows XP

maservant
fuente
1
Técnicamente, hace que el procesador genere una excepción de instrucción ilegal. Sin embargo, DOS tiene una protección de memoria muy limitada y capacidades de manejo de excepciones, y no me sorprendería si solo condujera a un comportamiento indefinido / bloqueo del sistema operativo. El OP no dijo que el núcleo tenía que detectar el error e imprimir "Instrucción ilegal" en la consola.
Maservant
44
Pensé en esta solución, pero no creo que sea válida. La pregunta requiere una señal de instrucción ilegal , no solo una trampa de procesador de instrucción ilegal , por lo que el objetivo era encontrar un sistema operativo que realmente generara una señal en respuesta a la #UDtrampa. (Además, decidí probarlo realmente, y parecía arrojar mi emulador de DOS a un bucle infinito).
2
Probé esto en MS-DOS real en un AMD K6-II. Ejecutarlo simplemente bloquea el sistema, con y sin EMM386 ejecutándose. (EMM386 atrapa algunos errores y detiene el sistema con un mensaje, por lo que valió la pena probar para ver si marcó la diferencia.)
Marque el
2
Sí, las ventanas basadas en DOS deberían ser capaces de atrapar la trampa y al menos bloquear la aplicación.
Asu
2
@Asu Puedo confirmar que esto funciona en XP de 32 bits, y probablemente funcionará en todos los demás sistemas Windows de 32 bits. Estoy de acuerdo en que esta no es una solución en DOS, ya que simplemente se bloquea.
maservant
13

C (Windows de 32 bits), 34 bytes

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

Esto solo funciona si se compila sin optimizaciones (de lo contrario, el código ilegal en la ffunción está "optimizado").

El desmontaje de la mainfunción se ve así:

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

Podemos ver que usa una pushinstrucción con un valor literal 0b0f(little-endian, por lo que sus bytes se intercambian). La callinstrucción empuja una dirección de retorno (de la ...instrucción), que se encuentra en la pila cerca del parámetro de la función. Al usar un [-1]desplazamiento, la función anula la dirección de retorno, por lo que señala 9 bytes antes, donde están los bytes 0f 0b.

Estos bytes provocan una excepción de "instrucción indefinida", como se diseñó.

anatolyg
fuente
12

Java, 50 43 24 bytes

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

Este es un java.util.function.Consumer<Runtime>1 cuyo comando es robado de la respuesta de fluffy . Funciona porque debes llamarlo como whateverNameYouGiveIt.accept(Runtime.getRuntime())!

Tenga en cuenta que esto creará un nuevo proceso y hará que arroje un SIGILL en lugar de arrojar un SIGILL.

1 - Técnicamente, también puede ser un java.util.function.Function<Runtime, Process>porque Runtime#exec(String)devuelve un java.lang.Processque puede usarse para controlar el proceso que acaba de crear ejecutando un comando de shell.


En aras de hacer algo más impresionante en un lenguaje tan detallado, aquí hay un bono 72 60 48 bytes:

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

Este es otro Consumer<Runtime>que pasa por TODOS los procesos (incluido él mismo), haciendo que cada uno de ellos arroje un SIGILL. Mejor prepararse para un choque violento.


Y otra bonificación (a Consumer<ANYTHING_GOES>), que al menos pretende lanzar un SIGILL en 20 bytes:

a->System.exit(132);
dorukayhan
fuente
8

Perl, 9 bytes

kill+4,$$

Simplemente llama a la función de biblioteca apropiada para señalar un proceso y hace que el programa se señale a sí mismo SIGILL. Aquí no hay instrucciones ilegales reales, pero produce el resultado apropiado. (Creo que esto hace que el desafío sea bastante barato, pero si algo está permitido, esta es la laguna que usarías ...)


fuente
Vine aquí para publicar lo mismo, con un espacio en lugar del +. :)
simbabque
2
Cuando las personas aprenden Perl para la programación que no es de golf, lo aprenden con un +. Después de jugar al golf por un tiempo, lo hacen de +vez en cuando para presumir. Eventualmente, han escrito suficientes programas donde necesitan evitar espacios en blanco por alguna razón u otra que se +convierta en hábito. (También analiza menos ambigua, ya que funciona en torno a desencadenar el caso especial en el programa de análisis de paréntesis.)
8

Lenguaje de ensamblador unificado ARM (UAL), 3 bytes

nop

Por ejemplo:

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

Después de ejecutar nop, el procesador interpreta la .ARM.attributessección como código y encuentra una instrucción ilegal en algún lugar:

$ 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

Probado en una Raspberry Pi 3.


fuente
De alguna manera esto no funciona en un Pi 2.
Mega Man
7

Microsoft C (Visual Studio 2005 en adelante), 16 bytes

main(){__ud2();}

No puedo probar esto fácilmente, pero de acuerdo con la documentación , debería producir una instrucción ilegal al intentar ejecutar intencionalmente una instrucción solo del núcleo desde un programa en modo de usuario. (Tenga en cuenta que debido a que la instrucción ilegal bloquea el programa, no tenemos que intentar regresar main, lo que significa que esta mainfunción de estilo K&R es válida. Visual Studio nunca haber pasado de C89 normalmente es algo malo, pero entró útil aquí.)


fuente
¿Se puede compilar para Linux con VS2015? Porque no creo que SIGILL esté definido en Windows, ¿verdad?
Andrew Savinykh
7

Rubí, 13 bytes

`kill -4 #$$`

Supongo que es seguro asumir que estamos ejecutando esto desde un shell * nix. Los literales de retroceso ejecutan el comando de shell dado. $$es el proceso de Ruby en ejecución y #es para la interpolación de cadenas.


Sin llamar al shell directamente:

Rubí, 17 bytes

Process.kill 4,$$
daniero
fuente
6

Cualquier shell (sh, bash, csh, etc.), cualquier POSIX (10 bytes)

Respuesta trivial pero no había visto a nadie publicarlo.

kill -4 $$

Solo envía SIGILL al proceso actual. Ejemplo de salida en OSX:

bash-3.2$ kill -4 $$
Illegal instruction: 4
mullido
fuente
Podría hacerlo kill -4 1si la pregunta no es específica sobre qué programa arroja el SIGILL
Mark K Cowan
@ MarkKCowan Heh, buen punto, aunque eso asume la raíz ...
esponjoso
2
You will have root in your programs- elimine un byte de su respuesta y consulte la pregunta ligeramente al mismo tiempo: D. BONIFICACIÓN: Tienes que matarinit
Mark K Cowan
2
@MarkKCowan: En (versiones modernas de?) Linux, en initrealidad es inmune a las señales que no ha solicitado específicamente recibir, incluso con root. Sin embargo, quizás podría solucionar esto utilizando un sistema operativo POSIX diferente.
2
kill -4 2entonces: D
Mark K Cowan
6

Código de máquina ELF + x86, 45 bytes

Este debería ser el programa ejecutable más pequeño en una máquina Unix que arroja SIGILL (debido a que Linux no reconoce el ejecutable si se hace más pequeño).

Compilar con nasm -f bin -o a.out tiny_sigill.asm, probado en una máquina virtual x64.

Binario real de 45 bytes:

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

Listado de ensamblaje (ver fuente a continuación):

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

Descargo de responsabilidad: código del siguiente tutorial sobre cómo escribir el programa de ensamblaje más pequeño para devolver un número, pero usando opcode ud2 en lugar de mov: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

Florian Castellane
fuente
2
Iba a publicar un ejecutable modificado de ese tutorial exacto, pero me ganaste. Esto merece ganar; Es un verdadero minimalista en el sentido de los recursos del sistema (no requiere más de 45 bytes tanto en el archivo como en la memoria, y es exactamente lo mismo en ambos), y ningún intérprete inflado como las otras soluciones de ensamblador. Simplemente es lo que es.
Iwillnotexist Idonotexist
5

AutoIt , 93 bytes

Usando el ensamblaje en línea del ensamblador plano

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

Cuando se ejecuta en modo interactivo SciTE, se bloqueará inmediatamente. El depurador de Windows debería aparecer por una fracción de segundo. La salida de la consola será algo como esto:

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

¿Dónde -1073741795está el código de error indefinido lanzado por WinAPI? Este puede ser cualquier número negativo.

Similar usando mi propio ensamblador LASM :

#include<LASM.au3>
$_=LASM_ASMToMemory("ud2"&@CRLF&"ret 16")
LASM_CallMemory($_,0,0,0,0)
mınxomaτ
fuente
5

NASM, 25 bytes

No sé cómo funciona esto, solo que lo hace específicamente en mi computadora (Linux x86_64).

global start
start:
jmp 0

Compilar y ejecutar como:

$ nasm -f elf64 ill.asm && ld ill.o && ./a.out
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400080
Illegal instruction
chico albaricoque
fuente
Probablemente pueda acortarlo a cuatro bytes, comoja 0
Mark K Cowan el
1
o tres comoud2
Mark K Cowan el
1
¿Probablemente porque está tratando de saltar a algunos datos?
Asu
5

Conjunto hexagonal TI-83, 2 bytes

PROGRAM:I
:AsmPrgmED77

Corre como Asm(prgmI). Ejecuta el código de operación ilegal 0xed77. Cuento cada par de dígitos hexadecimales como un byte.

Acosar
fuente
4

Python, 32 bytes

from os import*;kill(getpid(),4)
Torkel Bjørnson-Langen
fuente
1
Mismo recuento de bytes:import os;os.kill(os.getpid(),4)
Oliver Ni
3

x86 .COM, 1 byte

c

ARPLcausas #UDen modo de 16 bits

l4m2
fuente
1

Shell de Linux, 9 bytes

kill -4 0

Envía SIGILLal proceso con PID 0. No sé qué proceso tiene PID 0, pero siempre existe.

Pruébalo en línea!

MD XF
fuente
De man kill:0 All processes in the current process group are signaled.
Dennis
1

GNU C, 24 19 18 bytes

-4 gracias a Dennis
-1 gracias a ceilingcat

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

Pruébalo en línea! Esto supone ASCII y x86_64. Intenta ejecutar el código de la máquina 27, que ... es ilegal.


shortC , 10 5 4 bytes

AV"'

Equivalente al código GNU C anterior. Pruébalo en línea!

MD XF
fuente
L"\6"también es ilegal, suponiendo x86_64.
Dennis
@ Dennis ¿Qué instrucción es 0x06? Además, el Lno es necesario.
MD XF
No está asignado.
Dennis
No está asignado; eso es lo que lo hace ilegal. Además, 'es 39 = 0x27 , no 0x39 .
Dennis