C (x86_64), 11, 30, 34 ou 34 + 15 = 49 octets
main[]="/";
c=6;main(){((void(*)())&c)();}
main(){int c=6;((void(*)())&c)();}
J'ai présenté quelques solutions qui utilisent des fonctions de bibliothèque pour lancer, SIGILL
par divers moyens, mais on peut dire que c'est de la triche, car la fonction de bibliothèque résout le problème. Voici une gamme de solutions qui n'utilisent pas de fonctions de bibliothèque et émettent des hypothèses variables sur l'endroit où le système d'exploitation est prêt à vous permettre d'exécuter du code non exécutable. (Les constantes ici sont choisies pour x86_64, mais vous pouvez les changer pour obtenir des solutions qui fonctionnent pour la plupart des autres processeurs qui ont des instructions illégales.)
06
est l'octet du plus petit numéro du code machine qui ne correspond pas à une instruction définie sur un processeur x86_64. Donc, tout ce que nous avons à faire est de l'exécuter. (Alternativement, 2F
est également non défini et correspond à un seul caractère ASCII imprimable.) Ni l'un ni l'autre n'est garanti d'être toujours non défini, mais ils ne sont pas définis à ce jour.
Le premier programme s'exécute ici à 2F
partir du segment de données en lecture seule. La plupart des linkers ne sont pas capables de produire un saut de travail de .text
vers .rodata
(ou leur équivalent de système d'exploitation) car ce n'est pas quelque chose qui serait utile dans un programme correctement segmenté; Je n'ai pas encore trouvé de système d'exploitation sur lequel cela fonctionne. Vous devez également tenir compte du fait que de nombreux compilateurs souhaitent que la chaîne en question soit une chaîne large, ce qui nécessiterait un complément.L
; Je suppose que tout système d'exploitation sur lequel cela fonctionne a une vue assez dépassée des choses et qu'il est donc construit par défaut pour une norme antérieure à C94. Il est possible que ce programme ne fonctionne nulle part, mais il est également possible que quelque part ce programme fonctionne. Je le répertorie donc dans cette collection de réponses potentielles plus douteuses à moins douteuses. (Après avoir posté cette réponse, Dennis a également mentionné la possibilité main[]={6}
dans le chat, qui est de la même longueur et qui ne pose pas de problèmes de largeur de caractère, et a même laissé entendre que le potentiel existe main=6
. Je ne peux pas raisonnablement prétendre que ces réponses le mien, comme je n'y pensais pas moi-même)
Le deuxième programme s'exécute ici à 06
partir du segment de données en lecture-écriture. Sur la plupart des systèmes d’exploitation, cela entraînera une erreur de segmentation, car les segments de données en écriture sont considérés comme un défaut de conception qui rend les exploitations probables. Cela n’a pas toujours été le cas, donc cela fonctionne probablement sur une version suffisamment ancienne de Linux, mais je ne peux pas le tester facilement.
Le troisième programme s'exécute à 06
partir de la pile. Encore une fois, cela provoque une erreur de segmentation de nos jours, car la pile est normalement classée comme non inscriptible pour des raisons de sécurité. La documentation de l'éditeur de liens que j'ai beaucoup vue implique qu'il était légal d'exécuter à partir de la pile (contrairement aux deux cas précédents, il est parfois utile de le faire), donc bien que je ne puisse pas le tester, je suis assez sûr qu'il y a version de Linux (et probablement d’autres systèmes d’exploitation) sur laquelle cela fonctionne.
Enfin, si vous donnez -Wl,-z,execstack
(pénalité de 15 octets) à gcc
(si vous utilisez GNU ld
dans le backend), il désactivera explicitement la protection de pile exécutable, permettant ainsi au troisième programme de fonctionner et donnant un signal d’opération non conforme comme prévu. Je l' ai testé et vérifié cette version 49 octets au travail. (Dennis mentionne dans le chat que cette option fonctionne apparemment main=6
, ce qui donnerait un score de 6 + 15. Je suis assez surpris que cela fonctionne, étant donné que le 6 n'est pas flagrant; l'option de lien fait apparemment plus que son nom suggère.)
raise(SIGILL)
?