jsPlumb Toolkit库破解过程分析

来源:互联网 发布:网上药店 淘宝 编辑:程序博客网 时间:2024/06/01 12:12

网上看到JSPlumb这个图形库还不错,它本身提供一个开源版,但是开源版功能比较有限,还提供一个toolkit,这个版本功能比较强大,但是收费。本着学习的目的跟他们要了一个evaluation版本,当然在他们自己的网站demo里也可以自己下载toolkit版本。


下面是一些链接,如果不是特殊需求,请尽量使用开源版本:

下载链接,里面有开源版和收费版的介绍:https://jsplumbtoolkit.com/download

在线demo地址:https://jsplumbtoolkit.com/demos.html

在线文档以及API:https://jsplumbtoolkit.com/docs.html


如果使用开源版,我找到了两个比较好的例子和插件,仅供参考:

http://yurigor.com/pan-zoom-jsplumb-dagrejs-jqueryui-draggable/
http://www.cnblogs.com/sggx/p/3836432.html


下面继续介绍这个evalution版本或者从demo页面上下载的toolkit版本,都是压缩过的:

从demo网页上下载的版本如果直接在本地跑会抛出异常,也就是说这个版本做了一下限制,应该是针对域名的限制。

evalution版本跑起来倒是没啥问题,但是据我的经验,应该会针对时间有限制,比如到一定时间搞出几个alert之类的。


这里我只介绍evalution版本是如何通过代码做限制的,仅供学习参考:

打开它的压缩代码,如果你直接搜索alert,搜出来都是不相关的alert,所以需要自己看代码,看有什么特别的地方,可以找到下面这段在很多地方重复的代码,引起了我的注意:

_j = ~[], _j = {___ : ++_j,$$$$ : (!1 + "")[_j],__$ : ++_j,$_$_ : (!1 + "")[_j],_$_ : ++_j,$_$$ : ({} + "")[_j],$$_$ : (_j[_j] + "")[_j],_$$ : ++_j,$$$_ : (!0 + "")[_j],$__ : ++_j,$_$ : ++_j,$$__ : ({} + "")[_j],$$_ : ++_j,$$$ : ++_j,$___ : ++_j,$__$ : ++_j}, _j.$_ = (_j.$_ = _j + "")[_j.$_$] + (_j._$ = _j.$_[_j.__$]) + (_j.$$ = (_j.$ + "")[_j.__$]) + (!_j + "")[_j._$$] + (_j.__ = _j.$_[_j.$$_]) + (_j.$ = (!0 + "")[_j.__$]) + (_j._ = (!0 + "")[_j._$_]) + _j.$_[_j.$_$] + _j.__ + _j._$ + _j.$, _j.$$ = _j.$ + (!0 + "")[_j._$$] + _j.__ + _j._ + _j.$ + _j.$$, _j.$ = _j.___[_j.$_][_j.$_], _j.$(_j.$(_j.$$ + '"\\' + _j.__$ + _j.$_$ + _j.__$ + _j.$$$$ + "\\" + _j.$__ + _j.___ + "(\\" + _j.__$ + _j.$_$ + _j.$$_ + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j.$$$ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j.___ + _j.$__ + _j.$_$_ + _j.__ + _j.$$$_ + "().\\" + _j.__$ + _j.$__ + _j.$$$ + _j.$$$_ + _j.__ + "\\" + _j.__$ + _j._$_ + _j.$__ + "\\" + _j.__$ + _j.$_$ + _j.__$ + "\\" + _j.__$ + _j.$_$ + _j.$_$ + _j.$$$_ + "()\\" + _j.$__ + _j.___ + ">\\" + _j.$__ + _j.___ + _j.__$ + _j.$__ + _j.$$$ + _j.$___ + _j.$$_ + _j.$$_ + _j.$__ + _j._$$ + _j.$$$ + _j.$_$ + _j.___ + _j.$$$ + _j.__$ + "){" + _j.$_$_ + (!1 + "")[_j._$_] + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j._$_ + _j.__ + "('\\" + _j.__$ + _j.$_$ + _j._$_ + "\\" + _j.__$ + _j.$$_ + _j._$$ + "\\" + _j.__$ + _j._$_ + _j.___ + (!1 + "")[_j._$_] + _j._ + "\\" + _j.__$ + _j.$_$ + _j.$_$ + _j.$_$$ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j._$_ + _j.$__ + _j._$ + _j._$ + (!1 + "")[_j._$_] + "\\" + _j.__$ + _j.$_$ + _j._$$ + "\\" + _j.__$ + _j.$_$ + _j.__$ + _j.__ + "\\" + _j.$__ + _j.___ + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j.$$_ + _j.$_$_ + (!1 + "")[_j._$_] + _j._ + _j.$_$_ + _j.__ + "\\" + _j.__$ + _j.$_$ + _j.__$ + _j._$ + "\\" + _j.__$ + _j.$_$ + _j.$$_ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j.$$_ + _j.___ + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j._$_ + "\\" + _j.__$ + _j.$_$ + _j.__$ + _j._$ + _j.$$_$ + "\\" + _j.$__ + _j.___ + _j.$$$_ + "\\" + _j.__$ + _j.$$$ + _j.___ + "\\" + _j.__$ + _j.$$_ + _j.___ + "\\" + _j.__$ + _j.$_$ + _j.__$ + "\\" + _j.__$ + _j.$$_ + _j._$_ + _j.$$$_ + _j.$$_$ + ".');" + _j.__ + "\\" + _j.__$ + _j.$_$ + _j.___ + "\\" + _j.__$ + _j.$$_ + _j._$_ + _j._$ + "\\" + _j.__$ + _j.$$_ + _j.$$$ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j.$_$ + _j.$$_ + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j.$$$ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j.___ + _j.$_$ + "\\" + _j.__$ + _j.$$_ + _j._$_ + "\\" + _j.__$ + _j.$$_ + _j._$_ + _j._$ + "\\" + _j.__$ + _j.$$_ + _j._$_ + '();}"')())()

