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
Deve essere eseguito come root.
Ciò equivale a premere il pulsante di accensione e non è un modo sicuro per spegnere il PC. Assicurati di chiudere tutte le applicazioni aperte ed eseguire sync
per svuotare tutti i buffer del file system prima di eseguire questo programma, per minimizzare almeno il rischio di corruzione dei file.
Prova
$ 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:
Seguito dall'oscurità.
Come funziona
int $0x80
invoca un interrupt software. Funziona sia su x86 che x64, ma è ormai obsoleto da oltre un decennio e non dovrebbe essere usato nel codice di produzione. syscall
invece dovrebbe usare il codice x64 . x86 dovrebbe usare sysenter
, ma è troppo ingombrante per il codice golf.
L'azione risultante dalla syscall dipende dai registri EAX - EDX, ESI ed EDI. Il Linux Reference Syscall mostra tutte le chiamate di sistema che sono disponibili via int $0x80
.
Quando EAX contiene 0x58 (88) , viene chiamato il riavvio , che può anche essere utilizzato per spegnere, mettere in sospensione o ibernare il computer, nonché per cambiare kernel e disabilitare o abilitare la combinazione di tasti Ctrl - Alt - Canc .
All'inizio del programma - e compilando con as
o gcc -nostdlib
, possiamo assicurarci di essere effettivamente all'inizio del programma - la maggior parte dei registri è impostata su 0 . Questo include EAX, quindi possiamo usare mov $0x58, %al
per impostare gli 8 bit inferiori di EAX su 0x58 , quindi impostando EAX stesso su 0x58 . Ciò consente di risparmiare due byte sopra l'azzeramento manuale del registro xor %eax, %eax
e un altro sopra il rettilineo mov $0x58, %eax
che codifica 0x58 in 32 bit.
I primi due argomenti da riavviare sono numeri magici, presumibilmente per impedire riavvii accidentali, e vengono letti dai registri EBX ed ECX. A meno che questi numeri non siano uguali a determinate costanti, il riavvio si rifiuta di eseguire qualsiasi azione.
Il primo numero magico deve essere uguale a 0xfee1dead ( feel dead ), probabilmente riferito allo spegnimento / morte del PC.
Il secondo numero magico può essere uguale a quattro diverse costanti, sebbene le ultime tre non funzionassero nelle versioni antiche di Linux. Tutti sembrano riferirsi alla successiva accensione / nascita del PC.
0x28121969 rappresenta il compleanno di Linus Torvalds (28 dicembre 1969).
0x05121996 rappresenta il compleanno di Patricia Torvalds (5 dicembre 1996).
0x16041998 rappresenta il compleanno di Daniela Torvalds (16 aprile 1998).
0x20112000 rappresenta il compleanno di Celeste Torvalds (20 novembre 2000).
Patricia, Daniela e Celeste Torvalds sono le tre figlie di Linus Torvalds.
Il registro EDX seleziona il tipo di "riavvio" desiderato. 0x4321fedc è RB_POWER_OFF , spegnendo il PC e spegnendolo.
Infine, il valore del registro ESI viene ignorato per RB_POWER_OFF ; il valore del registro EDI viene ignorato interamente dal riavvio .
Versione alternativa, solo x64, 19 byte
Su x64, possiamo usare un syscall corretto per lo stesso conteggio byte.
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
Le uniche differenze risiedono nell'istruzione ( syscall
vs int $0x80
), nel valore di __NR_REBOOT ( 0xa9 vs 0x58 ) e nei registri coinvolti.