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 SIGILL
vá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, 2F
també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 2F
partir do segmento de dados somente leitura. A maioria dos vinculadores não é capaz de produzir um salto de trabalho .text
para .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 06
partir 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 06
partir 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 ld
como 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.)
raise(SIGILL)
?