问题
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 x86
Linux 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