zoukankan      html  css  js  c++  java
  • 系统蓝屏的几种姿势,确定不了解下么?

    前言

    蓝屏(BSOD)转储设置,看本文就够了! 这篇文章里比较详细的介绍了蓝屏转储设置。做好设置后,我们就可以在需要的时候使系统蓝屏了。这样我们就可以拿到一份系统转储,供我们分析问题了。本文介绍几种可以使系统蓝屏的办法。当然肯定还有其它办法,如果哪位小伙伴儿知道比较实用的方法,欢迎留言分享。

    几种蓝屏方法

    • 通过驱动

      思路是:在内核执行有问题的代码(比如,在驱动的入口处加上简单的 int* p = 0; *p = 0; ,然后加载有问题的驱动即可)。sysinternals 系列工具中的 NotMyFault 就是加载驱动,然后在驱动中模拟各种非法操作来使系统蓝屏的。

      NotMyFault

      我们可以点击 Colors... 按钮,来看看其它颜色的 “蓝屏” 效果。可以通过 Hang 让系统挂起,还可以通过 Leak 模拟内核级内存泄漏。

      我们还可以在命令行执行 notMyfault.exe /crash 来直接使系统蓝屏。如果我们想指定崩溃类型,可以使用 NotMyFault 的命令行版本 —— notmyfaultc.exe。具体选项大家可以直接运行 notmyfaultc.exe 查看或者参考下图:

      NotMyFaultC-Usage

    • 杀死系统关键进程

      如果系统关键进程挂掉了(比如,csrss.exe),那么系统也会蓝屏。

      kill-csrss-bsod-screen-record

      win7 系统中,具有管理员权限的进程可以杀死 csrss 进程,但是在 win10 中不能简单粗暴的杀死 csrss 进程了。

      can-not-terminate-csrss-on-win10

      win10 变通方法: 我们可以把其它进程设置为系统关键进程,然后杀掉。或者伪装成系统关键进程,然后自动退出。感谢 https://bytecode77.com/hacking/payloads/bsod

      int _tmain(int argc, _TCHAR* argv[])
      {
          typedef NTSTATUS (*pfnRtlSetProcessIsCritical) (BOOLEAN, PBOOLEAN, BOOLEAN); // __cdecl
          typedef BOOL(WINAPI * pfnRtlAdjustPrivilege) (ULONG, BOOL, BOOL, PBOOLEAN);
          auto ntdll = ::LoadLibrary(TEXT("ntdll.dll"));
          auto RtlAdjustPrivilege = (pfnRtlAdjustPrivilege)GetProcAddress((HINSTANCE)ntdll, "RtlAdjustPrivilege");
          auto RtlSetProcessIsCritical = (pfnRtlSetProcessIsCritical)GetProcAddress((HINSTANCE)ntdll, "RtlSetProcessIsCritical");
      
          BOOLEAN e = 0;
          RtlAdjustPrivilege(20, 1, 0, &e);
          RtlSetProcessIsCritical(1, 0, 0);
      
          return 0;
      }

      关键进程结束导致蓝屏

    • 使用快捷键

      如果系统由于某些原因挂起了,我们没办法杀死系统关键进程,也不能运行 NotMyFault 了。这时候我们还可以通过快捷键来使系统蓝屏!不过我们需要预先做一些设置才行。把下面的代码保存到 .reg 文件,然后双击导入注册表,重启生效

      Windows Registry Editor Version 5.00
      
      ;------------------------------------------------------------------------------
      ; enable BSOD by right CTRL + SCROLL + SCROLL 
      ;------------------------------------------------------------------------------
      ; For PS/2 keyboards
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesi8042prtParameters]
      "CrashOnCtrlScroll"=dword:00000001
      
      ; For USB keyboards
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceskbdhidParameters]
      "CrashOnCtrlScroll"=dword:00000001
      
      ; For Hyper-V keyboards (BCN:I never use this, copy it from document)
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceshyperkbdParameters]
      "CrashOnCtrlScroll"=dword:00000001

      重启后,按住右侧Ctrl 键,然后按两下 SCROLL LOCK 键就可以使系统蓝屏了。这个方法在极少数的情况下会失效。比如,系统挂起在更高的中断请求级别(IRQL),没办法处理按键。不过,我们应该没那么点背。正如微软官方文档介绍的那样,有时候即使 CTRL+ALT+DELETE 不响应了,RCTRL + SCROLL + SCROLL 还能工作。

      如果键盘上没有 Scroll Lock 键,怎么办?

    • 使用自定义快捷键

      也许有的小伙伴使用的笔记本电脑的键盘上没有 Scroll Lock 键,该怎么办呢?Windows 已经考虑到了这种情况,允许我们自定义蓝屏快捷键。具体设置可以参考 微软官方文档 —— Forcing a System Crash from the Keyboard 。保存下面的代码到 .reg 文件,双击导入注册表,重启生效

      Windows Registry Editor Version 5.00
      
      ;------------------------------------------------------------------------------
      ; enable BSOD by custom key, mutually exclusive with CrashOnCtrlScroll setting
      ; Dump1Keys: 20 stands for LEFT CTRL
      ; Dump2Key:  HEXadecimal INDEX in keyToScanTbl[134]
      ;            01 stands for `/~ key (left of 1/! key)
      ;            3d stands for space key.
      ;            1f stands for A key. but after test, ctrl + a will not work. 
      ;            WARNING: not sure this works for all keyboards, try your luck :)
      ;------------------------------------------------------------------------------
      
      ; For PS/2 keyboards
      ; disable CrashOnCtrlScroll first
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesi8042prtParameters]
      "CrashOnCtrlScroll"=-
      
      ; setup custom key
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesi8042prtcrashdump]
      "Dump1Keys"=dword:00000020
      "Dump2Key"=dword:00000001
      
      ; For USB keyboards
      ; disable CrashOnCtrlScroll first
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceskbdhidParameters]
      "CrashOnCtrlScroll"=-
      
      ; setup custom key
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceskbdhidcrashdump]
      "Dump1Keys"=dword:00000020
      "Dump2Key"=dword:00000001
      
      ; For Hyper-V keyboards (BCN:I never use this, reference above setting)
      ; disable CrashOnCtrlScroll first
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceshyperkbdParameters]
      "CrashOnCtrlScroll"=-
      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServiceshyperkbdcrashdump]
      "Dump1Keys"=dword:00000020
      "Dump2Key"=dword:00000001
      

      重启后,按住左侧Ctrl 键,然后连续按两下 ` 键就可以使系统蓝屏了。注意:一定要连续按两下! 按一下是不行的。

      想要正确设置自定义蓝屏快捷键,不是一件容易的事。需要了解以下几点:

      1. 使用自定义快捷键需要先关闭 CrashOnCtrlScroll 设置,上面的代码已经做好了。

      2. 因为不同类型的键盘对应的注册表位置不一样,怎么知道自己的机器上的键盘是哪种类型的?

        我们可以打开设备管理器,查看当前机器上的键盘信息。设备管理器——键盘设备

        我们可以用如下方法打开 设备管理器

        • win10 系统中,可以直接在搜索框(或者按一下 windows 键)输入 设备管理器 搜索打开。

        • win10 系统中,按 Windows + x 快捷键,在弹出的系统菜单里点击 设备管理器(M) 打开。

        • 输入 devmgmt.msc 打开。

        • 通过控制面版打开(不同系统中可能不一样)。
          control-panel-device-manager

        • 还有很多其它方法,不一一列举了。

      3. Dump1Keys 的值可以是组合值,比如,0x70 表示同时按下左侧的 ALT + CTRL + SHIFT。每一项的意义请参考下表(摘自微软官方文档):

      意义
      0x01 Rightmost SHIFT key
      0x02 Rightmost CTRL key
      0x04 Rightmost ALT key
      0x10 Leftmost SHIFT key
      0x20 Leftmost CTRL key
      0x40 Leftmost ALT key
      1. Dump2Key 是按键的扫描码在数组 keyToScanTbl[134] 中的索引值keyToScanTbl[134]的定义如下(摘自微软官方文档):
      const UCHAR keyToScanTbl[134] = { 
              0x00,0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
              0x0A,0x0B,0x0C,0x0D,0x7D,0x0E,0x0F,0x10,0x11,0x12,
              0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x00,
              0x3A,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,
              0x27,0x28,0x2B,0x1C,0x2A,0x00,0x2C,0x2D,0x2E,0x2F,
              0x30,0x31,0x32,0x33,0x34,0x35,0x73,0x36,0x1D,0x00,
              0x38,0x39,0xB8,0x00,0x9D,0x00,0x00,0x00,0x00,0x00,
              0x00,0x00,0x00,0x00,0x00,0xD2,0xD3,0x00,0x00,0xCB,
              0xC7,0xCF,0x00,0xC8,0xD0,0xC9,0xD1,0x00,0x00,0xCD,
              0x45,0x47,0x4B,0x4F,0x00,0xB5,0x48,0x4C,0x50,0x52,
              0x37,0x49,0x4D,0x51,0x53,0x4A,0x4E,0x00,0x9C,0x00,
              0x01,0x00,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,
              0x43,0x44,0x57,0x58,0x00,0x46,0x00,0x00,0x00,0x00,
              0x00,0x7B,0x79,0x70 };

      上面的例子中,` 键的扫描码是 0x29,在keyToScanTbl[134]的索引是 1

      1. 关于扫描码,按下和抬起按键时会产生不同的扫描码,我们需要关注的是按下时对应的扫描码。同时,不同的键盘可能有不同的扫描码。下面给出 101/102键 键盘(PC/AT 和 PS/2) 的扫描码。

        101/102键 键盘(PC/AT 和 PS/2)图,摘自Defrag-Tools-179

      2. 我们参考相关文档的时候需要注意 按下按键对应的术语是(Make),抬起按键对应的术语是(Break)。下面贴一张扫描码表的部分截图:扫描码对照表

        表格最后的说明非常重要:

        scancode-translation-table-note

        高亮部分的意思是:操作系统的其它部分和所有的应用程序按 Scan Code Set 1 里的值处理扫描码。所以我猜测微软官方文档里的 keyToScanTbl[134] 的值是按照 Scan Code Set 1 给出的。实在没精力调查的更清楚了,如果哪位小伙伴儿熟悉相关内容,请务必指点!我特意录制了使用自定义快捷键 CTRL + ` + ` 触发蓝屏的过程。按一次 ` 是不行的,一定要按两次

    使用 CTRL +  手动蓝屏
    使用 CTRL + 手动蓝屏

    • 借助硬件

      如果以上方法都行不通,还可以使用 PCI Express Dump Switch Card 使系统蓝屏,Windows 7, Windows Server 2008 R2 及更早的系统需要设置如下注册表项:

      [HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlCrashControl]
      "NMICrashDump"=dword:00000001
    • 内核调试器

      如果已经用内核调试器附加到目标系统了,我们可以直接使用 .dump 命令保存转储文件,没必要使系统蓝屏再保存转储文件。当然,如果我们喜欢,也可以使用 .crash 命令使系统蓝屏,如果执行完该命令后,系统没蓝屏,请执行 g 命令。**说明:**如果当前正在执行 bug check处理函数,不要使用 .crash 命令。

      注意:

      需要双机内核调试的时候才行。在本地内核调试的时候,不能使用 .dump 命令,也不能使用 .crash 命令!真是个坏消息!!!

    • 其它

    蓝屏转储一瞥

    杀死系统关键进程导致的蓝屏,对应的 Bug Check Code0xF4(CRITICAL_OBJECT_TERMINATION)。 通过 NMI 导致的蓝屏,对应的 Bug Check Code0x80(NMI_HARDWARE_FAILURE),表示这个蓝屏是由于硬件错误触发的。通过系统快捷键导致的蓝屏,对应的 Bug Check Code0xe2(MANUALLY_INITIATED_CRASH),表示这个蓝屏是用户手动触发的。

    我们可以用 !analyze -show 来查看转储文件中的 bug check code 信息。

    windbg !analyze -show & k
    windbg !analyze -show & k

    从输出结果可知,这个蓝屏是用户手动触发蓝屏产生的。从调用栈可知,是 i8042prt.sys 处理了我们的按键,从而导致的蓝屏。

    友情提示:

    如果直接用 windbg 打开 %SystemRoot%MEMORY.DMP 会提示权限不够。可以以管理员权限运行 windbg 后再打开。或者拷贝转储文件到其它目录后再打开即可。注意一定是拷贝,而不是剪切

    windbg 打开 MEMORY.dmp 失败

    总结

    • 特殊情况下,我们可能会主动使系统蓝屏来保存一份转储文件,供我们事后分析。
    • 我们可以通过本文介绍的几种方法来使系统蓝屏。我个人偏向使用 NotMyFault 或者蓝屏快捷键使系统蓝屏。
    • 使用自定义的蓝屏快捷键的时候,需要关闭 CrashOnCtrlScroll 设置。
    • Dump1Keys 的值可以是组合值,比如,0x70 表示同时按下左侧的 ALT + CTRL + SHIFT
    • Dump2Key 的值是对应按键的扫描码在数组 keyToScanTbl[134] 中的索引值,而且是 16 进制的。
    • 需要连续按两次设置的按键才能蓝屏!比如,我们需要按 CTRL + ` + `,而不是 CTRL + `
    • 尽量不要设置已经被占用的快捷键。我尝试使用 CTRL + A + A 作为快捷键,但是不能触发蓝屏,猜测是因为 CTRL + A 被占用了。但是 ALT + CTRL+ SHIFT + A + A 是可以的。
    • windbg 中通过 !analyze -show 可以查看转储文件中的 bug check code 信息。
    • 对于手动蓝屏得到的转储文件,使用 !analyze -v 不能得到更多有效的信息,我们需要分析转储文件中的其它信息。
    • %SystemRoot%MEMORY.DMP 需要管理员权限才能打开,可以拷贝(而不是剪切)一份到其它目录,就可以正常打开了。

    参考资料

  • 相关阅读:
    Array对象
    属性描述对象
    Object对象
    console对象与控制台
    编程风格
    错误处理机制
    13、百钱买百鸡之数学优化
    12、c程序中编程,统计一行中数字字符的个数。
    10、输入某年某月某日,判断这一天是这一年的第几天?
    9、c语言输入一个整数怎么分别输出它的每位上的数字
  • 原文地址:https://www.cnblogs.com/bianchengnan/p/12375664.html
Copyright © 2011-2022 走看看