QQ登录

只需一步,快速开始

步科PKG文件禁止反编译破解及工程文件解密方法研究

  [ 复制链接 ]
0.开场吐槽。
xxx到此一游。
写此帖子,心态一样,搞技术的都爱炫耀,身怕老板同事不知道。
其实经历的多了,这些都是忌讳。

步科在我没用过也没听过是什么之前,总跟科比关联起来。
后来有一年,有几个老设备,客户找上门说要改造升级,我才在网络找些资料了解。
设备控制,屏是步科的触摸屏,触摸屏连接的是台达的PLC。
两者连上电脑一上传,好家伙,都给禁止了,这是要重写的节奏啊?
台达的PLC倒是有见过也用过,破解早也有研究过,小意思,禁止上传捣鼓一个硬件分分钟钟的事。
小日本的东西,或是台湾的产品,这些工程师在设置硬件保护功能时都不太了解中国人智商,
总觉得自己技术牛的一逼或是啥原因,总爱留一手(比如留个超级密码),也不知是为好售后服务还是啥,
结果在中国市场,不管是触摸屏也好,还是PLC也摆,产品全线沦丧,一 一被破解。
中国人但到是很了解中国人,国产的品牌在保护方面基本都是把后路做死。
比如禁止上传,你尝试几次密码错误,直接硬件锁死无法用,寄厂维修。
比如禁止反编译,直接将全部工程文件,图片啥的删除,仅留下几KB的二进制文件给你下载到硬件。
比如加密的,算法直接用老美军用的,算法不可逆,结果不可逆,只能一个个输入密码试,
密码错误超过几次,直接提示都不弹,就把你硬件锁死。

1.步科是什么?
步科是什么?网络上一查,步科也就是一个中国的公司。
它自己给自己取了个英文名叫Kinco。

可以找到官网,说明还是挺正规的。
看公司图片,也就一栋楼,占地不大,给人印象就是一个小老板开的。
网上介绍说早期是台湾威纶的代理商,后面自己独立出来做了硬件研发与销售。
其触摸屏编程软件在使用上都跟威纶的相似, 我后面自己用了后,
软件灰头土脸的,XP时代的产品。
控件属性倒是有威纶影子,我对威纶倒是挺熟悉,在软件设计使用上,这点可以对比对比。
熟悉威纶,反过来再使用步科,可以很快上手。

下面是官网上对它自己的介绍:
上海布克自动化有限公司专注于工业自动化设备控制核心部件,
和工业物联网/互联网软硬件的研发、生产、销售及相关技术服务,为客户提供设备自动化控制,
数字化工厂和工业互联网解决方案,是中国为数不多的机器自动化和工厂智能解决方案供应商之一。
公司自动化设备控制核心部件主要包括工业人机界面、伺服系统、步进系统、可编程控制器、变频器等,
广泛应用于物流设备、机器人、包装设备、食品设备、服装设备、医疗设备等,
环保设备、轨道交通设备等自动化设备行业。
工业物联网/互联网软硬件产品主要包括现场智能终端、网关、数据采集器、SaaS软件、数据中心等,
主要用于食品、服装等行业的数字化化工厂建设和产销协同制造。


本想多找些步科触摸屏的相关资料,比如编程软件,用户手册,视频教程,通讯线制作,编程手册啥的。
发现很少,基本都是没用信息,编程软件也只在官网找到,旧一点的也看不见。
看到一些帖子也是网友早些年发的。

比如让我眼睛一亮的标题:
步科触摸屏如何破解-CSDN论坛(回复:2019年3月2日 抓时序,看数据)
步科文件反编译pkg反编译步科文件解密步.
INCO解密【plc解密吧】 - 百度贴吧.
步科触摸屏解密软件_步科破解,步科触摸屏破解软件-互联网
有没有步科MT4300C触摸屏密码锁破解软件啊?跪求! - 百度知道.
步科触摸屏解密软件_步科触摸屏解密-互联网工具类资源-CSD.

点击进去,
是提问的帖子基本没人回,或是回复无解。
是破解软件下载站的,下载下来,不是报毒就是不能用,
想想也是,这年头谁都唯利是图,做啥事都要成本,做公益都得饿死。
是文章的,直接空空如也,都是黄牛发的广告,
什么西门子可破啊,三菱可破啊的标题,唯独没找到步科相关信息,
看来只有靠自己花时间来研究了。

2.先熟悉步科工程目录。
开始编程或破解研究,先建立一个Kinco触摸屏的程序,了解一下程序文件夹结构。
我打开步科触摸屏编程软件HMIWare v2.5。

步科触摸屏编程软件HMIWare v2.5

步科触摸屏编程软件HMIWare v2.5

再新建立一个项目程序:gkbc8。
组态进步科触摸屏SZ7E,三菱PLC可编程控制器FX2N,串口通讯线。
组态好后,直接编译查看有没错误。
编译没问题后打开刚才创建的程序文件夹。

科触摸屏程序文件夹介绍

科触摸屏程序文件夹介绍

会看到很多文件与文件夹。
gkbc8.wpj是步科的工程文件,双击它可以打开触摸屏程序进行编辑。
gkbc8.pkg是编译后生成的二进制机器码,可直接下载到触摸屏使用或离线模拟。
gkbc8.bak,PLCGEDefaultProperties.xml是一些编译或保存时的中间过程临时文件,没用。
vg文件夹放置矢量类型的图片用,
temp文件夹备份整个工程文件用,这是怕你程序误操作,给你留一颗后悔药。
tar文件夹编译过程中生成的临时二进制文件,没用。
image文件夹放置位图类型的图片用。
HMI0文件夹一个触摸屏工程对应,放置屏工程文件,
打开还会发现有
HMI0.lg日志文件,
HMI0.whe屏程序文件。
文件夹macro放置此屏的宏相关文件。
其实上面乱七八糟的文件,通过双击工程文件gkbc8.wpj,
就可以按规则打开进行程序设计。


