Windows驱动开发学习记录-驱动中快速重启关闭计算机之一(Windows driver development learning record – one of the fast restart and shutdown computers in the driver)

  •  引言

 引言

  关于快速重启和关闭计算机,网上有不少软件在Ring3下调用ZwShutdownSystem (NtShutdownSystem)来实现,虽然速度很快,但还至少经历一些流程,比如向设备驱动发送停机通知等。以下内容摘自<<深入解析Windows操作系统 第6版(下册)>> P528:

  一旦Csrss已经完成了向系统进程传达系统停机的通知,Winlogon最后调用执行体子系统函数 NtShutdownSystem,从而结束停机过程。 NtShutdownSystem 函数又调用 PoSetSystemPowerState函数,来协调设备驱动程序和执行体子系统其余部分(即插即用管理器、电源管理器、执行体、I/O管理器、配置管理器和内存管理器)的停机处理。
  例如,PoSetSystemPowerState调用I/O管理器,以便给那些已经请求过停机通知的所有设备驱动程序发送停机I/O包。这一动作使得设备驱动程序有机会在Windows退出以前执行任何必要的特殊处理。工作者线程的内存栈被换入,配置管理器将任何修改过的注册表数据刷新到磁盘上,内存管理器将所有己修改过的且包含了文件数据的页面写回到它们各自的文件中。如果“在停机时清除页面文件”的选项已被打开,那么,内存管理器在这时候清除页面文件。I/O管理器还会被再次调用,以便告诉文件系统驱动程序;系统正在进行停机。系统停机过程最终在电源管理器中结束。电源管理器所执行的动作取决于用户指定的是停机、重新引导,还是关闭电源。

  一旦Csrss已经完成了向系统进程传达系统停机的通知,Winlogon最后调用执行体子系统函数 NtShutdownSystem,从而结束停机过程。 NtShutdownSystem 函数又调用 PoSetSystemPowerState函数,来协调设备驱动程序和执行体子系统其余部分(即插即用管理器、电源管理器、执行体、I/O管理器、配置管理器和内存管理器)的停机处理。
  例如,PoSetSystemPowerState调用I/O管理器,以便给那些已经请求过停机通知的所有设备驱动程序发送停机I/O包。这一动作使得设备驱动程序有机会在Windows退出以前执行任何必要的特殊处理。工作者线程的内存栈被换入,配置管理器将任何修改过的注册表数据刷新到磁盘上,内存管理器将所有己修改过的且包含了文件数据的页面写回到它们各自的文件中。如果“在停机时清除页面文件”的选项已被打开,那么,内存管理器在这时候清除页面文件。I/O管理器还会被再次调用,以便告诉文件系统驱动程序;系统正在进行停机。系统停机过程最终在电源管理器中结束。电源管理器所执行的动作取决于用户指定的是停机、重新引导,还是关闭电源。

  可以看到调用NtShutdownSystem还有不少处理的东西,所以我在想能不能调用更底层的实现来更快速的关机。

  再者有些防止关机的程序也是Hook了NtShutdownSystem,我们想办法用更底层的实现可以绕过Hook,不过话说已经在内核层驱动了,有啥不能干的呢^_^。

  • NtShutdownSystem分析

NtShutdownSystem分析

  下面的分析主要采用ReactOS、WindowsXP的代码以及Windbg调试:

 1 <<ReactOS>>
 2 NTSTATUS
 3 NTAPI
 4 NtShutdownSystem(IN SHUTDOWN_ACTION Action)
 5 {
 6     POWER_ACTION PowerAction;
 7  
 8     /* Convert to power action */
 9     if (Action == ShutdownNoReboot)
10     {
11         PowerAction = PowerActionShutdown;
12     }
13     else if (Action == ShutdownReboot)
14     {
15         PowerAction = PowerActionShutdownReset;
16     }
17     else if (Action == ShutdownPowerOff)
18     {
19         PowerAction = PowerActionShutdownOff;
20     }
21     else
22     {
23         return STATUS_INVALID_PARAMETER;
24     }
25  
26     /* Now call the power manager */
27     DPRINT("Setting state to: %lx\n", PowerAction);
28     return NtSetSystemPowerState(PowerAction,
29                                  PowerSystemSleeping3,
30                                  POWER_ACTION_OVERRIDE_APPS |
31                                  POWER_ACTION_DISABLE_WAKES |
32                                  POWER_ACTION_CRITICAL);
33 }

  这里调试的是NtSetSystemPowerState,再来看看NtSetSystemPowerState的实现(截取主要内容),可以看出最终调用PopGracefulShutdown:

 1 <<Windows XP>>
 2 NTSYSAPI
 3 NTSTATUS
 4 NTAPI
 5 NtSetSystemPowerState (
 6     IN POWER_ACTION SystemAction,
 7     IN SYSTEM_POWER_STATE LightestSystemState,
 8     IN ULONG Flags                  // POWER_ACTION_xxx flags
 9     )
