首页
社区
课程
招聘
[原创]西门子TIA MPK文件解包分析
发表于: 2021-1-5 16:39 7446

[原创]西门子TIA MPK文件解包分析

2021-1-5 16:39
7446

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的固件,我们也可以通过分析上位组态软件来进一步进行安全性分析。

#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()
#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

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 3
支持
分享
最新回复 (8)
雪    币: 26205
活跃值: (63302)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
感谢分享!
2021-1-6 16:06
0
雪    币: 1319
活跃值: (1960)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享!
2021-1-6 16:14
0
雪    币: 143
活跃值: (861)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
厉害
2021-1-8 14:23
0
雪    币: 14539
活跃值: (17553)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
5
mark,请问楼主目前是不是大部分固件都像你文中的固件一样做了强加密?
2021-1-8 14:52
0
雪    币: 10880
活跃值: (14674)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
6
pureGavin mark,请问楼主目前是不是大部分固件都像你文中的固件一样做了强加密?
就工控中的控制器来说,一般都作了加密,其他IoT设备只要开发有安全意识应该也会加密的。尤其是版权意识高的,比如爱快这些,都会加密。
2021-1-8 15:45
0
雪    币: 235
活跃值: (214)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
陈师傅厉害
2021-3-16 17:09
0
雪    币: 203
活跃值: (273)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
Thanks very much !!!!!
2021-4-21 07:09
0
雪    币: 206
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
谢谢分享
2021-4-21 10:26
0
游客
登录 | 注册 方可回帖
返回
//