VNCTF2022 WriteUp

17 篇文章 4 订阅
本文详细介绍了多个CTF挑战的解决方案,包括Crypto ezmath的SHA256计算,Web Game V4.0的base64编码flag,BabyMaze的字节码分析,Misc的图像处理,Strangeflag的文件系统编程语言,simplemacos的密码破解,以及prizewheel的图像解谜。通过这些挑战,展示了密码学、逆向工程和图像处理技术的应用。
摘要由CSDN通过智能技术生成

Crypto

ezmath

限制了60s 我只能说我这垃圾电脑边玩MC边跑根本跑不完777次我草

如果2^N-1能被15整除,那么自然数N应取那些值 百度搜(2^n-1) % 15就有

from pwn import *
context.log_level='debug'
import re
def sha256(enc,sec):
    table = string.ascii_letters+string.digits
    for i in table:
        for j in table:
            for k in table:
                for n in table:
                    s = i+j+k+n
                    s1 = s+sec
                    m = hashlib.sha256(s1.encode())
                    mi = m.hexdigest()
                    if(enc == mi):
                        return s

p = remote('node4.buuoj.cn',28865)
rec = p.recv()
sec = rec[16:32].decode()
sha = rec[37:-23].decode()
print(sec,sha)
result = sha256(sha,sec)
print(result)
p.sendline(result.encode())
i = 0
while 1:
    r = p.recv().decode()
    que = re.search('plz give me the (.*)\(n\)',r).group(1)[:-3]
    ans = str(int(que)*4).encode()
    print(i)
    p.sendline(ans)
    i += 1
    if(i == 777):
        p.recv()
        p.recv()
        p.recv()
    p.recvuntil('are so smart.\n')

Web

GameV4.0

找到/js/data.js。拉到最下面即可看到base64编码后的flag

VNCTF{Welcome_to_VNCTF2022}

Reverse

BabyMaze

直接打印出字节码,用老方法

import dis, marshal, sys

header_sizes = [
    # (size, first version this applies to)
    # pyc files were introduced in 0.9.2 way, way back in June 1991.
    (8,  (0, 9, 2)),  # 2 bytes magic number, \r\n, 4 bytes UNIX timestamp
    (12, (3, 6)),     # added 4 bytes file size
    # bytes 4-8 are flags, meaning of 9-16 depends on what flags are set
    # bit 0 not set: 9-12 timestamp, 13-16 file size
    # bit 0 set: 9-16 file hash (SipHash-2-4, k0 = 4 bytes of the file, k1 = 0)
    (16, (3, 7)),     # inserted 4 bytes bit flag field at 4-8
    # future version may add more bytes still, at which point we can extend
    # this table. It is correct for Python versions up to 3.9
]
header_size = next(s for s, v in reversed(header_sizes) if sys.version_info >= v)

with open('BabyMaze.pyc', "rb") as f:
    metadata = f.read(header_size)  # first header_size bytes are metadata
    code = marshal.load(f)          # rest is a marshalled code object

dis.dis(code)

在这里插入图片描述

可以看到得到了很多0,2和1个1和1个3,。

而且很明显是31*31

处理一下,画个图

s = '0000000000000000000000000000000010222222222222222220222222222002020000000002000002020000000200202220222222202220222020222020020000020000000002000002020202002220222022222222222220222022200002020002000000000000020000000022202022202222222220222022202002000202000200000002020002020200222220202220222020202220202220000000020200020202020002020002002222222022222022202022202022200200000000000000020202000202000022222220222222202022202220222002000002020202000200000200000000202220202020202220222222222220020202020202000200020000020002002020202020222022202022202022200202000202000200020202020002000022202220202222202020202220222002000202020200000202020002020200202220202022222220202020202020020200020200000000000202020202002022202020222222222020202020200200020202000002020202020202020022202020222220202022202220202000000200000002000200000002000200222220222220222022222220222220020000020002000200000002000002002222222220222222222222202222300000000000000000000000000000000'
from PIL import Image
pic = Image.new('RGB',(31,31),(255,255,255))
for i in range(31):
    for j in range(31):
        if(s[i*31+j] == '0'):
            pic.putpixel((j,i),(0,0,0))
        elif(s[i*31+j] == '1'):
            pic.putpixel((j,i),(255,255,0))
        elif(s[i*31+j] == '3'):
            pic.putpixel((j,i),(255,0,255))