10 {
11     KPROCESSOR_MODE         PreviousMode;
12     ......
13     CmSetLazyFlushState(FALSE);
14     ......
15     if (PopAction.Shutdown) {
16  
17         //
18         // Force reacquisition of the dev list. We will be telling Pnp
19         // to unload all possible devices, and therefore Pnp needs us to
20         // release the Pnp Engine Lock.
21         //
22         IoFreePoDeviceNotifyList(&PopAction.DevState->Order);
23         PopAction.DevState->GetNewDeviceList = TRUE;
24  
25         //
26         // We shut down via a system worker thread so that the
27         // current active process will exit cleanly.
28         //
29  
30         if (PsGetCurrentProcess() != PsInitialSystemProcess) {
31  
32             ExInitializeWorkItem(&PopShutdownWorkItem,
33                                  &PopGracefulShutdown,
34                                  NULL);
35  
36             ExQueueWorkItem(&PopShutdownWorkItem,
37                             PO_SHUTDOWN_QUEUE);
38  
39             // Clean up in prep for wait...
40             ASSERT(!PolicyLockOwned);
41  
42             //
43             // If we acquired the timer refresh lock (can happen if we promoted to shutdown)
44             // then we need to release it so that suspend actually suspends.
45             //
46             if (TimerRefreshLockOwned) {
47                 ExReleaseTimeRefreshLock();
48             }
49  
50             // And sleep until we're terminated.
51  
52             // Note that we do NOT clean up the dev state -- it's now
53             // owned by the shutdown worker thread.
54  
55             // Note that we also do not unlock the pagable image
56             // section referred to by ExPageLockHandle -- this keeps
57             // all of our shutdown code in memory.
58  
59             KeSuspendThread(KeGetCurrentThread());
60  
61             return STATUS_SYSTEM_SHUTDOWN;
62         } else {
63             PopGracefulShutdown (NULL);
64         }
65     }
66     ......
67  
68 }

  接着再看PopGracefulShutdown,可以看到这里也做了很多,IO管理器的关闭,配置管理器的关闭,缓存管理器的关闭等。在这里修改的文件、注册表等信息将被写到磁盘。最终调用PopShutdownSystem:

 1 <<Windows XP>>
 2 VOID
 3 PopGracefulShutdown (
 4     IN PVOID WorkItemParameter
 5     )
 6 {
 7     PVOID         Context;
 8     ......
 9     if (PoCleanShutdownEnabled()) {
10         //
11         // Terminate all processes.  This will close all the handles and delete
12         // all the address spaces.  Note the system process is kept alive.
13         //
14         PsShutdownSystem ();
15  
16         ......
17  
18     }
19     //
20     // Terminate Plug-N-Play.
21     //
22  
23     PpShutdownSystem (TRUE, 0, &Context);
24  
25     ExShutdownSystem (0);
26  
27     //
28     // Send shutdown IRPs to all drivers that asked for it.
29     //
30  
31     IoShutdownSystem (0);
32     
33     //
34     // Scrub the object directories
35     //
36     if (PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_OB) {
37         ObShutdownSystem (0);
38     }
39  
40     //
41     // Close the registry and the associated handles/file objects.
42     //
43     CmShutdownSystem ();
44     
45     ......
46     
47     MmShutdownSystem (0);
48  
49     //
50     // Inform drivers of the system shutdown state.
51     // This will finish shutting down Io and Mm.
52     // After this is complete,
53     // NO MORE REFERENCES TO PAGABLE CODE OR DATA MAY BE MADE.
54     //
55  
56     // ISSUE-2000/03/14-earhart: shutdown filesystems in dev shutdown
57     IoConfigureCrashDump(CrashDumpDisable);
58     CcWaitForCurrentLazyWriterActivity();
59     ExShutdownSystem(1);
60     IoShutdownSystem(1);
61     MmShutdownSystem(1);
62  
63     ......
64  
65     HalSetWakeEnable(FALSE);
66  
67     ......
68  
69     PpShutdownSystem (TRUE, 1, &Context);
70  
71     ExShutdownSystem (2);
72  
73     if (PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_OB) {
74         ObShutdownSystem (2);
75     }
76  
77     //
78     // Any allocated pool left at this point is a leak.
79     //
80  
81     MmShutdownSystem (2);
82  
83     //
84     // Implement shutdown style action -
85     // N.B. does not return (will bugcheck in preference to returning).
86     //
87  
88     PopShutdownSystem(PopAction.Action);
89 }

  接着看 PopShutdownSystem,可以看出最终调用的是HalReturnToFirmware:

 1 <<Windows XP>>
 2 VOID
 3 PopShutdownSystem (
 4     IN POWER_ACTION SystemAction
 5     )
 6 /*++
 7 Routine Description:
 8     Routine to implement a Shutdown style power actions
 9 Arguments:
10     SystemAction    - Action to implement (must be a valid shutdown type)
11 Return Value:
12     Status
13 --*/
14 {
15  
16     //
17     // Tell the debugger we are shutting down
18     //
19  
20     KD_SYMBOLS_INFO SymbolInfo = {0};
21     SymbolInfo.BaseOfDll = (PVOID)KD_REBOOT;
22     DebugService2(NULL, &SymbolInfo, BREAKPOINT_UNLOAD_SYMBOLS);
23  
24     //
25     // Perform the final shutdown operation
26     //
27  
28     switch (SystemAction) {
29         case PowerActionShutdownReset:
30  
31             //
32             // Reset the system
33             //
34  
35             PopInvokeSystemStateHandler (PowerStateShutdownReset, NULL);
36  
37             //
38             // Didn't do it, go for legacy function
39             //
40  
41             HalReturnToFirmware (HalRebootRoutine);
42             break;
43  
44         case PowerActionShutdownOff:
45         case PowerActionShutdown:
46  
47  
48             //
49             // Power down the system
50             //
51  
52             PopInvokeSystemStateHandler (PowerStateShutdownOff, NULL);
53  
54             //
55             // Didn't do it, go for legacy function
56             //
57  
58             HalReturnToFirmware (HalPowerDownRoutine);
59  
60             //
61             // Due to simulations we can try to power down on systems
62             // which don't support it
63             //
64  
65             PoPrint (PO_ERROR, ("PopShutdownSystem: HalPowerDownRoutine returned\n"));
66             HalReturnToFirmware (HalRebootRoutine);
67             break;
68  
69         default:
70             //
71             // Got some unexpected input...
72             //
73             HalReturnToFirmware (HalRebootRoutine);
74     }
75  
76     KeBugCheckEx (INTERNAL_POWER_ERROR, 5, 0, 0, 0);
77 }
  • HalReturnToFirmware分析

HalReturnToFirmware分析

 1 VOID
 2 HalReturnToFirmware(
 3     IN FIRMWARE_ENTRY Routine
 4     )
 5  
 6  
 7  
 8 {
 9     switch (Routine) {
10         case HalPowerDownRoutine:
11  
12 #if defined(NEC_98)
13  
14             HalpPowerDownFlag = TRUE;
15  
16 #endif // defined(NEC_98)
17  
18         case HalHaltRoutine:
19         case HalRestartRoutine:
20         case HalRebootRoutine:
21  
22             InbvAcquireDisplayOwnership();
23  
24             //
25             // Never returns
26             //
27  
28             HalpReboot();
29             break;
30         default:
31             DbgPrint("HalReturnToFirmware called\n");
32             DbgBreakPoint();
33             break;
34     }
35 }

  最终调用的是HalpReboot,在xp上,HalpReboot处理一些CMOS数据和PCI数据,就不再深入分析了。

        WinXP下FIRMWARE_ENTRY 定义如下:

typedef enum _FIRMWARE_REENTRY {
        HalHaltRoutine,
        HalPowerDownRoutine,
        HalRestartRoutine,
        HalRebootRoutine,
        HalInteractiveModeRoutine,
        HalMaximumRoutine
} FIRMWARE_REENTRY, * PFIRMWARE_REENTRY;

  HalReturnToFirmware也是我们可调用的最底层接口,因为它是导出的,可以在驱动中直接使用。

  在Win7 x64环境下Windbg反汇编的结果如下,跳转逻辑已用颜色标记出来:

