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
จะต้องเรียกใช้เป็นราก
นี่เทียบเท่ากับการกดปุ่มเปิดปิดไม่ใช่วิธีที่ปลอดภัยในการปิดพีซีของคุณ ตรวจสอบให้แน่ใจว่าคุณปิดแอปพลิเคชันที่เปิดอยู่ทั้งหมดและดำเนินการ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 แต่ได้รับการคัดค้านมานานกว่าทศวรรษแล้วและไม่ควรใช้ในรหัสการผลิต ควรใช้รหัส x64 syscall
แทน x86 ควรใช้sysenter
แต่มันยุ่งยากเกินไปสำหรับการตีกอล์ฟ
การกระทำที่เกิดขึ้นจาก syscall นั้นขึ้นอยู่กับการลงทะเบียน EAX - EDX, ESI และ EDI ลินุกซ์ syscall อ้างอิงแสดง syscalls 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 รุ่นโบราณ ดูเหมือนว่าทั้งหมดจะอ้างถึงการเปิด / ปิดเครื่อง PC ในภายหลัง
0x28121969แสดงถึงวันเกิดของ Linus Torvalds (28 ธันวาคม 2512)
0x05121996แสดงถึงวันเกิดของ Patricia Torvalds (5 ธันวาคม 1996)
0x16041998แสดงถึงวันเกิดของ Daniela Torvalds (16 เมษายน 2541)
0x20112000แสดงถึงวันเกิดของ Celeste Torvalds (20 พฤศจิกายน 2000)
Patricia, Daniela และ Celeste Torvalds เป็นลูกสาวสามคนของ Linus Torvalds
การลงทะเบียน EDX เลือกประเภทของ "reboot" ที่เราต้องการ 0x4321fedcคือRB_POWER_OFFปิดพีซีและปิดเครื่อง
ในที่สุดคุ้มค่าของการลงทะเบียน ESI ถูกละเว้นสำหรับRB_POWER_OFF ; คุ้มค่าของการลงทะเบียน EDI จะถูกละเลยโดยสิ้นเชิงรีบูต
รุ่นอื่น, x64- เท่านั้น, 19 ไบต์
บน x64 เราสามารถใช้ syscall ที่เหมาะสมสำหรับจำนวนไบต์เดียวกัน
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 ) และผู้ลงทะเบียนที่เกี่ยวข้อง