文章时间太早,图片丢失
# Misc-red_vs_blue
简单来说就是 66 轮试错,同一次 nc 里面的答案是一样的,要么输入 r, 要么输入 b,错了就输入 y 重来,因为有时间限制,只能上脚本(本来还想手搓)
from pwn import * | |
# sh=process ("./buu--rip") local 端 | |
sh = remote('node4.buuoj.cn', 28699) | |
s = [] | |
i=1 | |
tag=0 | |
q = sh.recvuntil(':') | |
while True: | |
if i==66: | |
break; | |
if tag==0: | |
sh.send('r') | |
q=sh.recvuntil(':') | |
print(q) | |
if b'again' not in q: | |
i+=1;s.append('r') | |
continue | |
else : | |
sh.send('y') | |
for m in s: | |
sh.recvuntil(':') | |
sh.send(m) | |
sh.recvuntil(':') # | |
tag = 1 | |
continue | |
elif tag==1: | |
sh.send('b') | |
q=sh.recvuntil(':') | |
print(q) | |
if b'again' not in q: | |
i += 1;s.append('b') | |
continue | |
else: | |
sh.send('y') | |
for m in s: | |
sh.recvuntil(':') | |
sh.send(m) | |
sh.recvuntil(':')# | |
tag = 0 | |
continue | |
print(i) | |
sh.interactive() |
代码稍微有点小问题,第 66 轮直接跳出来了,懒得改了。。。
就随便猜一下然后就可以拿到 flag。
# Misc-funny_maze
跟前面那题
差不多的思路,就是典型的迷宫问题多搞几次就能出来 flag.
from pwn import * | |
dirs=[(0,1),(1,0),(0,-1),(-1,0)] #当前位置四个方向的偏移量 | |
path=[] #存找到的路径 | |
def mark(maze,pos): #给迷宫 maze 的位置 pos 标 "2" 表示 “到过了” | |
maze[pos[0]][pos[1]]=2 | |
def passable(maze,pos): #检查迷宫 maze 的位置 pos 是否可通行 | |
return maze[pos[0]][pos[1]]==0 | |
def find_path(maze,pos,end): | |
mark(maze,pos) | |
if pos==end: | |
print(pos,end=" ") #已到达出口,输出这个位置。成功结束 | |
path.append(pos) | |
return True | |
for i in range(4): #否则按四个方向顺序检查 | |
nextp=pos[0]+dirs[i][0],pos[1]+dirs[i][1] | |
#考虑下一个可能方向 | |
if passable(maze,nextp): #不可行的相邻位置不管 | |
if find_path(maze,nextp,end):#如果从 nextp 可达出口,输出这个位置,成功结束 | |
print(pos,end=" ") | |
path.append(pos) | |
return True | |
return False | |
def see_path(maze,path,leng): #使寻找到的路径可视化 | |
length = 0 | |
for i,p in enumerate(path): | |
if i==0: | |
maze[p[0]][p[1]] ="E" | |
elif i==len(path)-1: | |
maze[p[0]][p[1]]="S" | |
else: | |
maze[p[0]][p[1]] =3 | |
print("\n") | |
for r in maze: | |
for c in r: | |
if c==3: | |
print('\033[0;31m'+"*"+" "+'\033[0m',end="") | |
length+=1 | |
elif c=="S" or c=="E": | |
print('\033[0;34m'+c+" " + '\033[0m', end="") | |
elif c==2: | |
print('\033[0;32m'+"#"+" "+'\033[0m',end="") | |
elif c==1: | |
print('\033[0;;40m'+" "*2+'\033[0m',end="") | |
else: | |
print(" "*2,end="") | |
print() | |
print(length+1) | |
leng=length+1 | |
return leng | |
def maze_change(num): | |
MAZE=[] | |
row=col=0 | |
M=str(sh.recvuntil("P")) | |
print(M) | |
MAZE.append([]) | |
for m in M: | |
if col == num: | |
MAZE.append([]) | |
row+=1 | |
col=0 | |
if m == '\n': | |
continue | |
elif m == '#': | |
MAZE[row].append(1) | |
col+=1 | |
elif m == ' ': | |
MAZE[row].append(0) | |
col+=1 | |
elif m == 'S': | |
MAZE[row].append(0) | |
start=(row,col) | |
col+=1 | |
elif m =='E': | |
MAZE[row].append(0) | |
end=(row,col) | |
col+=1 | |
elif m =='P': | |
break | |
print(MAZE) | |
return MAZE, start, end | |
def gets(num): | |
maze=[] | |
start=(0,0) | |
end=(0,0) | |
maze,start,end=maze_change(num) | |
find_path(maze,start,end) | |
leng=0 | |
leng=see_path(maze,path,leng) | |
sh.sendline(str(leng+1)) | |
sh=remote("node4.buuoj.cn",27512) | |
print(sh.recvuntil(b'game')) | |
sh.sendline("1") | |
gets(11) | |
print(sh.recvuntil(b'level!')) | |
dirs=[(0,1),(1,0),(0,-1),(-1,0)] #当前位置四个方向的偏移量 | |
path=[] #存找到的路径 | |
gets(21) | |
print(sh.recvuntil(b'level!')) | |
dirs=[(0,1),(1,0),(0,-1),(-1,0)] #当前位置四个方向的偏移量 | |
path=[] #存找到的路径 | |
gets(31) | |
print(sh.recvuntil(b'level!')) | |
dirs=[(0,1),(1,0),(0,-1),(-1,0)] #当前位置四个方向的偏移量 | |
path=[] #存找到的路径 | |
gets(101) | |
sh.interactive() |
其中迷宫问题的部分代码是从这里复制来的
值得注意的是多次循环,变量初始化的问题,我排查了好久 ( ̄_ ̄|||)
一开始没有注意到这个问题,还以为是我哪个顺序出错了,后来才发现。
# Misc-ezSteganography
比赛时只解出前半个,记录一下比赛时的错误思路 (。﹏。):
(根据第二个提示,后半大概率是 Green 通道里的图片藏了啥信息,然而第一个提示里的 QIM quantization 估计是加密方法,然后,我们就纠在 QIM 是啥的问题上了。。。 )
然而实际上只要把 g0 和 g1 通道的两张图异或一下就可以了,就用 stegsolve 里的 Image Combiner 的功能
前半 flag 加第一条提示 ↑
第二条提示 ↑
后半个 flag ↑
# Misc-Just a GIF
『赛后复现』和国赛 running_pixel 的题基本是一个思路,gif 分离出 451 张图,分为 41 组,每组 11 张图。
然后每组的第 i 张和第一组的第 i 张作比较,不一样的画黑,就可以了。
from PIL import Image | |
path = "Just_a_GIF/" #填自己的路径 | |
for i in range(11): | |
picn = Image.new("RGB",(119,83),(255,255,255)) | |
for j in range(1,41): | |
p1=Image.open(path+str(i)+'.png') | |
p2=Image.open(path+str(i+j*11)+'.png') | |
for w in range(119): | |
for h in range(83): | |
if p1.getpixel((w,h)) != p2.getpixel((w,h)): | |
picn.putpixel((w,h),(0,0,0)) | |
picn.save(str(i)+'.png') |
然后就拿到 11 张图片 ↓
手动拼接? ↓
网上搜一下,貌似是 DataMatrix,扫出 flag
DASCTF
# Misc-Nuclear wastewater
『赛后复现』彩色的二维码,比赛最后经队友提示,看了看它 RGB 才有了思路。
所有的色块竟然都是,三个通道两个为 0,剩一个有值,那肯定密码就藏在这里了。
写个脚本把数字转出来
from PIL import Image | |
img = Image.open("Nuclear wastewater.png") | |
for i in range(3): | |
for j in range(0,230,10): | |
for t in range(0,230,10): | |
rgb=list(img.getpixel((t,j))) | |
if rgb[i]>32 and rgb[i]<128: | |
print(chr(rgb[i]),end='') |
得到这个
Ys>UEJht#?ppeEFtstR#:hitR:@s@YRteK#e@KsR&E&:eR:Eht/#iKtteYKhYKYhhhihhKtC2tt:HVEesY&#@Rj!seRi:eitEtKsetKtEE:hh#h#eYKYihhYK(Kt@iSY$KY/@pRsEetsip:~h@eeEs!E&&::EsEEei#/iYe#/ieKKt//iKYhh
发现很多重复的字符,想到使用词频分析看一下
from collections import Counter | |
f = 'Ys>UEJht#?ppeEFtstR#~:hi~tR:@s@YRteK#e@KsR&E&:eR:Eht/#iKtteYKhYKYhhhihhKtC2tt:HVEesY&#@Rj!seRi:eitEtKsetKtEE:hh#h#eYKYihhYK(Kt@iSY$KY/@pRsEetsip:~h@eeEs!E&&::EsEEei#/iYe#/ieKKt//iKYhh' | |
print(Counter(f)) |
得到: theKEYis:#R@/&p~!>UJ?FC2HVj(S$
初步尝试,发现这个不太对,密码错误。。。
瞻仰一波套神的 wp 之后,原来 >UJ?FC2HVj(S$
词频为 1,所以顺序可能出错,推测词频为 1 的部分不是密码,
所以得到密码:
'#R@/&p~!'
解压得到 flag.txt.... (T_T)
果然我还是太天真了,还以为能直接拿到 flag...
瞅瞅内码,然后看到了这个:
哦吼,还有个零宽?
包含 U+200C U+200D U+200E,网址
隐藏内容是:
2021 年 4 月 13 日,核废水在 Citrix 县的 CTX1 市尤为严重
好吧,完全不知道....(;′⌒`)
搜了一下 Citrix CTX1,大概是某种加密,
终归还是了解的太少了
emm... 搜索发现 CyberChef 可以进行解密 §( ̄▽ ̄)§
解两次得到 flag:
flag
到这里,misc 就结束啦! (o゚v゚) ノ