1: kd> uf hal!HalReturnToFirmware hal!HalReturnToFirmware:fffff800`05412d68 48895c2408 mov qword ptr [rsp+8],rbxfffff800`05412d6d 55 push rbpfffff800`05412d6e 4883ec20 sub rsp,20hfffff800`05412d72 bd01000000 mov ebp,1fffff800`05412d77 85c9 test ecx,ecxfffff800`05412d79 7422 je hal!HalReturnToFirmware+0x35 (fffff800`05412d9d) //传入的参数为0
hal!HalReturnToFirmware+0x13:fffff800`05412d7b 3bcd cmp ecx,ebpfffff800`05412d7d 7419 je hal!HalReturnToFirmware+0x30 (fffff800`05412d98) //传入的参数为1,跳转到hal!HalpShutdown
hal!HalReturnToFirmware+0x17:fffff800`05412d7f 7e05 jle hal!HalReturnToFirmware+0x1e (fffff800`05412d86) //传入小于0的数值,非法
hal!HalReturnToFirmware+0x19:fffff800`05412d81 83f903 cmp ecx,3fffff800`05412d84 7e17 jle hal!HalReturnToFirmware+0x35 (fffff800`05412d9d) //传入的参数小于等于3,也就是2和3时
hal!HalReturnToFirmware+0x1e:fffff800`05412d86 488d0d13400100 lea rcx,[hal! ?? ::FNODOBFM::`string’ (fffff800`05426da0)]fffff800`05412d8d e84e350100 call hal!DbgPrint (fffff800`054262e0)fffff800`05412d92 cc int 3fffff800`05412d93 e9ca000000 jmp hal!HalReturnToFirmware+0xfa (fffff800`05412e62)
hal!HalReturnToFirmware+0x30:fffff800`05412d98 e8cb010000 call hal!HalpShutdown (fffff800`05412f68)
hal!HalReturnToFirmware+0x35:fffff800`05412d9d ff1555550100 call qword ptr [hal!_imp_InbvAcquireDisplayOwnership (fffff800`054282f8)]fffff800`05412da3 4533c0 xor r8d,r8dfffff800`05412da6 8bd5 mov edx,ebpfffff800`05412da8 33c9 xor ecx,ecxfffff800`05412daa e895230000 call hal!HalpMapPhysicalMemory64 (fffff800`05415144)fffff800`05412daf 4885c0 test rax,raxfffff800`05412db2 740c je hal!HalReturnToFirmware+0x58 (fffff800`05412dc0)
hal!HalReturnToFirmware+0x4c:fffff800`05412db4 b934120000 mov ecx,1234hfffff800`05412db9 66898872040000 mov word ptr [rax+472h],cx
hal!HalReturnToFirmware+0x58:fffff800`05412dc0 b9e8030000 mov ecx,3E8hfffff800`05412dc5 e8867bffff call hal!HalpAcquireCmosSpinLockEx (fffff800`0540a950)fffff800`05412dca fa clifffff800`05412dcb 803d33f6010000 cmp byte ptr [hal!HalpTimeSourceInitializationComplete (fffff800`05432405)],0fffff800`05412dd2 750d jne hal!HalReturnToFirmware+0x79 (fffff800`05412de1)
hal!HalReturnToFirmware+0x6c:fffff800`05412dd4 ba64000000 mov edx,64hfffff800`05412dd9 b0fe mov al,0FEhfffff800`05412ddb ee out dx,alfffff800`05412ddc e981000000 jmp hal!HalReturnToFirmware+0xfa (fffff800`05412e62)
hal!HalReturnToFirmware+0x79:fffff800`05412de1 ba70000000 mov edx,70hfffff800`05412de6 b00b mov al,0Bhfffff800`05412de8 ee out dx,alfffff800`05412de9 8bcd mov ecx,ebpfffff800`05412deb e8085b0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412df0 ba71000000 mov edx,71hfffff800`05412df5 ec in al,dxfffff800`05412df6 8ad8 mov bl,alfffff800`05412df8 8bcd mov ecx,ebpfffff800`05412dfa e8f95a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412dff 80e3bf and bl,0BFhfffff800`05412e02 ba71000000 mov edx,71hfffff800`05412e07 8ac3 mov al,blfffff800`05412e09 ee out dx,alfffff800`05412e0a 8bcd mov ecx,ebpfffff800`05412e0c e8e75a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e11 ba70000000 mov edx,70hfffff800`05412e16 b00a mov al,0Ahfffff800`05412e18 ee out dx,alfffff800`05412e19 8bcd mov ecx,ebpfffff800`05412e1b e8d85a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e20 ba71000000 mov edx,71hfffff800`05412e25 ec in al,dxfffff800`05412e26 8ad8 mov bl,alfffff800`05412e28 8bcd mov ecx,ebpfffff800`05412e2a e8c95a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e2f 80e3f6 and bl,0F6hfffff800`05412e32 ba71000000 mov edx,71hfffff800`05412e37 80cb06 or bl,6fffff800`05412e3a 8ac3 mov al,blfffff800`05412e3c ee out dx,alfffff800`05412e3d 8bcd mov ecx,ebpfffff800`05412e3f e8b45a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e44 ba70000000 mov edx,70hfffff800`05412e49 b015 mov al,15hfffff800`05412e4b ee out dx,alfffff800`05412e4c 8bcd mov ecx,ebpfffff800`05412e4e e8a55a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e53 e880a30000 call hal!HalpResetAllProcessors (fffff800`0541d1d8)fffff800`05412e58 e8d3010000 call hal!HalpWriteResetCommand (fffff800`05413030)fffff800`05412e5d e84e390100 call hal!HalpHalt (fffff800`054267b0)
hal!HalReturnToFirmware+0xfa:fffff800`05412e62 488b5c2430 mov rbx,qword ptr [rsp+30h]fffff800`05412e67 4883c420 add rsp,20hfffff800`05412e6b 5d pop rbpfffff800`05412e6c c3 ret

1: kd> uf hal!HalReturnToFirmware hal!HalReturnToFirmware:fffff800`05412d68 48895c2408 mov qword ptr [rsp+8],rbxfffff800`05412d6d 55 push rbpfffff800`05412d6e 4883ec20 sub rsp,20hfffff800`05412d72 bd01000000 mov ebp,1fffff800`05412d77 85c9 test ecx,ecxfffff800`05412d79 7422 je hal!HalReturnToFirmware+0x35 (fffff800`05412d9d) //传入的参数为0

hal!HalReturnToFirmware+0x13:fffff800`05412d7b 3bcd cmp ecx,ebpfffff800`05412d7d 7419 je hal!HalReturnToFirmware+0x30 (fffff800`05412d98) //传入的参数为1,跳转到hal!HalpShutdown

hal!HalReturnToFirmware+0x17:fffff800`05412d7f 7e05 jle hal!HalReturnToFirmware+0x1e (fffff800`05412d86) //传入小于0的数值,非法

hal!HalReturnToFirmware+0x19:fffff800`05412d81 83f903 cmp ecx,3fffff800`05412d84 7e17 jle hal!HalReturnToFirmware+0x35 (fffff800`05412d9d) //传入的参数小于等于3,也就是2和3时

hal!HalReturnToFirmware+0x1e:fffff800`05412d86 488d0d13400100 lea rcx,[hal! ?? ::FNODOBFM::`string’ (fffff800`05426da0)]fffff800`05412d8d e84e350100 call hal!DbgPrint (fffff800`054262e0)fffff800`05412d92 cc int 3fffff800`05412d93 e9ca000000 jmp hal!HalReturnToFirmware+0xfa (fffff800`05412e62)

hal!HalReturnToFirmware+0x30:fffff800`05412d98 e8cb010000 call hal!HalpShutdown (fffff800`05412f68)

hal!HalReturnToFirmware+0x35:fffff800`05412d9d ff1555550100 call qword ptr [hal!_imp_InbvAcquireDisplayOwnership (fffff800`054282f8)]fffff800`05412da3 4533c0 xor r8d,r8dfffff800`05412da6 8bd5 mov edx,ebpfffff800`05412da8 33c9 xor ecx,ecxfffff800`05412daa e895230000 call hal!HalpMapPhysicalMemory64 (fffff800`05415144)fffff800`05412daf 4885c0 test rax,raxfffff800`05412db2 740c je hal!HalReturnToFirmware+0x58 (fffff800`05412dc0)

hal!HalReturnToFirmware+0x4c:fffff800`05412db4 b934120000 mov ecx,1234hfffff800`05412db9 66898872040000 mov word ptr [rax+472h],cx

hal!HalReturnToFirmware+0x58:fffff800`05412dc0 b9e8030000 mov ecx,3E8hfffff800`05412dc5 e8867bffff call hal!HalpAcquireCmosSpinLockEx (fffff800`0540a950)fffff800`05412dca fa clifffff800`05412dcb 803d33f6010000 cmp byte ptr [hal!HalpTimeSourceInitializationComplete (fffff800`05432405)],0fffff800`05412dd2 750d jne hal!HalReturnToFirmware+0x79 (fffff800`05412de1)

hal!HalReturnToFirmware+0x6c:fffff800`05412dd4 ba64000000 mov edx,64hfffff800`05412dd9 b0fe mov al,0FEhfffff800`05412ddb ee out dx,alfffff800`05412ddc e981000000 jmp hal!HalReturnToFirmware+0xfa (fffff800`05412e62)

hal!HalReturnToFirmware+0x79:fffff800`05412de1 ba70000000 mov edx,70hfffff800`05412de6 b00b mov al,0Bhfffff800`05412de8 ee out dx,alfffff800`05412de9 8bcd mov ecx,ebpfffff800`05412deb e8085b0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412df0 ba71000000 mov edx,71hfffff800`05412df5 ec in al,dxfffff800`05412df6 8ad8 mov bl,alfffff800`05412df8 8bcd mov ecx,ebpfffff800`05412dfa e8f95a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412dff 80e3bf and bl,0BFhfffff800`05412e02 ba71000000 mov edx,71hfffff800`05412e07 8ac3 mov al,blfffff800`05412e09 ee out dx,alfffff800`05412e0a 8bcd mov ecx,ebpfffff800`05412e0c e8e75a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e11 ba70000000 mov edx,70hfffff800`05412e16 b00a mov al,0Ahfffff800`05412e18 ee out dx,alfffff800`05412e19 8bcd mov ecx,ebpfffff800`05412e1b e8d85a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e20 ba71000000 mov edx,71hfffff800`05412e25 ec in al,dxfffff800`05412e26 8ad8 mov bl,alfffff800`05412e28 8bcd mov ecx,ebpfffff800`05412e2a e8c95a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e2f 80e3f6 and bl,0F6hfffff800`05412e32 ba71000000 mov edx,71hfffff800`05412e37 80cb06 or bl,6fffff800`05412e3a 8ac3 mov al,blfffff800`05412e3c ee out dx,alfffff800`05412e3d 8bcd mov ecx,ebpfffff800`05412e3f e8b45a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e44 ba70000000 mov edx,70hfffff800`05412e49 b015 mov al,15hfffff800`05412e4b ee out dx,alfffff800`05412e4c 8bcd mov ecx,ebpfffff800`05412e4e e8a55a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e53 e880a30000 call hal!HalpResetAllProcessors (fffff800`0541d1d8)fffff800`05412e58 e8d3010000 call hal!HalpWriteResetCommand (fffff800`05413030)fffff800`05412e5d e84e390100 call hal!HalpHalt (fffff800`054267b0)

hal!HalReturnToFirmware+0xfa:fffff800`05412e62 488b5c2430 mov rbx,qword ptr [rsp+30h]fffff800`05412e67 4883c420 add rsp,20hfffff800`05412e6b 5d pop rbpfffff800`05412e6c c3 ret

  Win7 x64位下逻辑有所改变,从hal!HalReturnToFirmware+0x79 开始其实就为XP下HalpReboot的具体实现。

  • 代码实现

代码实现

  综上所述,代码实现就比较简单了:

  头文件定义

 1 #pragma once
 2  
 3 typedef enum _FIRMWARE_REENTRY {
 4         HalHaltRoutine,
 5         HalPowerDownRoutine,
 6         HalRestartRoutine,
 7         HalRebootRoutine,
 8         HalInteractiveModeRoutine,
 9         HalMaximumRoutine
10 } FIRMWARE_REENTRY, * PFIRMWARE_REENTRY;
11  
12 //再定义导出函数 HalReturnToFirmware
13 EXTERN_C NTKERNELAPI VOID NTAPI HalReturnToFirmware(
14         LONG lReturnType
15 );

  实现:

1 VOID ComputerPowerOffByHal()
2 {
3         HalReturnToFirmware(HalPowerDownRoutine);
4 }
5  
6 VOID ComputerResetByHal()
7 {
8         HalReturnToFirmware(HalRebootRoutine);
9 }
————————
  • introduction

introduction

For fast restart and shutdown of the computer, many software on the Internet call ZW shutdown system (ntshutdown system) under RING3. Although it is fast, it still goes through at least some processes, such as sending shutdown notice to the device driver. The following is taken from & lt& lt; In depth analysis of Windows operating system version 6 (Volume 2) & gt& gt; P528:

Once Csrss has completed the notification of the system shutdown to the system process, Winlogon finally calls the execution subsystem function NtShutdownSystem to end the downtime process. The ntshutdown system function also calls the posetsystempowerstate function to coordinate the shutdown processing of the device driver and the rest of the actuator subsystem (plug and play manager, power manager, actuator, I / O Manager, configuration manager and memory manager).
For example, posetsystempowerstate calls the I / O Manager to send shutdown I / O packets to all device drivers that have requested shutdown notifications. This action gives the device driver the opportunity to perform any necessary special processing before windows exits. The memory stack of the worker thread is replaced, the configuration manager flushes any modified registry data to the disk, and the memory manager writes all modified pages containing file data back to their respective files. If the option “clear pagefile during shutdown” is turned on, the memory manager clears the pagefile at this time. The I / O Manager will also be called again to tell the file system driver; The system is shutting down. The system shutdown process ends in the power manager. The actions performed by the power manager depend on whether the user specifies to shut down, reboot, or turn off the power.

  一旦Csrss已经完成了向系统进程传达系统停机的通知,Winlogon最后调用执行体子系统函数 NtShutdownSystem,从而结束停机过程。 NtShutdownSystem 函数又调用 PoSetSystemPowerState函数,来协调设备驱动程序和执行体子系统其余部分(即插即用管理器、电源管理器、执行体、I/O管理器、配置管理器和内存管理器)的停机处理。
  例如,PoSetSystemPowerState调用I/O管理器,以便给那些已经请求过停机通知的所有设备驱动程序发送停机I/O包。这一动作使得设备驱动程序有机会在Windows退出以前执行任何必要的特殊处理。工作者线程的内存栈被换入,配置管理器将任何修改过的注册表数据刷新到磁盘上,内存管理器将所有己修改过的且包含了文件数据的页面写回到它们各自的文件中。如果“在停机时清除页面文件”的选项已被打开,那么,内存管理器在这时候清除页面文件。I/O管理器还会被再次调用,以便告诉文件系统驱动程序;系统正在进行停机。系统停机过程最终在电源管理器中结束。电源管理器所执行的动作取决于用户指定的是停机、重新引导,还是关闭电源。

You can see that there are still a lot of things to deal with when calling ntshutdown system, so I wonder if I can call a lower level implementation to shut down more quickly.

In addition, some programs to prevent shutdown are also hook ntshutdown system. We try to bypass hook with a lower level implementation, but it is already driven in the kernel layer. What can’t we do.

  • NtShutdownSystem分析

NtShutdownSystem分析

The following analysis mainly adopts ReactOS, WindowsXP code and WinDbg debugging:

 1 <<ReactOS>>
 2 NTSTATUS
 3 NTAPI
 4 NtShutdownSystem(IN SHUTDOWN_ACTION Action)
 5 {
 6     POWER_ACTION PowerAction;
 7  
 8     /* Convert to power action */
 9     if (Action == ShutdownNoReboot)
10     {
11         PowerAction = PowerActionShutdown;
12     }
13     else if (Action == ShutdownReboot)
14     {
15         PowerAction = PowerActionShutdownReset;
16     }
17     else if (Action == ShutdownPowerOff)
18     {
19         PowerAction = PowerActionShutdownOff;
20     }
21     else
22     {
23         return STATUS_INVALID_PARAMETER;
24     }
25  
26     /* Now call the power manager */
27     DPRINT("Setting state to: %lx\n", PowerAction);
28     return NtSetSystemPowerState(PowerAction,
29                                  PowerSystemSleeping3,
30                                  POWER_ACTION_OVERRIDE_APPS |
31                                  POWER_ACTION_DISABLE_WAKES |
32                                  POWER_ACTION_CRITICAL);
33 }

Ntsetsystempowerstate is debugged here. Let’s take a look at the implementation of ntsetsystempowerstate (intercepting the main content). It can be seen that popgracefulshutdown is finally called:

 1 <<Windows XP>>
 2 NTSYSAPI
 3 NTSTATUS
 4 NTAPI
 5 NtSetSystemPowerState (
 6     IN POWER_ACTION SystemAction,
 7     IN SYSTEM_POWER_STATE LightestSystemState,
 8     IN ULONG Flags                  // POWER_ACTION_xxx flags
 9     )
10 {
11     KPROCESSOR_MODE         PreviousMode;
12     ......
13     CmSetLazyFlushState(FALSE);
14     ......
15     if (PopAction.Shutdown) {
16  
17         //
18         // Force reacquisition of the dev list. We will be telling Pnp
19         // to unload all possible devices, and therefore Pnp needs us to
20         // release the Pnp Engine Lock.
21         //
22         IoFreePoDeviceNotifyList(&PopAction.DevState->Order);
23         PopAction.DevState->GetNewDeviceList = TRUE;
24  
25         //
26         // We shut down via a system worker thread so that the
27         // current active process will exit cleanly.
28         //
29  
30         if (PsGetCurrentProcess() != PsInitialSystemProcess) {
31  
32             ExInitializeWorkItem(&PopShutdownWorkItem,
33                                  &PopGracefulShutdown,
34                                  NULL);
35  
36             ExQueueWorkItem(&PopShutdownWorkItem,
37                             PO_SHUTDOWN_QUEUE);
38  
39             // Clean up in prep for wait...
40             ASSERT(!PolicyLockOwned);
41  
42             //
43             // If we acquired the timer refresh lock (can happen if we promoted to shutdown)
44             // then we need to release it so that suspend actually suspends.
45             //
46             if (TimerRefreshLockOwned) {
47                 ExReleaseTimeRefreshLock();
48             }
49  
50             // And sleep until we're terminated.
51  
52             // Note that we do NOT clean up the dev state -- it's now
53             // owned by the shutdown worker thread.
54  
55             // Note that we also do not unlock the pagable image
56             // section referred to by ExPageLockHandle -- this keeps
57             // all of our shutdown code in memory.
58  
59             KeSuspendThread(KeGetCurrentThread());
60  
61             return STATUS_SYSTEM_SHUTDOWN;
62         } else {
63             PopGracefulShutdown (NULL);
64         }
65     }
66     ......
67  
68 }

Then look at popgracefulshutdown. You can see that a lot has been done here, such as closing the IO manager, closing the configuration manager, closing the cache manager, etc. The file, registry and other information modified here will be written to disk. Finally, call popshutdown system:

 1 <<Windows XP>>
 2 VOID
 3 PopGracefulShutdown (
 4     IN PVOID WorkItemParameter
 5     )
 6 {
 7     PVOID         Context;
 8     ......
 9     if (PoCleanShutdownEnabled()) {
10         //
11         // Terminate all processes.  This will close all the handles and delete
12         // all the address spaces.  Note the system process is kept alive.
13         //
14         PsShutdownSystem ();
15  
16         ......
17  
18     }
19     //
20     // Terminate Plug-N-Play.
21     //
22  
23     PpShutdownSystem (TRUE, 0, &Context);
24  
25     ExShutdownSystem (0);
26  
27     //
28     // Send shutdown IRPs to all drivers that asked for it.
29     //
30  
31     IoShutdownSystem (0);
32     
33     //
34     // Scrub the object directories
35     //
36     if (PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_OB) {
37         ObShutdownSystem (0);
38     }
39  
40     //
41     // Close the registry and the associated handles/file objects.
42     //
43     CmShutdownSystem ();
44     
45     ......
46     
47     MmShutdownSystem (0);
48  
49     //
50     // Inform drivers of the system shutdown state.
51     // This will finish shutting down Io and Mm.
52     // After this is complete,
53     // NO MORE REFERENCES TO PAGABLE CODE OR DATA MAY BE MADE.
54     //
55  
56     // ISSUE-2000/03/14-earhart: shutdown filesystems in dev shutdown
57     IoConfigureCrashDump(CrashDumpDisable);
58     CcWaitForCurrentLazyWriterActivity();
59     ExShutdownSystem(1);
60     IoShutdownSystem(1);
61     MmShutdownSystem(1);
62  
63     ......
64  
65     HalSetWakeEnable(FALSE);
66  
67     ......
68  
69     PpShutdownSystem (TRUE, 1, &Context);
70  
71     ExShutdownSystem (2);
72  
73     if (PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_OB) {
74         ObShutdownSystem (2);
75     }
76  
77     //
78     // Any allocated pool left at this point is a leak.
79     //
80  
81     MmShutdownSystem (2);
82  
83     //
84     // Implement shutdown style action -
85     // N.B. does not return (will bugcheck in preference to returning).
86     //
87  
88     PopShutdownSystem(PopAction.Action);
89 }

Keep looking   From popshutdown system, we can see that halreturntofirmware is finally called:

 1 <<Windows XP>>
 2 VOID
 3 PopShutdownSystem (
 4     IN POWER_ACTION SystemAction
 5     )
 6 /*++
 7 Routine Description:
 8     Routine to implement a Shutdown style power actions
 9 Arguments:
10     SystemAction    - Action to implement (must be a valid shutdown type)
11 Return Value:
12     Status
13 --*/
14 {
15  
16     //
17     // Tell the debugger we are shutting down
18     //
19  
20     KD_SYMBOLS_INFO SymbolInfo = {0};
21     SymbolInfo.BaseOfDll = (PVOID)KD_REBOOT;
22     DebugService2(NULL, &SymbolInfo, BREAKPOINT_UNLOAD_SYMBOLS);
23  
24     //
25     // Perform the final shutdown operation
26     //
27  
28     switch (SystemAction) {
29         case PowerActionShutdownReset:
30  
31             //
32             // Reset the system
33             //
34  
35             PopInvokeSystemStateHandler (PowerStateShutdownReset, NULL);
36  
37             //
38             // Didn't do it, go for legacy function
39             //
40  
41             HalReturnToFirmware (HalRebootRoutine);
42             break;
43  
44         case PowerActionShutdownOff:
45         case PowerActionShutdown:
46  
47  
48             //
49             // Power down the system
50             //
51  
52             PopInvokeSystemStateHandler (PowerStateShutdownOff, NULL);
53  
54             //
55             // Didn't do it, go for legacy function
56             //
57  
58             HalReturnToFirmware (HalPowerDownRoutine);
59  
60             //
61             // Due to simulations we can try to power down on systems
62             // which don't support it
63             //
64  
65             PoPrint (PO_ERROR, ("PopShutdownSystem: HalPowerDownRoutine returned\n"));
66             HalReturnToFirmware (HalRebootRoutine);
67             break;
68  
69         default:
70             //
71             // Got some unexpected input...
72             //
73             HalReturnToFirmware (HalRebootRoutine);
74     }
75  
76     KeBugCheckEx (INTERNAL_POWER_ERROR, 5, 0, 0, 0);
77 }
  • HalReturnToFirmware分析

HalReturnToFirmware分析

 1 VOID
 2 HalReturnToFirmware(
 3     IN FIRMWARE_ENTRY Routine
 4     )
 5  
 6  
 7  
 8 {
 9     switch (Routine) {
10         case HalPowerDownRoutine:
11  
12 #if defined(NEC_98)
13  
14             HalpPowerDownFlag = TRUE;
15  
16 #endif // defined(NEC_98)
17  
18         case HalHaltRoutine:
19         case HalRestartRoutine:
20         case HalRebootRoutine:
21  
22             InbvAcquireDisplayOwnership();
23  
24             //
25             // Never returns
26             //
27  
28             HalpReboot();
29             break;
30         default:
31             DbgPrint("HalReturnToFirmware called\n");
32             DbgBreakPoint();
33             break;
34     }
35 }

The final call is halpreboot. On XP, halpreboot processes some CMOS data and PCI data, so it will not be analyzed in depth.

Firmware under WinXP_ ENTRY   It is defined as follows:

typedef enum _FIRMWARE_REENTRY {
        HalHaltRoutine,
        HalPowerDownRoutine,
        HalRestartRoutine,
        HalRebootRoutine,
        HalInteractiveModeRoutine,
        HalMaximumRoutine
} FIRMWARE_REENTRY, * PFIRMWARE_REENTRY;

Hallreturntofirmware is also the lowest interface we can call, because it is exported and can be used directly in the driver.

The results of WinDbg disassembly in win7 x64 environment are as follows, and the jump logic has been marked with color:

1: kd> uf hal!HalReturnToFirmware hal!HalReturnToFirmware:fffff800`05412d68 48895c2408 mov qword ptr [rsp+8],rbxfffff800`05412d6d 55 push rbpfffff800`05412d6e 4883ec20 sub rsp,20hfffff800`05412d72 bd01000000 mov ebp,1fffff800`05412d77 85c9 test ecx,ecxfffff800`05412d79 7422 je hal!HalReturnToFirmware+0x35 (fffff800`05412d9d) //传入的参数为0
hal!HalReturnToFirmware+0x13:fffff800`05412d7b 3bcd cmp ecx,ebpfffff800`05412d7d 7419 je hal!HalReturnToFirmware+0x30 (fffff800`05412d98) //传入的参数为1,跳转到hal!HalpShutdown
hal!HalReturnToFirmware+0x17:fffff800`05412d7f 7e05 jle hal!HalReturnToFirmware+0x1e (fffff800`05412d86) //传入小于0的数值,非法
hal!HalReturnToFirmware+0x19:fffff800`05412d81 83f903 cmp ecx,3fffff800`05412d84 7e17 jle hal!HalReturnToFirmware+0x35 (fffff800`05412d9d) //传入的参数小于等于3,也就是2和3时
hal!HalReturnToFirmware+0x1e:fffff800`05412d86 488d0d13400100 lea rcx,[hal! ?? ::FNODOBFM::`string’ (fffff800`05426da0)]fffff800`05412d8d e84e350100 call hal!DbgPrint (fffff800`054262e0)fffff800`05412d92 cc int 3fffff800`05412d93 e9ca000000 jmp hal!HalReturnToFirmware+0xfa (fffff800`05412e62)
hal!HalReturnToFirmware+0x30:fffff800`05412d98 e8cb010000 call hal!HalpShutdown (fffff800`05412f68)
hal!HalReturnToFirmware+0x35:fffff800`05412d9d ff1555550100 call qword ptr [hal!_imp_InbvAcquireDisplayOwnership (fffff800`054282f8)]fffff800`05412da3 4533c0 xor r8d,r8dfffff800`05412da6 8bd5 mov edx,ebpfffff800`05412da8 33c9 xor ecx,ecxfffff800`05412daa e895230000 call hal!HalpMapPhysicalMemory64 (fffff800`05415144)fffff800`05412daf 4885c0 test rax,raxfffff800`05412db2 740c je hal!HalReturnToFirmware+0x58 (fffff800`05412dc0)
hal!HalReturnToFirmware+0x4c:fffff800`05412db4 b934120000 mov ecx,1234hfffff800`05412db9 66898872040000 mov word ptr [rax+472h],cx
hal!HalReturnToFirmware+0x58:fffff800`05412dc0 b9e8030000 mov ecx,3E8hfffff800`05412dc5 e8867bffff call hal!HalpAcquireCmosSpinLockEx (fffff800`0540a950)fffff800`05412dca fa clifffff800`05412dcb 803d33f6010000 cmp byte ptr [hal!HalpTimeSourceInitializationComplete (fffff800`05432405)],0fffff800`05412dd2 750d jne hal!HalReturnToFirmware+0x79 (fffff800`05412de1)
hal!HalReturnToFirmware+0x6c:fffff800`05412dd4 ba64000000 mov edx,64hfffff800`05412dd9 b0fe mov al,0FEhfffff800`05412ddb ee out dx,alfffff800`05412ddc e981000000 jmp hal!HalReturnToFirmware+0xfa (fffff800`05412e62)
hal!HalReturnToFirmware+0x79:fffff800`05412de1 ba70000000 mov edx,70hfffff800`05412de6 b00b mov al,0Bhfffff800`05412de8 ee out dx,alfffff800`05412de9 8bcd mov ecx,ebpfffff800`05412deb e8085b0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412df0 ba71000000 mov edx,71hfffff800`05412df5 ec in al,dxfffff800`05412df6 8ad8 mov bl,alfffff800`05412df8 8bcd mov ecx,ebpfffff800`05412dfa e8f95a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412dff 80e3bf and bl,0BFhfffff800`05412e02 ba71000000 mov edx,71hfffff800`05412e07 8ac3 mov al,blfffff800`05412e09 ee out dx,alfffff800`05412e0a 8bcd mov ecx,ebpfffff800`05412e0c e8e75a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e11 ba70000000 mov edx,70hfffff800`05412e16 b00a mov al,0Ahfffff800`05412e18 ee out dx,alfffff800`05412e19 8bcd mov ecx,ebpfffff800`05412e1b e8d85a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e20 ba71000000 mov edx,71hfffff800`05412e25 ec in al,dxfffff800`05412e26 8ad8 mov bl,alfffff800`05412e28 8bcd mov ecx,ebpfffff800`05412e2a e8c95a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e2f 80e3f6 and bl,0F6hfffff800`05412e32 ba71000000 mov edx,71hfffff800`05412e37 80cb06 or bl,6fffff800`05412e3a 8ac3 mov al,blfffff800`05412e3c ee out dx,alfffff800`05412e3d 8bcd mov ecx,ebpfffff800`05412e3f e8b45a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e44 ba70000000 mov edx,70hfffff800`05412e49 b015 mov al,15hfffff800`05412e4b ee out dx,alfffff800`05412e4c 8bcd mov ecx,ebpfffff800`05412e4e e8a55a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e53 e880a30000 call hal!HalpResetAllProcessors (fffff800`0541d1d8)fffff800`05412e58 e8d3010000 call hal!HalpWriteResetCommand (fffff800`05413030)fffff800`05412e5d e84e390100 call hal!HalpHalt (fffff800`054267b0)
hal!HalReturnToFirmware+0xfa:fffff800`05412e62 488b5c2430 mov rbx,qword ptr [rsp+30h]fffff800`05412e67 4883c420 add rsp,20hfffff800`05412e6b 5d pop rbpfffff800`05412e6c c3 ret

1: kd> uf hal!HalReturnToFirmware hal!HalReturnToFirmware:fffff800`05412d68 48895c2408 mov qword ptr [rsp+8],rbxfffff800`05412d6d 55 push rbpfffff800`05412d6e 4883ec20 sub rsp,20hfffff800`05412d72 bd01000000 mov ebp,1fffff800`05412d77 85c9 test ecx,ecxfffff800`05412d79 7422 je hal!HalReturnToFirmware+0x35 (fffff800`05412d9d) //传入的参数为0

hal!HalReturnToFirmware+0x13:fffff800`05412d7b 3bcd cmp ecx,ebpfffff800`05412d7d 7419 je hal!HalReturnToFirmware+0x30 (fffff800`05412d98) //传入的参数为1,跳转到hal!HalpShutdown

hal!HalReturnToFirmware+0x17:fffff800`05412d7f 7e05 jle hal!HalReturnToFirmware+0x1e (fffff800`05412d86) //传入小于0的数值,非法

hal!HalReturnToFirmware+0x19:fffff800`05412d81 83f903 cmp ecx,3fffff800`05412d84 7e17 jle hal!HalReturnToFirmware+0x35 (fffff800`05412d9d) //传入的参数小于等于3,也就是2和3时

hal!HalReturnToFirmware+0x1e:fffff800`05412d86 488d0d13400100 lea rcx,[hal! ?? ::FNODOBFM::`string’ (fffff800`05426da0)]fffff800`05412d8d e84e350100 call hal!DbgPrint (fffff800`054262e0)fffff800`05412d92 cc int 3fffff800`05412d93 e9ca000000 jmp hal!HalReturnToFirmware+0xfa (fffff800`05412e62)

hal!HalReturnToFirmware+0x30:fffff800`05412d98 e8cb010000 call hal!HalpShutdown (fffff800`05412f68)

hal!HalReturnToFirmware+0x35:fffff800`05412d9d ff1555550100 call qword ptr [hal!_imp_InbvAcquireDisplayOwnership (fffff800`054282f8)]fffff800`05412da3 4533c0 xor r8d,r8dfffff800`05412da6 8bd5 mov edx,ebpfffff800`05412da8 33c9 xor ecx,ecxfffff800`05412daa e895230000 call hal!HalpMapPhysicalMemory64 (fffff800`05415144)fffff800`05412daf 4885c0 test rax,raxfffff800`05412db2 740c je hal!HalReturnToFirmware+0x58 (fffff800`05412dc0)

hal!HalReturnToFirmware+0x4c:fffff800`05412db4 b934120000 mov ecx,1234hfffff800`05412db9 66898872040000 mov word ptr [rax+472h],cx

hal!HalReturnToFirmware+0x58:fffff800`05412dc0 b9e8030000 mov ecx,3E8hfffff800`05412dc5 e8867bffff call hal!HalpAcquireCmosSpinLockEx (fffff800`0540a950)fffff800`05412dca fa clifffff800`05412dcb 803d33f6010000 cmp byte ptr [hal!HalpTimeSourceInitializationComplete (fffff800`05432405)],0fffff800`05412dd2 750d jne hal!HalReturnToFirmware+0x79 (fffff800`05412de1)

hal!HalReturnToFirmware+0x6c:fffff800`05412dd4 ba64000000 mov edx,64hfffff800`05412dd9 b0fe mov al,0FEhfffff800`05412ddb ee out dx,alfffff800`05412ddc e981000000 jmp hal!HalReturnToFirmware+0xfa (fffff800`05412e62)

hal!HalReturnToFirmware+0x79:fffff800`05412de1 ba70000000 mov edx,70hfffff800`05412de6 b00b mov al,0Bhfffff800`05412de8 ee out dx,alfffff800`05412de9 8bcd mov ecx,ebpfffff800`05412deb e8085b0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412df0 ba71000000 mov edx,71hfffff800`05412df5 ec in al,dxfffff800`05412df6 8ad8 mov bl,alfffff800`05412df8 8bcd mov ecx,ebpfffff800`05412dfa e8f95a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412dff 80e3bf and bl,0BFhfffff800`05412e02 ba71000000 mov edx,71hfffff800`05412e07 8ac3 mov al,blfffff800`05412e09 ee out dx,alfffff800`05412e0a 8bcd mov ecx,ebpfffff800`05412e0c e8e75a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e11 ba70000000 mov edx,70hfffff800`05412e16 b00a mov al,0Ahfffff800`05412e18 ee out dx,alfffff800`05412e19 8bcd mov ecx,ebpfffff800`05412e1b e8d85a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e20 ba71000000 mov edx,71hfffff800`05412e25 ec in al,dxfffff800`05412e26 8ad8 mov bl,alfffff800`05412e28 8bcd mov ecx,ebpfffff800`05412e2a e8c95a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e2f 80e3f6 and bl,0F6hfffff800`05412e32 ba71000000 mov edx,71hfffff800`05412e37 80cb06 or bl,6fffff800`05412e3a 8ac3 mov al,blfffff800`05412e3c ee out dx,alfffff800`05412e3d 8bcd mov ecx,ebpfffff800`05412e3f e8b45a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e44 ba70000000 mov edx,70hfffff800`05412e49 b015 mov al,15hfffff800`05412e4b ee out dx,alfffff800`05412e4c 8bcd mov ecx,ebpfffff800`05412e4e e8a55a0000 call hal!KeStallExecutionProcessor (fffff800`054188f8)fffff800`05412e53 e880a30000 call hal!HalpResetAllProcessors (fffff800`0541d1d8)fffff800`05412e58 e8d3010000 call hal!HalpWriteResetCommand (fffff800`05413030)fffff800`05412e5d e84e390100 call hal!HalpHalt (fffff800`054267b0)

hal!HalReturnToFirmware+0xfa:fffff800`05412e62 488b5c2430 mov rbx,qword ptr [rsp+30h]fffff800`05412e67 4883c420 add rsp,20hfffff800`05412e6b 5d pop rbpfffff800`05412e6c c3 ret

The logic of win7 x64 bit is changed from < strong > Hal! HalReturnToFirmware+0x79   In fact, it was the specific implementation of halpreboot under XP at the beginning.

  • code implementation

code implementation

To sum up, the code implementation is relatively simple:

Header file definition

 1 #pragma once
 2  
 3 typedef enum _FIRMWARE_REENTRY {
 4         HalHaltRoutine,
 5         HalPowerDownRoutine,
 6         HalRestartRoutine,
 7         HalRebootRoutine,
 8         HalInteractiveModeRoutine,
 9         HalMaximumRoutine
10 } FIRMWARE_REENTRY, * PFIRMWARE_REENTRY;
11  
12 //再定义导出函数 HalReturnToFirmware
13 EXTERN_C NTKERNELAPI VOID NTAPI HalReturnToFirmware(
14         LONG lReturnType
15 );

Implementation:

1 VOID ComputerPowerOffByHal()
2 {
3         HalReturnToFirmware(HalPowerDownRoutine);
4 }
5  
6 VOID ComputerResetByHal()
7 {
8         HalReturnToFirmware(HalRebootRoutine);
9 }