0

论如何又收一个新年解谜红包 – 2020篇

 4 years ago
source link: https://blog.kaaass.net/archives/1247
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

没错,今年的解谜红包又lei了。由于武汉疫情,大家想必都积极响应国家号召躲在家里吧,所以我又整了这么个红包。今年的题面是: http://app.kaaass.net/Redpacket2020.zip不过需要注意,有一个牌子写错了:’\x10/1;%=\x0f\x11W\x18b.lK’=> ‘dGhlcGlhbm8v==’。 以下是题解。

Stage1 – 红石大师

题面是一个Minecraft存档,需要1.14+版本才可以打开。进入存档后,可以得到一本书:

6re2632.png!web

拉开活塞后,进入到一个房间,里面放了与门、或门和非门。

z6zyY3J.png!web

之后是两个简单的红石谜题,操作就是调整拉杆。不过如果你打开存档的时候注意到了作弊没关,可以直接切换为创造模式逃课(

解开最后一个谜题之后,应该会发现地上的红石灯开始闪烁。闪烁间隔又长又短,亮灯时间也又长又短,不难猜测是摩斯电码,跟着阅读就能得到:458/26/638。没错,这就是一个坐标,而且格式正是F3调试画面中中显示的坐标格式。接下来可以通过使用tp指令/tp 458 26 638,或直接挖过去的方法达到下一关。

One more thing…

如果你感觉读电码太过困难,可以试试群里豆豆dalao的方法,用中继器引出红石信号:

vayaQvB.png!web

另外,简单讲解下这个机器。整个机器分为两部分,即上部的摩尔斯编码部分,与下侧的活塞轮存储部分。活塞轮用来存储需要发送的数据,而摩尔斯编码则是根据活塞轮的内容进行发报。

2MrIB3Z.png!web

活塞轮连接一个脉冲发生器,用来定时旋转活塞轮。活塞轮的原理是透明方块不可被充能而不透明方块可以,详细可以参考Minecraft wiki的红石部分。

FzaArub.png!web

之后,活塞轮的输出被引到摩尔斯编码器。摩尔斯编码器的一侧是一个上边沿检测器,用来把活塞轮的输入转为脉冲。之后把脉冲送入编码器上方由中继器组成的时轴。

ZZNv6n3.png!web

时轴上可以随时引出当前的脉冲。若需要某一刻输出1,则在玻璃上放置一个中继器即可。单个单元结构如下:

3qiEni6.png!web

阅读当前的配置就可发现,活塞轮从输入端自左向右分别编码:/987612345。当然如果只是为了解题,你不需要看懂这个机器,只需要读摩尔斯电码即可。

Stage2 – 三位一体

MJzum2A.png!web

来到指定坐标后,看到告示牌指示向前走。在一片黑暗中,大概会掉落到一个坑里,周围奏响了“希望之花”的旋律。定睛一看可以看到三个神秘内容的告示牌,和一个提示。

UVJreuI.png!web

非常尴尬且抱歉的是,我还写错了一个牌子,中期更正的三个牌子内容为:

‘\x17\x05\x0f<%=%\x13TG\x0ch\x1d\x1b’  ‘dGhlcGlhbm8v==’  ‘\x07*>\x07\x00\x00*\x02\x03_nFqP’

最靠谱的,显然是’dGhlcGlhbm8v==’。看起来就很像base64,但是丢进解码器会发现解码失败?其实如果你了解base64,“==”实际上是用来补3的占位符,而这段内容并不需要补占位,去掉后解码可以得到“thepiano/”,果然这就是base64。现在问题就是另外两个了。其实占位符已经暗示了,这一段base64其实只是一大段base64的一部分,另外两段应该也是base64。而恢复它们的方法需要参考提示——“三位一体”。有什么东西可以合并呢?没错,就是异或,按照顺时针顺序,从’dGhlcGlhbm8v==’开始异或可以得到:

‘dGhlcGlhbm8v==’ XOR ‘\x07*>\x07\x00\x00*\x02\x03_nFqP’ = ‘cmVkcGFja2V0Lm’

‘cmVkcGFja2V0Lm’ XOR ‘\x17\x05\x0f<%=%\x13TG\x0ch\x1d\x1b’ = thYWFzcy5uZXQv

然后再按照顺时针拼接,就可以得到:’cmVkcGFja2V0LmthYWFzcy5uZXQvdGhlcGlhbm8v==’,解码得到: redpacket.kaaass.net/thepiano/

Stage3 – 希望之花

打开网页之后,可以看到一个钢琴。

EjaAniR.png!web

点击图片发现,这个钢琴事实上是可以演奏的。查看网页逻辑,其实相当的简单,就是点击按键之后播放“play.php?key=按键音名”。

ieem2q2.png!web

随便请求一个(比如:http://redpacket.kaaass.net/thepiano/play.php?key=G4)会发现并不会发生什么,检查网页发现,需要带上cookie“session”才可以正常返回音频。而且返回音频后,session竟然发生了变化。研究session发现,这其实是一个base64,解码后内容类似:,,,,,A4,E4,E5,D4,B4,F4,D5,D4,E5,E4,C5,A4,G4,F4,F4,G4,G4。也就是你刚刚弹奏的内容,这强烈暗示了你要弹奏什么。那弹什么呢?还记得第二关掉到洞里面听到的“希望之花”(mi si la si #do #do)嘛?

弹奏的过程中,你可能会注意到一个奇怪的事情。比如弹si的时候,如果你是按照旋律弹奏的,那你会发现如果是mi si请求的是:http://redpacket.kaaass.net/thepiano/piano_voice/414fd923-c377-4766-a062-9009f12273ee.mp3。而直接弹请求的是:http://redpacket.kaaass.net/thepiano/piano_voice/6d4f974d-8c48-4264-887b-de68340e663a.mp3。不妨下载下来研究下。研究发现,第一个音频比第二个稍微大了一点点,并且前面的内容完全一样,而且文件末尾还能看到“redpacket2020/dest”的字样。

没错,文件末尾还隐藏了内容!事实上,弹奏中的每个音都隐藏了一段。不过mp3文件没有明确的文件尾标志,一般需要使用一些能解析文件结构的程序(如010editor)才能识别出哪一段是隐藏内容的开始。不过幸好不按顺序弹奏能获得原本的音频,因此可以直接进行比对。总共有八个音,也就是说有八段内容。按顺序拼接之后,我们就得到了下一关的题目。

One more thing…

这一关希望提醒大家,html还有一个map标签。19年中,我意外发现很多网页在实现区域点击的时候实现都乱七八糟,不同设备下定位还会偏移。其实使用map标签就能解决这个问题。

另外,因为Stage2的失误,因此在这里放了个抱歉的红包,这个红包的红包码在cookie内。

Stage4 – AWSL

如果你懒得拼接,我帮你拼了一份: http://app.kaaass.net/attachment/dest.bin

不难发现,这是一个pyc文件,因此随便找一个在线反编译器丢进去……如果你不幸运的话,会发现报错了。这其实是因为,代码包含了一个“花命令”:新版本的类型注解。所以你需要一个船新版本的反编译器: https://python-decompiler.com/ 。反编译得到结果:

import requests
 
 
def xor(a, b):
    return ''.join((lambda cur_char: [chr(ord(x[0]) ^ x[1]) for x in cur_char])(zip(a, b)))
 
 
def load_asset():
    url = 'http://redpacket.kaaass.net/kksk.bmp'
    return requests.get(url).content
 
 
def check(data : bytes, key1, key2):
    key2 = int(key2)
    cipher = data[key2: key2 + 8]
    return xor(key1, cipher) == 'sh92a40a'
 
 
if __name__ == '__main__':
    print('加载资源中...')
    data = load_asset()
    print('请输入密码1:')
    key1 = input()
    print('请输入密码2:')
    key2 = input()
    if check(data, key1, key2):
        print('密码正确!')
    else:
        print('密码错误!')

代码下载了一个资源文件,并要求输入key1和key2,key2需要是一个整数。检查时,取资源的key2处8个字节,与key1异或,若结果是’sh92a40a’则正确。

由于异或的性质,我们可以得到:xor(‘sh92a40a’, cipher) == key1。因此简单异或应该就能得到答案了。那么先把资源文件下过来康康(wp不接受bmp图片,因此博客内图片并非源文件,请自行下载)。

VfIVJru.jpg!web

是熊猫人,awsl。等等,先别死,这文件1.5mb,能异或出150多万行,怎么找结果啊???

这一关解法有很多,我能想到的就有两个。如果dalao们有新的想法,欢迎评论告诉我。

方法1 – 暴力

根据代码,key1拢共8位,不难猜到这就是红包码。而红包码是8位数字,不如直接找出所有xor(‘sh92a40a’, cipher)是数字的结果。编码寻找发现,符合8位都是数字的只有一个。

方法2 – 以图搜图

所以为什么不直接找原图呢?作为bmp文件(而且是BMP_RGB),一大段文件内容都是像素点,不如直接找出原图比较一下。使用某度以图搜图找到一张尺寸一样的原图,然后转成bmp格式,发现只有几处不同(我测试的时候是2处)。用不同处偏移尝试就能获得结果。

隐藏Stage

秉持优良传统,今年也藏了一个隐藏红包,同样欢迎大家来玩,同样也回复可见2333333

抱歉!需要才能阅读隐藏内容。

算上今年,解谜红包已经整了3年了。而今年无疑是最失败的一年。没错,红包无人解出,log里Stage3只有一个请求。仔细想想,每一年我都想把红包设计的更加复杂,并且绞尽脑汁想加入更多编程中的实用内容,比如今年有base64结构、mp3结构和python花命令。但是仔细想想,红包的意义在于被收,乐趣其实体现在收的过程。像Stage2那样的关卡实在是太不和蔼了。如果明年还发红包,那一定不会再设置这种很难想的题目了(也不会搞要下载mc那么复杂的操作了)。

最后祝大家新年快乐,身体健康!也希望武汉疫情早日结束~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK