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
Muss als root ausgeführt werden.
Dies entspricht dem Drücken des Netzschalters und ist keine sichere Methode zum Ausschalten des PCs. Stellen Sie sicher, dass Sie alle geöffneten Anwendungen schließen und ausführen sync
, um alle Dateisystempuffer zu leeren, bevor Sie dieses Programm ausführen, um das Risiko einer Dateibeschädigung zumindest zu minimieren.
Testlauf
$ 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:
Gefolgt von Dunkelheit.
Wie es funktioniert
int $0x80
ruft einen Software-Interrupt auf. Es funktioniert sowohl auf x86 als auch auf x64, ist jedoch seit über einem Jahrzehnt veraltet und sollte nicht im Produktionscode verwendet werden. syscall
Stattdessen sollte x64-Code verwendet werden. x86 sollte verwenden sysenter
, aber es ist zu umständlich für Code-Golf.
Die sich aus dem Systemaufruf ergebende Aktion hängt von den Registern EAX - EDX, ESI und EDI ab. Die Linux-Syscall-Referenz zeigt alle Syscalls, die über verfügbar sind int $0x80
.
Wenn EAX 0x58 (88) enthält , wird ein Neustart aufgerufen, mit dem der Computer ausgeschaltet, in den Energiesparmodus versetzt oder in den Ruhezustand versetzt sowie der Kernel gewechselt und die Tastenkombination Strg - Alt - Entf deaktiviert oder aktiviert werden kann .
Zu Beginn des Programms - und indem wir mit as
oder kompilieren gcc -nostdlib
, können wir sicherstellen, dass wir tatsächlich am Anfang des Programms sind - werden die meisten Register auf 0 gesetzt . Dies schließt EAX ein, sodass wir mov $0x58, %al
die unteren 8 Bits von EAX auf 0x58 setzen können , wodurch EAX selbst auf 0x58 gesetzt wird . Dies spart zwei Bytes beim manuellen Nullsetzen des Registers xor %eax, %eax
und eines weiteren Bytes beim geraden Weiterleiten mov $0x58, %eax
, das 0x58 in 32 Bits codiert .
Die ersten beiden Argumente für einen Neustart sind magische Zahlen, vermutlich, um versehentliche Neustarts zu verhindern. Sie werden aus den Registern EBX und ECX gelesen. Wenn diese Zahlen nicht bestimmten Konstanten entsprechen, wird beim Neustart keine Aktion ausgeführt.
Die erste magische Zahl muss gleich 0xfee1dead ( sich tot fühlen ) sein und bezieht sich wahrscheinlich auf das Ausschalten / den Tod des PCs.
Die zweite magische Zahl kann vier verschiedenen Konstanten entsprechen, obwohl die letzten drei in alten Linux-Versionen nicht funktionierten. Alle scheinen sich auf das spätere Einschalten / Aufkommen des PCs zu beziehen.
0x28121969 repräsentiert Linus Torvalds Geburtstag (28. Dezember 1969).
0x05121996 repräsentiert Patricia Torvalds Geburtstag (5. Dezember 1996).
0x16041998 repräsentiert Daniela Torvalds Geburtstag (16. April 1998).
0x20112000 repräsentiert Celeste Torvalds Geburtstag (20. November 2000).
Patricia, Daniela und Celeste Torvalds sind die drei Töchter von Linus Torvalds.
Das EDX-Register wählt die Art des gewünschten "Neustarts" aus. 0x4321fedc ist RB_POWER_OFF , fährt den PC herunter und schaltet ihn aus.
Schließlich wird der Wert des ESI-Registers für RB_POWER_OFF ignoriert ; Der Wert des EDI-Registers wird beim Neustart vollständig ignoriert .
Alternative Version, nur x64, 19 Byte
Auf x64 können wir einen richtigen Syscall für die gleiche Bytezahl verwenden.
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
Die einzigen Unterschiede liegen in der Anweisung ( syscall
vs int $0x80
), dem Wert von __NR_REBOOT ( 0xa9 vs 0x58 ) und den beteiligten Registern.