TIA Portal 是西门子推出的自动化工具平台,也是S7系列PLC最为常用的组态软件。出于安全考虑,一些敏感的密钥,资源以及配置文件等经常会被加密,被打包到MPK(MetaPackage)文件中。为了提取MPK文件中的关键数据,必须对MPK的解包算法进行分析,本篇文章将会介绍如何对解包算法进行逆向分析以及解包算法的编写。
使用十六进制编辑软件打开MPK文件,可以很明显看到‘PK’文件头,这应该是一个ZIP压缩包。 尝试使用解压缩软件打开MPK文件,提示要输入密码: 接下来就需要找到解压缩密码,由于TIA软件大部分组件是使用C#编写的,所以可以使用dnspy进行调试分析,为了快速定位到关键地方,搜索”.mpk”字符串,跟踪调用链,找到了一个关键地方,如下图所示,压缩包的密码来源于s_var1: 继续跟踪s_var来源,可以看到是从一个native方法里面获取的。 该方法实现很简单,就是简单返回字符串,该字符串为:“SIEMENS_TIAP”,即为压缩包密码。 有了密码,通过解压缩软件进行一次解压尝试,如下图所示,密码竟然不对,一定是哪里出了一些问题。 再次从头分析了一遍,找到了解压缩用的库zlib128-tia.dll,该解压方法调用了标准的unzOpenCurrentFilePassword进行解压。众所周知,该方法使用的解密算法和常用的zip解密算法(PKZIP兼容的加解密算法)并不兼容,而且由于zlib提供的算法强度不够,导致容易被已知明文攻击,zlib组织已经宣布不在维护该算法标准。找到了原因之后,解决方法很简单,直接使用zlib提供的minizip进行带密码的解压缩,就可以解压成功。 解压结果如下:
使用十六进制编辑器再次打开解压后的文件,可以看到数据是以“x”开头的,很明显,又被压缩了一次: 使用zlib进行解压缩,但是解压缩失败了,看来应该没那么简单。 继续回到dnspy分析代码,这次发现了一个参数:s_Var2,这个应该是一个非常重要的参数,让我们继续往下分析。 跟踪s_Var2的来源,和密码一样,也是从native获取到的,该值为"<./>\r\n"。 显而易见,这应该是压缩字典,用于提高压缩率(在配置文件中"<./>\r\n"这些字符出现的频率很高)。 解决方法也很简单,在解压时加上dict参数"<./>\r\n",下面给出批量解压的代码:
简单地总结了上面算法流程,如下图所示: 前面已经非常详细描述了如何去解包mpk文件,对解包后的mpk文件进行分析发现mpk不仅存储大量重要的配置文件和资源文件,同时还有一些PLC通信过程中敏感的ECC加密公钥,如下所示: 内容如下:
通过上面的分析,我们分析了S7CommPlus协议中的ECC密钥的来源,并直接在MPK文件中提取了密钥。这也说明了不仅可以分析S7 PLC的固件,我们也可以通过分析上位组态软件来进一步进行安全性分析。
import
io
import
os
import
zlib
if
__name__
=
=
'__main__'
:
indir
=
r
'in'
outdir
=
r
'out'
for
path, subdirs, files
in
os.walk(indir):
for
filename
in
files:
infilename
=
path
+
os.sep
+
filename
size
=
os.path.getsize(infilename)
with
open
(infilename,
'rb'
) as inFile:
data
=
inFile.read()
inFile.close()
dic
=
b
"<./>\r\n"
obj
=
zlib.decompressobj(zdict
=
dic)
result
=
obj.decompress(data)
outfilename
=
outdir
+
os.sep
+
infilename.replace(indir, '',
1
)
print
(outfilename)
outPath,outFilename
=
os.path.split(outfilename)
if
not
os.path.exists(outPath):
os.makedirs(outPath)
with
open
(outfilename,
'wb'
) as outFile:
outFile.write(result)
outFile.close()
import
io
import
os
import
zlib
if
__name__
=
=
'__main__'
:
indir
=
r
'in'
outdir
=
r
'out'
for
path, subdirs, files
in
os.walk(indir):
for
filename
in
files:
infilename
=
path
+
os.sep
+
filename
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课