Código mais curto para lançar SIGILL


76

fundo

Já temos um desafio em jogar o SIGSEGV , por que não um desafio em jogar o SIGILL?

O que é o SIGILL?

SIGILL é o sinal para uma instrução ilegal no processador, o que acontece muito raramente. A ação padrão depois de receber o SIGILL está finalizando o programa e gravando um dump principal. O ID do sinal do SIGILL é 4. Você encontra o SIGILL muito raramente, e eu não tenho absolutamente nenhuma idéia de como gerá-lo no seu código, exceto via sudo kill -s 4 <pid>.

Regras

Você terá raiz nos seus programas, mas se não quiser, por qualquer motivo, também poderá usar um usuário normal. Estou em um computador Linux com código de idioma alemão e não sei o texto em inglês que é exibido após a captura do SIGILL, mas acho que é algo como 'Instrução ilegal'. O programa mais curto que lança SIGILL vence.


6
Você pode esclarecer se a instrução deve ser gerada pelo kernel ou não. Em particular, você deseja permitir que o programa o gere diretamente usando a chamada libc raise(SIGILL)?

1
Realmente diz Illegal instruction (core dumped).
Erik the Outgolfer

@ ais523 Tudo é permitido.
Mega Man

5
Para qualquer hardware que possa aumentar o SIGILL, a resposta será igual à duração da instrução. Basta colocar uma instrução ilegal em algum lugar e tentar executá-la. A única coisa interessante será a cadeia de ferramentas complicada envolvida.
precisa saber é o seguinte

3
* pessoas postando programas antigos que tiveram que não funcionou *
RudolfJelin

Respostas:


112

Assembler do PDP-11 (UNIX sexta edição), 1 byte

9

A instrução 9 não é válida no PDP-11 (em octal, seria 000011, o que não aparece na lista de instruções (PDF)). O montador PDP-11 que acompanha o UNIX Sexta Edição aparentemente reproduz tudo o que não entende diretamente no arquivo; nesse caso, 9 é um número e, portanto, gera uma instrução literal 9. Também possui a propriedade ímpar (incomum nas linguagens assembly atualmente) que os arquivos começam a ser executados desde o início, portanto, não precisamos de nenhuma declaração para fazer o programa. trabalhos.

Você pode testar o programa usando este emulador , embora tenha que lutar um pouco com ele para inserir o programa.

Veja como as coisas terminam quando você descobre como usar o sistema de arquivos, o editor, o terminal e coisas semelhantes que você pensou que já sabia usar:

% a.out
Illegal instruction -- Core dumped

Confirmei com a documentação que este é um SIGILLsinal genuíno (e até tinha o mesmo número de sinal, 4, todo o caminho naquela época!)


1
Tinha o mesmo número de sinal porque POSIX e UNIX e o SUS estão intimamente relacionados :) #
cat

4
Quase todos os números de sinal na V6 ainda têm os mesmos significados hoje; os mnemônicos têm sido menos estáveis ​​que os números. Compare minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/sys/param.h com github.com/freebsd/freebsd/blob/master/sys/sys/signal.h - semântica idêntica para 1 a 13, mas apenas 1, 2 e 13 têm exatamente os mesmos nomes. (SIGALRM / 14 e SIGTERM / 15 foram adicionados apenas na V7.) (A linhagem System V possui algumas alterações, movendo o SIGBUS de 10 para 7 (substituindo o inútil SIGEMT) e o SIGSYS acima de 15, para dar espaço ao SIGUSR1 e SIGUSR2).
Zwol

4
@cat POSIX e SUS na verdade não especificam os valores dos sinais - eles especificam o significado de alguns números quando passados ​​como argumentos para o comando kill, mas o SIGILL não está incluído.
Random832

7
a.outpossui vários bytes, na verdade (a 9instrução é compilada em dois bytes, e o assembler também adiciona um cabeçalho e rodapé para tornar o programa executável). Por isso escrevi o programa em linguagem assembly, não em código de máquina. O programa em linguagem assembly possui apenas um byte e é compilado em um programa com mais bytes em; esse é um problema de código-golfe (minimize o tamanho da fonte), não um problema de codificação de tamanho (minimize o tamanho do executável); portanto, é importante o tamanho de 1 byte da fonte.

2
Abuso muito inteligente de um sistema antigo, mas impressionante.
Mast

81

C (x86_64, tcc ), 7 bytes

main=6;

Inspirado por esta resposta .

Experimente online!

Como funciona

A montagem gerada se parece com isso.

    .globl  main
