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
Phải được chạy như root.
Điều này tương đương với việc nhấn nút nguồn và không phải là cách an toàn để tắt nguồn PC của bạn. Đảm bảo bạn đóng tất cả các ứng dụng đang mở và thực thi sync
để xóa tất cả các bộ đệm hệ thống tệp trước khi thực hiện chương trình này, để ít nhất giảm thiểu rủi ro hỏng tệp.
Chạy thử nghiệm
$ 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:
Tiếp theo là bóng tối.
Làm thế nào nó hoạt động
int $0x80
gọi một ngắt phần mềm. Nó hoạt động trên cả x86 và x64, nhưng đã bị phản đối trong hơn một thập kỷ nay và không nên được sử dụng trong mã sản xuất. Mã x64 nên sử dụng syscall
thay thế. x86 nên sử dụng sysenter
, nhưng nó quá cồng kềnh đối với mã golf.
Hành động kết quả từ tòa nhà phụ thuộc vào các thanh ghi EAX - EDX, ESI và EDI. Các Linux syscall tham khảo cho thấy tất cả syscalls mà có sẵn thông qua int $0x80
.
Khi EAX giữ 0x58 (88) , khởi động lại được gọi, cũng có thể được sử dụng để tắt nguồn, đưa vào chế độ ngủ hoặc ngủ đông máy tính, cũng như chuyển đổi hạt nhân và vô hiệu hóa hoặc bật tổ hợp phím Ctrl - Alt - Del .
Khi bắt đầu chương trình - và bằng cách biên dịch với as
hoặc gcc -nostdlib
, chúng tôi có thể đảm bảo rằng chúng tôi thực sự bắt đầu chương trình - hầu hết các thanh ghi được đặt thành 0 . Điều này bao gồm EAX, vì vậy chúng ta có thể sử dụng mov $0x58, %al
để đặt 8 bit EAX thấp hơn thành 0x58 , do đó tự đặt EAX thành 0x58 . Điều này giúp tiết kiệm hai byte bằng cách hủy bỏ thanh ghi xor %eax, %eax
một cách thủ công và thêm một byte qua straighforward mov $0x58, %eax
mã hóa 0x58 trong 32 bit.
Hai đối số đầu tiên để khởi động lại là các số ma thuật, có lẽ là để ngăn chặn việc khởi động lại ngẫu nhiên và được đọc từ các thanh ghi EBX và ECX. Trừ khi những con số này bằng với một số hằng số nhất định, khởi động lại từ chối thực hiện bất kỳ hành động nào.
Số ma thuật đầu tiên phải bằng 0xfee1dead ( cảm thấy đã chết ), có lẽ liên quan đến việc tắt / chết máy tính.
Số ma thuật thứ hai có thể bằng bốn hằng số khác nhau, mặc dù ba hằng số sau không hoạt động trong các phiên bản Linux cổ. Tất cả chúng dường như đề cập đến việc bật / tắt nguồn tiếp theo của PC.
0x28121969 đại diện cho sinh nhật của Linus Torvalds (ngày 28 tháng 12 năm 1969).
0x05121996 đại diện cho sinh nhật của Patricia Torvalds (ngày 5 tháng 12 năm 1996).
0x16041998 đại diện cho sinh nhật của Daniela Torvalds (ngày 16 tháng 4 năm 1998).
0x20112000 đại diện cho sinh nhật của Celeste Torvalds (ngày 20 tháng 11 năm 2000).
Patricia, Daniela và Celeste Torvalds là ba cô con gái của Linus Torvalds.
Thanh ghi EDX chọn loại "khởi động lại" mà chúng ta muốn. 0x4321fedc là RB_POWER_OFF , tắt PC và tắt nguồn.
Cuối cùng, giá trị của thanh ghi ESI bị bỏ qua cho RB_POWER_OFF ; giá trị của thanh ghi EDI bị bỏ qua hoàn toàn bằng cách khởi động lại .
Phiên bản thay thế, chỉ x64, 19 byte
Trên x64, chúng ta có thể sử dụng một tòa nhà cao tầng thích hợp cho cùng một số 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
Sự khác biệt duy nhất nằm ở hướng dẫn ( syscall
vs int $0x80
), giá trị của __NR_REBOOT ( 0xa9 so với 0x58 ) và các thanh ghi liên quan.