刚才,卡巴斯基实验室发现了我们之前本应该发现的一些情况—-老版本的Stuxnet包含一个文件(atmpsvcn.ocx)而这个文件在本质上同样是Flamer的插件。除此以外,Stuxnet和Flamer在代码上难道就完全不同么?
我正在查看Stuxnet PLC的钩子dll,s7otbxdx.dll,因为我需要提取出PLC MC7的字节码对象并用于其他工作。出于娱乐的目的我在IDA中又运行了在我前一篇博客中提到的Flamer解码脚本,令我格外惊讶的是,解码脚本发现Flamer的字符串解码函数也在s7otbxdx.dll中。
flamedec: IDAPython Flamer decryption tool. flamedec: (C) 2012 Snorre Fagerland, Norman ASA. ------------------------------------------------ flamedec: ANSI string decoder found at 10010bbf
来看一下代码,它们的相似性很明显了。Stuxnet的解码部分与Flamer都使用了同样的字符串存储格式,在偏移量8的位置是字节长度的加密标记,在偏移量9的位置是字长度的字符串长度,而字符串存储在偏移量为11的位置。在汇编语言中他们只有极小的差异,比如在解码后使用MOV代替AND来清除加密标记,但是从功能上来说他们是相同的。
点击图片查看完整对比图
跟进到解码循环的内部,我们看到它们在解码的功能实现上也是相同的。这是Stuxnet的版本:
void __cdecl Stuxnet__DecodeString(int a1, unsigned int a2) { unsigned int v2; // edi@1 v2 = 0; if ( a2 ) { do { *(_BYTE *)(v2 + a1) -= Stuxnet__GetKey(v2); ++v2; } while ( v2 < a2 ); } }
下面是Flamer的解码部分:
void __cdecl Flamer__SOAPR32_DecodeString(int a1, unsigned int a2) { unsigned int v2; // edi@1 v2 = 0; if ( a2 ) { do { *(_BYTE *)(v2 + a1) -= Flamer__SOAPR_GetKey(v2); ++v2; } while ( v2 < a2 ); } }
生成Key的函数对比如下:
点击图片查看完整对比图
它们看起来不同,但是事实上它们非常相似并且会生成相同的输出。为了这个例子,我升级了我的Flamer解码器并使用它对Stuxnet的一个组件进行解码:
flamedec: ANSI string decoder found at 10010bbf flamedec: Found decoding algorithm type 6 flamedec: New decryption loop. Using decryption function at 10010bbf flamedec: ------------------------------------------------------------ 1004206c : DP_RECV 10042088 : s7otbxsx.dll 100420cc : 6ES7 417 100420ac : 6ES7 315-2 10042c64 : s7otbxdx.dll 10042c88 : CCRtsLoader.exe 10042dfc : SOFTWARE\SIEMENS\SINEC\LogDevices 10042e34 : CP_TYPE 10043574 : advapi32.dll 10043540 : InitializeSecurityDescriptor 10043510 : SetSecurityDescriptorDacl
事实上Stuxnet和Flamer并不只在文件组件上相似,它们还包含非常多的相似功能的实现,可以猜测这两个项目共享着一份相同的源代码。他们也许由不同的团队开发,但是如果真是这样,这些组织应该也能够使用公有资源。
小编:工业级的黑客攻击要逐渐走上舞台了,随着各国对网络安全的重视,越来越多的正规军开始出现,看来信息战已经成为各国国防发展中不可缺少的一部分了。