Shutdown the computer using assembly

后端 未结 10 634
日久生厌
日久生厌 2020-12-08 11:27

How can I shutdown the computer using only assembly code?

相关标签:
10条回答
  • 2020-12-08 11:36

    In Linux read reboot(2).

    sources files of interest:

    kernel/sys.c kernel/exit.c and arch/x86/kernel/apm.c

    not a complete answer but i think it's a good start. I'll have to read my BIOS machine code to see what they do. but this part is machine specific. maby if you know wich IC contol power on your motherboard you can figure out wich IO port, register and command you need. then setup proper board/devices states and then issue command to turn the power off.

    BIOS manage power via INT 15h ah=53h ( so called Advanced Power Management aka APM ) function al=07 used in Linux is the set power state cmd. parameters bx=0001h mean all devices and cx=0003k mean stop.

    0 讨论(0)
  • 2020-12-08 11:37

    GRUB

    $ bzr branch http://bzr.savannah.gnu.org/r/grub/trunk/grub
    $ vi grub/grub-core/commands/acpihalt.c +303
    

    or here on a Github mirror:

    https://github.com/dajhorn/grub/blob/trunk/grub/grub-core/commands/acpihalt.c#L303

    0 讨论(0)
  • 2020-12-08 11:38

    This is the 29 byte program that I have been using to turn the computer off in DOS mode for years.

    ;Connect to APM API
    MOV     AX,5301
    XOR     BX,BX
    INT     15
    
    ;Try to set APM version (to 1.2)
    MOV     AX,530E
    XOR     BX,BX
    MOV     CX,0102
    INT     15
    
    ;Turn off the system
    MOV     AX,5307
    MOV     BX,0001
    MOV     CX,0003
    INT     15
    
    ;Exit (for good measure and in case of failure)
    RET
    

    You can lookup more functions with Ralf Brown’s Interrupt List at DJGPP.

    0 讨论(0)
  • 2020-12-08 11:45

    You can try using shellcode for x86Linux machine, this is not malicious code you know, just for fun. This shellcode only executes /sbin/poweroff only tested on Debian version 5.0.5.

    #include <stdio.h>
    #include <string.h>
    
    char *shellcode = "\x31\xc0\x50\x68\x72\x6f\x66"
                      "\x66\x68\x70\x6f\x77\x65\x68"
                      "\x6e\x2f\x2f\x2f\x68\x2f\x73"
                      "\x62\x69\x89\xe3\x50\x53\x89"
                      "\xe1\xb0\x0b\xcd\x80\x31\xc0"
                      "\x50\x89\xe3\xb0\x01\xcd\x80";
    
    int main(int argc, char *argv[]) {
        printf("shellcode length ->  %d bytes\n", (int)strlen(shellcode));
        int (*ret)()=(int(*)())shellcode;
        ret();
    
        return 0;
    }
    

    Or this shellcode executes shutdown -h now (run with root) :

    #include <stdio.h>
    #include <string.h>
    
    char *shellcode =  "\x31\xc0\x31\xd2\x50\x66\x68\x2d"
                       "\x68\x89\xe7\x50\x6a\x6e\x66\xc7"
                       "\x44\x24\x01\x6f\x77\x89\xe7\x50"
                       "\x68\x64\x6f\x77\x6e\x68\x73\x68"
                       "\x75\x74\x68\x6e\x2f\x2f\x2f\x68"
                       "\x2f\x73\x62\x69\x89\xe3\x52\x56"
                       "\x57\x53\x89\xe1\xb0\x0b\xcd\x80";
    
    int main(int argc, char *argv[]) {
        printf("shellcode length ->  %d bytes\n", (int)strlen(shellcode));
        int (*ret)()=(int(*)())shellcode;
        ret();
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-08 11:46

    You need to say what processor family it is and which OS you're using. Also what privileges your code is running under - if it's kernel code then it has more privileges than user code.

    Assuming you're using some member of the Windows NT family (including XP or Vista) on an Intel x86 family CPU, and your code is normal (userspace) code, then... you need to call the Windows built-in function to do this. You can't just execute some magic sequence of assembly.

    Even if you could just execute some magic sequence of assembly, you wouldn't want to - you almost certainly want to give the OS chance to write data from the disk cache to disk, and do other graceful-shutdown stuff.

    If you're writing your own OS for x86, then you need to look at the ACPI (or APM) specs. If GPL code is OK, then the relevent Linux kernel routines are here (ACPI) and here (APM).

    0 讨论(0)
  • 2020-12-08 11:51

    Converting @larz answer above to nasm assembly is done as follows:

    Prerequisites: Bochs, Nasm

    This example was run on debian wheezy with standard packages.

    Code (filename: shutdown.asm):

        org 0x7c00
        jmp main
    
    Shutdown:
        mov ax, 0x1000
        mov ax, ss
        mov sp, 0xf000
        mov ax, 0x5307
        mov bx, 0x0001
        mov cx, 0x0003
        int 0x15
    
    WaitForEnter:
        mov ah, 0
        int 0x16
        cmp al, 0x0D
        jne WaitForEnter
        ret
    
    main:   
        call WaitForEnter
        call Shutdown
    
    times 510-($-$$) db 0
    dw 0xaa55
    

    Nasm compliation:

    nasm -f bin -o boot_sect.img shutdown.asm
    

    Bochs configuration file (filename: .bochsrc) in the same directory as code (shutdown.asm)

    display_library: sdl
    floppya: 1_44=boot_sect.img, status=inserted
    boot: a
    

    *Note I am using the sdl library for bochs which is a seperate package from bochs itself

    Running bochs (from the same directory as before):

    bochs
    

    Hit enter to shutdown

    *Note I am not sure that all the lines between the Shutdown label and WaitForEnter label are neccessary

    0 讨论(0)
提交回复
热议问题