diff --git a/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.cpp b/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.cpp new file mode 100644 index 0000000..93ce52c --- /dev/null +++ b/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.cpp @@ -0,0 +1,104 @@ +// NTV_01_Bluescreen.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// + +//NtRaiseHardError演示程序 + +#include +#include //Windows API +#include //PUNICODE_STRING结构体 + +//准备NtRaiseHardError所需的两个未公开的类型和函数指针,直接从PPT复制。 +typedef enum _HARDERROR_RESPONSE_OPTION +{ + OptionAbortRetryIgnore, + OptionOk, + OptionOkCancel, + OptionRetryCancel, + OptionYesNo, + OptionYesNoCancel, + OptionShutdownSystem +} HARDERROR_RESPONSE_OPTION, * PHARDERROR_RESPONSE_OPTION; + +typedef enum _HARDERROR_RESPONSE +{ + ResponseReturnToCaller, + ResponseNotHandled, + ResponseAbort, + ResponseCancel, + ResponseIgnore, + ResponseNo, + ResponseOk, + ResponseRetry, + ResponseYes +} HARDERROR_RESPONSE, * PHARDERROR_RESPONSE; + +//漏掉了一个PUNICODE_STRING,这个结构体在另一个头文件中 +//typedef struct _UNICODE_STRING +//{ +// USHORT Length; +// USHORT MaximumLength; +// PWSTR Buffer; +//}UNICODE_STRING, *PUNICODE_STRING; + +typedef UINT(CALLBACK* NTRAISEHARDERROR)(NTSTATUS, ULONG, PUNICODE_STRING, PVOID, HARDERROR_RESPONSE_OPTION, PHARDERROR_RESPONSE); + +bool GetShutdownPrivilege() +{ + HANDLE hToken; + TOKEN_PRIVILEGES priv = { 0 }; + LUID ShutdownLUID; + //打开当前进程的Token,用于调整特权的Token需要使用TOKEN_ADJUST_PRIVILEGES指定 + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + return false; + //检查获取的Token是否正确 + if ((hToken == NULL) || (hToken == INVALID_HANDLE_VALUE)) + return false; + //根据特权的名称查找LUID + //SE_SHUTDOWN_NAME是Windows预定义的宏,值为shutdown特权的名称 + if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &ShutdownLUID)) + return false; + //使用TOKEN_PRIVILIEGES结构体存储获取到的信息 + priv.PrivilegeCount = 1; //需要更改的特权数 - 一个 + priv.Privileges[0].Luid = ShutdownLUID; //存入LUID + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //指定启用该特权 + //调整Token的特权 + if (!AdjustTokenPrivileges(hToken, FALSE, &priv, NULL, NULL, NULL)) + return false; + //判断是否所有特权修改都生效了 + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + return false; + return true; +} + +UINT NtRaiseHardError(NTSTATUS ErrorStatus, ULONG NumberOfParameters, PUNICODE_STRING UnicodeStringParameterMask OPTIONAL, PVOID Parameters, HARDERROR_RESPONSE_OPTION ResponseOption, PHARDERROR_RESPONSE Response) +{ + //加载ntdll.dll + HMODULE hNtdll = LoadLibrary(L"ntdll.dll"); + if (hNtdll == NULL) + return -1; + //GetProcAddress获取函数所在的地址并转换为函数指针 + NTRAISEHARDERROR _NtRaiseHardError = (NTRAISEHARDERROR)GetProcAddress(hNtdll, "NtRaiseHardError"); + //释放dll + FreeLibrary(hNtdll); + //传递参数,通过函数指针调用函数 + return _NtRaiseHardError(ErrorStatus, NumberOfParameters, UnicodeStringParameterMask, Parameters, ResponseOption, Response); +} + +int main() +{ + //先获取Shutdown特权 + if (!GetShutdownPrivilege()) + { + std::cout << "提权失败" << std::endl; + return -1; + } + HARDERROR_RESPONSE Resp; + //要制造蓝屏,我们只需要关注第一个参数和第五个参数 + //第一个参数是蓝屏代码,会在蓝屏界面中显示出来 + //第五个参数必须指定为OptionShutdownSystem + //第六个参数返回的Resp并不需要理会,因为这个函数执行后电脑已经蓝屏了 + //需要注意的是,第一个参数的蓝屏代码一旦超出范围就有可能导致无法正常蓝屏 + //0xc00000021a(x) + //0xc000021a(√) + return NtRaiseHardError(0xc000021a, 0, NULL, NULL, OptionShutdownSystem, &Resp); +} \ No newline at end of file diff --git a/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj b/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj new file mode 100644 index 0000000..6fbf8c4 --- /dev/null +++ b/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj @@ -0,0 +1,148 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {6896fda9-2a9c-4f53-ac12-0d5ce1c4bfa0} + NTV01Bluescreen + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + RequireAdministrator + + + + + + + + + \ No newline at end of file diff --git a/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj.filters b/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj.filters new file mode 100644 index 0000000..fe140aa --- /dev/null +++ b/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj.user b/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj.user new file mode 100644 index 0000000..0f14913 --- /dev/null +++ b/NTV_01_Bluescreen/NTV_01_Bluescreen/NTV_01_Bluescreen.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file