传送门:2020新年解谜
祝大家2020元旦快乐。以下是游戏的题解。
第一关
传送门:第一关。
答案:对
。
打开后只有闪烁的背景颜色。查看网页源码后发现,颜色闪烁是由 websocket 服务器控制的。
window.addEventListener("load", function () {
websocket = new WebSocket("wss://harrynull.tech/2020/ws/lvl1");
websocket.onmessage = function (evt) { $("body").animate({
backgroundColor: evt.data == 'L' ? '#FFC500' : '#FFA500'
}, 500); };
}, false);
实际上,这里的颜色闪烁代表摩尔斯电码。写一个程序分析亮灭之间时间间隔(注意在较差的网络环境下得到时间可能会不大稳定)。
websocket = new WebSocket("wss://harrynull.tech/2020/ws/lvl1");
function now(){return new Date().getTime(); }
var lastL=new Date().getTime();
var lastO=new Date().getTime();
websocket.onmessage = function (evt) {
if(evt.data=='L') {console.log("Empty " + Math.round((now() - lastO)/1000) ); lastL=now();}
if(evt.data=='O') {console.log("On " + Math.round((now() - lastL)/1000) ); lastO=now();}
};
可发现间隔时间有Empty 1
代表一个短间隔,Empty 3
代表一个长间隔,Empty 6
代表序列重复间的间隔。On 1
代表短,On 2
代表长。按照此规则可写出解码程序。
var res = "";
websocket.onmessage = function (evt) {
if(evt.data=='L') {res+=(Math.round((now() - lastO)/1000)==1?"":" "); lastL=now();}
if(evt.data=='O') {res+=(Math.round((now() - lastL)/1000)==1?".":"-"); lastO=now();}
};
得到摩尔斯电码. ..... .- ..-. -... ----.
,解码得E5AFB9
,即对
的 utf-8 编码。
附本关 python 源码
async def lvl1(websocket):
pattern = '. ..... .- ..-. -... ----.' # E5AFB9 对
while True:
for c in pattern:
if c==' ':
await asyncio.sleep(2)
continue
await websocket.send('L')
await asyncio.sleep(1 if c=='.' else 2)
await websocket.send('O')
await asyncio.sleep(1)
await asyncio.sleep(5)
第二关
传送门:第二关。
答案:年
。
观察 URL 可得本关地址。这一关既可以手动/js半手动解,也可以写脚本解。基本方法是二分+递归。
附本关 python 源码
async def lvl2(websocket):
import random
import time
FLAG = '年'
CHECK_INTERVAL = 10
i=random.randint(0, 999)
j=i
while j==i: j=random.randint(0, 999)
while True:
message = await websocket.recv()
message = message[0] + decompress([ord(i) for i in message[1:]])
await asyncio.sleep(CHECK_INTERVAL)
if message[0]=='A':
await websocket.send(FLAG if message.count('1')==2 and message[i]=='1' and message[j]=='1' else 'Incorrect')
elif message[0]=='T':
await websocket.send('Conflict' if message[i]=='1' and message[j]=='1' else 'OK')
第三关
传送门:第三关。
答案:纳
。
设计解法:
反编译 wasm 得到判断密码正确的算法。其原始 C 代码如下:
int f(int g){
return g==0?0:g+f(g/2);
}
int checkPassword(int pwd){
return f(pwd)==64859?pwd:0; // 纳 32435
}
然后这里可以用遍历等方式获得 pwd 值为 32435,即“纳”的 utf-16 编码。
暴力解法:
直接用 javascript 遍历可能的 unicode 值。
for(var i=0;i<100000;i++) if(checkpwd(i)) console.log(i);
得到32435
, String.fromCharCode(32435)
得“纳”。
第四关
传送门:第四关。
答案:喜
。
提示是 esolang,即 “esoteric programming languages”。这里网页里实际上包括了一段 whitespace 代码,如下。
转换成伪代码则是
push 21915
push 1
add
end
即21916
,喜
的 UTF-16 编码。
红包
根据主页的说明,红包口令即为对年纳喜20
。