NSSCTF Round#4 部分题目复盘

本来想着做出来的题都蛮基础的就不写了,后来寻思着把没有出的复现一下,顺便就把做了的所有题目记录下来

MISC

Signin

签到题,dockerhub 一搜就出了

Pixel_Signin

先把像素点提出来

from PIL import Image
f = open("1.txt",'w+')
image = Image.open("Pixel_Signin.png")
rgb_im = image.convert('RGB')
for i in range(31):
	for j in range(31):
		r,g,b = rgb_im.getpixel((j,i))
		print(r,g,b,file=f)

发现都是几十到一百冒头,考虑转字符看一下

看到中间的 "AFFPGS{Unehxv_vf_AFF_FHCREZNA_fb_guvf_gnfx_vf_rnfl}"

解一下凯撒得到 flag

Type Message

解压看到 D,T,M,F 四个文件,找到一个解密工具 dtmf2num,然后解一下四个音频

得到

627474238133
3118161334374
7333221535393
322217493

然后找到一个叫手机键盘密码的东西

但好像不怎么对啊,从 T.wav 开始就对不上号了,貌似每个文件的输出都多了一个数字,看 wp 说有一个在线网站 Detect DTMF Tones,嗯挺好使,正确的数应该是

627474238133
318161334374
733221535393
32217493

得到 "NSSCTF DTMFIS REALLY EASY"

Knight's Tour!

zip 打不开,winhex 看一下发现是 rar 头,改了头以后还是打不开(悲),ziprepair 修复一下就可以了,得到一个棋盘和一句话

本来想写个脚本走来着,但一想有写脚本的时间不如自己手算,以及赛后看群里讨论的说是找到一个只出现一次的字母开始走,或许这样更简单吧,但其实 t 看似很多,绝大部分路线却都是一眼假,唯一一个看似合理的走几步也能发现是错的,所以很容易得到起点为第三行第七列,然后手动走一下并给它上个色

一开始以为到每一点的步数和这一点的字母会有关联,于是算了很久 ascii,甚至编出了一个可以使前三位为 NSS 的计算公式,但再往后就一团乱,最终也没能得到一个合理的答案(悲)。然后得知是二进制,红 0 黄 1,每行转换过来是

01000011
01101000
00110001
01110110
01000000
01101100
01110010
01111001

得到:Ch1v@lry

RE

hide_and_seek

IDA 打开看到 main 函数里有两串数据长得蛮可疑的

看着下面那串像是 flag 的后半段,于是就试着上面的数据打印了一下,发现长得和前半段似的

#include <bits/stdc++.h>
using namespace std;
int a[] = {
  0x51, 0x17, 0x53, 0x43, 0x54, 0x46, 0x7B, 0x77
};
int main() {
  for (int i = 0; i < 8; i++) cout << (char)a[i];
  //QSCTF{w
  return 0;
}

两段合起来,是长这样的 "QSCTF{wud3_0n@,34p}"

我也没有仔细分析程序都干了啥,也懒得开虚拟机动调,但很明显有问题的字符的序号是 0 1 14 15,2~6 肯定是没问题的。然后直接就猜会不会是序号 0 1 7 8 14 15 的这些数分别异或某两个特定值,经过计算相邻的前后两个数分别异或 31 和 68,得到 "NSSCTF{h1d3_0n_h34p}",云里雾里的就结束了

web

菜比第一次见 wasm 的题,直接开摆,现在来复现一下,参考 官方 wp

先反编译

  • sudo apt install wabt
  • wasm-decompile wasm.wasm -o 1

根据 index.js,需要另 check 函数返回 true,在反编译后的文件里找到 assembly_index_check

先康康 lp

整理一下就是如下条件约束

a[0]+a[5] == a[1]+a[9]
a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9] == 1022
a[7]-a[8] == 10
a[3]+a[2]+a[1] == 330
a[5]*a[6]*a[8] == 617500
a[6]*2 == a[3]+15
a[7] == a[5]+a[4]-a[2]+3
a[8]+a[4] == 209
a[1]+a[8]+a[9]-a[4] == 204
a[0]*a[1]*a[2] == 1350628

用 z3 解一下

from z3 import *

a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = BitVecs('a0 a1 a2 a3 a4 a5 a6 a7 a8 a9', 32)
s = Solver()
s.add(a0 < 128)
s.add(a1 < 128)
s.add(a2 < 128)
s.add(a3 < 128)
s.add(a4 < 128)
s.add(a5 < 128)
s.add(a6 < 128)
s.add(a7 < 128)
s.add(a8 < 128)
s.add(a9 < 128)
s.add(a0 + a5 == a1 + a9)
s.add(a0 + a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 == 1022)
s.add(a7 - a8 == 10)
s.add(a3 + a2 + a1 == 330)
s.add(a5 * a6 * a8 ==  617500)
s.add(a6 * 2 == a3 + 15)
s.add(a7 == a5 + a4 - a2 + 3)
s.add(a8 + a4 == 209)
s.add(a1 + a8 + a9 - a4 == 204)
s.add(a0 * a1 * a2 == 1350628)
check = s.check()
print(check)
model = s.model()
print(model)

得到前十个字符:vvasm_And_,然后看 rp

其实就是传入的数据异或 2 与数组 c 作比较,而 c 是从 528 的地方开始取 20 个字节

即 vjcliq]dmp]{mwp]umpi,异或后得到 "thanks_for_your_work"

vvasm_And_thanks_for_your_work

小结:等夏活等的心里发毛,就想着参加个能做出题的小比赛转移一下注意力。一开始以为在晚上,上午搁那里快乐划水,划着划着才发现比赛已经开始了。反正我菜,纯属看题玩玩的,于是边跟朋友聊天边做,慢慢悠悠做的也比其他师傅慢得多,这场比赛如果从玩玩的角度出发确实蛮快乐的

posted @ 2022-08-05 14:51  Moominn  阅读(523)  评论(0编辑  收藏  举报