3.开始研究步科加密破解。
0>步科触摸屏加密破解。
步科用过一段时间后,发现可以通过加密保护的地方很多,
有些做的真不错,有些就如虚设一样,咱们做设备写程序的,建议都用上就对了。
首先是工程文件加密,也就是对上边那个文件gkbc8.wpj进行加密保护。
打开编程软件菜单,文件,工程密码保护,可以进行设置。
如下图:

步科触摸屏工程密码保护

步科触摸屏工程密码保护

步科工程文件加密搞的很好,
密码忘记了,一点后悔机会都不会给你。
如上图的注意提示:
密码为空,则不加密,请牢记密码,密码一旦丢失,工程将无法打开!!
刚开始我也不以为然,按以往破解其他品牌的经验,密码加密了,你自己软件在解密时总要用吧。
于是我进一步研究编程软件是如何使用密码的。

0.可能打开加密的文件时,先从文件读取密码,再与用户输入的密码对比?
那我来偷窥一个,你进行比对时,我就瞄一眼,就一眼。
测试发现它是将两密码对相同内容如:工控编程吧网址是gkbc8.com专注工控领域编程与破解进行加密后,
将加密的结果以字节为单位逐一对比,完全一致才表示密码相同,我干。

1.那密码对比结果可以拿来做文章吧?
密码错误结果为0,我给你搞成1,那编程软件不就当密码正确了么。
结果我一试,编程软件直接奔溃,汗。
其实想想也对。
用一个规则保存好的文件,你用其他乱七八糟的规则打开,那结果肯定随机。

