攻防世界和Nepnep战队主办的公益赛事,拯救流浪猫 !
Misc
Nepnep 祝你新年快乐啦!
找个按帧查看视频的软件,在最后几帧有flag。
MeowMeow
010分析png图片,发现有base编码:解密内容提示ascii art,用AsciiArtStudio打开,根据语义和提示猜测flag:CatCTF{CAT_GOES_MEOW}
Peekaboo
按照当时赛季的英雄一个个猜就行。
miao~
foremost分离出wav文件,用AU查看频谱看到CatCTF,deepsound解密,CatCTF作为密码,得到一个flag.txt,兽语解密即可。
Cat_Jump
notepad打开搜字符串CatCTF。
CatFlag
直接linux下cat flag,出题人设置的效果很酷。
CatCat
在猫猫.jpg里搜索password可以找到密码,根据txt文件名可以猜测是rabbit解密(密码就是jpg里的),然后base91解码,最后解码。
CatchCat
给了gps的数据,不难猜测直接解析数据然后把轨迹画出来就是flag。脚本的在这里。exp:
import pynmea2
import folium
import os
locations = []
file = open('CatchCat.txt','r')
for line in file.readlines():
record = pynmea2.parse(line)
locations.append([record.latitude,record.longitude])
def draw_gps(locations, output_path, file_name):
"""
绘制gps轨迹图
:param locations: list, 需要绘制轨迹的经纬度信息,格式为[[lat1, lon1], [lat2, lon2], ...]
:param output_path: str, 轨迹图保存路径
:param file_name: str, 轨迹图保存文件名
:return: None
"""
m = folium.Map(locations[0], zoom_start=15, attr='default') # 中心区域的确定
folium.PolyLine( # polyline方法为将坐标用线段形式连接起来
locations, # 将坐标点连接起来
weight=3, # 线的大小为3
color='orange', # 线的颜色为橙色
opacity=0.8 # 线的透明度
).add_to(m) # 将这条线添加到刚才的区域m内
# 起始点,结束点
folium.Marker(locations[0], popup='<b>Starting Point</b>').add_to(m)
folium.Marker(locations[-1], popup='<b>End Point</b>').add_to(m)
m.save(os.path.join(output_path, file_name)) # 将结果以HTML形式保存到指定路径
draw_gps(locations,'./','flag.html')
catnim
,只要满足每一轮拿掉物品之后的所有堆异或值为0即可,我的思路:设一共有n堆,让n-1堆先异或得到一个值xo,从剩下的那一堆拿掉一些值t,使其等于xo就行。如何选取剩下的那个值很重要,因为有时(很多时候),取的那个值小于xo,这就无法从里面取值,解决方案也很简单,就是从min开始遍历。完整exp:
from pwn import *
import copy
io = remote('223.112.5.156',51013)
print(io.recvuntil(b'Do you want just have a try,if you do that you can not get flag and without time limit(Y/N)?'))
io.sendline(b'N')
io.recvline()
while True:
pile = io.recvline().strip()
start = pile.find(b': ')
piles = list(map(int,pile[start+2:].split(b' ')))
# 浅拷贝
piles_ = copy.copy(piles)
print(piles_)
piles.sort()
print(piles_)
j = 0
while True:
# 这里从最小一个数遍历,用最大数会超时
min_num = piles[j]
print('min',min_num)
index = piles_.index(min_num)
print('index',index)
xo = 0
ff = True
for i in piles:
if i == min_num:
if ff == True:
ff = False
continue
xo = xo ^ i
if min_num > xo:
print('xo',xo)
t = min_num - xo
print('t',t)
print(io.recvuntil(b'where:'))
io.sendline(str(index).encode())
print(io.recvuntil(b'count:'))
io.sendline(str(t).encode())
print(io.recvline())
print(io.recvline())
print(io.recvline())
break
j = j + 1
print(j)
Crypto
cat’s gift
,所以就是pi即CatCTF{pie}。
cat_theory
感觉和范畴论也没有特别强的联系,提示像是为了增加逼格。就是同态加乘的性质。
from Crypto.Util.number import *
c1c2 = 127944711034541246075233071021313730868540484520031868999992890340295169126051051162110
c2c3 = 63052655568318504263890690011897854119750959265293397753485911143830537816733719293484
c3c1 = 70799336441419314836992058855562202282043225138455808154518156432965089076630602398416
m2_m1 = c2c3 - c3c1
m2 = (m2_m1 + c1c2)//2
m1 = c1c2 - m2
m3 = c2c3 - m2
m = c1c2 + m3
print(long_to_bytes(m))
盖茨比
根据解密出的明文之间的关系进行异或处理构造出以m1为key的mtp。
import base64
from Crypto.Cipher import AES
import binascii
from pwn import xor
from Crypto.Util.number import *
key = b'+0zkhmid1PFjVdxSP09zSw=='
cc = b'A0bzFxdM95YoXm64g0gZkiTloPsBAq7iV56t1M7Q4zVNxRJSTdZH0lzOMa7QyIQbKN/ftm01iZgQAk+JVgCB6hlCdMPWkdpKYHix8BTq/ClEHUPwMEjUEvgKD4tH3T/thoccBw1jfJ9RjhXbMFByWn5cyA/gHVvEEJRpII/ryKMQkzelioQ5b0MfhSy4INLqQk6yAgLzihip5ho7lDJCbYcaz85bDksOo5n9kjOfjFnjUn9G7jX+AtyhygPlGfrvauTeuPdVxqrJTVHvrzUNAqiqtCElX+BWpicP2mkZLt5B/gpquTv8U+StrdTOcr7UkWuz+YdhXkTJYUZguv7EbEnRy+M64QzqfnNf8Zk0tJQ5xOumbY8hxGTuZ8w3rWxjPKLhdgTGLgMcMYF3hPb2eqG9VZKC3T9zElI5MWPyIdkmqkrLEt6vGT8AxWJy1hl2ApkGhrJFB0DobJircN6kXUXvZXitjXSH+BA48muaRlAwK13re+zIcbI+B7+Tm3LuRT9j5NWD9RBoy+IeAQvR05IKWqEpqXEScmZsQxpAFZCSnbchYaYNAuHvBwMcMW7vTMyxROHRtyZ+gWNUhpd8CcZ9FA6w+cwQLMWW5D4nUCMK+NEsSyTBBm/jTiAp/waq+2dTVyBhbQtmm9pBtZtHJtfeVRKuZRXduNnlWDa7Wlwv0Jk2EIJpAaXxosuZnO0PHW3oX+WO5F9ydIfIJAFUpBrn4fMx3c7IJ08+bKwAfBw/johSs1ieyX/YjOOL1KbE9J6Hz3ZBBR4waQ4p9sdLsJ9UFnNghH0ZuB2F7bGoH7SurvaMglo3FyQAfM+n/EVCGWnax/JGEcw5YZuS2c7y5Gd4oOCmpFO/lVj0IaOlZsFsMgQ3GUsBT2h1yh4yarlYUczvGNyOyfUXfueCDBQJNJ7adbdra/DHpV3LXieADKED2HankT+9ACs8oVYPpZhji0UuCdvs1txytsCqPSf5l7JLDkrGP3/7Ob7UcCA4h/B+6/0xg7h+ZJ6ZR41sDpOR8S4pmPlfJkU/np52QZfplY0sKpKlaYhuhUmMSle2TAcvNUGHobNTReFV/MOfX5/HX6behFAeOwHGI14AvUbDmrmkVvbyU88DzBW2YQ/tTTiSLg/wgggkkhLd17NZAMB3XbKuw3WdkdyJfTTpyiN05DqMwV3q64fpzasFXFNQ7ix8Q/APov/TmBYtgFw4ys2jKC6Yws166RXRkrQXzY4Ey9Xvjp5i5nUgW2HLHRGz2B5lg0jI9oWjj5+89Y0Tcqb81OFD5SfeqTbg7Y2WoW6YjQ/Hzvt1l0+p/lFrnOy3ORfhwl+DFBZi4P9i+Hh7/uC1kCW8Lil2M9oVaAH4YB2yhm61AqEk4NPhSeTuioaFfvUY5lD75QiM6BdDFMTlNkC7crXmuiUpztHTzIS6E1kVARI8xsGeljjmJmuKIfQPPQfvSnnAjGeaxCNmRPDMgFGltFiGy63Pv/tVRWbUWiB27APHPsqM2qcV/nM8IwDx5xmwExl/atQXGzn/LL4xyqzmyzD+2qMeZqfzcKZWOjoWIX+SycPvc62HAQmsKqZK5ZO2JKq5OeuFEovG9oOcRYve1XStbTQYiocEbQ4XX/c6xE0cm9P/I5NM1Mlr6CT6qt3Pqb/m+7s/kwzww59FKOq5R6HmK7SHCQ6gwTQ1ciGWbJF3NLHuOpe08X4xl/l0tJengSfJRJ39Q9WwZbgBlEPf7NYeMlR9zU9QQxvZ+r4LiaJVYrQYSCcDj37Vk9XVRMijBDWDWFbK5sgkDHQYmwGYiwH4hEAqAAXDNj1/f2eRFbIU2GN6Wfj89fEINJjoG/1O/I5Q8S7tHnlWFQNoXJQ2e4r2Aca9RPLVCWz7Nq96YUKBRN3afW/9FSwWLLvjsBptQmoRj4FwmJzJf7Vj6KCOkm6mdaZ4l6FB4/E2Lk9aopD7Q473leULPM1CydXWme/8WKUqEucDwraXS57+Z+iGRMvQ8MABtZboAVFK2B1mzNL4Ba/bxVE4puy4HwvQI+N1tKmeMf99FfR13IA0y+FWL3eCzXKw8gimaJCW1e3QJJWDorDXRRjExeokMGGHzOd8MrTfNNFGWSPqZRTdGJxW7wOWQi3bHT0WSqP1fBpdU9m+WKHIxy57dL/8JFJJ97R56P76rlToRrM825JcTBEfrK0Nb9Q+2RI83vyTA2UxH9s9cSnWd+e7nacrfXjV7EjkGHgblEGHX9LqNETaZpBAL0NG9OAJ0+f+6id4/Ixcee0jx4b8k5xvblujFEdK0q2MRo2uTxSAFMpelt8JY0EZbnF9uT88N4LPms3cNeKBt0KBhx+vshFKMc/b3W7OMCo6m7EyzmcTmMe+Y6CO0x0FF0p6h1bTnJu3MMok1hO27iBSfYusHgKWVmKpgNHjiDfuBYnuBCysa+hHQZW23zxNRqi2OGAy6zCGPOY4E4nyUA6g/jlVOjq6fFv1VHN1tlQlBOCvB9r5B0os1zI2XL/Mlb9eggNuA8nw2igDm+9qkBtLxOXojAGDonAPzBagHXnVd+0kLdUGEoddt45A2fgSSociCx4tVDMd5ag1zR4VxdADAy0lnmW0n8noAT5y60SV7gICvMOphILBRjk365Mu6GNA3C+n8k5YH9sRnS7Z5EVEKdSeYigJs4XNavD50/paKnJcux2l3gzm/1aTUMzLd8tw7vZuUWv1XaYULcez8ieEMeACETyN53+RlcPQefupgszELvwlKz0prl5ydHCPOA7+ZS2zfUZOEmRSBNaIZUCd5euNg+HXMeFa/Qb452+KKEjq7vRthC4hH9gluaYMl/eXboQvvVu4xDhfVW403enI7sxdMR3t2WO1cOaLE8IN5c71W+IqhaRbJ/Prlo/pk/XAtMvimZxIN4y5/oP5vQ/lCt5jM9wAtPKSoQbJxWIYWNrXVfkZUOOwD2tlOmyxMCcKFr8921JHgtWqcYliElNX19hzmYhow+19EV3zhITzsGOX/PP1BHIKz/NJyKcGqx1hlfrDfDVedhJWkQL9sg4clbfguprs3KG5YNbbjclaK9JoEboBY3EGBGHtsWfmIRAREwy1a53y/a/NUDLaQxrMsyV/YnbiyBevGjMVNnqIY5T0YtPLL/s5Wvmq7EU9qoMDIlaosCf616TagcZalGFQumL15q6wx3FxwVB5EAjFa/MKnZNc0CqbFhXgEevp1ZXRnjEAdSK99gyAmwVawWpxIWXZQvQ5w7tIQ+nF8utoG4ab/AdLbZyKCtT8pxjiHifNcCCkLfew8Qq9S2JnrhCUMs9SEiRrLZHiE9JVlwbUJzAQjCM6G4tdeLNEApqDv4eZ7zh2U9K2+Gk9OjBgSk5xMjRkCzKCrNAKgRLoJ1Gu8L4T9LSBp1juhUsyaIaK'
f = open('Problem.txt','w')
key = base64.b64decode(key)
aes = AES.new(key,AES.MODE_ECB)
cc = base64.b64decode(cc)
mm = []
for i in range(16,len(cc),16):
c1 = cc[i:i+16]
tmp = aes.decrypt(c1)
m1 = xor(tmp,cc[i-16:i])
if i == 16:
m = m1
mm.append(m)
else:
m = xor(mm[-1],m1)
mm.append(m)
t = str(binascii.b2a_hex(m))[2:-1] + '\n'
f.write(t)
import Crypto.Util.strxor as xo
import codecs, numpy as np
def isChr(x):
if ord('a') <= x and x <= ord('z'): return True
if ord('A') <= x and x <= ord('Z'): return True
return False
def infer(index, pos):
if msg[index, pos] != 0:
return
msg[index, pos] = ord(' ')
for x in range(len(c)):
if x != index:
msg[x][pos] = xo.strxor(c[x], c[index])[pos] ^ ord(' ')
dat = []
def getSpace():
for index, x in enumerate(c):
res = [xo.strxor(x, y) for y in c if x!=y]
f = lambda pos: len(list(filter(isChr, [s[pos] for s in res])))
cnt = [f(pos) for pos in range(len(x))]
for pos in range(len(x)):
dat.append((f(pos), index, pos))
f.close()
c = [codecs.decode(x.strip().encode(), 'hex') for x in open('Problem.txt', 'r').readlines()]
msg = np.zeros([len(c), len(c[0])], dtype=int)
getSpace()
dat = sorted(dat)[::-1]
for w, index, pos in dat:
infer(index, pos)
print('\n'.join([''.join([chr(c) for c in x]) for x in msg]))
DDH_Game
参考,这里n有两个大因子所以求阶也是很困难的,但我们只需要求mod 3111017785926752437899的a、b、c即可判定,因为当 c=a·b mod n成立的时候,再全部模一个数也是成立的。有个坑点在于sols = m.bits()
函数是低位高位倒置的,所以求出来还要倒转比特。
from sage.all import *
p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
K = GF(p)
a = K(0x00)
b = K(0x04)
E = EllipticCurve(K, (a, b))
E.set_order(0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001 * 0x396C8C005555E1568C00AAAB0000AAAB)
G = E(3745324820672390389968901155878445437664963280229755729082200523555105705468830220374025474630687037635107257976475, 2578846078515277795052385204310204126349387494123866919108681393764788346607753607675088305233984015170544920715533)
n = G.order()
print(n)
print(factor(n))
primes = [3,11,10177,859267,52437899]
out = []
mult = 3*11*10177*859267*52437899
m = ''
count = 1
for i in out:
aG = E.point(i[0])
bG = E.point(i[1])
cG = E.point(i[2])
dlogs_a = []
dlogs_b = []
dlogs_c = []
for fac in primes:
t = int(n/int(fac))
dlog_b = discrete_log(t*bG,t*G,operation='+')
dlogs_b += [dlog_b]
dlog_c = discrete_log(t*cG,t*G,operation='+')
dlogs_c += [dlog_c]
dlog_a = discrete_log(t*aG,t*G,operation='+')
dlogs_a += [dlog_a]
b = crt(dlogs_b,primes)
c = crt(dlogs_c,primes)
a = crt(dlogs_a,primes)
if (b*a%mult)*G != c*G:
m = m + '0'
else:
m = m + '1'
print(count)
print(m)
count+=1
print(int(m,2))