main:
    .long 6

Observe que o TCC não coloca a "função" definida em um segmento de dados .

Após a compilação, _start apontará para main como de costume. Quando o programa resultante é executado, ele espera o código em main e localiza o inteiro little-endian (!) De 32 bits 6 , codificado como 0x06 0x00 0x00 0x00 . O primeiro byte - 0x06 - é um código de operação inválido, portanto o programa termina com o SIGILL .


C (x86_64, gcc ), 13 bytes

const main=6;

Experimente online!

Como funciona

Sem o modificador const , o assembly gerado se parece com isso.

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

O vinculador do GCC trata a última linha como uma dica de que o objeto gerado não requer uma pilha executável. Como main é explicitamente colocado em uma seção de dados , o código de operação que ele contém não é executável; portanto, o programa termina com SIGSEGV (falha de segmentação).

Remover a segunda ou a última linha fará com que o executável gerado funcione como pretendido. A última linha pode ser ignorada com o sinalizador do compilador -zexecstack( Experimente online! ), Mas isso custa 12 bytes .

Uma alternativa mais curta é declarar main com o modificador const , resultando na seguinte montagem.

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

Isso funciona sem nenhum sinalizador de compilador. Observe que main=6;escreveria a "função" definida nos dados , mas o modificador const fará com que o GCC a escreva em rodata , que (pelo menos na minha plataforma) tem permissão para conter código.


Adoro evitar completamente o uso de uma função :) Como isso funciona em termos de C? O compilador vê que mainé um 6 e tenta chamá-lo (o que eu acho que faria desistir e tentar a instrução)?
Mia yun Ruse

11
@JackDobson, é um comportamento indefinido, portanto não funciona em termos de C; você está à mercê do compilador. Clang ainda tem um aviso por esse motivo: "a variável denominada 'main' com ligação externa tem um comportamento indefinido".
Bobby Sacamano

2
O GCC se queixará de mainnão ser uma função, mas somente se você ativar os avisos (faça -Wallou o -pedanticfará).
Zwol

Eu acho que é bastante padrão para executáveis ​​em sistemas tipo Unix ter segmentos de texto / dados / bss . O vinculador coloca a .rodata seção dentro do segmento de texto do executável, e espero que este seja o caso em praticamente qualquer plataforma. (O carregador de programas do kernel se preocupa apenas com segmentos, não seções).
Peter Cordes

3
Observe também que 06é apenas uma instrução inválida em x86-64. No modo de 32 bits, é PUSH ES, portanto, esta resposta funciona apenas com compiladores padrão -m64. Consulte ref.x86asm.net/coder.html#x06 . A única sequência de bytes que está garantido para decodificar como uma instrução ilegal em todas as futuras CPUs x86 é o 2 byte UD2 : 0F 0B. Qualquer outra coisa pode ser algum prefixo futuro ou codificação de instruções. Ainda assim, com o voto positivo de uma maneira interessante de fazer com que um compilador C cole um mainrótulo em alguns bytes!
Peter Cordes

39

Rápido, 5 bytes

[][0]

Acesse o índice 0 de uma matriz vazia. Isso chama fatalError(), que imprime uma mensagem de erro e trava com um SIGILL. Você pode tentar aqui .


Este é um dos mais complicados;)
Mega Man

26
... por que diabos ele bate com um SIGILL? Quem pensou que era um sinal apropriado?
Descolados

4
@Asu No; fatalError()falha intencionalmente ao executar ud2. Por que eles escolheram fazer isso eu não sei, mas talvez eles achem que a mensagem de erro "Instrução ilegal" fazia sentido porque o programa fez algo ilegal.
NobodyNada

2
Brilhante. Aposto que esse também é o código Swift mais curto que causa um acidente.
JAL

3
@JAL Yeah; Não consigo pensar em nada mais curto. Eu tentei nil!, mas o compilador não conseguiu inferir o tipo de resultado. (Além disso, oi JAL!)
NobodyNada

23

GNU C, 25 bytes

main(){__builtin_trap();}

O GNU C (um dialeto específico de C com extensões) contém uma instrução para travar o programa intencionalmente. A implementação exata varia de versão para versão, mas geralmente os desenvolvedores tentam implementar a falha o mais barato possível, o que normalmente envolve o uso de uma instrução ilegal.

A versão específica que eu costumava testar é gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0; no entanto, esse programa causa um SIGILL em uma ampla variedade de plataformas e, portanto, é bastante portátil. Além disso, ele faz isso realmente executando uma instrução ilegal. Aqui está o código do assembly que o acima compila com as configurações de otimização padrão:

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

