这是C++语言中一个由于空指针错误导致的内存安全问题。
作为一名专业的C++程序员,我将为你解析这个堆栈跟踪信息。
计算机内存被组织成一个巨大的数字数组,我们在这里用十六进制表示这些数字,因为它更容易处理。
问题出在计算机试图读取内存地址0x9c(也就是156)。这个区域对任何程序来说都是无效的。任何试图从这个区域读取的程序都会被Windows立即终止。
这就是你在堆栈跟踪中看到的情况。
那么,为什么会出现尝试读取内存地址0x9c的情况呢?这是因为程序员的错误。
C++,Crowdstrike使用的语言,使用地址0x0作为一个特殊值,表示“这里什么都没有”,如果尝试访问它,程序将会崩溃。
程序员在C++中传递对象时应该检查这个空指针。
通常,代码看起来像这样:
string* p = get_name();
if (p == NULL) { print("Could not get name"); }
这里的string*表示我们有一个指向字符串开始的“指针”。如果它是空的,那就表示那里没有数据,不应该尝试访问。
让我们以一个包含数据的通用对象为例:
struct Obj {
int a;
int b;
};
如果我们创建一个指向它的指针:
Obj* obj = new Obj();
我们可以获取它的起始地址,假设是随机的,比如0x9030。
然后地址是:
obj is 0x9030
obj->a is 0x9030 + 0x4
obj->b is 0x9030 + 0x8
每个成员都是从起始地址开始的偏移量。
现在,如果假设:
Obj* obj = NULL;
那么地址是:
obj is 0
obj->a is 0 + 4
obj->b is 0 + 8
如果我在空指针上这样做:
print(obj->a);
程序就会像上面看到的那样产生堆栈转储。它无法读取地址0x000000004的值。
在这个堆栈转储中,你看到它试图读取内存值0x9c。换算成十进制,这是值156。
发生的事情是程序员忘记检查他正在处理的对象是否有效,它试图访问对象的成员变量...
空指针加上0x9C得到的是0x9C,也就是156。
这是一个无效的内存区域。
这很糟糕,因为这是一个特殊的程序,叫做系统驱动程序,它对计算机有特权访问。因此操作系统被迫立即出于极度谨慎而崩溃。
这就是导致蓝屏死机的原因。计算机可以从非特权代码的崩溃中恢复,只需简单地终止程序,但系统驱动程序不行。当你的电脑崩溃时,95%的时间是因为系统驱动程序崩溃。
如果程序员进行了空指针检查,或者如果他们使用了可以自动检查这类问题的现代工具,这个问题本可以被避免。但不知何故它被部署到了生产环境,然后被Crowdstrike作为强制更新推送... 意外!
未来的解决方案是,微软需要有更严格的政策来回滚有缺陷的驱动程序,避免向客户推送冒险的更新。
Crowdstrike可能会提升他们的代码安全官,并引入代码安全检查工具来自动捕获这类问题。
Crowdstrike可能会认真考虑将他们的系统驱动程序从C++重写为像Rust这样的更现代的语言,后者没有这个问题。
对于那些寻找阴谋的人来说,C++的替代语言Rust,被一些人认为受到了一些具有特定意识形态的人的影响。
这可能是一个将关键任务代码转移到Rust的计划。它是Linux除了C之外唯一允许的语言。但真相如何,我们无从得知。
原文地址 :
https://threadreaderapp.com/thread/1814376668095754753.html?utm_campaign=topunroll
原文始发于微信公众号(独眼情报):crowdstrike蓝屏事件的代码分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论