标题：超级工厂病毒
名词简介：
Stuxnet又名“震网”，是针对微软件系统以及西门子工业系统的最新病毒，目前已感染多个国家及地区的工业系统和个人用户，此病毒可通过网络传播，与以往病毒不同，其代码非常精密 　曾造成伊朗核电站推迟发电的全球首个“超级工厂病毒”Stuxnet目前已经侵入我国。瑞星昨日发布的预警显示，国内已有近500万网民及多个行业的领军企业遭Stuxnet蠕虫病毒攻击，而且由于安全制度上的缺失，该病毒还存在很高的大规模传播风险。 　据瑞星安全专家介绍，Stuxnet蠕虫病毒是世界上首个专门针对工业控制系统编写的破坏性病毒，能够利用对windows系统和西门子SIMATIC WinCC系统的7个漏洞进行攻击。特别是针对西门子公司的SIMATIC WinCC监控与数据采集 (SCADA) 系统进行攻击，由于该系统在我国的多个重要行业应用广泛，被用来进行钢铁、电力、能源、化工等重要行业的人机交互与监控。 　Stuxnet及其变种是一种利用最新的Windows Shell漏洞传播恶意文件的蠕虫。造成这个漏洞的原因是Windows 错误地分析快捷方式，当用户单击特制快捷方式的显示图标时可能执行恶意代码（文件带有.LNK扩展名）。[1]
安全建议
由于Stuxnet蠕虫病毒是首个针对工业控制系统编写的破坏性病毒，对大型工业、企业用户存在一定的风险，所以，冠群金辰公司病毒防护专家给企业用户提出如下安全防护建议，以提高企业抵御未知安全风险的能力： 
在终端设备上开启防火墙功能。 
为终端设备上所有的应用系统安装最新的补丁程序。 
在终端上安装防病毒系统，设置为实时更新病毒库，并将病毒库升级到最新版本。 
在终端上的用户设置最小用户权限。 
在打开附件或通过网络接收文件时，弹出安全警告或提示。 
在打开网络链接时，发出安全警告或提示。 
尽量避免下载未知的软件或程序。 
使用强口令，以保护系统免受攻击。
两个月前，赛门铁克首次披露了W32.Stuxnet针对工业生产控制系统(ICS) 进行攻击，如应用于管道和核动力工厂的控制系统。读者可参见赛门铁克2010年7月19日的博客– “W32.Stuxnet 攻击微软零日漏洞利用USB设备大肆传播”。
2010年9月29日，我们还将在Virus Bulletin 会议上发布一篇包含W32.Stuxnet详尽技术细节的论文。同时我们也注意到，最近非常多的人开始对Stuxnet感染系统且不易检测的事情表示关注。
由于Stuxnet针对某个特定的工业生产控制系统进行攻击，而这些行为不会在测试环境中出现，因此在测试环境下观察到的病毒行为不全面，很可能产生误导。事实上，运行后，Stuxnet会立即尝试进入一个可编程逻辑控制器(PLC) 的数据块—DB890。这个数据块其实是Stuxnet自己加的，并不属于目标系统本身。Stuxnet 会监测并向这个模块里写入数据，以根据情况和需求实时改变PLC的流程。
在这篇博客里，我们会深入探讨Stuxnet的PLC感染方式和Rootkit功能，特别是以下几个方面：
它如何选择作为攻击目标的工业生产控制系统；感染PLC代码块的方法；注入PLC的恶意代码；在被感染Windows机器中的PLC Rootkit代码。 这四点我们会分开讲，因为用来实现这些目的的代码差异很大。
Stuxnet的目的是通过修改PLC来改变工业生产控制系统的行为，包括拦截发送给PLC的读/写请求，以此判断系统是否为潜在的攻击目标；修改现有的PLC代码块，并往PLC中写入新的代码块；利用Rootkit功能隐藏PLC感染，躲避PLC管理员或程序员的检测。这些任务之间差别很大，比如，在被感染的Windows 机器中隐藏感染代码使用的是标准的C/C++ 代码，而Stuxnet 试图在工业生产控制系统及PLC中执行的恶意代码则是用MC7字节码写的。MC7 是PLC 环境中运行的一种汇编语言，并常用STL 进行编写。
在讨论Stuxnet攻击PLC的技术之前，让我们先来看看PLC是如何访问和编写的。
  要进入PLC, 首先需要安装特殊的软件；Stuxnet 会专门针对编写PLC某些模块的WinCC/Step 7软件进行攻击。安装这些软件后，程序员可以通过数据线连接PLC，以访问其中的内容，重新配置PLC，下载程序至PLC，或调试之前加载的代码。一旦PLC被配置和编译后，Windows机器就可以断开和PLC的联系了，PLC会自行运行。为了使您有一个更直观的感受，下图显示了在实际操作中，实验室里一些基本的设备配置：
  下面的截图显示了Step7 STL编译器中Stuxnet恶意代码的一部分。其中，编写Stuxnet功能代码块的MC7代码的开始部分是可视的；下面显示的代码来自于反汇编后的FC1873模块。
  Step 7 软件使用库文件s7otbxdx.dll 来和PLC通信。当Step7 程序准备进入PLC时，它会调用该DLL文件中不同的例程。例如，如果一个代码块需要用Step 7从PLC中读出，那么，例程s7blk_read就会被调用到。s7otbxdx.dll中的代码会进入PLC, 读出其中的代码，并把它传回Step 7程序，如下图所示：
  现在让我们看看当Stuxnet是如何进入PLC的。运行后，Stuxnet会将原始的s7otbxdx.dll文件重命名为s7otbxsx.dll。然后，它将用自身取代原始的DLL文件。现在，Stuxnet就可以拦截任何来自其他软件的访问PLC的命令。
  被Stuxnet修改后的s7otbxdx.dll 文件保留了原来的导出表，导出函数为109个，这就令Stuxnet可以应付所有相同的请求。大部分导出命令会转发给真正的DLL，即重命名后的s7otbxsx.dll，并不会出现什么难对付的状况；事实上，109种导出形式中的93种都会照这样处理。然而，真正的“诡计”使用在剩下的16种导出命令中。这16种导出不会被简单的转发，而是被改动后的DLL 拦截了。被拦截的导出命令为在PLC中读、写、定位代码块的例程。通过拦截这些请求，Stuxnet 可以在PLC 管理员没有察觉的情况下，修改发送至PLC 或从PLC返回的数据。同时，通过利用这些例程，Stuxnet 可以将恶意代码隐藏在PLC 中。