2.既然简单的不行,那你研究你算法总可以了吧?
你算法是将数据+密码1+1=2,那我2-1=1不就得出原始的被加密的工程文件gkbc8.wpj了。
于是乎我花了个把星期研究算法,发现好复杂啊,好像也没法反推算算法啊。
加密过程总的步骤是这样的:
定义一个常量int KeyLenMulBlckLen=0xff,表示循环生成加密用数据的次数。
定义16个长度为0xff的常量数组,因为密码最长为16位,用于生成对应一位密码。
然后再获取用户输入的密码,循环迭代生成加密用的数据,进行文件的间接加密。
因为用户输入的密码是随机,所以生成的解密用的数据也是随机,
循环这么多次,它爹妈都不认识了根本没法反向,
真够恶心。
其实算法与WINRAR压缩文件,WORD文档相似,都是代码都是公开的。
开源的加密库都可以下载来研究。
下面是我几个星期的研究结果,真是浪费时间。

  1.   v2 = (unsigned __int16 *)this;

  2.   if ( ~*(_BYTE *)(Archivea2 + 0x18) & 1 )
  3.   {
  4.     v3 = *(_WORD *)this;
  5.     v4 = *(_DWORD *)(Archivea2 + 0x28) + 2;
  6.     if ( v4 > *(_DWORD *)(Archivea2 + 0x2C) )
  7.       CArchive::Flush((CArchive *)Archivea2);

  8.     v5 = *(_WORD **)(Archivea2 + 0x28);
  9.     v84 = v4;
  10.     *(_DWORD *)&v85[1] = &v84;
  11.     *v5 = v3;
  12.     *(_DWORD *)(Archivea2 + 40) += 2;
  13.     ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(
  14.       &v84,
  15.       v2 + 2);
  16.     v100 = -1;
  17.     WriteStringAndLength_45EBE0((CArchive *)Archivea2);
  18.     *(_DWORD *)&v85[1] = &v84;
  19.     ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(
  20.       &v84,
  21.       v2 + 4);
  22.     v100 = -1;
  23.     WriteStringAndLength_45EBE0((CArchive *)Archivea2);
  24.     *(_DWORD *)&v85[1] = &v84;
  25.     ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(
  26.       &v84,
  27.       v2 + 6);
  28.     v100 = -1;
  29.     WriteStringAndLength_45EBE0((CArchive *)Archivea2);
  30.     v6 = *((_DWORD *)v2 + 5);
  31.     if ( !(~*(_BYTE *)(Archivea2 + 24) & 1) )
  32.     {
  33.       v7 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  34.       AfxThrowArchiveException(2, v7);
  35.     }
  36.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 4) > *(_DWORD *)(Archivea2 + 44) )
  37.       CArchive::Flush((CArchive *)Archivea2);
  38.     **(_DWORD **)(Archivea2 + 40) = v6;
  39.     v8 = *(_DWORD *)(Archivea2 + 24);
  40.     *(_DWORD *)(Archivea2 + 40) += 4;
  41.     v9 = *((_BYTE *)v2 + 24);
  42.     if ( !(~(_BYTE)v8 & 1) )
  43.     {
  44.       v10 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  45.       AfxThrowArchiveException(2, v10);
  46.     }
  47.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 1) > *(_DWORD *)(Archivea2 + 44) )
  48.       CArchive::Flush((CArchive *)Archivea2);
  49.     v11 = *(_BYTE **)(Archivea2 + 40);
  50.     v84 = 80;
  51.     *v11 = v9;
  52.     ++*(_DWORD *)(Archivea2 + 40);
  53.     CArchive::Write((CArchive *)Archivea2, v2 + 14, v84);
  54.     v12 = v2[54];
  55.     if ( !(~*(_BYTE *)(Archivea2 + 24) & 1) )
  56.     {
  57.       v13 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  58.       AfxThrowArchiveException(2, v13);
  59.     }
  60.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 2) > *(_DWORD *)(Archivea2 + 44) )
  61.       CArchive::Flush((CArchive *)Archivea2);
  62.     **(_WORD **)(Archivea2 + 40) = v12;
  63.     v14 = *(_DWORD *)(Archivea2 + 24);
  64.     *(_DWORD *)(Archivea2 + 40) += 2;
  65.     v15 = v2[55];
  66.     if ( !(~(_BYTE)v14 & 1) )
  67.     {
  68.       v16 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  69.       AfxThrowArchiveException(2, v16);
  70.     }
  71.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 2) > *(_DWORD *)(Archivea2 + 44) )
  72.       CArchive::Flush((CArchive *)Archivea2);
  73.     **(_WORD **)(Archivea2 + 40) = v15;
  74.     v17 = *(_DWORD *)(Archivea2 + 24);
  75.     *(_DWORD *)(Archivea2 + 40) += 2;
  76.     v18 = v2[56];
  77.     if ( !(~(_BYTE)v17 & 1) )
  78.     {
  79.       v19 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  80.       AfxThrowArchiveException(2, v19);
  81.     }
  82.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 2) > *(_DWORD *)(Archivea2 + 44) )
  83.       CArchive::Flush((CArchive *)Archivea2);
  84.     **(_WORD **)(Archivea2 + 40) = v18;
  85.     *(_DWORD *)(Archivea2 + 40) += 2;
  86.     sub_7BEF50((int)(v2 + 58), (CArchive *)Archivea2);
  87.     v20 = *((_BYTE *)v2 + 1912);
  88.     if ( !(~*(_BYTE *)(Archivea2 + 24) & 1) )
  89.     {
  90.       v21 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  91.       AfxThrowArchiveException(2, v21);
  92.     }
  93.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 1) > *(_DWORD *)(Archivea2 + 44) )
  94.       CArchive::Flush((CArchive *)Archivea2);
  95.     **(_BYTE **)(Archivea2 + 40) = v20;
  96.     v22 = *(_DWORD *)(Archivea2 + 24);
  97.     ++*(_DWORD *)(Archivea2 + 40);
  98.     v23 = *((_BYTE *)v2 + 1913);
  99.     if ( !(~(_BYTE)v22 & 1) )
  100.     {
  101.       v24 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  102.       AfxThrowArchiveException(2, v24);
  103.     }
  104.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 1) > *(_DWORD *)(Archivea2 + 44) )
  105.       CArchive::Flush((CArchive *)Archivea2);
  106.     **(_BYTE **)(Archivea2 + 40) = v23;
  107.     v25 = *(_DWORD *)(Archivea2 + 24);
  108.     ++*(_DWORD *)(Archivea2 + 40);
  109.     v26 = *((_BYTE *)v2 + 1914);
  110.     if ( !(~(_BYTE)v25 & 1) )
  111.     {
  112.       v27 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  113.       AfxThrowArchiveException(2, v27);
  114.     }
  115.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 1) > *(_DWORD *)(Archivea2 + 44) )
  116.       CArchive::Flush((CArchive *)Archivea2);
  117.     **(_BYTE **)(Archivea2 + 40) = v26 != 0;
  118.     v28 = *(_DWORD *)(Archivea2 + 24);
  119.     ++*(_DWORD *)(Archivea2 + 40);
  120.     v29 = v2[958];
  121.     v30 = ~v28;
  122.     if ( !(v30 & 1) )
  123.     {
  124.       v31 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  125.       AfxThrowArchiveException(2, v31);
  126.     }
  127.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 2) > *(_DWORD *)(Archivea2 + 44) )
  128.       CArchive::Flush((CArchive *)Archivea2);
  129.     v32 = *(unsigned __int16 **)(Archivea2 + 40);
  130.     v84 = v30;
  131.     *(_DWORD *)&v85[1] = &v84;
  132.     *v32 = v29;
  133.     *(_DWORD *)(Archivea2 + 40) += 2;
  134.     ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(
  135.       &v84,
  136.       v2 + 960);
  137.     v100 = -1;
  138.     WriteStringAndLength_45EBE0((CArchive *)Archivea2);
  139.     v33 = *((_BYTE *)v2 + 1924);
  140.     if ( !(~*(_BYTE *)(Archivea2 + 24) & 1) )
  141.     {
  142.       v34 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  143.       AfxThrowArchiveException(2, v34);
  144.     }
  145.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 1) > *(_DWORD *)(Archivea2 + 44) )
  146.       CArchive::Flush((CArchive *)Archivea2);
  147.     v35 = *(bool **)(Archivea2 + 40);
  148.     *v35 = v33 != 0;
  149.     v36 = *(_DWORD *)(Archivea2 + 24);
  150.     ++*(_DWORD *)(Archivea2 + 40);
  151.     v37 = *((_DWORD *)v2 + 482);
  152.     if ( !(~(_BYTE)v36 & 1) )
  153.     {
  154.       v38 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  155.       AfxThrowArchiveException(2, v38);
  156.     }
  157.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 4) > *(_DWORD *)(Archivea2 + 44) )
  158.       CArchive::Flush((CArchive *)Archivea2);
  159.     v39 = *(_DWORD **)(Archivea2 + 40);
  160.     v84 = (int)v35;
  161.     *(_DWORD *)&v85[1] = &v84;
  162.     *v39 = v37;
  163.     *(_DWORD *)(Archivea2 + 40) += 4;
  164.     ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(
  165.       &v84,
  166.       v2 + 8);
  167.     v100 = -1;
  168.     WriteStringAndLength_45EBE0((CArchive *)Archivea2);
  169.     v40 = *((_DWORD *)v2 + 483);
  170.     if ( !(~*(_BYTE *)(Archivea2 + 24) & 1) )
  171.     {
  172.       v41 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  173.       AfxThrowArchiveException(2, v41);
  174.     }
  175.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 4) > *(_DWORD *)(Archivea2 + 44) )
  176.       CArchive::Flush((CArchive *)Archivea2);
  177.     **(_DWORD **)(Archivea2 + 40) = v40;
  178.     v42 = *(_DWORD *)(Archivea2 + 24);
  179.     *(_DWORD *)(Archivea2 + 40) += 4;
  180.     v43 = *((_DWORD *)v2 + 484);
  181.     if ( !(~(_BYTE)v42 & 1) )
  182.     {
  183.       v44 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  184.       AfxThrowArchiveException(2, v44);
  185.     }
  186.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 4) > *(_DWORD *)(Archivea2 + 44) )
  187.       CArchive::Flush((CArchive *)Archivea2);
  188.     **(_DWORD **)(Archivea2 + 40) = v43;
  189.     v45 = *(_DWORD *)(Archivea2 + 24);
  190.     *(_DWORD *)(Archivea2 + 40) += 4;
  191.     v46 = *((_DWORD *)v2 + 485);
  192.     if ( !(~(_BYTE)v45 & 1) )
  193.     {
  194.       v47 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  195.       AfxThrowArchiveException(2, v47);
  196.     }
  197.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 4) > *(_DWORD *)(Archivea2 + 44) )
  198.       CArchive::Flush((CArchive *)Archivea2);
  199.     **(_DWORD **)(Archivea2 + 40) = v46;
  200.     v48 = *(_DWORD *)(Archivea2 + 24);
  201.     *(_DWORD *)(Archivea2 + 40) += 4;
  202.     v49 = *((_DWORD *)v2 + 486);
  203.     if ( !(~(_BYTE)v48 & 1) )
  204.     {
  205.       v50 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  206.       AfxThrowArchiveException(2, v50);
  207.     }
  208.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 4) > *(_DWORD *)(Archivea2 + 44) )
  209.       CArchive::Flush((CArchive *)Archivea2);
  210.     **(_DWORD **)(Archivea2 + 40) = v49;
  211.     v51 = *(_DWORD *)(Archivea2 + 24);
  212.     *(_DWORD *)(Archivea2 + 40) += 4;
  213.     v52 = *((_BYTE *)v2 + 1948);
  214.     if ( !(~(_BYTE)v51 & 1) )
  215.     {
  216.       v53 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  217.       AfxThrowArchiveException(2, v53);
  218.     }
  219.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 1) > *(_DWORD *)(Archivea2 + 44) )
  220.       CArchive::Flush((CArchive *)Archivea2);
  221.     **(_BYTE **)(Archivea2 + 40) = v52 != 0;
  222.     v54 = *(_DWORD *)(Archivea2 + 24);
  223.     ++*(_DWORD *)(Archivea2 + 40);
  224.     v55 = *((_DWORD *)v2 + 488);
  225.     if ( !(~(_BYTE)v54 & 1) )
  226.     {
  227.       v56 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  228.       AfxThrowArchiveException(2, v56);
  229.     }
  230.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 4) > *(_DWORD *)(Archivea2 + 44) )
  231.       CArchive::Flush((CArchive *)Archivea2);
  232.     **(_DWORD **)(Archivea2 + 40) = v55;
  233.     v57 = *(_DWORD *)(Archivea2 + 24);
  234.     *(_DWORD *)(Archivea2 + 40) += 4;
  235.     v58 = *((_BYTE *)v2 + 1956);
  236.     if ( !(~(_BYTE)v57 & 1) )
  237.     {
  238.       v59 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  239.       AfxThrowArchiveException(2, v59);
  240.     }
  241.     if ( (unsigned int)(*(_DWORD *)(Archivea2 + 40) + 1) > *(_DWORD *)(Archivea2 + 44) )
  242.       CArchive::Flush((CArchive *)Archivea2);
  243.     **(_BYTE **)(Archivea2 + 40) = v58 != 0;
  244.     v60 = *(_DWORD *)(Archivea2 + 24);
  245.     ++*(_DWORD *)(Archivea2 + 40);
  246.     v61 = *((_DWORD *)v2 + 490);
  247.     if ( !(~(_BYTE)v60 & 1) )
  248.     {
  249.       v62 = (const wchar_t *)ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(Archivea2 + 20);
  250.       AfxThrowArchiveException(2, v62);
  251.     }
  252.     result = *(_DWORD *)(Archivea2 + 40) + 4;
  253.     if ( (unsigned int)result > *(_DWORD *)(Archivea2 + 44) )
  254.       CArchive::Flush((CArchive *)Archivea2);
  255.     **(_DWORD **)(Archivea2 + 40) = v61;
  256.     *(_DWORD *)(Archivea2 + 40) += 4;
  257.   }
  258.   else
  259.   {
  260.     Read2Byte_405E20(Archivea2, this);
  261.     ReadString_45EC50(Archivea2, (int)(v2 + 2));
  262.     ReadString_45EC50(Archivea2, (int)(v2 + 4));
  263.     ReadString_45EC50(Archivea2, (int)(v2 + 6));
  264.     ReadOneDWORD_4082D0(Archivea2, (int)(v2 + 10));
  265.     ReadOneByte_405DD0(Archivea2, (int)(v2 + 12));
  266.     if ( *v2 >= 6u )
  267.     {
  268.       if ( *v2 >= 0xDu )
  269.         v84 = 80;
  270.       else
  271.         v84 = 32;
  272.       CArchive::Read((CArchive *)Archivea2, v2 + 14, v84);
  273.     }
  274.     else
  275.     {
  276.       CArchive::Read((CArchive *)Archivea2, &v86, 0x20u);
  277.       v84 = *((_DWORD *)v2 + 5);
  278.       v64 = ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(v2 + 6);
  279.       v65 = ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(v2 + 4);
  280.       v66 = GetPlcType(v65, v64, v84);
  281.       if ( v66 >= 0 && (unsigned __int16)GetLinkType(v66) )
  282.       {
  283.         v67 = v88;
  284.         v68 = v87;
  285.         *((_DWORD *)v2 + 14) = v86;
  286.         v69 = v89;
  287.         *((_BYTE *)v2 + 34) = v67;
  288.         v70 = v91;
  289.         *((_BYTE *)v2 + 35) = v69;
  290.         v71 = v92;
  291.         v2[27] = v68;
  292.         *((_BYTE *)v2 + 36) = v90;
  293.         v2[16] = v70;
  294.         *((_DWORD *)v2 + 7) = v71;
  295.       }
  296.       else
  297.       {
  298.         v72 = v86;
  299.         v73 = v93;
  300.         v2[17] = v87;
  301.         v74 = v88;
  302.         v2[16] = v72;
  303.         LOBYTE(v72) = v94;
  304.         *((_BYTE *)v2 + 36) = v74;
  305.         *(unsigned __int16 *)((char *)v2 + 37) = v92;
  306.         v75 = v95;
  307.         *((_BYTE *)v2 + 40) = v72;
  308.         LOBYTE(v72) = v97;
  309.         *((_BYTE *)v2 + 39) = v73;
  310.         v76 = v96;
  311.         *(_DWORD *)((char *)v2 + 41) = v75;
  312.         LOBYTE(v75) = v98;
  313.         *(_DWORD *)((char *)v2 + 45) = v76;
  314.         LOBYTE(v76) = v99;
  315.         *((_BYTE *)v2 + 49) = v72;
  316.         v77 = HIWORD(v86);
  317.         *((_BYTE *)v2 + 50) = v75;
  318.         *((_BYTE *)v2 + 51) = v76;
  319.         *((_DWORD *)v2 + 7) = v77;
  320.       }
  321.     }
  322.     result = *v2;
  323.     if ( (_WORD)result )
  324.     {
  325.       if ( (unsigned __int16)result < 5u )
  326.       {
  327.         ReadOneByte_405DD0(Archivea2, (int)v85);
  328.         v84 = (int)(v2 + 55);
  329.         v2[54] = (unsigned __int8)v85[0];
  330.         Read2Byte_405E20(Archivea2, v84);
  331.         ReadOneByte_405DD0(Archivea2, (int)v85);
  332.         result = (unsigned __int8)v85[0];
  333.         v2[56] = (unsigned __int8)v85[0];
  334.       }
  335.       else
  336.       {
  337.         Read2Byte_405E20(Archivea2, (int)(v2 + 54));
  338.         Read2Byte_405E20(Archivea2, (int)(v2 + 55));
  339.         result = (int)Read2Byte_405E20(Archivea2, (int)(v2 + 56));
  340.       }
  341.     }
  342.     if ( *v2 > 1u )
  343.       result = sub_7BEF50((int)(v2 + 58), (CArchive *)Archivea2);
  344.     if ( *v2 > 2u )
  345.     {
  346.       ReadOneByte_405DD0(Archivea2, (int)(v2 + 956));
  347.       ReadOneByte_405DD0(Archivea2, (int)v2 + 1913);
  348.       ReadOneByteAsBool_408320(Archivea2, (int)(v2 + 957));
  349.       Read2Byte_405E20(Archivea2, (int)(v2 + 958));
  350.       ReadString_45EC50(Archivea2, (int)(v2 + 960));
  351.     }
  352.     if ( *v2 > 3u )
  353.       result = (int)ReadOneByteAsBool_408320(Archivea2, (int)(v2 + 962));
  354.     if ( *v2 > 6u )
  355.       result = (int)ReadOneDWORD_4082D0(Archivea2, (int)(v2 + 964));
  356.     if ( *v2 < 9u )
  357.     {
  358.       v84 = *((_DWORD *)v2 + 5);
  359.       v78 = ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(v2 + 6);
  360.       v79 = ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(v2 + 4);
  361.       result = GetPlcType(v79, v78, v84);
  362.       if ( result >= 0 && (result = (unsigned __int16)GetLinkType(result), (_WORD)result) )
  363.       {
  364.         LOWORD(result) = 100 * *((unsigned __int8 *)v2 + 34);
  365.         v2[25] = result;
  366.       }
  367.       else
  368.       {
  369.         v2[29] = 100 * *((unsigned __int8 *)v2 + 34);
  370.       }
  371.     }
  372.     if ( *v2 >= 0xAu )
  373.       ReadString_45EC50(Archivea2, (int)(v2 + 8));
  374.     if ( *v2 >= 0xBu )
  375.     {
  376.       ReadOneDWORD_4082D0(Archivea2, (int)(v2 + 966));
  377.       ReadOneDWORD_4082D0(Archivea2, (int)(v2 + 968));
  378.       ReadOneDWORD_4082D0(Archivea2, (int)(v2 + 970));
  379.       ReadOneDWORD_4082D0(Archivea2, (int)(v2 + 972));
  380.       v84 = *((_DWORD *)v2 + 5);
  381.       v80 = ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(v2 + 6);
  382.       v81 = ATL::CSimpleStringT<wchar_t,1>::operator wchar_t const *(v2 + 4);
  383.       v82 = GetPlcType(v81, v80, v84);
  384.       v83 = v82;
  385.       result = BlkSizesProgrammable(v82);
  386.       if ( (_BYTE)result )
  387.       {
  388.         SetMaxBitBlkSize(v83, *((_DWORD *)v2 + 483) / 16);
  389.         result = SetMaxWordBlkSize(v83, v2[968]);
  390.       }
  391.     }
  392.     if ( *v2 >= 0xCu )
  393.     {
  394.       ReadOneByteAsBool_408320(Archivea2, (int)(v2 + 974));
  395.       ReadDWORD_40DB30(Archivea2, (int)(v2 + 976));
  396.       ReadOneByteAsBool_408320(Archivea2, (int)(v2 + 978));
  397.       result = (int)ReadDWORD_40DB30(Archivea2, (int)(v2 + 980));
  398.     }
  399.     *v2 = 13;
  400.   }
