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
Должен запускаться от имени root.
Это эквивалентно нажатию кнопки питания и не является безопасным способом выключения компьютера. Убедитесь, что вы закрыли все открытые приложения и выполнили sync
сброс всех буферов файловой системы перед выполнением этой программы, чтобы по крайней мере минимизировать риск повреждения файла.
Тестовый забег
$ 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:
Вслед за темнотой.
Как это устроено
int $0x80
вызывает программное прерывание. Он работает как на x86, так и на x64, но уже более десяти лет устарел и не должен использоваться в производственном коде. syscall
Вместо этого следует использовать код x64 . x86 следует использовать sysenter
, но это слишком громоздко для кода гольфа.
Результирующее действие системного вызова зависит от регистров EAX - EDX, ESI и EDI. Linux Системный вызов Reference показывает все системные вызовы, которые доступны через int $0x80
.
Когда EAX удерживает значение 0x58 (88) , вызывается перезагрузка , которую также можно использовать для выключения компьютера, перевода его в спящий режим или спящего режима компьютера, а также для переключения ядер и отключения или включения комбинации клавиш Ctrl - Alt - Del .
В начале программы - и, компилируя с помощью as
или gcc -nostdlib
, мы можем убедиться, что мы на самом деле в начале программы - большинство регистров устанавливаются в 0 . Это включает EAX, поэтому мы можем использовать mov $0x58, %al
для установки младших 8 битов EAX значение 0x58 , таким образом, устанавливая сам EAX в 0x58 . Это экономит два байта при ручном обнулении регистра xor %eax, %eax
и еще один при простомmov $0x58, %eax
кодировании 0x58 в 32 бита.
Первые два аргумента для перезагрузки - это магические числа, предположительно для предотвращения случайных перезагрузок, которые считываются из регистров EBX и ECX. Если эти числа не равны определенным константам, перезагрузка отказывается выполнять какие-либо действия.
Первое магическое число должно равняться 0xfee1dead ( чувствовать себя мертвым ), вероятно, ссылаясь на выключение / смерть ПК.
Второе магическое число может быть равно четырем различным константам, хотя последние три не работали в древних версиях Linux. Все они, похоже, относятся к последующему включению / рождению ПК.
0x28121969 представляет день рождения Линуса Торвальдса (28 декабря 1969 года).
0x05121996 представляет день рождения Патриции Торвальдс (5 декабря 1996 г.).
0x16041998 представляет день рождения Даниэлы Торвальдс (16 апреля 1998 г.).
0x20112000 представляет день рождения Селесты Торвальдс (20 ноября 2000 года).
Патриция, Даниэла и Селеста Торвальдс - три дочери Линуса Торвальдса.
Регистр EDX выбирает желаемый тип «перезагрузки». 0x4321fedc - это RB_POWER_OFF , который выключает компьютер и выключает его.
Наконец, значение регистра ESI игнорируется для RB_POWER_OFF ; значение регистра EDI полностью игнорируется при перезагрузке .
Альтернативная версия, только для x64, 19 байт
На x64 мы можем использовать правильный системный вызов для того же количества байтов.
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
Единственные различия заключаются в инструкции ( syscall
vs int $0x80
), значении __NR_REBOOT ( 0xa9 против 0x58 ) и задействованных регистрах.