从4号开始第一次抢小米,然后利用两个晚上看了代码写了日志,竟发到了人人网上,后来觉得发到人人上算什么。所以放到了这里,从后面的分析来看,这篇里面不乏有些错误,只是原样放到了这里跟大家分享一下我的经历。
By:小宗
今天晚上不想干活,研究了一下小米2014年3月4号抢购的页面。时间不多所以只看了主要看了一下抢购时间到了之后执行的代码,没有看其他的地方。小米页面整理后又近1000行的代码,因此不可能在一个晚上全部看完,因此只看了点击“立即购买”这一条线的代码。不能保证分析的正确性。
内容枯燥,不喜欢的可以直接跳到结论去看
首先,小米抢购页面是这样的,开始抢购之后下面的“即将开始”会变成“立即订购”
所以重要的是点击“立即订购”后发生了什么,打开网站的源代码,以红米为例,上图方框中的代码是:
这里面没有事件,因此抢购开始后或一开始加载时会用JS添加事件之类的。可以看到它有一个DIV标签的ID是“hongmiBtn”,在一个页面中这个唯一,要添加事件一般都用它。然后再看页面的JS代码:
可以看到有四段JS,把所有代码都写在了一行。。。。囧
前三段似乎没什么用。。。页面布局的,可能是。
其实写在一行也没啥难的,插个广告,FireFox27.0的代码速记里有美化代码,整理后就是这样的(漂亮多了):
现在搜索“hongmiBtn”,可是在代码里竟然搜不到。。。。
我们发现一开始定义了一个字符串数组_$[](在JS里面变量名是可以有$的,所以有些库的名字就是$),好吧,使用16进制写的。就像在C里可以用'A'表示A也可以用‘\x41’,所以这也不是什么难题,复制一下,当作字符串输出就好了。。。搞定。。。
我觉得小米之所以这样做是因为怕别人读代码(其实也不是什么难事),其次就是有些存了一些特殊字符,总是用转义不好看,用文本编辑器编辑好之后统一转为16进制比较方便
翻译好之后发现 _$[164]就是“hongmiBtn”。下面使用这个变量的值是 这句:
这句意思应该是把ID是hongmiBtn的对象赋给f,也就是刚才那个DIV标签,让后给这个对象内部HTML改写成c.buy。当然最后这两个是一句代码,意思是根据经过一系列判断确定给f内部HTML改写成什么值,不用细读buy就暴露了c.buy是购买代码。
可见c.buy的值就是_$[156]为:
呵呵,终于见到了“立即购买”,这句的意思就是点击“立即购买”后会执行Util.showBox('phone');它是什么呢?
一大串但是有用的并不多检测之后就是getStatus.requestHdGet()这个的定义是:
基本没用,就是调用了This.jsonInter(CONFIG.srcs.hdget, _$[117],true)
其中有三个参数,第一个是全局变量CONFIG
_$[9] 的值是字符串
那么jsonInter函数的定义是
其实也没啥代码,就是给第一个参数又加了一个时间戳后,调用了createJs。createJs代码如下 :
重要的是两句,其中_$[55]的值是“script”就是说第一句给页面有添加了一段JS代码,它的地址是d.src=a;上面的分析之a= [photo-media] +时间戳1+时间戳2;其中var d。。。上面那就是把a中的两个{{。。}}替换掉。至于替换的是什么,应该是Showbox里面第二个if可以看出应该是产品类型和验证码。
懂URL结构的人都应该知道这个URL的中“?”前面是服务器地址,后面有三个变量product,fk和_,前两个的值刚才说过应该是产品类型和验证码,由变量名也可以印证。
至于返回的JS代码是什么又是怎么执行的我就不知道了,可惜没有打开网络分析看一下,不过据说是返回的JSON格式的数据,就是有关抢没抢到的,30秒后自动刷新,读取这个JSON的数据。或许因此那个函数叫做jsonInner吧,另外我似乎还看到了付款的代码。
结论
经过这么多步,其实就是用三个参数像服务器请求了一段JS代码,前两个不管(应该是型号和验证码,因为没看具体代码,或许验证码是在前几步验证),第三个变量或许应该特别注意。
第三个变量名叫_,是由打开页面的时间(精确到毫秒,没注意页面在时间到了之后会不会自动刷新,所以不知道这个值是最后一次手动刷新的还是到时间后自动刷新的时间)和按完“立即购买”后的时间组成的字符串(注意:这两个时间都是你电脑的本地时间),这是服务器唯一一个从本地获得的或许与抢购有关的变量,也许就关系到能不能抢到。 这两个时间由于是本地发送的,所以可以在发送的值可以手动控制,至于怎么样的值容易抢到这个要看服务器的代码吧。或许是两个值是过了12点且差越小越好(可能性很大,但是估计不能太小,否则服务器认为是不是手动输的验证码),或者是第一个值越早越好(没有读所有代码,所以第一个可能是值提前登录的早的好,不过可能性很小),或者是第二个值在过了12点之后里12点越近越好。
由于已经给出了JS购买代码,所以是可以提前使用JS提交,提交的通用方法就是在浏览器地址栏输入javascript: Util.showBox("phone")(区分大写小写),但是在没到抢购时间的时候提交上去服务器是不是认可你的提交就不知道了。上次抢华为X3,提前提交,那个服务器返回的就是时间未到,请更正系统时间之类的话。
还有一点儿问题是没有看页面倒计时的时间是从系统获得的还是从服务器获得的。X3的页面倒计时时间是从本地读取的。所以可以把表调快然后就可以点击购买了,但是服务器就返回了上面的话。
这是3月4号的抢购页面代码,明天的页面代码还不知道是什么,其实在页面内改个变量名一切就都变了。
以上就是我用所读到的信息能想到的,但不保证正确性
香农说,信息是减少不确定性的唯一因素,如果我多看一下代码,然后知道了第一个时间是抢购时间到了自动刷新的时间(假设),那个第一个时间就不可能是越早越好了。求两个时间差的可能性就更大了。
最后的最后,我应该是说祝我好运呢还是祝师妹好运呢?