ud2 é uma instrução que a Intel garante sempre permanecerá indefinida.


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

Além disso, eu não sei como contamos bytes para a montagem cru, mas 00 00 0f 0bé a linguagem de máquina para ud2...
wchargin

5
@charchar: essa é uma resposta x86 + GNU C. Este é portátil para todos os sistemas GNU. Observe também que o UD2 tem apenas 2 bytes . IDK de onde você obteve esses 00bytes; eles não fazem parte do código de máquina do UD2. BTW, como eu comentei na resposta de Dennis , há instruções ilegais de um byte no x86-64 por enquanto, mas não é garantido que elas permaneçam assim.
Peter Cordes

@charchar: contamos bytes para funções / programas de código de máquina como você esperaria. Veja algumas das minhas respostas, como Adler32 em 32 bytes de código de máquina x86-64 ou GCD em 8 bytes de código de máquina x86-32 .
Peter Cordes

1
@Ruslan: Eles não são; 00 00decodifica o mesmo em x86-64 (as add [rax], al). 00 00 0f 0busualmente SIGSEGV antes da SIGILL, a menos que você tenha um ponteiro gravável rax.
Peter Cordes

22

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

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

Enviei algumas soluções que usam funções de biblioteca para executar de SIGILLvárias maneiras, mas é indiscutível que isso é trapaça, pois a função de biblioteca resolve o problema. Aqui está uma série de soluções que não usam funções de biblioteca e fazem suposições variadas sobre onde o sistema operacional está disposto a permitir que você execute código não executável. (As constantes aqui são escolhidas para x86_64, mas você pode alterá-las para obter soluções funcionais para a maioria dos outros processadores que possuem instruções ilegais.)

06é o byte de código de máquina com o número mais baixo que não corresponde a uma instrução definida em um processador x86_64. Então, tudo o que precisamos fazer é executá-lo. (Como alternativa, 2Ftambém é indefinido e corresponde a um único caractere ASCII imprimível.) Não é garantido que nenhum deles seja sempre indefinido, mas não está definido atualmente.

O primeiro programa aqui é executado a 2Fpartir do segmento de dados somente leitura. A maioria dos vinculadores não é capaz de produzir um salto de trabalho .textpara .rodata(ou o equivalente do sistema operacional), pois não é algo que jamais seria útil em um programa segmentado corretamente; Ainda não encontrei um sistema operacional no qual isso funcione. Você também teria que permitir o fato de que muitos compiladores desejam que a cadeia em questão seja uma cadeia ampla, o que exigiria um adicionalL; Estou assumindo que qualquer sistema operacional em que isso funcione tenha uma visão bastante desatualizada das coisas e, portanto, esteja criando um padrão pré-C94 por padrão. É possível que não haja nenhum lugar onde este programa funcione, mas também é possível que haja algum lugar em que esse programa funcione, e, portanto, estou listando-o nesta coleção de respostas potenciais mais duvidosas para menos duvidosas. (Depois de postar esta resposta, Dennis também mencionou a possibilidade main[]={6}no bate-papo, que tem o mesmo tamanho e que não apresenta problemas com a largura dos caracteres, e até sugeriu o potencial para main=6; não posso razoavelmente reivindicar essas respostas como meu, como eu não pensei neles.)

O segundo programa aqui é executado a 06partir do segmento de dados de leitura e gravação. Na maioria dos sistemas operacionais, isso causa uma falha de segmentação, porque os segmentos de dados graváveis ​​são considerados uma falha de projeto ruim que torna as explorações mais prováveis. Porém, nem sempre foi esse o caso, por isso provavelmente funciona em uma versão suficientemente antiga do Linux, mas não posso testá-lo facilmente.

O terceiro programa é executado a 06partir da pilha. Novamente, isso causa uma falha de segmentação atualmente, porque a pilha é normalmente classificada como não gravável por motivos de segurança. A documentação do vinculador que eu vi implica fortemente que costumava ser legal executar a partir da pilha (ao contrário dos dois casos anteriores, isso é útil ocasionalmente), portanto, embora eu não possa testá-lo, tenho certeza de que há alguns versão do Linux (e provavelmente outros sistemas operacionais) em que isso funciona.

