援力满满交易所的自动许愿

​ 前几天在逛V2EX的时候发现一个帖子,是一个二次元虚拟人物交易所的引流贴,因为自己简历上也是类似的项目所以超激动的点进去了。发现是一个差不多10年的程序员新开了一个项目也是做ACGN交易所,在寻找一起玩的玩家。点进去后发现这个项目早在8年前就有人构思过并实现了,并且站长凭借当初的交易所项目拿到了进入IT行业的敲门砖。(怎么感觉很眼熟的样子。。。)

​ 帖子里还提到了更早以前就由类似的玩法不过是好莱坞明星的虚拟交易市场。这个新的项目使用 VUE+ELE+RAILS+SIDKIQ 写的(话说我觉得RAILS的官方网站响应超级快。。)。也提到了台湾也有个ACGN交易所。顺带吐槽了那个类似90年代的界面。感觉台湾人确实在一些网页界面上莫名的遵循古制。对,说的就是PTT。

​ 援力满满这个网站的玩法和ACGN不太一样,现在还是测试阶段,站长给了每个人每个股1000的原始股做测试。看了看网站界面,比ACGN-STOCK好多了,但是股票不多,也没看到可以提交股票申请上市的选项。

​ 这个网站代币的获得方式目前只有 “许愿” ,许愿会随机的给予一定的代币或者股票。通过这样放出代币活跃市场。但是许愿并不是没有代价的。如果没有代价就会有人无限制的点许愿了不是。许愿需要本地计算机提供工作量证明(LOVE_POW),方式大概是和现在的区块链一样。目前网站要求的工作量证明使用的算法是SHA512。

​ 这时候坏想法就出来了,网页上的许愿次数只有一次和十次的选项。作为一名合格的计算机学生这种重复性的工作肯定不能接受啊。于是想着怎么用脚本来刷"许愿"

​ 首先通过CHROME元素查看许愿给服务器发送了些什么数据,通过Network栏看到点击许愿后的这段时间里有5个请求。其中一个名为wishs的POST请求发送的数据是许愿的请求。其他的都是一些股票数据的更新。

​ 其中数据部分发送了

cheer_word:"TEST"
code: "ERIRI"
love_power:63895713284

​ 其中cheer_word应该是是许愿时候那段可以自定义的文字,默认是“我永远喜欢泽村·斯宾塞·英梨梨”。code应该是动漫任务的代码,关联你对那个人物许愿。其中love_power应该就是我们关键的工作量证明。这个love_power是本地JavaScript计算出来的。通过这几个关键的字段发送到服务器验证是否通过然后给账户添加代币或者是股票。这时候得弄清楚其中的ove_power是怎么被计算出来的。

​ 好消息是JavaScript这种脚本语言是保留在计算机本地直接可以查看的。坏消息是为了便与传输JavaScript一般会在发布的时候加混淆。

​ 通过Chrome的Sources栏查看网站附带的几个JS,发现其中一个名为app的最长。于是试着搜索了一下(虽然这里说说很简单,实际上这里看了好久找了好久才找到的。可能也是我菜吧)

​ 发现了其中工作量证明的部分代码。其实我不是很懂这里的部分是在做什么,但是里面的部分差不多可以猜到。

o是取unix时间,精确到分钟。(毕竟网络这部分有延迟,本地和服务器不一致计算出来的就不对了)

I是去股票的代码,估计就是ERIRI

r是那段可以自定义的祈祷词。

s是一个随机的数,范围是0-99999999999

c是r + s + o + i

然后对c进行sha512运算,正则判断是否有连续的四个0.

​ 在尝试理解love_power的由来以后尝试在Python里吧这个过程实现一遍

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    unixtime = int(time.mktime(time.strptime(time.strftime("%Y-%m-%d %H:%M:00", time.localtime()), '%Y-%m-%d %H:%M:%S')))
    stockcode = 'ERIRI'
    cheerWord = 'TEST'
    s = random.randint(0,99999999999)
    c = "{}{}{}{}".format(cheerWord, s, unixtime, stockcode).encode()
    res = hashlib.sha512(c).hexdigest()
    while re.search(r'0{4}$', res) is  None:
        unixtime = int(
            time.mktime(time.strptime(time.strftime("%Y-%m-%d %H:%M:00", 		        time.localtime()), '%Y-%m-%d %H:%M:%S')))
        s = random.randint(0, 99999999999)
        c = "{}{}{}{}".format(cheerWord, s, unixtime, stockcode).encode()
        res = hashlib.sha512(c).hexdigest()

在发送到服务器后返回的response也验证了我的猜想,证明我这工作量证明猜想是正确的。

1
2
3
{"success":true,"type":"coin","amount":608}
<_sre.SRE_Match object; span=(124, 128), match='0000'> 92230011940 b'TEST922300119401527526500ERIRI'
1527526500

有没有优化的空间呢?

可能有的。因为unix时间取值进度是分钟,所以我们在计算完一个love_power后是可以在该分钟内重复发送的。

但是如果今后服务器添加了已经验证过的love_power不能再验证就失效了。不过今后再说吧。

事后发现今天下午就已经有大佬用脚本刷了百万代币,果然我还是太菜了。