为了更好的了解Stuxnet 如何进入和感染PLC，我们先来看看各种类型的数据。PLC 会处理由管理员加载到PLC的代码和数据。这里，我们将简要介绍一下最常见的模块和他们的功能：
数据模块(DB)包含了程序相关的数据，比如数字，结构等。系统数据模块(SDB) 包含了PLC 的配置信息； 它们是根据连接到PLC 的硬件模块的数量/种类设立的。组织模块(OB) 是程序的入口。他们由CPU 循环执行。针对Stuxnet， 有两个特别需要的OB:OB1 是PLC 程序的入口。它没有特别的时间要求，总是循环执行。OB35 是一个标准的“看门狗”模块，系统会每100ms执行一次。这个功能可能包含了所有用于监控紧要输入的逻辑，以达到立即响应，执行功能的目的。功能模块（FC）都是标准的代码快。它们包含了会被PLC 执行的代码。一般说来，OB1模块会引用至少一个FC 模块。下面的部分会详细讲述之前提到的威胁的四大方面。
感染原理
1. 如何选择PLCStuxnet会根据目标系统的特点，使用不同的代码来感染PLC。
一个感染的序列包括了许多PLC 模块（代码模块和数据模块），用以注入PLC来改变目标PLC 的行为。这个威胁包括了三个感染序列。其中两个非常相似，功能也相同，我们将其命名为序列A和B。第三个序列我们命名为序列C。Stuxnet通过验证“指纹”来判断系统是否为计划攻击的目标。它会检查：
PLC种类/家族：只有CPU 6ES7-417 和6ES7-315-2 会被感染。系统数据模块：SDB 会被解析；根据他们包含的数据，感染进程会选择A,B或其它感染方式开始行动。当解析SDB 时，代码会搜索这两个值是否存在-- 7050h and 9500h；然后根据这两个数值的出现次数，选择序列A 或B 中的一种来感染PLC。 代码还会在SDB 模块的50h 子集中搜索字节序2C CB 00 01, 这个字节序反映了通信处理器CP 342-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）:
  而序列C 的程序流则更加复杂，可以从下面的图表中看到:
  4. Rootkit
Stuxnet PLC rootkit代码全部藏身于假冒的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 感染代码令问题更加难以解决。仅仅关于注入的MC7代码（我们于几个月前通过逆向工程获得）就可以讨论很久。