pic.show()
pic.save('flag.png')

在这里插入图片描述

在后面还能看到如果在29,29就输出flag,说明起点是1,1。

手动走一下

ssssddssaassddddwwwwddwwddddddwwddddddssddwwddddddddssssaawwaassaassaassddssaassaawwwwwwaaaaaaaassaassddddwwddssddssssaassddssssaaaaaawwddwwaawwwwaassssssssssssddddssddssddddddddwwaaaaaawwwwddssddwwwwwwwwddssddssssssssddddss

md5一下就是flag(重新走的,flag不确定是不是这个了)

VNCTF{801f190737434100e7d2790bd5b0732e}

Misc

问卷

VNCTF{See_You_Next_Time!!!}

仔细找找

直接脚本近邻发现间隔不相同,想用蓝帽半决的爆破脚本发现找不到,PS也没成功弄出来,最后本来想着一个个手撸,然后发现其实第24列和15排,就只有黑色和白色,那只提取白色,不就有了横坐标和纵坐标的索引。

from PIL import Image
pic = Image.open('flag.png')
w,h = [],[]
for i in range(pic.size[0]):
    if(pic.getpixel((i,15)) == (255,255,255)):
        w.append(i)
for i in range(pic.size[1]):
    if(pic.getpixel((24,i)) == (255,255,255)):
        h.append(i)
img = Image.new('RGB',(len(w),len(h)),(255,255,255))
for i in range(len(w)):
    for j in range(len(h)):
        img.putpixel((i,j),pic.getpixel((w[i],h[j])))
img.show()

在这里插入图片描述

vnctf{34aE@w}

Strange flag

其实就是用tree里面是否有文件夹来代表0和1,是一种esolang,叫Folders。举例:

然后手撸

在这里插入图片描述

只能说第一次还少了一个字母

vnctf{d23903879df57503879bcdf1efc141fe}

simple macos

不是给了hint说是弱密码吗,一开始我就对着keychain和login-keychain爆破,后者用了rockyou,前者用了常见6000密码,依旧没有爆破出来。搜VNCTF(含大小写)及其16进制和base也没搜出什么名堂来。题目主要是说system,于是就去system文件夹找。除了Preboot以外其他都是空的,直接进去。然后就是一个个翻了(系统文件没看)

接着在/var/db下发现东西。为CryptoUserInfo.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>79FABCCE-3636-4266-A6CF-8E3BB40332B4</key>
	<dict>
		<key>FullName</key>
		<string>Scr1pt</string>
		<key>PasswordHint</key>
		<string>our secret need a password</string>
		<key>PictureData</key>
		<data>
		base串,不方便展示
		</data>
		<key>PictureFormat</key>
		<string>JPEG</string>
		<key>ShortName</key>
		<string>scr1pt</string>
		<key>UserType</key>
		<string>OpenDirectory</string>
	</dict>
</dict>
</plist>

passwordHint oursecret

在这里插入图片描述

当然,不给提示看文件尾也是很明显是oursecret,因为oursecret靠的这些特征块来识别的

在这里插入图片描述

很明显,文件尾现在掺杂了其他数据,且有},猜测是后半部分的flag。于是复制出来并删掉下面部分

在这里插入图片描述

这时再结合弱口令。试了两个就出了。密码是123456

在这里插入图片描述

合起来得到flag

VNCTF{Macos_Forensllc_1s_s1MMple}

prize wheel

首先是python-exe-unpacker-master逆

然后再用BabyMaze说的方法弄出字节码

能很明显找到password:f6a623a2c577de3b46c079267d4bdd6e

在这里插入图片描述

解压出来。
在这里插入图片描述

然后成功做了6个多小时