Finalmente, se você der -Wl,-z,execstack(penalidade de 15 bytes) a gcc(se estiver usando o GNU ldcomo parte do back-end), ele desativará explicitamente a proteção da pilha executável, permitindo que o terceiro programa funcione e emita um sinal de operação ilegal conforme o esperado. Eu tenho testado e verificado esta versão 49-byte para o trabalho. (Dennis menciona no bate-papo que essa opção aparentemente funciona main=6, o que daria uma pontuação de 6 + 15. Estou surpreso que isso funcione, já que os 6 não estão descaradamente na pilha; a opção de link aparentemente faz mais do que o nome sugere.)


No x86-64 / linux com o gcc6 no modo padrão (branda), const main=6;funciona, assim como várias variações. Esse vinculador (que eu suspeito que também seja seu vinculador) é capaz de gerar um salto de .textpara .rodata; o problema que você estava constenfrentando é que, sem , você está pulando no segmento de dados graváveis ( .data), que não é executável no hardware moderno. Teria funcionado no x86 mais antigo, onde o hardware de proteção de memória não podia marcar as páginas como legíveis, mas não executáveis.
Zwol

Observe que, mesmo em C89, mainé necessário que seja uma função (§5.1.2.2.1) - não sei por que o gcc considera que a declaração maincomo um objeto de dados merece apenas um aviso e apenas -pedanticna linha de comando. Alguém no início dos anos 90 talvez pensasse que ninguém faria isso por acidente, mas não é uma coisa útil a se fazer de propósito, exceto nesse tipo de jogo.
Zwol

1
... Relendo novamente, parece que você esperava main[]="/"pular para o segmento de dados somente leitura, porque os literais de seqüência de caracteres entram em rodata. Você foi pego pela diferença entre char *foo = "..."e char foo[] = "...". char *foo = "..."é um açúcar sintático para const char __inaccessible1[] = "..."; char *foo = (char *)&__inaccessible1[0];, portanto, a string literal entra em rodata e fooé uma variável global gravável separada que aponta para ela. Com char foo[] = "...", no entanto, toda a matriz entra no segmento de dados graváveis.
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

Deve haver uma maneira de expressar isso em uma "fonte" de dois bytes ...
OrangeDog 21/11

Oh, esperto. Eu queria saber se havia uma maneira de criar isso que colocaria o ponto de entrada no início do arquivo (sem declarações) e que não incorreria em penalidades por uma configuração incomum do sistema de compilação. Não consegui encontrar um, mas parece que você encontrou.

@ ais523: sim, meu script de construção NASM / YASM habitual ( asm-link) para programas de brinquedo de arquivo único criaria um executável a partir dessa fonte da mesma maneira, já que o ldpadrão é o ponto de entrada para o início do segmento de texto ou algo parecido. Eu só não pensar em ir para o tamanho fonte asm em um presente: P
Peter Cordes

18

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

Não é o meu trabalho. Eu apenas relato o trabalho de outro. Não estou nem em posição de testar a alegação. Como uma parte crucial desse desafio parece estar em um ambiente em que esse sinal será gerado e capturado, não incluo o tamanho do QEMU, Raspbian ou bash.

Em 27 de fevereiro de 2013 às 20:49, o usuário emlhalac relatou " Obtendo 'instruções ilegais' ao tentar chroot " nos fóruns do Raspberry Pi.

ping

produzindo

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

Eu imagino que comandos muito mais curtos produzirão essa saída, por exemplo tr,.

EDIT: Com base no comentário do @ fluffy , reduziu o limite inferior conjecturado no comprimento da entrada para "1?".


5
Eu acho que o [comando venceria. :)
fluffy

17

x86 arquivo COM do MS-DOS, 2 bytes

EDIT: Como indicado nos comentários, o próprio DOS não interceptará a exceção da CPU e simplesmente travará (não apenas o aplicativo, todo o sistema operacional). A execução em um sistema operacional baseado em NT de 32 bits, como o Windows XP, realmente dispara um sinal de instrução ilegal.

0F 0B

A partir da documentação :

Gera um código de operação inválido. Esta instrução é fornecida para teste de software para gerar explicitamente um código de operação inválido.

O que é bastante auto-explicativo. Salve como um arquivo .com e execute qualquer emulador do DOS. Os emuladores do DOS simplesmente falham. Execute no Windows XP, Vista ou 7 de 32 bits.

SIGILL no Windows XP


1
Tecnicamente, faz com que o processador gere uma exceção de instrução ilegal. No entanto, o DOS possui recursos de proteção de memória e manipulação de exceções muito limitados, e não me surpreenderia se isso levasse a um comportamento indefinido / travamento do sistema operacional. O OP não disse que o kernel tinha que pegar o erro e imprimir "Instrução ilegal" no console.
maservant

