CatCTF—2022-赛事分享社区-弘客联盟新手区-弘客联盟

CatCTF—2022

攻防世界和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解码,最后brainfuck-Ook编解码在线工具解码。

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

莱布尼兹级数π/4=1-1/3+1/5-1/7+…的几何原理,所以就是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'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'

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))

 

请登录后发表评论

    • 英短的头像-弘客联盟英短徽章-资深玩家-弘客联盟等级-HAC-LV1-弘客联盟作者0
随便看看