dsong 发表于 2017-8-5 16:11

DoSWF 5.5.0 注册机编写+网络验证模拟 (能解锁商业授权功能)

DoSWF 5.5.0(包含商业授权功能)破解
2017/8/5

一、背景了解
DoSWF是曾经的一款被喻为最强大的SWF加密软件。
本文使用的DoSWF版本是DoSWF Pro 5.5.0,是目前的最新版。由于它已经好久没更新了,再加上Flash已死的消息,我猜测作者已经基本放弃这款软件,所以给出完美破解思路。(其实在几个月前我已经完成了完整的破解)
下图证明可以使用它的商业授权功能。



二、破解方法
鉴于SWF文件的特殊性,它的破解方法可谓极其容易。按照DoSWF目前的加密与混淆强度,内存提取完全可以得到基本上已经解密的SWF文件,并且得到逻辑上正确的代码。

三、破解准备
1. JPEXS Free Flash Decompiler (只需要文件内存提取功能)
2. AS3 Sorcerer (或者ffdec也是可以的,只不过我认为这个查看起来方便一点,主要是反编译速度较快。没有搜索功能,可以导出AS3文件后使用编辑器的文件夹搜索,比如sublime text中就有这个功能。)

四、本地算法还原
(省略SWF内存提取过程)
1. 短暂浏览即可找到这个KeyScope:

2. 查看关键字符串:

3. 找到关键函数:

4. 还原被混淆函数:(就是把定义的字符串替换掉关键函数里的)
还原前:

还原后:
private var checkUserFromServer__MN18862:* = "soft";
private var key2_MN15285:* = "laan";
private var key2_MN15283:* = "15";
private var key4_MN18861:* = "_";
private var key4_MN18865:* = "64";
private var key4_MN11447:* = "16";
private function validateKey__():void
{
    var _local_2:String;
    if (((((!(this.appKey_MN18836)) || (!(this.appKey_MN18836.appId))) || (!(this._key))) || (!(this._userName))))
    {
      return;
    };
    if (this._userName.indexOf(String.fromCharCode("64")) < 0) // char = "@" : There must be "@" in the userName. (should be email address, from the snap from the official website.)
    {
      while ("laan".length)
      {
            "laan" = ("laan" + "laan");
      };
    };
    var _local_1:String = this._key.substr(-2); // The last 2 characters of the key.
    if (_local_1 == "16")
    {
      _local_2 = (MD5.hash(((((((((this.appKey_MN15235 + "_") + "_") + "laan") + MD5.hash((this._userName + "_"))) + "15") + "soft") + "_") + this.appKey_MN18836.appId)) + _local_1);
      this._isValidated = (_local_2 == this._key);
    }
    else
    {
      if (_local_1 == "15")
      {
            _local_2 = (MD5.hash((((((((this.appKey_MN15235 + MD5.hash(this._userName)) + "_") + "laan") + "_") + "soft") + "_") + this.appKey_MN18836.appId)) + _local_1);
            this._isValidated = (_local_2 == this._key);
      }
      else
      {
            dispatchEvent(new Ⱥ(Ⱥ.Ϭ, "The key system had updated, please use the new key."));
      }; // the last two character must be "15" or "16".
    };
    ɂ.instance.a = _local_1;
}
5. 找回缺失字符串

… 查找”KeyScope”:

… 查找” ȿ”:

… 查找”isInternalUsed_MN10638”:

6. 返回继续还原:
// appKey_MN18836.appId = 776
// appKey_MN15235 = "newSprite()"
替换后:

进一步简化后:

7. 注册机编写
(略,把上面的最简代码直接拷贝进Flash即可。)
只需要注意,要自己导入库的。必须自己下载下面的库:
import com.adobe.crypto.MD5;
或者用其他语言编写。
我是直接用Flash写的。
下面给出一组可用的注册码:
用户名:190720@evaluation.only
注册码:fd88ea01ca576b022395ef861018a10015

8. 试试看
好高兴对吧,终于算出一组注册码。试一试,呃,注册成功后,又弹出“Your licence has been removed.”。好吧,有网络验证。抓包,得到网址,或者从下面得到网址全部屏蔽掉,注册得以保留。但是实际试用,会发现“删除数据类型声明”和“方法同化”是不能使用的。仔细分析(见下一节),会发现有网络验证。


五、模拟网络验证
1. 找关键函数
关键函数还是在KeyScope里面:

