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
Musi być uruchomiony jako root.
Jest to równoważne z naciśnięciem przycisku zasilania i nie jest bezpiecznym sposobem na wyłączenie komputera. sync
Przed uruchomieniem tego programu należy zamknąć wszystkie otwarte aplikacje i wykonać, aby opróżnić wszystkie bufory systemu plików, aby przynajmniej zminimalizować ryzyko uszkodzenia plików.
Testowe uruchomienie
$ 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:
Następnie ciemność.
Jak to działa
int $0x80
wywołuje przerwanie oprogramowania. Działa zarówno na x86, jak i x64, ale jest przestarzały od ponad dekady i nie powinien być stosowany w kodzie produkcyjnym. syscall
Zamiast tego należy użyć kodu x64 . x86 powinno użyć sysenter
, ale jest zbyt kłopotliwe dla golfa kodowego.
Wynikowa akcja wywołania syscall zależy od rejestrów EAX - EDX, ESI i EDI. Linux syscall referencyjny pokazuje wszystkie wywołań systemowych, które są dostępne za pośrednictwem int $0x80
.
Gdy EAX ma wartość 0x58 (88) , wywoływany jest restart , który można również wykorzystać do wyłączenia zasilania, uśpienia lub hibernacji komputera, a także do przełączania jądra i wyłączania lub włączania kombinacji klawiszy Ctrl - Alt - Del .
Na początku programu - i kompilując się z as
lub gcc -nostdlib
możemy upewnić się, że faktycznie jesteśmy na początku programu - większość rejestrów jest ustawiona na 0 . Obejmuje to EAX, więc możemy użyć, mov $0x58, %al
aby ustawić niższe 8 bitów EAX na 0x58 , a tym samym ustawić EAX na 0x58 . Pozwala to zaoszczędzić dwa bajty na ręcznym zerowaniu rejestru za pomocą xor %eax, %eax
i jeszcze jeden na prostym, mov $0x58, %eax
który koduje 0x58 w 32 bitach.
Pierwsze dwa argumenty do ponownego uruchomienia to magiczne liczby, prawdopodobnie w celu uniknięcia przypadkowego ponownego uruchomienia, i są odczytywane z rejestrów EBX i ECX. Jeśli te liczby nie są równe pewnym stałym, ponowne uruchomienie odmawia wykonania jakiejkolwiek akcji.
Pierwsza magiczna liczba musi być równa 0xfee1dead ( czuć się martwym ), prawdopodobnie odnosząc się do wyłączenia zasilania / śmierci komputera.
Druga magiczna liczba może być równa czterem różnym stałym, chociaż trzy ostatnie nie działały w starożytnych wersjach Linuksa. Wszystkie wydają się odnosić do późniejszego włączenia / narodzin komputera.
0x28121969 reprezentuje urodziny Linusa Torvaldsa (28 grudnia 1969 r.).
0x05121996 reprezentuje urodziny Patricii Torvalds (5 grudnia 1996 r.).
0x16041998 reprezentuje urodziny Danieli Torvalds (16 kwietnia 1998 r.).
0x20112000 reprezentuje urodziny Celeste Torvalds (20 listopada 2000).
Patricia, Daniela i Celeste Torvalds są trzema córkami Linusa Torvaldsa.
Rejestr EDX wybiera rodzaj „restartu”, jaki chcemy. 0x4321fedc to RB_POWER_OFF , wyłączanie komputera i wyłączanie go.
Na koniec wartość rejestru ESI jest ignorowana dla RB_POWER_OFF ; wartość rejestru EDI jest całkowicie ignorowana przez restart .
Wersja alternatywna, tylko x64, 19 bajtów
Na x64 możemy użyć odpowiedniego wywołania systemowego dla tej samej liczby bajtów.
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
Jedyne różnice dotyczą instrukcji ( syscall
vs int $0x80
), wartości __NR_REBOOT ( 0xa9 vs 0x58 ) i zaangażowanych rejestrów.