鼠年啦,快来玩鼠年春节限定红包!→ https://hb.lohu.info
下面是一些你应该知道的事情:
- 这是一个 CTF 闯关游戏,利用你的知识(现学也是可以的啦)解决所有题目,获得红包口令,口令可进入支付宝领取红包。
- 你应该需要电脑才能愉快玩耍。
- 你拿到的所有答案都是八位数字,为了方便控制开始和结束时间,在支付宝领取时,前面需要加上一个“鼠”字。如解题得到 66741003,那么最后的红包口令是“鼠66741003”。
- 如果你是和别人一起完成的,希望你们能只领取一次,然后大家分。
- 通过一关后自然会得到进入下一关的线索,一共有四关。
- 本次活动时间从 2020 年 1 月 24 日 20 时开始,持续 24 个小时,如果红包被提前领完,则游戏提前结束。
- 共设 2 个红包。第 1 个红包总额 50 人民币元,分 20 个;第 2 个红包总额 66 人民币元,分 12 个。红包领取规则均为“拼手气红包”。
- 游戏结束后也将在当前页面上放出题解。如有疑问也请通过博客的“关于我”页面上所述的联系方式联系。
- 最后祝大家,新年快乐!
- 近期 2019-nCoV 疫情严峻,大家要注意防范哦!
活动结束后将在下面更新题解。加油!新年快乐!
题解已放出,欢迎围观。
往期回顾
因为去年题目只有两个人做出来,所以今年大幅降低了难度。然后第一个红包两个小时就被领完了……
0x01 第一关
第一关点击“开”按钮,就出现了一张图片。将这张图片下载下来。使用二进制查看器打开,可以在最后看到一串 base64 编码的神秘代码。解码可得通往第二关的 URL。
0x02 第二关
第二关是一个神秘的系统,首先告诉了你一个账号,我们用这个账号试试。
并没有用,还被嘴臭了一番……不过它提示了我们要用“admin”去登录,但是不知道密码,该怎么办呢?遇事不决查看源代码。
发现了有调试信息没有删除,由此可知,数据库是 MongoDB。在数据库开发的时候很容易遇到的一个问题就是注入,而 MongoDB 可以使用形如 fieldName: { $condition: value }
的方式来查询,如果后端没有对这里进行检查,而是直接使用 $_POST['field']
的话就会被注入。那么我们将密码的 name 属性改成 password[$ne]
,$ne
就是 MongoDB 中的不等于。这样子提交以后,后端查询的就是 { username: 'admin', password: { $ne: '' } }
了。
现在提交就能进入系统了。并获得第一份红包口令,以及下一关的地址。
0x03 第三关
第三关下载的是一个 bin 文件。观察得知这是一个 gzip 压缩过的文件,里面是一个 pcapng 文件。解压后将其丢进 Wireshark。
可见这是一个对 USB 进行抓包得到的数据。虽然没说这是啥,但是看包大小,以及每个包之间十分相似的结构,只有几个字节变化的数据,可以猜测应该是键盘鼠标等 HID 设备的数据。实际上就是对我的 Type Cover 进行抓包得到的。
这个包里只有单纯的数据,没有设备刚插上的时候的初始化数据,所以什么是键盘什么是触摸板的数据,就得靠自己分析了。触摸板一般是短时间内连续十分多的(表现出连续性的),像这些 0x04 开头的应该就是触摸板了。
这种两个一组的,第一个字节 0x01 的,第三个字节一下子是 0x00 一下子是另一个值的,就是键盘的数据了。
用 usb.capdata[0]==0x01
在 Wireshark 中筛选出来,然后将余下的包导出为 CSV 或者 JSON 方便后续进行数据处理。
虽然各个厂商的数据结构可能不一样,但是键盘键位对应的值是确定的,规定在 HID Usage Table 里面。第三个字节呢对应的就是键盘上的键位,第二个字节则是 Shift、Alt 之类的键位。于是可以写出这样的代码来解析数据:
const fs=require('fs');
const data=JSON.parse(fs.readFileSync('keyboard_packets.json').toString());
const keyboardPackets=data.map(o => o._source.layers['usb.capdata'].split(':').map(n => parseInt(n, 16)));
const _MODKEY=[
[0x01, "LCtrl"],
[0x02, "LShift"],
[0x04, "LAlt"],
[0x08, "LMeta"],
[0x10, "RCtrl"],
[0x20, "RShift"],
[0x40, "RAlt"],
[0x80, "RMeta"],
];
const _KEY=[
null, 'ErrorRollOver', 'POSTFail', 'ErrorUndefined',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'Enter', 'ESC', 'Backspace', 'Tab', 'Space',
'-', '=', '[', ']', '\\', '`', ';', '\'', 'GraveAccent', ',', '.', '/',
'CapsLock', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12',
'PrintScreen', 'ScrollLock', 'Pause', 'Insert', 'Home', 'PageUp', 'DeleteForward', 'End', 'PageDown',
'RIGHT', 'LEFT', 'DOWN', 'UP', // Keyboard all here
];
const outputBuffer = []
keyboardPackets.forEach((d, i, a) => {
const mod=d[1], key=d[2];
if(!mod && !key){
return; // this packet is empty
}
const nextPacket=a[i+1] || [];
if(nextPacket[1] == mod && !key && !!nextPacket[2]){
return; // this key with mod key is not finished
}
const keyNames=_MODKEY.filter(([code]) => mod & code).map(([_,name]) => name);
if(_KEY[key] !== null){
keyNames.push(_KEY[key]);
if(keyNames.length === 1 && keyNames[0].length === 1){
outputBuffer.push(keyNames[0]);
}else{
outputBuffer.push(`<${keyNames.filter(o => o !== null).join('+')}>`);
}
}
});
console.log(outputBuffer.join(''));
最后可以分析数据,发现这里有 https,后面跟了一个 URL。将后面那个目录拉出来塞进去就行了。(这里我特意打得特别慢,怕抖动导致包不对)
0x04 第四关
访问那个目录,得到第四关的信息:
dig 可得一个 IPv6 地址。并不需要 IPv6 环境就可以解得口令,这个地址的最后半部分 26150521 就是一个八位的数字,就是红包口令。
如果你拥有 IPv6 环境,通过 HTTP 访问我还会给你一个聊胜于无的温馨提示:
根据这个页面的访问记录,应该至少有六位朋友看到了这个提示,但是可能很多人都没看出来 2615:521
的完整形式是 2615:0521
。
0x05 彩蛋红包
如果打开源代码仔细看过,就可以发现注释中提示了有“彩蛋红包”。那么它在哪儿呢?
找来找去,其实没地方能藏,唯一能藏的就是那个 SVG。打开 SVG 就可以发现玄机了。
0x06 结局
这里的时间都是基于 24 日晚上 8 点的偏移。
第一个红包
被领走 20/20,+0:13:41 第一次被领取,+1:35:15 被领完。
第二个红包
被领走 2/12,+2:31:48 第一次被领取,+20:11:13 第二次被领取。恭喜通关的两位大佬!
彩蛋红包
被领走 44/50,+0:5:45 第一次被领取。
我们明年见!
学习学习~
reply
学习学习大佬
reply
想不到吧 今年还是只有两个人
我觉得这个USB题 太容易卡了 我通过查表和猜测 猜测04是数位板 03是键盘
然后发现这个键盘和ctf-wiki里面键盘的传输协议差别有点大 就感觉我猜错了(
然后数位板 找了好半天协议文档 也没有对应上这个04
搞了一个来小时就放弃了(
reply
同楼上。触控板的坐标让我猜出来了,画出来每一笔没发现有啥内容,但是没发现 03 是键盘,于是卡到那边了。
reply
每个厂商的数据格式都不一样的,我刚去拜读了一下 ctf-wiki 确实是不一样的。具体该如何解读是在设备刚插上的时候告诉系统的,所以只能靠分析。
reply
键盘才出来了,网上随便找的脚本,解出来是791DE18AC27DFBF[unknown]52ED990FF87,试了半天没想到中间是个/
reply
见上面的回复,如何解析我的这个数据以文中的脚本为准。
reply
还有个疑问:有时候请求头部出来的「x-happy-new-year: 09a29bc6-83d1-47fa-b94d-d3219d946f03.png」是什么意思?一直以为是个 flag,但是没猜出来后面怎么进去。
reply
那个是去年的线索。是CDN的锅,好像部分地区会有这个问题,我点了强制所有节点刷新也没用_(:3
reply
hhhhhhh,USB 那个太妙了,膜大佬(
reply
去年的 x-happy-new-year 还留着坑了我半天,,看了往期回顾才发现 /bj(第一次玩)
reply
每次看完soha佬的文都会进入贤者时间
reply