4
Pensei nessa solução, mas não acredito que seja válida. A pergunta requer um sinal de instrução ilegal , não apenas uma armadilha de processador de instrução ilegal , então o objetivo era encontrar um sistema operacional que realmente gerasse um sinal em resposta à #UDarmadilha. (Além disso, eu decidi realmente testá-lo, e ele apareceu para jogar meu emulador DOS em um loop infinito.)

2
Eu testei isso no MS-DOS real em um AMD K6-II. A execução apenas trava o sistema, com e sem o EMM386 em execução. (EMM386 armadilhas alguns erros e pára o sistema com uma mensagem, por isso foi pena testar para ver se ele fez a diferença.)
Mark

2
Sim, as janelas baseadas em DOS devem ser capazes de realmente capturar a armadilha e pelo menos travar o aplicativo.
Asu

2
@Asu Posso confirmar que isso funciona no XP de 32 bits e provavelmente funcionará em todos os outros sistemas Windows de 32 bits. Concordo que essa não é uma solução no DOS, pois apenas trava.
maservant

13

C (Windows de 32 bits), 34 bytes

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

Isso funciona apenas se compilar sem otimizações (caso contrário, o código ilegal na ffunção é "otimizado").

A desmontagem da mainfunção fica assim:

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

Podemos ver que ele usa uma pushinstrução com um valor literal 0b0f(little-endian, para que seus bytes sejam trocados). A callinstrução envia um endereço de retorno (da ...instrução), que está situado na pilha perto do parâmetro da função. Usando um [-1]deslocamento, a função substitui o endereço de retorno para que aponte 9 bytes anteriormente, onde 0f 0bestão os bytes .

Esses bytes causam uma exceção de "instrução indefinida", conforme projetado.


12

Java, 50 43 24 bytes

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

Este é um java.util.function.Consumer<Runtime>1 cujo comando é roubado da resposta do fluffy . Funciona porque você deve chamá-lo como whateverNameYouGiveIt.accept(Runtime.getRuntime())!

Observe que isso criará um novo processo e fará com que ele jogue um SIGILL em vez de lançar um SIGILL.

1 - Tecnicamente, também pode ser um java.util.function.Function<Runtime, Process>porque Runtime#exec(String)retorna a java.lang.Processque pode ser usado para controlar o processo que você acabou de criar executando um comando shell.


Para fazer algo mais impressionante em uma linguagem tão detalhada, aqui está um bônus de 72 60 e 48 bytes:

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

Este é outro Consumer<Runtime>que passa por TODOS os processos (inclusive ele próprio), fazendo com que cada um deles jogue um SIGILL. Melhor suporte para um acidente violento.


E outro bônus (a Consumer<ANYTHING_GOES>), que pelo menos finge lançar um SIGILL em 20 bytes:

a->System.exit(132);

8

Perl, 9 bytes

kill+4,$$

Simplesmente chama a função de biblioteca apropriada para sinalizar um processo e obtém o programa para sinalizar a si próprio SIGILL. Nenhuma instrução ilegal real está envolvida aqui, mas produz o resultado apropriado. (Eu acho que isso torna o desafio razoavelmente barato, mas se algo for permitido, essa é a brecha que você usaria ...)


Vim aqui para postar o mesmo, com um espaço em vez do +. :)
simbabque 21/11

2
Quando as pessoas aprendem Perl para programação que não seja golfe, elas aprendem com a +. Depois de jogar golfe por um tempo, eles +ocasionalmente se exibem. Eventualmente, eles escreveram programas suficientes onde precisavam evitar espaços em branco por algum motivo ou outro que +se tornasse hábito. (Ele também analisa a menos ambígua, porque funciona em torno provocando o caso especial no analisador de parênteses.)

8

Linguagem de montagem unificada (UAL) do ARM, 3 bytes

nop

Por exemplo:

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

Após a execução nop, o processador interpreta a .ARM.attributesseção como código e encontra uma instrução ilegal em algum 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

Testado em um Raspberry Pi 3.


De alguma forma, isso não funciona em um Pi 2.
Mega Man

7

Microsoft C (Visual Studio 2005 em diante), 16 bytes

main(){__ud2();}

Não posso testar isso facilmente, mas de acordo com a documentação, ele deve produzir uma instrução ilegal, intencionalmente, tentando executar uma instrução somente do kernel de um programa no modo de usuário. (Observe que, como a instrução ilegal trava o programa, não precisamos tentar retornar main, o que significa que essa mainfunção no estilo K&R é válida. O Visual Studio nunca tendo migrado do C89 normalmente é uma coisa ruim, mas veio útil aqui.)


