如何仅使用汇编代码关闭计算机?
答案 0 :(得分:10)
您需要说明它是什么处理器系列以及您正在使用的操作系统。还有你的代码运行的特权 - 如果它是内核代码,那么它拥有比用户代码更多的特权。
假设您在Intel x86系列CPU上使用Windows NT系列的某些成员(包括XP或Vista),并且您的代码是正常(用户空间)代码,那么......您需要调用Windows内置的在功能上做到这一点。你不能只执行一些神奇的装配序列。
即使你只能执行一些神奇的汇编序列,你也不会想要 - 你几乎肯定想让操作系统有机会将数据从磁盘缓存写入磁盘,并且其他优雅关闭的东西。
如果您正在为x86编写自己的操作系统,那么您需要查看ACPI(或APM)规范。如果GPL代码没问题,则相关的Linux内核例程为here (ACPI)和here (APM)。
答案 1 :(得分:9)
这是我用来在DOS模式下关闭电脑多年的29字节程序。
;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
lookup可以使用Ralf Brown’s Interrupt List DJGPP更多功能。
答案 2 :(得分:6)
在Linux中读取reboot(2)。
感兴趣的文件:
kernel / sys.c kernel / exit.c和arch / x86 / kernel / apm.c
不是一个完整的答案,但我认为这是一个好的开始。我将不得不阅读我的BIOS机器代码,看看他们做了什么。但这部分是机器特定的。如果您知道主板上的IC控制电源,您可以找出所需的IO端口,寄存器和命令。然后设置正确的板/设备状态,然后发出命令关闭电源。
BIOS通过INT 15h ah = 53h管理电源(所谓的高级电源管理又称APM) 在Linux中使用的函数al = 07是设置电源状态cmd。参数bx = 0001h表示所有设备,cx = 0003k表示停止。
答案 3 :(得分:4)
将上面的@larz答案转换为nasm程序集如下:
先决条件:Bochs,Nasm
这个例子是在带有标准软件包的debian wheezy上运行的。
代码(文件名: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配置文件(文件名:.bochsrc)与代码(shutdown.asm)在同一目录中
display_library: sdl
floppya: 1_44=boot_sect.img, status=inserted
boot: a
*注意我正在使用bochs的sdl库,这是bochs本身的单独包装
运行bochs(与之前相同的目录):
bochs
按Enter键关闭
*注意我不确定Shutdown标签和WaitForEnter标签之间的所有行都是必需的
答案 4 :(得分:3)
来自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);
}
}
代码现在位于apm_32.c。搜索“apm_power_off”。
答案 5 :(得分:2)
这很容易。另外,伙计们,OP可能正在为他自己的电源经理工作。我正在做同样的事情。 这是一个允许用户关闭机器的示例。很简单,只需给用户一个OK和取消的消息框。如果用户点击OK,机器将关闭,如果用户点击取消,程序将退出。它是在基于NT的Windows版本上测试的,应该适用于旧版本,如ME,95和98.
这是我自己的代码,每个人都可以自由使用它。 http://pastebin.com/ccw3mWtw
答案 6 :(得分:1)
调用kernel32.dll中的ExitWindowsEx API函数
答案 7 :(得分:1)
您可以尝试在x86
Linux机器上使用shellcode,这不是恶意代码,只是为了好玩。此shellcode仅执行/sbin/poweroff
,仅在Debian版本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;
}
或者此shellcode执行shutdown -h now
(以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;
}
答案 8 :(得分:0)
$ bzr branch http://bzr.savannah.gnu.org/r/grub/trunk/grub
$ vi grub/grub-core/commands/acpihalt.c +303
或者在Github镜像上:
https://github.com/dajhorn/grub/blob/trunk/grub/grub-core/commands/acpihalt.c#L303
答案 9 :(得分:0)
使用此代码的32位操作系统:
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