复制代码

其实研究过程中我是有发现一些加密算法相关的关键字,
加之也买有一些密码学资料,
一搜索,这个算法还有个学名AES。
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),
在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。
这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。
看算法主要是生成加密用的数据时死循环了N多次,生成的数组也长,数据量大,根本没法反向推出密码。
何况最后还有执行一次,通过用户输入的密码结合解密用中间变量,生成最终文件。
主要还是中间数据量大,我这高配电脑一秒也只能生成几千次。
工程密码任何可输入字符都支持,如中文符号,数字,字母,密码长度16位。
那么密码是什么就有N个可能了,简单拿ASCII表的255个编译来举例,
密码就有255的16次方种可能,普通计算器没法显示结果,可以网络找些计算器计算。
所以在我们设置好密码后还是建议备份好,
如上图官方提示的,忘记了,工程就真将无法打开了。

那么有人要问了,我公司设备真要改造,技术员,设备厂家都不在了,炸整?
寄给步科官方能给找回么?
官方已经做出提示了,你花钱官方也搞不了啊,人家都解释很清楚了,没有预留超级密码。
你只能根据设备厂家,技术员等能找到的相关信息,或通过社会工程,一个个输入试。
我06年从事工控行业的,使用步科也很长时间,在专业上,效率与技巧会比那些只有兴趣的多些吧。工控相关脑力,苦力活可以找我。

