Stuxnet病毒是怎样“入侵”PLC的?

1.如何选择需要感染的plc。
stuxnet会根据目标系统的特点,使用不同的代码来感染plc。一个感染的序列包括了许多plc模块(代码模块和数据模块),用以注入plc来改变目标plc的行为。这个威胁包括了三个感染序列。其中两个非常相似,功能也相同,我们将其命名为序列a和b。第三个序列我们命名为序列c。stuxnet通过验证“指纹”来判断系统是否为计划攻击的目标。它会检查:plc种类/家族:只有cpu6es7-417和6es7-315-2会被感染。系统数据模块:sdb会被解析;根据他们包含的数据,感染进程会选择a,b或其它感染方式开始行动。当解析sdb时,代码会搜索这两个值是否存在--7050hand9500h;然后根据这两个数值的出现次数,选择序列a或b中的一种来感染plc。代码还会在sdb模块的50h子集中搜索字节序2ccb0001,这个字节序反映了通信处理器cp342-5(用作profibus-dp)是否存在。而选择序列c进行感染的条件则由其他因素构成。
2.感染方法。
stuxnet使用“代码插入”的感染方式。当stuxnet感染ob1时,它会执行以下行为:增加原始模块的大小;在模块开头写入恶意代码;在恶意代码后插入原始的ob1代码。stuxnet也会用类似于感染ob1的方式感染ob35。它会用自身来取代标准的协同处理器dp_recv代码块,然后在profibus(一个标准的用作分布式i/o的工业网络总线)中挂钩网络通信。利用a/b方法的感染步骤如下:检查plc类型;该类型必须为s7/315-2;检查sdb模块,判断应该写入序列a或b中的哪一个;找到dp_recv,将其复制到fc1869,并用stuxnet嵌入的一个恶意拷贝将其取代;在序列中写入恶意模块(总共20个),由stuxnet嵌入;感染ob1,令恶意代码可以在新的周期开始时执行;感染ob35,它将扮演“看门狗”的角色。
3.感染代码。
被注入ob1功能的代码是用来感染序列a和b的。这些序列包含了以下模块:代码块:fc1865至fc1874,fc1876至fc1880(注意:fc1869并非stuxnet的一部分,而是plc的dp_recv模块的一个拷贝);数据模块:db888至db891。序列a和b用dp_recv挂钩模块来拦截profibus中的数据包,并根据在这些模块中找到的数值,来构造其他的数据包并发送出去。这由一个复杂的状态机控制(状态机被建立在上面提到的fc模块中)。这个状态机可部分受控于数据块db890中的dll。在某些条件下,序列c会被写入一个plc。这个序列比a和b包含更多的模块:fc6055至fc6084;db8062,db8063;db8061,db8064至db8070(在运行中产生)。序列c主要为了将i/o信息读写入plc的内存文件映射的i/o区域,以及外围设备的i/o。程序a/b的控制流如下图所示,在之前的step7编辑器的截图中也有部分显示(数据模块fc1873)
4.rootkitstuxnetplcrootkit代码全部藏身于假冒的s7otbxdx.dll中。
为了不被plc所检测到,它至少需要应付以下情况:对自己的恶意数据模块的读请求;对受感染模块(ob1,ob35,dp_recv)的读请求;可能覆盖stuxnet自身代码的写请求。stuxnet包含了监测和拦截这些请求的代码,它会修改这些请求以保证stuxnet的plc代码不会被发现或被破坏。下面列出了几个stuxnet用被挂钩的导出命令来应付这些情况的例子:s7blk_read:监测读请求,而后stuxnet会返回:真实请求的dp_recv(保存为fv1869);错误信息,如果读请求会涉及到它的恶意模块;ob1或ob35的干净版本的拷贝s7blk_write:监测关于ob1/ob35的写请求,以保证他们的新版本也会被感染。s7blk_findfirst/s7blk_findnext:这些例程被用于枚举plc中的模块。恶意模块会被自动跳过。s7blk_delete:监测对模块的“删除”操作。如上文所述,stuxnet是一个非常复杂的威胁,而其中的plc感染代码令问题更加难以解决。