【wp】2021DASCTF July X CBCTF 4th

第一天打dfjk去了,打完回来看发现逆向一道Golang一道lua,不太想啃,于是干脆光速转行做杂项= =

也没想到能差一题就ak杂项了(逃。学到很多,顺手总结总结(RE手要跑路啦)。

回头有空复现一下剩下的那道杂项和那个lua逆向(咕咕咕

Misc

red_vs_blue

连上去以后乱答了几次,发现在同一次连接的情况下(重来的时候按y),每一场的预测都是一样的。

image-20210801204741907

所以直接pwntools连上去爆破即可:

#!/usr/bin/env python # ------ Python2 ------ from pwn import * # context.log_level='debug' host="node4.buuoj.cn" port=25384 r=remote(host,port) myInput='' pred='rb' cnt=0 for _ in range(3): r.recvline() while True: r.recvline() r.recvline() r.sendline(pred[cnt%2]) r.recvline() r.recvline() rslt=r.recvline() print(pred[cnt%2],rslt) if 'successful' in rslt: myInput+=pred[cnt%2] print("[input] -> "+myInput) if len(myInput)==66: break else: r.sendline('y') for x in myInput: r.recvuntil('\n') r.recvline() r.sendline(x) r.recvline() r.recvline() r.recvline() cnt+=1 r.interactive()

image-20210801212244559

flag{783e1bfd-0803-47b6-b302-28591dcb9fca}

funny_maze

连上去发现是走迷宫,3和2都看了一下分别是:

image-20210801212517120

要点在:输入路径的长度,并且有时间限制。

一开始以为这个and的意思是先输入路径再输入长度,结果写完脚本以后一直跑都不对,甚至跑去问工作人员了(x)。后来看到有解,才发现应该是自己理解出了问题XD

去年年底打zhb的时候也有一道杂项是远程迷宫(当时写过一版bfs),于是直接拿来改了,微调了一下recvline的次数:

#!/usr/bin/env python # ------ Python2 ------ from pwn import * # import time # t=time.clock() # context.log_level='debug' host="node4.buuoj.cn" port=29294 r=remote(host,port) r.recvuntil('game\n') r.sendline('1') dirs=[[0,1],[1,0],[0,-1],[-1,0]] flag_char='dsaw' cntSuccess=0 while True: if cntSuccess==0: maze=r.recvuntil('answer:\n').split('\n')[:-1] else: maze=r.recvuntil('answer:\n').split('\n')[3:-1] cntSuccess+=1 print("------") for rows in maze: print(''.join(rows)) print("------") maze=[list(n) for n in maze] row=len(maze) col=len(maze[0]) path=[] flag="" book=[[(0,0,0) for _ in range(col)] for _ in range(row)] head=0 tail=1 cnt=0 for i in range(len(maze)): if 'S' in maze[i]: start=(i,maze[i].index('S')) cnt+=1 if 'E' in maze[i]: end=(i,maze[i].index('E')) cnt+=1 if cnt==2: break path.append(start) book[start[0]][start[1]]=path[head]+('*',) maze[start[0]][start[1]]='#' isSuccess=0 while head<tail: for i in range(4): x,y=path[head][0]+dirs[i][0],path[head][1]+dirs[i][1] if x not in range(row) or y not in range(col) or maze[x][y]=='#': continue maze[x][y]='#' book[x][y]=path[head]+(flag_char[i],) path.append((x,y)) tail+=1 if x==end[0] and y==end[1]: isSuccess=1 break if isSuccess==1: break head+=1 cur=book[end[0]][end[1]] while cur[2]!='*': flag+=cur[2] cur=book[cur[0]][cur[1]] flag=flag[::-1] r.sendline(str(len(flag)+1)) print(flag) if cntSuccess==4: break # print('time: ',round(time.clock()-t,2),'s') r.interactive()

image-20210801213047317

拿到flag:flag{a2189c60-2011-4e1d-a369-28f6417fe0f7}

ezSteganography

图片隐写题,拿到手第一步当然是拿Stegsolve翻啦~果然能翻到一些不同寻常的东西:

image-20210801213402811

看到Green plane 0时黑点点突然密集了,感觉是LSB,于是解了一下:

image-20210801213526432

看到开头有典型的png文件头,猜测是一张png,所以直接Save Bin然后改后缀名为png,得到:

green0

拿到flag的前半部分flag{2e9ec6480d0515和提示关键词QIM quantizetion,查了一下是QIM量化,并且给出了步长为20。

在github上找了几个脚本都不能直接用,看了一眼相关论文,最后拿QuantizationIndexModulation/qim.py at master · pl561/QuantizationIndexModulation的脚本改了一下,对原图进行处理:

import numpy as np from PIL import Image class QIM: def __init__(self, delta): self.delta = delta def embed(self, x, m): x = x.astype(float) d = self.delta y = np.round(x/d) * d + (-1)**(m+1) * d/4. return y def detect(self, z): shape = z.shape z = z.flatten() m_detected = np.zeros_like(z, dtype=float) z_detected = np.zeros_like(z, dtype=float) z0 = self.embed(z, 0) z1 = self.embed(z, 1) d0 = np.abs(z - z0) d1 = np.abs(z - z1) gen = zip(range(len(z_detected)), d0, d1) for i, dd0, dd1 in gen: if dd0 < dd1: m_detected[i] = 0 z_detected[i] = z0[i] else: m_detected[i] = 255 z_detected[i] = z1[i] z_detected = z_detected.reshape(shape) m_detected = m_detected.reshape(shape) return z_detected, m_detected.astype(int) delta = 20 # quantization step qim = QIM(delta) filename = 'ezSteganography-flag.png' image = Image.open(filename) imdata = np.array(image) z_detected, msg_detected = qim.detect(imdata) im=Image.fromarray(np.uint8(msg_detected)) im.show()

res

拿到了flag的另外半部分。

最后拼一下flag有:flag{2e9ec6480d05150c211963984dcbc9f1}

Just a GIF

gif看不出什么,一般套路就是先把每一帧分离出来再说。

所以拿脚本分离:

from PIL import Image im=Image.open('./Just_a_GIF.gif') while True: try: cur=im.tell() im.save('frames/frame_'+str(cur).rjust(3,'0')+'.png') im.seek(cur+1) except EOFError: break

image-20210801215817427

就可以得到451帧的图片。

观察可以知道,每11张图片就是一个循环,有451/11=41个这样的循环。

一开始想比对一下各组循环的同一个位置的图片是不是同一张(比如frame_000.pngframe_011.png),所以写了个脚本跑了一下,xor两张图的对应像素,把黑的地方((0,0,0))置成白色,方便看一点:

res

发现有一些黑点点,意识到不对劲+1。

而下一组(frame_011.pngframe_022.png)的xor结果里黑点点更多了:

res2

所以猜测是把同一个位置的全部xor起来。

但是41组异或完肯定又变成原来这个图为底图(xor的奇数特性),所以异或前40组和后40组都试了一下,发现后40组的更清晰(猜测第一组是原图,没有魔改那种),所以写脚本xor:

from PIL import Image def xorTuple(t1,t2,size): ret=() for i in range(size): ret+=(t1[i]^t2[i],) return ret for x in range(11): width=119 height=83 res=[[(0,0,0) for _ in range(height)] for _ in range(width)] for pos in range(11+x,451,11): # 后40组 im=Image.open('frames/frame_'+str(pos).rjust(3,'0')+'.png') img=im.convert('RGB') for i in range(width): for j in range(height): res[i][j]=xorTuple(res[i][j],img.getpixel((i,j)),3) resImg=Image.new("RGB",(width,height)) for i in range(len(res)): for j in range(len(res[0])): if res[i][j]!=(0,0,0): resImg.putpixel([i,j],res[i][j]) else: resImg.putpixel([i,j],(255,255,255)) resImg.save("res_"+str(x).rjust(3,'0')+".png")

拿到了十一张图片:

res_000

res_001

res_002

res_003

res_004

res_005

res_006

res_007

res_008

res_009

res_010

很明显就是要根据最后两张指示的位置来拼前九张图片。

写了个脚本拼接有:

from PIL import Image ans_list=[[7,9,5],[1,3,2],[6,4,8]] #横过来的 width=83 height=83 ans=[[(0,0,0) for _ in range(height*3)] for _ in range(width*3)] for pi in range(3): for pj in range(3): im=Image.open('res_'+str(ans_list[pi][pj]-1).rjust(3,'0')+'.png') img=im.convert('RGB') for i in range(width): for j in range(height): ans[pi*83+i][pj*83+j]=img.getpixel((i,j)) ansImg=Image.new("RGB",(width*3,height*3)) for i in range(len(ans)): for j in range(len(ans[0])): ansImg.putpixel([i,j],ans[i][j]) ansImg.save("ans.png")

ans

从之前学校ISCNU的科普(CTF知识树 | 第五期: 你不知道的那些二维码)可以知道是data matrix,用解码网站(Read Data Matrix Barcode Online)扫一下就能拿到flag:

DASCTF{6bb73086aeb764b5727529d82b084cce}

问卷题

直接做问卷拿flag

DASCTF{79f3bb47a2e2d46def82c052eccb7b80}

Crypto

Yusa的密码学签到——BlockTrick

不懂密码学啥攻击方式的人看着这个脚本真的一脸懵逼(

但是想了想……签到题嘛说不定能瞎猫碰上死耗子,加上这个for _ in range(2):有点奇怪,感觉是专门能用来复用信息的,于是把第一次的输出当成第二次的输入再丢进去,就成了= =

image-20210801223008233

flag{edbffcb1-eb55-4ae3-8cc5-3b65663f1fec}


__EOF__

本文作者c10udlnk
本文链接https://www.cnblogs.com/c10udlnk/p/15846180.html
关于博主:欢迎关注我的个人博客-> https://c10udlnk.top/
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   c10udlnk  阅读(128)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示