评经验这应该是版本限制的关键之处,由于evalution版本能直接跑起来,所以是不是这段代码,还需要分析。如果是从demo页上下载的版本,简单的方法可以直接全文搜索,把这种代码都去掉,看还会不会报错,就知道是不是这段代码做了限制,有兴趣的自己去试。


分下一下这段代码,看怎么个过程:

上来使用了一个js中的位操作符~处理了一个空数组,在Chrome中运行,结果是-1,关于~操作符的意义,自己去查吧。这里多说一句,我们经常使用indexOf方法,这个方法会返回-1,在用if判断时候,还要和-1进行比较,其实可以用这个~操作符像下面这样写:

if(~str.indexOf("aaa")){//str.indexOf("aaa")==-1}//这样写比较难懂,so不建议这样搞

接着是对_j变量的赋值,用Chrome运行一下,看结果:


我们看到_j里面的变量已经得到0-9数字以及几个字符,从代码中你并没有看到任何字符,它就得到了“abcdef”,主要是通过下面这种方法得到字符串,然后在通过数组索引提取字符:

(!1+"")=="false"(!0+"")=="true"({}+"")=="[object Object]"
还可以通过越界访问数组的方式得到“undefined”,例如:[][-1]+""

_j.$_ = (_j.$_ = _j + "")[_j.$_$] + (_j._$ = _j.$_[_j.__$]) + (_j.$$ = (_j.$ + "")[_j.__$]) + (!_j + "")[_j._$$] + (_j.__ = _j.$_[_j.$$_]) + (_j.$ = (!0 + "")[_j.__$]) + (_j._ = (!0 + "")[_j._$_]) + _j.$_[_j.$_$] + _j.__ + _j._$ + _j.$

上面这段代码得到了字符串“constructor”,接着

_j.$$ = _j.$ + (!0 + "")[_j._$$] + _j.__ + _j._ + _j.$ + _j.$$,
上面这段代码又得到了字符串“return”

_j.$ = _j.___[_j.$_][_j.$_],//0["constructor"]["constructor"]
上面这代码得到了Function对象,是通过Number对象找到Function对象,原型关系


通过得到Function对象就可以运行用字符串表示的代码了,非常利于使用混淆的字符串进行操作。

最后我们把_j.$看成是Fucntion,看看Function里面是怎么构造的:

_j.$$ + '"\\' + _j.__$ + _j.$_$ + _j.__$ + _j.$$$$ + "\\" + _j.$__ + _j.___ + "(\\" + _j.__$ + _j.$_$ + _j.$$_ + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j.$$$ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j.___ + _j.$__ + _j.$_$_ + _j.__ + _j.$$$_ + "().\\" + _j.__$ + _j.$__ + _j.$$$ + _j.$$$_ + _j.__ + "\\" + _j.__$ + _j._$_ + _j.$__ + "\\" + _j.__$ + _j.$_$ + _j.__$ + "\\" + _j.__$ + _j.$_$ + _j.$_$ + _j.$$$_ + "()\\" + _j.$__ + _j.___ + ">\\" + _j.$__ + _j.___ + _j.__$ + _j.$__ + _j.$$$ + _j.$___ + _j.$$_ + _j.$$_ + _j.$__ + _j._$$ + _j.$$$ + _j.$_$ + _j.___ + _j.$$$ + _j.__$ + "){" + _j.$_$_ + (!1 + "")[_j._$_] + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j._$_ + _j.__ + "('\\" + _j.__$ + _j.$_$ + _j._$_ + "\\" + _j.__$ + _j.$$_ + _j._$$ + "\\" + _j.__$ + _j._$_ + _j.___ + (!1 + "")[_j._$_] + _j._ + "\\" + _j.__$ + _j.$_$ + _j.$_$ + _j.$_$$ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j._$_ + _j.$__ + _j._$ + _j._$ + (!1 + "")[_j._$_] + "\\" + _j.__$ + _j.$_$ + _j._$$ + "\\" + _j.__$ + _j.$_$ + _j.__$ + _j.__ + "\\" + _j.$__ + _j.___ + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j.$$_ + _j.$_$_ + (!1 + "")[_j._$_] + _j._ + _j.$_$_ + _j.__ + "\\" + _j.__$ + _j.$_$ + _j.__$ + _j._$ + "\\" + _j.__$ + _j.$_$ + _j.$$_ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j.$$_ + _j.___ + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j._$_ + "\\" + _j.__$ + _j.$_$ + _j.__$ + _j._$ + _j.$$_$ + "\\" + _j.$__ + _j.___ + _j.$$$_ + "\\" + _j.__$ + _j.$$$ + _j.___ + "\\" + _j.__$ + _j.$$_ + _j.___ + "\\" + _j.__$ + _j.$_$ + _j.__$ + "\\" + _j.__$ + _j.$$_ + _j._$_ + _j.$$$_ + _j.$$_$ + ".');" + _j.__ + "\\" + _j.__$ + _j.$_$ + _j.___ + "\\" + _j.__$ + _j.$$_ + _j._$_ + _j._$ + "\\" + _j.__$ + _j.$$_ + _j.$$$ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j.$_$ + _j.$$_ + _j.$$$_ + "\\" + _j.__$ + _j.$$_ + _j.$$$ + "\\" + _j.$__ + _j.___ + "\\" + _j.__$ + _j.___ + _j.$_$ + "\\" + _j.__$ + _j.$$_ + _j._$_ + "\\" + _j.__$ + _j.$$_ + _j._$_ + _j._$ + "\\" + _j.__$ + _j.$$_ + _j._$_ + '();}"'


通过Chrome运行可以看到上面这段代码返回结果是:

return"\151f\40(\156e\167\40\104ate().\147et\124\151\155e()\40>\401478664375071){ale\162t('\152\163\120lu\155b\40\124ool\153\151t\40e\166aluat\151o\156\40\160e\162\151od\40e\170\160\151\162ed.');t\150\162o\167\40\156e\167\40\105\162\162o\162();}"

看上去乱了些,因为使用escape了,我们unescape一下就OK了:

return if (new Date().getTime() > 1478663379071){alert('jsPlumb Toolkit evaluation period expired.');throw new Error();}
看到了吧,是不是很巧妙,在这里检查了时间,如果大于某一时间就alert,并且抛异常。


这就是evalution版本的限制,估计demo版本里面肯定是检查了域名,道理一样。以上分析过程仅供学习参考,看看js的巧妙使用方法。


注:本人非常反对拿破解的js库使用在收费或者商业的产品中,请尽量使用开源版本!







0 0
原创粉丝点击