#技术向 新年CTF红包-2020年
本文最后更新于 181 天前,其中的信息可能已经有所发展或是发生改变。

在刚刚过去的一段时间,各位大佬都做了一些CTF红包,在这里我会说一下我当时是怎么领到这些红包的。(应该不会有大佬来捶我的吧)多图预警!!!流量不多的不要点进来哦,或者连上WiFi再看。

第一个:由Martian(麻田)大佬发出的红包,那么我们现在开始。
首先我们打开第一关的页面,看到如下错误提示

麻田哥哥第一关-1

我们仔细观察这个错误页,是不是和平常的错误页不太一样?(线索!)

大意:在此服务器上没有找到您请求的虚拟主机

没有找到虚拟主机?唔,那也就是说我们需要找到对应的域名才能访问。那怎么找到域名呢?这里我恰好用nmap扫描了一下,nmap给我返回了一个rDNS(反向DNS)

Martian第一关-2

那有没有可能是它呢?由于得到的域名并不是一个域名后缀,我们尝试将这个“域名”使用Hosts解析到这台服务器。 Bingo~ 我们得到了新的页面
随后看了看页面没啥,然后打开了F12(开发者工具),发现线索
Martian第一关-3

查询 RFC3912 可以得到提示是关于 WHOIS 的细节。直接查询 103...185 的 WHOIS 可以得到

~ whois 103...185
… # 部分略去
inetnum: 103...185 – 103...185
netname: HAPPY-NEW-YEAR
descr: Happy new year of rat – Round 1
… # 部分略去
last-modified: 2020-01-23T04:30:05Z
remarks: ||.|.||||.|…|| 2020 ||..|..||||||.|. |.|||.|||||.|||.
remarks: ||..|.|.||||..|| ||.|..||||.||.|. ||…|..|||…||
source: APNIC
… # 部分略去

将 remarks 字段里的 | 换成 1,. 换成 0,再用GB系列编码二进制转换成汉字(经测试在 GB2312、GB18030、GBK 中均可转换):

1101011110100011 ==转码=> 祝
2020             ==保留=> 2020
1100100111111010 ==转码=> 生
1011101111101110 ==转码=> 活
1100101011110011 ==转码=> 鼠
1101001111011010 ==转码=> 于
1100010011100011 ==转码=> 你

连起来就是口令 “祝2020生活鼠于你”。

Round2

在页面的noscript标签里使用了颜文字混淆了 Javascript 代码,参考 aaencode

Martian第二关-1

直接复制执行,得到一个 Word 文档的下载链接。

Martian第二关-2

下载的文件名为 “[Round 2]国家*****发表二〇二〇年新年贺词.docx”,可以发现这个文件仅包含不到两千字,但体积却有 12.9MB,这里是第一个提示。
打开后,粗略浏览可以看到正文除了几个特别的字外,其余的字体均一致且为仿宋。而这几个字的字体为 “HappyNEWYearofRats-Meow”,这是第二个提示。

Martian第二关-3

解法1

将这些字复制到纯文本环境 (如 Sublime Text, 浏览器的输入框)中,会发现字发生了变化。所有文字对应关系如下(按在 Word 中出现的顺序):

Word 中 => 纯文本环境中
三      => 年
四      => 有
五      => 鼠
一      => 祝
不      => 六
二      => 新
完      => 七
乐      => 十
的      => 八
快      => 九

将上述对应关系按照从 “一” 到 “十” 排序,即得到口令 “住新年有鼠不完的快乐”。

解法2

将 Word 文件后缀改为任一压缩包格式,解压分析 XML 源数据。在这里也可以看到占用空间较大的字体,然后找到这个字体名在正文 XML 中对应的内容。

接下来是Soha (超级大佬)的,但我看到这个的时候没电脑没条件做233,我就抄官方题解好了(滑稽)

Soha题目首页

0x01 第一关

Soha第一关-1

第一关点击“开”按钮,就出现了一张图片。将这张图片下载下来。使用二进制查看器打开,可以在最后看到一串 base64 编码的神秘代码。解码可得通往第二关的 URL。
Soha第一关-2

0x02 第二关

Soha第二关-1

第二关是一个神秘的系统,首先告诉了你一个账号,我们用这个账号试试。
Soha第二关-2