Você pode compilar para linux com o VS2015? Porque eu não acho que o SIGILL esteja definido no Windows, é?
Andrew Savinykh

7

Ruby, 13 bytes

`kill -4 #$$`

Eu acho que é seguro assumir que estamos executando isso a partir de um shell * nix. Os literais de backtick executam o comando shell fornecido. $$é o processo Ruby em execução e #é para interpolação de strings.


Sem chamar o shell diretamente:

Ruby, 17 bytes

Process.kill 4,$$

6

Qualquer shell (sh, bash, csh, etc.), qualquer POSIX (10 bytes)

Resposta trivial, mas eu não tinha visto ninguém postá-lo.

kill -4 $$

Apenas envia o SIGILL para o processo atual. Exemplo de saída no OSX:

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

Você poderia fazer kill -4 1se a questão não é específico sobre qual programa lança a SIGILL
Mark K Cowan

@MarkKCowan Heh, bom ponto, embora que assume raiz ...
macia

2
You will have root in your programs- bata um byte na sua resposta e remova a pergunta um pouco ao mesmo tempo: D. Bônus: Você começa a matarinit
Mark K Cowan

2
@MarkKCowan: No (versões modernas do?) Linux, initna verdade , é imune a sinais que não solicitou especificamente para receber, mesmo com root. Talvez você possa solucionar isso usando um sistema operacional POSIX diferente.

2
kill -4 2então: D
Mark K Cowan

6

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

Este deve ser o menor programa executável em uma máquina Unix que lança o SIGILL (devido ao Linux não reconhecer o executável, se for menor).

Compile com nasm -f bin -o a.out tiny_sigill.asm, testado em uma máquina virtual x64.

Binário 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

Lista de montagem (veja a fonte abaixo):

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

Isenção de responsabilidade: codifique o seguinte tutorial sobre como escrever o menor programa de montagem para retornar um número, mas usando o opcode ud2 em vez de mov: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html


2
Eu ia postar um executável modificado desse tutorial exato, mas você me venceu. Isso merece ganhar; É um verdadeiro minimalista no sentido de recursos do sistema (requer não mais que 45 bytes no arquivo e na memória, e é exatamente o mesmo nos dois), e nenhum intérprete inchado como as outras soluções de montagem. Simplesmente é o que é.
Iwillnotexist Idonotexist

5

AutoIt , 93 bytes

Usando montagem embutida flatassembler:

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

Quando executado no modo interativo SciTE, ele falha imediatamente. O depurador do Windows deve aparecer por uma fração de segundo. A saída do console será algo como isto:

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

Onde -1073741795está o código de erro indefinido lançado pela WinAPI. Este pode ser qualquer número negativo.

Similar usando meu próprio LASM de assembler :

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

5

NASM, 25 bytes

Não sei como isso funciona, apenas no meu computador especificamente (Linux x86_64).

global start
start:
jmp 0

Compile e execute como:

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

Você provavelmente pode encurtar a quatro bytes, comoja 0
Mark K Cowan

1
ou três comoud2
Mark K Cowan

1
Provavelmente porque está tentando pular para alguns dados?
Asu

5

Conjunto hexagonal TI-83, 2 bytes

PROGRAM:I
:AsmPrgmED77

Executar como Asm(prgmI). Executa o opcode 0xed77 ilegal. Eu conto cada par de dígitos hexadecimais como um byte.



3

x86 .COM, 1 byte

c

ARPLcausa #UDno modo de 16 bits


1

Shell Linux, 9 bytes

kill -4 0

Envia SIGILLpara o processo com PID 0. Não sei qual processo possui o PID 0, mas ele sempre existe.

Experimente online!


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

1

GNU C, 24 19 18 bytes

-4 graças a Dennis
-1 graças a ceilingcat

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

Experimente online! Isso pressupõe ASCII e x86_64. Ele tenta executar o código da máquina 27, o que é ilegal.


shortC , 10 5 4 bytes

AV"'

Equivalente ao código GNU C acima. Experimente online!


L"\6"também é ilegal, assumindo x86_64.
Dennis

@Dennis Que instrução é 0x06? Além disso, o Lnão é necessário.
MD XF

Não está atribuído.
Dennis

Não está atribuído; é isso que a torna ilegal. Além disso, 'é 39 = 0x27 , não 0x39 .
Dennis

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.