发现好像还挺高级,使用到二进制“与”运算。
2. 适当理解与简化:
      private function checkUserFromServer__MN10009(_arg_1:Event):void
      {
            var _local_5:Array;
            var _local_6:String;
            var _local_2:URLLoader = (_arg_1.target as URLLoader);
            _local_2.removeEventListener(Event.COMPLETE, this.checkUserFromServer__MN10009);
            _local_2.removeEventListener(IOErrorEvent.IO_ERROR, this.checkUserFromServer__MN10141);
            _local_2.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, this.checkUserFromServer__MN10141);
            ɂ.instance.d = _arg_1.type;
            // the code above are the process of getting returned value from the server
            var _local_3:String = (_local_2.data as String); // get returned data
            var _local_4:String = MD5.hash(this.checkRandom + this._key + MD5.hash(this._userName + "laan_soft"));
            if (((_local_3) && (_local_3.indexOf(_local_4) > 0))) // there must be _local_4 in a part of _local_3
            {
                this._keyCode = uint(_local_3.substring(1, _local_3.indexOf("]"))); // _keyCode = _local_3"]
                ǹ.setData("kc", this._keyCode); // Make it 'public'.
                _local_3 = _local_3.replace(/(\[\d+\]|)/g, "").replace(_local_4, ""); // get rid of unwanted characters.
                _local_5 = _local_3.split(",");
                _local_6 = _local_5.shift();
                if (((_local_6) && (this._keyCode & 0x01)))
                {
                  dispatchEvent(new Ⱥ(Ⱥ.Ϭ, _local_6)); // display the message from the server.
                };
                if ((this._keyCode & 0x02))
                {
                  this.setUserNameUsable_MN18838(true); // Success.
                  ǹ.setData("cft", 0);
                  ɂ.instance.e = (ɂ.instance.e + this._userName);
                  if ((this._keyCode & 0x10))
                  {
                        this.ҏ_MN18841 = _local_5.shift(); // Expire Time.
                  };
                  dispatchEvent(new Ⱥ(Ⱥ.VERIFIED));
                }
                else
                {
                  this.setUserNameUsable_MN18838(false);
                  this.removeKey_();
                };
            }
            else
            {
                this.checkUserFromServer__MN10141(_arg_1);
            };
            dispatchEvent(new Ⱥ(Ⱥ.REMOTE_CHECK_COMPLETE));
      }
3. 校验码的生成
显然,_local_4是校验的关键,于是抓包分析发送的数据:

发送数据中,真正在验证算法中有用的只有r、k、u三项。与DoSWF程序中变量对应关系如下:
r = checkRandom
u = _userName
k = _key
所以,以php举例,返回数据的代码应是:
echo md5($r.$k.md5($u."laan_soft"));
4. 其他数据的返回
现在好像有点没头绪了,因为此处没有对于商业版与否的校验。
不过,好在“与”运算特征明显,只要搜索“& 0x”,找到两处关键:
(I)

“c” = 商业授权,“p” = 个人授权。所以keyCode& 0x04 必须不为0。
(II)

一看,就知道这个是命令行功能,是商业版才能用的。所以keyCode & 0x08 必须也不为0。
5. 梳理思路
首先,返回数据必须有校验码,而且根据代码的情况来看,这个校验码最好放在返回字符串的最后。
返回字符串最开始,可以是的形式。中间还可以有服务器返回的提示消息,还可以有授权到期日期。
这个d就是程序内获取到的keyCode,且 d & 0x02 && d & 0x04 && d & 0x08 ==true.
这个的话,自己写个程序过滤50以内的数,就可以获得符合要求的。
如果要让程序与服务器通信后显示消息,d & 0x01也要是true.
如果要让程序有授权过期时间,d & 0x10也要是true.
所以,这些条件一限制,50以内符合要求的数就不多了,最多两个。
估计这个程序对于d最大也有限制,我没有研究这个。最小的数经过测试都是可以的。
下面给出一个既有过期时间,又有服务器返回提示的php示例代码:
echo ''.'Commercial Cracked by 190720,20191231';
echo md5($r.$k.md5($u."laan_soft"));
6. 测试效果:


六、总结
其实,这个DoSWF 5.5.0的破解过程就是需要人的仔细与耐心,看到一个个不认识的字符不要慌,按照逻辑走下去就是。从中可以学习到的是,作者把软件中经常出现的字符串作为生成Key的关键字,所以使用一般的查找就容易找不到。还有,在进行网络验证的同时返回校验码,如果校验码错误就移除license,这也是值得学习的地方。
但是,可见,DoSWF的加密程度已经无法抵御成熟的反编译软件。在之后,将继续写出最新版的DoSWF加密的程序的破解方法。

a7107925 发表于 2017-8-22 01:49

zsksssss 发表于 2017-8-5 16:19

感谢分享谢谢

beatone 发表于 2017-8-5 16:23

谢谢分享教程。

天宫太祖 发表于 2017-8-5 17:25

很好的破解教程,学习了!

左殇魂 发表于 2017-8-5 17:48

不明觉厉!!

爱情街 发表于 2017-8-5 17:48

看不懂········小白后排支持

biyongjun 发表于 2017-8-5 18:03

谢谢分享教程。

DreamMiu 发表于 2017-8-5 19:38

感谢分享谢谢老大

zz650008 发表于 2017-8-5 20:01

谢谢分享

幻想 发表于 2017-8-5 22:06

说实话,真的厉害
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: DoSWF 5.5.0 注册机编写+网络验证模拟 (能解锁商业授权功能)