并没有用,还被嘴臭了一番……不过它提示了我们要用“admin”去登录,但是不知道密码,该怎么办呢?遇事不决查看源代码。
Soha第二关-3

发现了有调试信息没有删除,由此可知,数据库是 MongoDB。在数据库开发的时候很容易遇到的一个问题就是注入,而 MongoDB 可以使用形如 fieldName: { $condition: value } 的方式来查询,如果后端没有对这里进行检查,而是直接使用 $_POST[‘field’] 的话就会被注入。那么我们将密码的 name 属性改成 password[$ne],$ne 就是 MongoDB 中的不等于。这样子提交以后,后端查询的就是 { username: ‘admin’, password: { $ne: ” } } 了。

Soha第二关-4

现在提交就能进入系统了。并获得第一份红包口令,以及下一关的地址。
Soha第二关-5

0x03 第三关

第三关下载的是一个 bin 文件。观察得知这是一个 gzip 压缩过的文件,里面是一个 pcapng 文件。解压后将其丢进 Wireshark。

Soha第三关-1

Soha第三关-2

可见这是一个对 USB 进行抓包得到的数据。虽然没说这是啥,但是看包大小,以及每个包之间十分相似的结构,只有几个字节变化的数据,可以猜测应该是键盘鼠标等 HID 设备的数据。实际上就是对我的 Type Cover 进行抓包得到的。

这个包里只有单纯的数据,没有设备刚插上的时候的初始化数据,所以什么是键盘什么是触摸板的数据,就得靠自己分析了。触摸板一般是短时间内连续十分多的(表现出连续性的),像这些 0x04 开头的应该就是触摸板了。

Soha第三关-3

这种两个一组的,第一个字节 0x01 的,第三个字节一下子是 0x00 一下子是另一个值的,就是键盘的数据了。
Soha第三关-4

用 usb.capdata[0]==0x01 在 Wireshark 中筛选出来,然后将余下的包导出为 CSV 或者 JSON 方便后续进行数据处理。
Soha第三关-5

虽然各个厂商的数据结构可能不一样,但是键盘键位对应的值是确定的,规定在 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。将后面那个目录拉出来塞进去就行了。(这里我特意打得特别慢,怕抖动导致包不对)

Soha第三关-6

0x04 第四关

访问那个目录,得到第四关的信息:

Soha第四关-1

dig 可得一个 IPv6 地址。并不需要 IPv6 环境就可以解得口令,这个地址的最后半部分 26150521 就是一个八位的数字,就是红包口令。
Soha第四关-2

如果你拥有 IPv6 环境,通过 HTTP 访问我还会给你一个聊胜于无的温馨提示:
Soha第四关-3

根据这个页面的访问记录,应该至少有六位朋友看到了这个提示,但是可能很多人都没看出来 2615:521 的完整形式是 2615:0521。
Soha第四关-Log

0x05 彩蛋红包

如果打开源代码仔细看过,就可以发现注释中提示了有“彩蛋红包”。那么它在哪儿呢?

Soha-彩蛋-1

找来找去,其实没地方能藏,唯一能藏的就是那个 SVG。打开 SVG 就可以发现玄机了。
Soha-彩蛋-2

0x06 结局

这里的时间都是基于 24 日晚上 8 点的偏移。

第一个红包

被领走 20/20,+0:13:41 第一次被领取,+1:35:15 被领完。

第二个红包

被领走 2/12,+2:31:48 第一次被领取,+20:11:13 第二次被领取。恭喜通关的两位大佬!

Soha-第二个红包领取记录

彩蛋红包

被领走 44/50,+0:5:45 第一次被领取。

今年的新年CTF红包就写到这吧,以后如果有时间而且有红包的话,我应该也会写?唔,到时候看看吧。就这样。
感谢阅读~

评论

  1. haima 博主
    Windows Chrome 81.0.4033.0
    10月前
    2020-1-27 15:28:54

    转载本文章或使用部分文字图片请遵守CC-BY-NC-SA 4.0协议,本文部分文字与图片版权归属于对应站点所有者,若您要使用这些内容也请遵守对应的版权协议,若没有或不适用请联系对应站点获得授权后再使用,谢谢。

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