步科触摸屏加密保护方式还是有很多的,都是使用了相同算法,只是密码字符和长度会有所不同。
比如
允许上传的上传密码,
使用下载密码,
允许反编译的反编译密码。
分期付款的每期密码。
32个用户权限的密码。
16个用户等级密码。
这些密码设置都可以在触摸屏组态界面,双击触摸屏打开窗口设置。
站在咱们做设备写程序的同行角度讲,程序设计好,能保护的设置都建议设置上。
密码一律使用最长,数字+字母+字符+其他,再做好密码备份。
为什么?因为想盗取你劳动成果的人都舍得请技术破解。

触摸屏组态界面设置密码

触摸屏组态界面设置密码


1>步科触摸屏反编译破解。
步科触摸屏程序设计好后是要进行反编译,生成二进制的机器码下载到触摸屏供硬件使用的。
有很多时候需要再将此二进制文件还原成可二次编辑设计的文件,用编程软件打开编辑。
所以就出现了两个专业名称,编译与反编译。
一般反编译都是从触摸屏读取机器码后才有需要,也就是使用者会有反编译需求,
因为如果程序是自己设计,直接双击工程文件进行编辑就好。
所以反编译加密保护其实意义不大,加上官方搞的密码长度相对工程文件都减半,不建议使用此功能。

