mov $0x58, %al # 2 bytes: b0 58
mov $0xfee1dead, %ebx # 5 bytes: bb ad de e1 fe
mov $0x28121969, %ecx # 5 bytes: b9 69 19 12 28
mov $0x4321fedc, %edx # 5 bytes: ba dc fe 21 43
int $0x80 # 2 bytes: cd 80
Doit être exécuté en tant que root.
Cela équivaut à appuyer sur le bouton d'alimentation et n'est pas un moyen sûr d'éteindre votre PC. Assurez-vous de fermer toutes les applications ouvertes et d’exécuter sync
pour vider tous les tampons du système de fichiers avant d’exécuter ce programme, afin de minimiser au minimum le risque de corruption du fichier.
Essai
$ as -o poweroff.o poweroff.s
$ ld -o poweroff poweroff.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400078
$ sudo sh -c 'sync && ./poweroff'
root's password:
Suivi par les ténèbres.
Comment ça fonctionne
int $0x80
invoque une interruption logicielle. Il fonctionne à la fois sur x86 et x64, mais est obsolète depuis plus de dix ans et ne devrait pas être utilisé dans le code de production. Le code x64 devrait utiliser à la syscall
place. x86 devrait l’utiliser sysenter
, mais c’est trop lourd pour le code golf.
L'action résultant de l'appel système dépend des registres EAX-EDX, ESI et EDI. La référence Linux Syscall montre tous les appels système disponibles via int $0x80
.
Lorsque EAX contient 0x58 (88) , un redémarrage est appelé, ce qui peut également être utilisé pour éteindre, mettre en veille ou pour mettre en veille prolongée l'ordinateur, ainsi que pour changer de noyau et désactiver ou activer le combo Ctrl-Alt-Suppr .
Au début du programme - et en compilant avec as
ou gcc -nostdlib
, nous pouvons nous assurer que nous en sommes réellement au début du programme - la plupart des registres sont mis à 0 . Cela inclut EAX. Nous pouvons donc utiliser mov $0x58, %al
pour définir les 8 bits inférieurs de EAX sur 0x58 , fixant ainsi EAX lui-même sur 0x58 . Cela économise deux octets sur la mise à zéro manuelle du registre avec xor %eax, %eax
et un de plus sur le directement mov $0x58, %eax
qui code 0x58 sur 32 bits.
Les deux premiers arguments pour redémarrer sont des nombres magiques, supposés empêcher les redémarrages accidentels, et sont lus à partir des registres EBX et ECX. À moins que ces nombres ne soient égaux à certaines constantes, le redémarrage refuse d'effectuer toute action.
Le premier nombre magique doit être égal à 0xfee1dead ( sensation de mort ), faisant probablement référence à la mise hors tension / à la mort du PC.
Le deuxième nombre magique peut être égal à quatre constantes différentes, bien que les trois dernières ne fonctionnent pas dans les anciennes versions de Linux. Tous semblent se référer à la mise sous tension / à la naissance du PC.
0x28121969 représente l'anniversaire de Linus Torvalds (28 décembre 1969).
0x05121996 représente l'anniversaire de Patricia Torvalds (5 décembre 1996).
0x16041998 représente l'anniversaire de Daniela Torvalds (16 avril 1998).
0x20112000 représente l'anniversaire de Celeste Torvalds (20 novembre 2000).
Patricia, Daniela et Celeste Torvalds sont les trois filles de Linus Torvalds.
Le registre EDX sélectionne le type de "redémarrage" souhaité. 0x4321fedc est RB_POWER_OFF , éteint le PC et l'éteint.
Enfin, la valeur du registre ESI est ignorée pour RB_POWER_OFF ; la valeur du registre EDI est entièrement ignorée lors du redémarrage .
Version alternative, x 64 uniquement, 19 octets
Sur x64, nous pouvons utiliser un appel système approprié pour le même nombre d'octets.
mov $0xa9, %al # 2 bytes: b0 a9
mov $0xfee1dead, %edi # 5 bytes: bf ad de e1 fe
mov $0x28121969, %esi # 5 bytes: be 69 19 12 28
mov $0x4321fedc, %edx # 5 bytes: ba dc fe 21 43
syscall # 2 bytes: 0f 05
Les seules différences résident dans l'instruction ( syscall
vs int $0x80
), la valeur de __NR_REBOOT ( 0xa9 vs 0x58 ) et les registres impliqués.