在这里插入图片描述

第一想法是一圈圈的读,然后重排,结果是这样的

在这里插入图片描述

就很奇怪。

给出了索引这个hint,立刻联想到了[HECTF2021]七色彩虹、[b01lers2020]image_adjustments。具体是什么去看wp

于是有了更奇怪的图。这里因为调试覆盖掉了所以不放图。

之后,想到了将上面两者联系起来。即转圈圈读、找索引、平铺写入

在这里插入图片描述

大概得到这个鸟样的图片。

很明显可以看出什么,那就是他们越来越扁。然后结合这是个大转盘,诶想出来了。

应该转圈圈读、找索引、转圈圈写入

之后就是调了快一个小时的脚本,我太菜了。

from PIL import Image
def get_round(w):
    tb = []
    #从左上到右上、从右上到右下、从右下到左下、从左下到左上,分四步
    for i in range(w,609-w):
        tmp = img.getpixel((i,w))
        # print(tmp)
        tb.append(tmp)
    # print(len(tb))
    for i in range(w+1,609-w):
        tmp = img.getpixel((609-1-w,i))
        tb.append(tmp)
    for i in range(w+1,609-w):
        tmp = img.getpixel((609-1-i,609-w-1))
        tb.append(tmp)
    for i in range(w+1,609-w-1):
        tmp = img.getpixel((w,609-1-i))
        tb.append(tmp)
    # print(len(tb)) #2432== 609*2+607*2
    return tb

def put_round(w,img,tb): #用和上面一样的方法,只不过要放值进去,就这样。
    ind = 0
    for i in range(w,609-w):
        tmp = img.putpixel((i,w),tb[ind])
        ind += 1
    # print(len(tb))
    for i in range(w+1,609-w):
        tmp = img.putpixel((609-1-w,i),tb[ind])
        ind += 1
    for i in range(w+1,609-w):
        tmp = img.putpixel((609-1-i,609-w-1),tb[ind])
        ind += 1
    for i in range(w+1,609-w-1):
        tmp = img.putpixel((w,609-1-i),tb[ind])
        ind += 1

if __name__ == '__main__':
    # 除去最中间那个点,一共(609-1)//2
    img = Image.open('flag.png')
    pic = Image.new('RGBA',(609,609),(255,255,255,255))
    for i in range(304):
        table = get_round(i)
        ind = table.index((255,255,255,255))
        # print(ind)
        new_table = table[ind:] + table[:ind] #当时这里我一直是用两个循环去弄的,跟个傻子一样
        put_round(i,pic,new_table)
    pic.show()

在这里插入图片描述

vnctf{3fd2f296-60cf-46d7-82b2-2f9949664ed7}

这里为了更好看一点,小修一下。

(后面部分属于赛后复现)

因为这里可以发现,都是从(i,i)点作为起点,所以那根白色的线,是斜着的。

那么想办法让他横着就行。

但是捏,依然要从(i,i)点作为起点。这样的话,只需要让白色像素在横着的水平面或者竖着的水平面上就可以了

只需要把main改成这样:

if __name__ == '__main__':
    # 除去最中间那个点,一共(609-1)//2
    img = Image.open('flag.png')
    pic = Image.new('RGBA',(609,609),(255,255,255,255))
    for i in range(304):
        table = get_round(i)
        ind = table.index((255,255,255,255))
        # print(ind)
        new_table = table[ind:] + table[:ind] #当时这里我一直是用两个循环去弄的,跟个傻子一样
        new_table = new_table[len(new_table)//8:] + new_table[:len(new_table)//8]
        put_round(i,pic,new_table)
    # pic.show()
    pic.save('real_flag.png')

在这里插入图片描述

我超!太好看了叭
你可能以为一开始代码就这么简洁
错了
一开始的代码边调试边猜边写一共200多行,乱的一批。
甚至一个写出了一个高叟操作花了十五分钟才在不报错只是一片白的图里面知道原因

                    for k in range(f,len(table)):
                        img.putpixel((i_2, j_2),table[f])
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值