当地时间7月19日,全世界只要部署了Crowdstrike安全软件的计算机系统都发生了蓝屏死机。嗯。。。这公司名字就起的很好,“Crowdstrike”,属于是实现公司理想了

谁能想到,windows有史以来最严重的大面积瘫痪,罪魁祸首竟然是“安全软件”(保安打晕了小区所有的人)

谁能想到,windows有史以来最严重的大面积瘫痪,罪魁祸首竟然是“安全软件”(保安打晕了小区所有的人)

成因分析:

Crowdstrike Falcon会安装一个名为“Falcon Sensor(猎鹰传感器)”的轻量级工具。猎鹰传感器会安装服务,但最重要的是它会加载驱动程序—它们以内核模式运行,使用系统回调监控系统活动。这基本上是所有安全软件的常见做法

一般如果是常规应用程序崩溃,我们可以再次双击启动它就可以了,并不会导致电脑无法运行 - 因为它处于用户模式。但由于 Falcon 传感器在内核模式下运行,可以理解成和Windows系统内核在一个内存空间里面,所以如果驱动程序发生一点点错误,比如对一个不正确的地址进行读写都会导致电脑蓝屏死机,这变相也是微软的保护措施之一,就怕你的驱动在内核层乱搞


对于 Falcon 传感器,故障驱动程序的文件名以“C-00000291”开头,以 .sys 结尾。故障驱动程序更新本身导致内核崩溃。根据崩溃转储文件的堆栈跟踪,驱动程序似乎对 0x9c无效地址进行了读写

为什么地址会是0x9c?在c/cpp编程范式里会大量用到结构体/对象,如下所示:

struct Obj { int a; int b; };

如果创建一个指向它的指针Obj* obj = new Obj();

假如创建对象成功,obj的地址是0xffff,8800,那么寻址结构体成员就是:

obj->a 是 0xffff,8800 + 0x4 

obj->b 是 0xffff,8800 + 0x8 

这是每个成员都是距离起始地址的偏移量,因为是int类型,所以是4个字节步长

那么假如Obj* obj = NULL; 也就是0x00000000000;那么:

obj- > a 是 0 + 4 

obj- > b 是 0 + 8 

所以如果对 NULL 指针执行此操作:进行任何访问读写,例如NtReadVirtualMemory(obj- > a); 

程序崩溃转储就会如上所示。它无法读取值 0x000000004,

显然,这是一个非常低级的错误,程序员没有检查NULL,部署之前没经过测试吗?

修复办法:

由于设备驱动程序在计算机启动时加载,这会导致Windows进入恢复模式。唯一的解决方法是:进入安全模式,并从C:\Windows\System32\drivers\Crowdstrike目录中删除C-00000291*.sys(基本上是所有以“C-00000291”开头的“.sys”文件)

最后通过此次事件我们可以看出驱动开发的复杂性和挑战性。驱动程序开发与普通应用程序开发不同,因为驱动程序直接与操作系统内核交互,处理硬件设备的低级操作。这种高度敏感的环境要求驱动程序必须非常稳定和可靠,任何小的错误都可能导致系统崩溃或蓝屏死机

Crowdstrike Falcon 传感器因驱动程序的一个小错误导致系统蓝屏死机,提醒我们驱动开发并非易事。驱动程序直接与操作系统内核交互,处理硬件设备的低级操作,任何细小的错误都可能导致严重的系统问题。