步科触摸屏针对反编译提供两种保护方法:
反编译加密保护与禁止反编译保护。
反编译加密保存的设置如上图,组态界面双击触摸屏可弹出屏属性设置窗口,就可进行设置。
和工程文件加密相似,只是密码长度少了很多。
也是建议能够多复杂就多复杂,再设置成禁止反编译多重保护。

我们再继续研究禁止反编译保护方法。
同样在HMI属性设置窗口(也就是上边的图),触摸屏扩展属性设置标签页下,
去除<允许反编译>勾选,完成禁止反编译保护设置。
那么允许反编译勾选与不勾,是不是只是一个标识不同呢?
比如编程软件在执行反编译时,先读取一下这个标识。
标识为1,执行反编译,验证反编译密码,标识为0不执行反编译,提示禁止反编译。
如果是这样,那我搞定这个标识不就好。
于是我验证了一下。
发现真有这个标识,设置禁止反编译了,这个标识真为0。
设置允许反编译,这个标识不为0,但也不为1,而是很大的一个数值。
我继续验证,设置禁止反编译,将这个标识搞成1,假想着让编程软件执行反编译。
不想编程软件直接奔溃。
汗,怎么什么都来个奔溃啊。
按我多年经验,这么大的数据不是随机数,就是地址。
于是我设置允许反编译,又多次编译观察此标识,每次不一样,还真有随机的感觉,但相差不大。
于是我双将禁止反编译的文件,与没有禁止反编译的文件,进行属性对比。
2021-05-17_131239.jpg

会发现两者文件大小相差几KB。
于是乎我又往工程里添加大量大尺寸图片再对比。
编译后的文件相差不是一点的大啊,
总结萌生:刚才的那标识其实是工程文件数据地址,禁止反编译的PKG文件不带工程文件。
为了验证这一想法。
我特意做了几天的测试。
发再加密反编译保护的,只是将工程文件夹内非临时文件全部统一压缩加密打包。
一并保存于PKG文件中,刚才那标识就是这数据包的地址,地址有略微变化。
因为官方使用了大量随机长度不一干扰数据。
如果禁止反编译了,直接就不打包加密了,数据地址为0。
我给它搞成1了,编程软件不奔溃才怪。
我干,真是简单粗暴又高效。
看来禁止反编译的,破解的机会都不留,
不像三菱的,绕一绕,改一改,编程软件就可正常打开程序。

