一、背景
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”,下面给出批量解压的代码:
#coding=UTF-8
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()
四、解包MPK
简单地总结了上面算法流程,如下图所示:
前面已经非常详细描述了如何去解包mpk文件,对解包后的mpk文件进行分析发现mpk不仅存储大量重要的配置文件和资源文件,同时还有一些PLC通信过程中敏感的ECC加密公钥,如下所示:
内容如下:
五、总结
解包mpk过程虽然简单,但是分析过程还得需要有足够的耐心。通过解包mpk文件,可以查看或者修改一些关键的敏感信息,为分析TIA的安全性打好基础。