Shutdown the computer using assembly

十年热恋 提交于 2020-01-09 09:08:47

问题


How can I shutdown the computer using only assembly code?


回答1:


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).




回答2:


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.




回答3:


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.




回答4:


From arch/x86/kernel/amp.c:

/**
 * apm_power_off - ask the BIOS to power off
 *
 * Handle the power off sequence. This is the one piece of code we
 * will execute even on SMP machines. In order to deal with BIOS
 * bugs we support real mode APM BIOS power off calls. We also make
 * the SMP call on CPU0 as some systems will only honour this call
 * on their first cpu.
 */

static void apm_power_off(void)
{
 unsigned char po_bios_call[] = {
  0xb8, 0x00, 0x10, /* movw  $0x1000,ax  */
  0x8e, 0xd0,  /* movw  ax,ss       */
  0xbc, 0x00, 0xf0, /* movw  $0xf000,sp  */
  0xb8, 0x07, 0x53, /* movw  $0x5307,ax  */
  0xbb, 0x01, 0x00, /* movw  $0x0001,bx  */
  0xb9, 0x03, 0x00, /* movw  $0x0003,cx  */
  0xcd, 0x15  /* int   $0x15       */
 };

 /* Some bioses don't like being called from CPU != 0 */
 if (apm_info.realmode_power_off) {
  set_cpus_allowed_ptr(current, cpumask_of(0));
  machine_real_restart(po_bios_call, sizeof(po_bios_call));
 } else {
  (void)set_system_power_state(APM_STATE_OFF);
 }
}

The code is now in apm_32.c. Search for "apm_power_off".




回答5:


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




回答6:


It's quite easy. Also, guys, OP might be working on his own power manager. The same exact thing I'm doing. This is an example that'll allow the user to shutdown the machine. Quite simple, just gives the user a messagebox with OK and Cancel. If the user hits OK the machine will shutdown, if the user hits cancel, the program will just exit. It is tested on the NT based windows versions, and should work on the older versions such as ME, 95, and 98.

This is my own code, and everyone is free to use it. http://pastebin.com/ccw3mWtw




回答7:


Call the ExitWindowsEx API function in kernel32.dll




回答8:


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;
}



回答9:


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




回答10:


for 32bit operation system using this code :

BITS 32

global _start
section .text

_start:

; Local variables:
;
; [ebp-4] Address of ntdll.dll
; [ebp-8] Address of ntdll.dll's export table
; [ebp-12] Space for RtlAdjustPrivilege's output

push ebp
mov ebp,esp
sub esp,12

; Save registers

push ebx
push esi
push edi

jmp get_delta_offset ; Get the delta offset

get_delta_offset2:
    pop ebx
    jmp start ; Jump to main code

get_delta_offset:
    call get_delta_offset2

data:
    NtShutdownSystem_s db "NtShutdownSystem"
    NtShutdownSystem_len equ $-NtShutdownSystem_s

    RtlAdjustPrivilege_s db "RtlAdjustPrivilege"
    RtlAdjustPrivilege_len equ $-RtlAdjustPrivilege_s

get_function_address:

    ; Save registers

    push ebx
    push esi
    push edi

    mov eax,[ebp-8]
    mov ebx,[eax+0x20] ; ebx now points to the export names array

    add ebx,[ebp-4]
    xor eax,eax

    .get_function_address_loop:
        mov esi,edx ; esi now points to the function
        mov edi,[ebx+eax*4]
        add edi,[ebp-4] ; edi now points to the export name

        push ecx ; Save the function name length
        cld ; Clear the direction flag

        rep cmpsb ; Do the comparison
        pop ecx ; Restore the length

        je .get_function_address_end
        inc eax

        cmp eax,[ebx+0x14]
        jl .get_function_address_loop

    .get_function_address_fail:
        pop edi
        pop esi
        pop ebx

        xor eax,eax
        ret

    .get_function_address_end:
        mov ebx,[ebp-8]
        mov ecx,[ebx+0x1c]

        add ecx,[ebp-4] ; ecx now points to the function addresses array

        mov edx,[ebx+0x24]
        add edx,[ebp-4] ; edx now points to the ordinals array

        movzx eax,word [edx+eax*2] ; eax now holds the ordinal
        mov eax,[ecx+eax*4] ; eax now holds the RVA of the function

        add eax,[ebp-4] ; eax now holds the address of the function

        ; Restore registers

        pop edi
        pop esi
        pop ebx

        ret

start:

xor ecx,ecx
mov eax,[fs:ecx+0x30] ; eax now points to the PEB

mov eax,[eax+0xc] ; eax now points to loader data
mov eax,[eax+0x14]

mov eax,[eax+ecx]
mov eax,[eax+0x10] ; eax now holds the address of ntdll.dll

mov [ebp-4],eax ; Save the address of ntdll.dll

add eax,[eax+0x3c] ; eax now points to the PE header
mov eax,[eax+0x78] ; eax now points to the export directory
add eax,[ebp-4] ; eax now points to the export table

mov [ebp-8],eax
xor ecx,ecx

mov cl,NtShutdownSystem_len
mov edx,ebx

add ebx,ecx ; Move to next string
call get_function_address

test eax,eax
je exit

mov esi,eax
xor ecx,ecx

mov cl,RtlAdjustPrivilege_len
mov edx,ebx

call get_function_address

test eax,eax
je exit

mov edi,eax
xor eax,eax

; Enable SeShutdownPrivilege

lea ecx,[ebp-12]

push ecx
push eax ; CurrentThread = FALSE
push 1 ; Enable = TRUE
push 19 ; SeShutdownPrivilege

call edi ; Call RtlAdjustPrivilege
xor eax,eax

push eax ; ShutdownNoReboot
call esi ; Call NtShutdownSystem

exit:

pop edi
pop esi
pop ebx

mov esp,ebp
pop ebp
ret


来源:https://stackoverflow.com/questions/678458/shutdown-the-computer-using-assembly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!