那么真的需要程序怎么办呢?
那只能找搞技术的了,搞工控编程的老油条。
步科的PKG文件可以在电脑模拟,也可以直接在触摸屏上一页页操作。
然后技术的事就交给搞技术的了。
你一个工控爱好或老板出身,半个月完成,我工控数十载的半个小时搞成。

2>步科触摸屏禁止上传。
要研究禁止上传就得有硬件了。
我手上千百块买的屏没舍得试,是拿公司老旧的,坏了可以寄修,修的理由随意写。
我先是也是网络找帖子看。
有人验证上传密码三次错误会锁机的,我没敢试。
已经有很多人在打广告,接禁止上传的活了。
都是要寄送,折机读取芯片数据几百M,再提取出出程序文件几M;
技术活就不多说了,那些花钱投广告的也不容易。同行相互尊重,工控产品成千上万,总有互补合作的时候。

步科的研究过程就说到这里吧。
对步科总的印象不是很好,使用时内心是抵制的。
编程软件工具栏图标,菜单栏与工作区文字,都没法一眼见其意,
字体太小,界面灰白丑陋。
宏界面都极不友好,宏编程时,你删除一字符,会给你多出一字符,真是无语。

编写程序多了,在使用中你还会发现有大量的图形文字,点阵文字,
以及很多控件如管道等等都搞成图片形式编译到屏,
可以试试管道控件,属性全部打勾,会发现工程文件夹多了三张管道图片。
编译也是直接压缩加密全部工程文件到PKG中,反编译时再解密解压缩。
可以猜测步科触摸屏可能是运算能力不足,然后用存储空间来弥补。
当然这只是猜测。

我也都是看在客户钱的份上才用它一用。
我06年开始从事工控编程,技术活可以找我合作。
什么工业视觉,C语言上位机,PLC,触摸屏编程啥的。
合作共赢。
当前这步科也可以找我编程。












回复

使用道具 举报

大神点评(20)

我叫一建平 2021-5-17 14:22:40 显示全部楼层
大神有出步科触摸屏的视频教程么?
刚好我公司现场有设备用到,想学习学习。
都没找到比较满意的教程

大神有出步科触摸屏的视频教程么

大神有出步科触摸屏的视频教程么

回复

使用道具 举报

qq263946146 楼主 2021-5-17 14:23:27 显示全部楼层
我叫一建平 发表于 2021-5-17 14:22
大神有出步科触摸屏的视频教程么?
刚好我公司现场有设备用到,想学习学习。
都没找到比较满意的教程

一步步来吧,官方的资料先参考着学。
很不错
回复

使用道具 举报

wkd1980 2021-5-17 21:49:31 显示全部楼层
好家伙,店长又出新品啦?
刚好昨天有个客户给我一个文件步科PKG,
反编译时提示PKG文件禁止反编译。
不知道可以不可以破解。

反编译时提示PKG文件禁止反编译

反编译时提示PKG文件禁止反编译


回复

使用道具 举报

qq263946146 楼主 2021-5-17 21:55:32 显示全部楼层
wkd1980 发表于 2021-5-17 21:49
好家伙,店长又出新品啦?
刚好昨天有个客户给我一个文件步科PKG,
反编译时提示PKG文件禁止反编译。

禁止反编译的没有将工程文件都编译保存到PKG文件。
所以无从破解,步科是将这种保护做绝的,不像三菱的,文件里本就有工程文件数据,软件改一改,绕一绕就可以正常反编译出工程文件。

如果是设备上急用,时间很紧,可以发文件过来,我帮你看看。
如果说是自己学习用啥的,那就拉倒吧,自己重写学到的会更多。

咱们精力时间都有限。
都要吃饭,时间都得花在刀刃上。


回复

使用道具 举报

wkd1980 2021-5-17 21:57:22 显示全部楼层
qq263946146 发表于 2021-5-17 21:55
禁止反编译的没有将工程文件都编译保存到PKG文件。
所以无从破解,步科是将这种保护做绝的。
如果是设 ...

那站长你代写程序么?
回复

使用道具 举报

qq263946146 楼主 2021-5-17 21:58:59 显示全部楼层
wkd1980 发表于 2021-5-17 21:57
那站长你代写程序么?

本人就是工控出身,当然可以哦。
钱给到位,程序可代写,陪聊也愿意。

回复

使用道具 举报

站长你好,我今天从客户搞了两台设备。
一台可以正常打开编辑,
一台如图显示,要工程密码,问了步科的电话,也是说忘记了就没有办法了。

一台如图显示,要工程密码

一台如图显示,要工程密码

看了你了帖子,有什么方法么?
这种设备重写很费时的。
有偿求助,如果让你帮忙重写程序,一天半天的真可以写好么?


回复

使用道具 举报

qq263946146 楼主 2021-5-23 17:05:01 显示全部楼层
工控终极高手 发表于 2021-5-23 17:01
站长你好,我今天从客户搞了两台设备。
一台可以正常打开编辑,
一台如图显示,要工程密码,问了步科的电 ...

这种加密了的,就像WINRAR压缩包加密一样,一个个试吧。密码长度16位,可以是中文英文符号数字任意形式,基本无解不用考虑。

可以把文件先发我分析看看。
虽说基本无解,但梦想还是要有的,万一实现了呢?
要我帮你重写程序也是可以的。
效率绝对超乎你想象


回复

使用道具 举报

jysl1970 2021-7-28 09:49:59 显示全部楼层
我这也有一块步科MT510T的触摸屏。

步科触摸屏5T510T

步科触摸屏5T510T

