Sunshine
通常情况下,我们可以通过调用 NtShutdownSystem 未导出的内核 API 函数,来在内核层下实现计算机的关机和重启等操作。 这种实现方式虽然在内核层下实现,但是相对来说,还是太过于表层了。
本文要介绍一种在内核层下实现的强制关机以及重启的方法,即通过汇编 OUT 指令,控制端口输出,从而实现计算机的关机和重启。这种方式,较为低层,而且更难防御和监控。现在,我就把程序实现过程和原理,整理成文档,分享给大家。
我们通过汇编 OUT 指令,控制端口的输出,从而实现控制计算机关机或者重启。
对于实现关机操作,则可以向 1004H 端口,写入 2001H,汇编代码为:
mov ax, 2001h
mov dx, 1004h
out dx,ax
ret
则,对应的机器码为:
{0x66,0xB8,0x01,0x20,0x66,0xBA,0x04,0x10,0x66,0xEF,0xC3}
对于实现重启操作,则可以向 64H 端口,写入 0FEH,汇编代码为:
mov al, 0FEh
out 64h, al
ret
则,对应的机器码为:
{0xB0,0xFE,0xE6,0x64,0xC3}
所以,我们可以通过申请一块非分页内存,写入 Shellcode 数据,并声明函数指针,调用 Shellcode 数据并执行,从而实现相应的关机或者重启操作。当然,我们也可以直接写成汇编代码,但是,要注意 64 位系统下汇编代码要保存为 .asm 汇编文件,添加到工程中。
// 强制关机
BOOLEAN ShutdownForce()
{
// {0x66, 0xB8, 0x01, 0x20, 0x66, 0xBA, 0x04, 0x10, 0x66, 0xEF, 0xC3}
UCHAR ShellCode[11] = { 0x66, 0xB8, 0x01, 0x20, 0x66, 0xBA, 0x04, 0x10, 0x66, 0xEF, 0xC3 };
ULONG ulShellcodeSize = 11;
#ifdef _WIN64
// 64 位
typedef VOID(__fastcall *typedef_SHUTDOWNFUNC)();
#else
// 32 位
typedef VOID(__stdcall *typedef_SHUTDOWNFUNC)();
#endif
// 申请内存
typedef_SHUTDOWNFUNC ShutdownFunc = (typedef_SHUTDOWNFUNC)ExAllocatePool(NonPagedPool, ulShellcodeSize);
if (NULL == ShutdownFunc)
{
DbgPrint("ExAllocatePool Error!\n");
return FALSE;
}
// 写入数据
RtlCopyMemory(ShutdownFunc, ShellCode, ulShellcodeSize);
// 执行Shellcode代码实现关机
ShutdownFunc();
// 释放内存
ExFreePool(ShutdownFunc);
return TRUE;
}
// 强制重启
BOOLEAN RebootForce()
{
// {0xB0, 0xFE, 0xE6, 0x64, 0xC3}
UCHAR ShellCode[11] = { 0xB0, 0xFE, 0xE6, 0x64, 0xC3 };
ULONG ulShellcodeSize = 5;
#ifdef _WIN64
// 64 位
typedef VOID(__fastcall *typedef_REBOOTFUNC)();
#else
// 32 位
typedef VOID(__stdcall *typedef_REBOOTFUNC)();
#endif
// 申请内存
typedef_REBOOTFUNC RebootFunc = (typedef_REBOOTFUNC)ExAllocatePool(NonPagedPool, ulShellcodeSize);
if (NULL == RebootFunc)
{
DbgPrint("ExAllocatePool Error!\n");
return FALSE;
}
// 写入数据
RtlCopyMemory(RebootFunc, ShellCode, ulShellcodeSize);
// 执行Shellcode代码实现重启
RebootFunc();
// 释放内存
ExFreePool(RebootFunc);
return TRUE;
}
在 Win7 32 位系统下,驱动程序正常运行;在 Win10 64 位系统下,驱动程序正常运行。
对于这个层序,虽然编码较为简单,但是要想兼容 32 位和 64 位计算机,则需要特别注意一个问题:
在声明函数指针的时候,对于 32 位函数,调用约定为 __stdcall;对于 64 位函数,调用约定为 __fastcall。
所以,一定要注意不同系统位数下,函数的调用约定声明。否则,会出现错误。
keyboard_arrow_left上一篇 : 使用VS2013编译Crypto++加密库 大数据 Spark平台5-3、spark-sql : 下一篇keyboard_arrow_right