好像不能上传程序,禁止上传了。
我搞维修的,自己拆机处理,但还是提取禁止反编译。
不知道站长能不能搞定。
2.jpg
是发芯片文件给你,还是发这个屏给你呢?

回复

使用道具 举报

qq263946146 楼主 2021-7-28 09:55:41 显示全部楼层
jysl1970 发表于 2021-7-28 09:49
我这也有一块步科MT510T的触摸屏。

好像不能上传程序,禁止上传了。

步科禁止反编译

步科禁止反编译

提示是图片上的内容么?那基本不用考虑,无解。
步科禁止反编译的,工程文件都没有编译保存到文件,所以没破解一说。
但具体是什么情况,还是发来看看,可以给你分析分析。
我经常使用步科,会熟悉些。
回复

使用道具 举报

2345 2021-7-28 10:10:30 显示全部楼层
我在老设备上也搞了一块触摸屏。eview的,网上查了下也是步科触摸屏。


网上查了下也是步科触摸屏

网上查了下也是步科触摸屏

可以上传得到程序,但也是保护了的。
看楼主专业水平,不知可否帮我看看。
是帮我重写还是怎么处理。
破解的话费用是多少?
重写的话周期多久?

回复

使用道具 举报

qq263946146 楼主 2021-7-28 10:16:25 显示全部楼层
2345 发表于 2021-7-28 10:10
我在老设备上也搞了一块触摸屏。eview的,网上查了下也是步科触摸屏。

文件具体是什么情况,得先发来看看。
我没法像黄牛那样,什么都不看,一上来就给你开价二百五
也建议你搞次搞技术的帮忙,不然黄牛一问三不知耽误你项目工程进度。
所以还是发来看看先吧,步科编程问题我也可以协助协助你。
回复

使用道具 举报

PLC编程高手 2021-9-14 11:22:41 显示全部楼层
刚遇到一个问题,打开工程文件提示,缺少系统编号为155的PLC,请问是工程文件保护了要破解,还是什么原因。

缺少系统编号为155的PLC

缺少系统编号为155的PLC



回复

使用道具 举报

qq263946146 楼主 2021-9-14 11:28:47 显示全部楼层
PLC编程高手 发表于 2021-9-14 11:22
刚遇到一个问题,打开工程文件提示,缺少系统编号为155的PLC,请问是工程文件保护了要破解,还是什么原因。
...

我经常破解,是有遇到相似问题,不是PLC编号不识别就是HMI编号不识别。一般是文件来路问题,导致文件破损。可选择通过硬件确定型号,手工修正。

具体针对这个155 PLC编号。我刚遇到过。
你硬件应该是串口自由协议啥的吧?单片机?

回复

使用道具 举报

PLC编程高手 2021-9-14 11:29:12 显示全部楼层
qq263946146 发表于 2021-9-14 11:28
我经常破解,是有遇到相似问题,不是PLC编号不识别就是HMI编号不识别。一般是文件来路问题,导致文件破损 ...

EN,EN,有具体解决方法么?

回复

使用道具 举报

qq263946146 楼主 2021-9-14 11:47:36 显示全部楼层
PLC编程高手 发表于 2021-9-14 11:29
EN,EN,有具体解决方法么?

你这种问题是系统缺少PLC驱动导致的,驱动还得自己编写哦,不过你工程PKG文件原先的应该也在。
具体我给你写点文字,你也可以找我有偿帮助。
0下载附件,步科Kinco生成新PLC开发包由工控编程提供.
1在编程软件根目录创建文件夹如  D:\Kinco\customized_driver。
2解压文件,放进去,会得到三个文件夹及一个文档。
对着文档操作,生成一个自定义的PLC,便可在编程软件里添加此PLC。
你的工程也可以正常打开。
会发现这个由我们自己生成的PLC编号正是155.

请点击此处下载

查看状态:需购买或无权限

您的用户组是:游客

文件名称:步科Kinco生成新PLC开发包由工控编程提供.rar 
文件大小:236.83 KB 
下载权限: 捐助会员 以上或 VIP会员   [购买捐助会员]   [充值积分]   有问题联系我


回复

使用道具 举报

ycxlzhb 2021-10-3 12:07:45 显示全部楼层

畜禽管理系统

畜禽管理系统


我这有个畜禽管理系统,也是步科触摸屏写的。
加密了不知道能不能破解出来?
柜子里屏型号是 MT4414TE,
PLC 是modbus的。
可以的话给你包红包

回复

使用道具 举报

qq263946146 楼主 2021-10-3 12:08:32 显示全部楼层
ycxlzhb 发表于 2021-10-3 12:07
我这有个畜禽管理系统,也是步科触摸屏写的。
加密了不知道能不能破解出来?
柜子里屏型号是 MT4414T ...

可以直接加我微信263946126,
文件或硬件发我分析看看
回复

使用道具 举报

Byron 2022-6-7 15:23:47 显示全部楼层
我这有块步科触摸屏,型号是GL070。
不知道能不能破解。
禁止上传了。
上传密码不知道。
还有PLC是一个modbus模块。
回复

使用道具 举报

qq263946146 楼主 2022-6-7 15:28:58 显示全部楼层
Byron 发表于 2022-6-7 15:23
我这有块步科触摸屏,型号是GL070。
不知道能不能破解。
禁止上传了。

有处理过相似的。如下图,
一般设置了禁止上传。
都会设置禁止下载,
禁止反编译。
所以如果在破解你的硬件会很繁琐。
禁止上传要破解,禁止反编译在破解,也就是半重写。
禁止下载如果要涉及的话,也得破解。

型号是GL070

型号是GL070



回复

使用道具 举报

点击查看
快速回复 返回列表 客服中心 搜索