CTBUCTF2024 Writeup
S Stuck 题目做到一半思路卡壳
F Finished 完成该题
1 First Blood 获得一血
2 Second Blood 获得二血
3 Third Blood 获得三血

Misc

F1 | 签到 |

直接化身CV工程师,复制粘贴flag

coctf{CTBUCTF2024}

F1 | 网络迷踪✈ |

根据题目描述可以知道应该是于4月25日从重庆飞往北京的一趟航班,并且落地时间应该是在20:08左右或之前,搜索得到flag

Snipaste_2024-05-10_16-34-04

coctf{CA4147}

F2 | Invitation letter |

在QQ群发送"邀请函id"得到一张图片,是通道隐写,改变通道查看,发现flag(有一说一,电脑屏幕就那么大,图也那么大,flag又特别小,第一次过了一遍完全没看到)

Snipaste_2024-05-10_18-52-16

coctf{welcom3_7o_c7buc7f2024}

F1 | 爱你老妈 |

根据压缩包备注进行小写字母暴力破解得到压缩包密码,图片显示CRC值错误,修复宽高得到flag。

image-20240512165740002

coctf{d34r_mOm_h4ppy_mOth3r's_d4y}

F1 | 从前的遗憾 |

进入服务器轩哥说挖土块换flag,换的画看上去没什么异常,根据题目描述应该是需要在材质包中寻找。

在游戏安装路径下的server-resource-packs文件夹中可以看到进入服务器后下载的服务器材质包,解压assets文件

image-20240512170322625

解压后在文件夹中搜索flag发现那张画的png图片

image-20240512170453749

检测得到flag

Snipaste_2024-05-10_21-49-21

coctf{ed031326-eb76-4513-9f44-bda36b805fd5}

F1 | 火水未济 |

首先得到的是六十四卦的图形编码(自带记事本打开时方块,Word,vscode和其他文本查看器打开能正常显示),根据提示需要先对图形编码进行01的替换('—' 为1 '--'为0),这里如果编码数量不多的话可以直接转化成卦名进行解码,但是本题数量太多会卡住。转化后我们利用脚本进行解码,六十四卦的原理是将6位二进制转化成8位二进制,再转化成16进制

import binascii 

b=''
dic={'䷁': '000000', '䷖': '000001', '䷇': '000010', '䷓': '000011', '䷏': '000100', '䷢': '000101', '䷬': '000110', '䷋': '000111', '䷎': '001000', '䷳': '001001', '䷦': '001010', '䷴': '001011', '䷽': '001100', '䷷': '001101', '䷞': '001110', '䷠': '001111', '䷆': '010000', '䷃': '010001', '䷜': '010010', '䷺': '010011', '䷧': '010100', '䷿': '010101', '䷮': '010110', '䷅': '010111', '䷭': '011000', '䷑': '011001', '䷯': '011010', '䷸': '011011', '䷟': '011100', '䷱': '011101', '䷛': '011110', '䷫': '011111', '䷗': '100000', '䷚': '100001', '䷂': '100010', '䷩': '100011', '䷲': '100100', '䷔': '100101', '䷐': '100110', '䷘': '100111', '䷣': '101000', '䷕': '101001', '䷾': '101010', '䷤': '101011', '䷶': '101100', '䷝': '101101', '䷰': '101110', '䷌': '101111', '䷒': '110000', '䷨': '110001', '䷻': '110010', '䷼': '110011', '䷵': '110100', '䷥': '110101', '䷹': '110110', '䷉': '110111', '䷊': '111000', '䷙': '111001', '䷄': '111010', '䷈': '111011', '䷡': '111100', '䷍': '111101', '䷪': '111110', '䷀': '111111'}

a=b.strip()

s = ''
i = 0
while i < len(a):
    try:
        s += dic[a[i]]
    except:
        s += dic[a[i] + a[i + 1]]
        i += 1
    i += 1
decimal = int(s, 2)
hexadecimal_str = hex(decimal)
print(hexadecimal_str)

f=open("C:/Users/Xia/Desktop/1.png","ab")
pic = binascii.a2b_hex(hexadecimal_str.encode())
f.write(pic)
f.close()

# 0x89504e470d0a1a0a0000000d4948445200000202000001……

image-20240512171531569

通过观察发现开头几位是89504e,是png图象的文件头,将十六进制转化成png图片,得到一张六十四卦图

image-20240512171710383

检测得到flag

Snipaste_2024-05-10_16-36-16

coctf{7b9bd007-34fe-42b2-9eea-5ba1057ac22d}

F1 | 简简单单的高数 |

编程题,大体是需要计算300道计算题,根据所给要求进行求导或者积分并赋值

import pwn
from sympy import *

x = symbols('x')
begin=b'press enter to start'

io = pwn.remote("ctf.ctbu.edu.cn", 33465)

while True:
    io.sendline(" ")

    data = io.recvuntil(begin).decode()

    for i in range(300):
        temp = io.recvuntil(b'\n').decode()
        str1 = temp.split(">")[-1].split('\n')[0]
        print(str1)

        question=str1[2:-9]
        type=str1[-7:-6]
        x_value=str1[-2:]
        print("question:",question)
        print("type:",type)
        print("x:",x_value)

        if "i" in type: #取积分
            answer = integrate(question, x).subs(x, x_value)    
            print("answer:", answer)

        if "d" in type: #求导
            derivative_question = diff(question, x) 
            answer=derivative_value = derivative_question.subs(x, x_value)
            print("answer:",answer)

        io.sendline(str(answer).encode())
        print(io.recvline())
        print(io.recvline())

    print(io.recvall())

    # coctf{yoUr_mATh_i5_50_6ooD_27ffdd1a0c88}

Snipaste_2024-05-11_13-02-44

需要注意的是,题目中信息的输出以及信息的接收,计算有现成库,没有其他什么问题应该就可以跑起来了


S | 二向箔 |

hint.zip更改格式为doc可以得到一个b站视频讲关于希尔伯特曲线曲线降维打击的

这里借用ranfey老师的代码

import numpy as np
from PIL import Image

def xy_from_d(d, n):
    x, y = 0, 0
    t = d
    s = 1
    while s < n:
        rx = 1 & (t // 2)
        ry = 1 & (t ^ rx)
        x, y = rotate_and_flip(s, x, y, rx, ry)
        x += s * rx
        y += s * ry
        t //= 4
        s *= 2
    return x, y

def rotate_and_flip(n, x, y, rx, ry):
    if ry == 0:
        if rx == 1:
            x = n - 1 - x
            y = n - 1 - y
        return y, x
    return x, y

def hilbert_curve_transform(one_d_array, n):
    if len(one_d_array) != n * n:
        raise ValueError("The length of the array must be n^2.")
    two_d_array = np.zeros((n, n))
    for i in range(len(one_d_array)):
        x, y = xy_from_d(i, n)
        two_d_array[x, y] = one_d_array[i]
    return two_d_array

input_path = "12.png"  # 一维图像文件的路径
output_path = "22hilbert_image.png"  # 保存转换后的二维图像文件的路径

# 加载图像并转换为灰度
image = Image.open(input_path).convert("L")
one_d_array = np.array(image).flatten()

# 检查一维数组长度是否为262144
if len(one_d_array) != 262144:
    raise ValueError(
        "The input image size must be exactly 512x512 pixels when flattened."
    )

# 转换到二维
n = 512  # 选择一个合适的n值
two_d_array = hilbert_curve_transform(one_d_array, n)

# 将结果保存为图像
two_d_image = Image.fromarray(two_d_array.astype(np.uint8))  # 确保数据类型正确
two_d_image.save(output_path)

不愧是GPT高手,佩服!

将一维图象按照希尔伯特曲线填充,得到二维图片

22hilbert_image

再通过gaps拼图得到原始图片,得到flag

PixPin_2024-05-11_23-22-58

coctf{d3str0y1ng_y0u_h4s_n0th1ng_t0_d0_w1th_y0u}

这里放上ranfey老师的博客连接:然飞ranfeyのブログ世界 – きたくれてありがとう

有很多有用的知识,有兴趣的可以去看看


Crypto(all kill)

F2 | EZ_Caesar |

古罗马大帝凯撒未能统一欧洲,那就帮他统一两个字母王国,让他能够巡游从大到小的字母国家吧!!!

根据题目描述,需要将大小写字母合并进行自定义凯撒,想了一下用单表替换

def replace_letters(input_string):
    letter_mapping = {
        'A': 's', 'B': 't', 'C': 'u', 'D': 'v', 'E': 'w', 'F': 'x',
        'G': 'y', 'H': 'z', 'I': 'A', 'J': 'B', 'K': 'C', 'L': 'D',
        'M': 'E', 'N': 'F', 'O': 'G', 'P': 'H', 'Q': 'I', 'R': 'J',
        'S': 'K', 'T': 'L', 'U': 'M', 'V': 'N', 'W': 'O', 'X': 'P',
        'Y': 'Q', 'Z': 'R',
        'a': 'S', 'b': 'T', 'c': 'U', 'd': 'V', 'e': 'W', 'f': 'X',
        'g': 'Y', 'h': 'Z', 'i': 'a', 'j': 'b', 'k': 'c', 'l': 'd',
        'm': 'e', 'n': 'f', 'o': 'g', 'p': 'h', 'q': 'i', 'r': 'j',
        's': 'k', 't': 'l', 'u': 'm', 'v': 'n', 'w': 'o', 'x': 'p',
        'y': 'q', 'z': 'r'
    }

    replaced_string = ""
    for char in input_string:
        if char in letter_mapping:
            replaced_string += letter_mapping[char]
        else:
            replaced_string += char

    return replaced_string

input_str = "kwkBn{wOnbIMsrrhhqltxOaeDeOROalfmcyBSCfbsu}"
output_str = replace_letters(input_str)
print(output_str)

# coctf{2e9db394-1e9a-4274-81b2-5bac6eaeceb2}

F3 | EZ_MATH |

from Crypto.Util.number import *
import gmpy2
import sympy
n = 56079040798736232364023170475610220337209677850425080793400289960159513091712519768798156822032410501763563682749797766575091334186888860388448719030785592302519869635624768832411292792325522320363789766644652838776351213129457527426376448092002254683565222976822380646026820966946551017266613854073904872287
e = 65537
c = 14645882922691032310419649407293538671245953738079783975808482204013927983467152197846644439096975965995930755151145585185865474690024783683733602738133566981423530581096820853664318840400220667866066047863579101952950790806854404705656078773881494207446388122240319935417684193608577624876402536308661055481
h = 121919582681467201213803796120628726927940930577191449030524564282892277463950517324649028467574623614799862788704076763961225559372403020120655107059152397772644943351024203548815686571893878863348719177482783998171656956410054591246919152253621841966071730397491090103034414492357178841744670135704697988277870623584131585034130124875274453908225506851159069189948358034323707535009755969433427877318405348304920464465422614407889226076728167746862375695382876022907971187762212071667478054007713001367120695264281884428168314331552164696050154132553115711231554408323708972675371474522897311285430452028804431117790906746580080057319794704491807392733830045455091806773479997303423930202185832979489093315126506531153858892406548147937380808588347341201362108335497412600750331692972682305254837270582349962803483359752621402776701503362910962104166285452673389342257904074438000031604933879016198496264480366911069102448
p,q = sympy.symbols("p q")
eq1 = p**6-q**3-h
eq2 = p*q-n
sol = sympy.solve((eq1,eq2),(p,q))
p = sol[0][0];p = int(p)
q = sol[0][1];q = int(q)
phi=(p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = long_to_bytes(pow(c,d,n))
print(m)

# b'coctf{2e9db394-1e9a-4274-81b2-5bac6eaeceb2}'

F3 | ez_RSA |

维纳攻击

import gmpy2
from Crypto.Util.number import *

def continuedFra(x, y):
    """计算连分数
    :param x: 分子
    :param y: 分母
    :return: 连分数列表
    """
    cf = []
    while y:
        cf.append(x // y)
        x, y = y, x % y
    return cf
def gradualFra(cf):
    """计算传入列表最后的渐进分数
    :param cf: 连分数列表
    :return: 该列表最后的渐近分数
    """
    numerator = 0
    denominator = 1
    for x in cf[::-1]:
        # 这里的渐进分数分子分母要分开
        numerator, denominator = denominator, x * denominator + numerator
    return numerator, denominator
def solve_pq(a, b, c):
    """使用韦达定理解出pq,x^2−(p+q)∗x+pq=0
    :param a:x^2的系数
    :param b:x的系数
    :param c:pq
    :return:p,q
    """
    par = gmpy2.isqrt(b * b - 4 * a * c)
    return (-b + par) // (2 * a), (-b - par) // (2 * a)
def getGradualFra(cf):
    """计算列表所有的渐近分数
    :param cf: 连分数列表
    :return: 该列表所有的渐近分数
    """
    gf = []
    for i in range(1, len(cf) + 1):
        gf.append(gradualFra(cf[:i]))
    return gf

def wienerAttack(e, n):
    """
    :param e:
    :param n:
    :return: 私钥d
    """
    cf = continuedFra(e, n)
    gf = getGradualFra(cf)
    for d, k in gf:
        if k == 0: continue
        if (e * d - 1) % k != 0:
            continue
        phi = (e * d - 1) // k
        p, q = solve_pq(1, n - phi + 1, n)
        if p * q == n:
            return d

n=58971066496331195596562931093881139811880490972823975190652945951120207719806493000856700063410122456770507111582351229105831221948659558329166810410736487891299500916043287300563231499740646193934897203715520004956228592403417744357110481113081279960032648000847164890285846160594645828549471004319655521507
e=9054957186173813729567689764104392479672428229438136451704762954639796514448086598056945565117597658657950899680587490433206188632641457208436770156130587464382479005980799664985016252069671231228167439151884620115685941046128363647750468901782641667100116288505860964351890796777533573467597425631532828637
c=13919338073617716764778053992864840600478391989380389957147868355399684928241734368027833445245395519102730792567678310337001860179822945055083751501927338811023804995478939608142378530394248125265928856329994849370573228301105789712574999722322983824214626070471763140057973082426183047827450452500693637920

d=wienerAttack(e, n)
m=pow(c, d, n)
print(long_to_bytes(m))

# b'coctf{a986a269-ca0d-4c3a-baaa-cbda3df12ed7}'

F | Chaining |

from Crypto.Util.number import *

c=[93437224, 1719034208, 1355999525, 913865070, 1389490238, 1664056437, 1267441726, 2100962338, 1086585451, 1902584100, 1134223705]

IV = bytes_to_long(b'cbc!')
m = [bytes_to_long(b'coct')]
k = IV ^ m[0] ^ c[0]
print(k)

for i in range(len(c)-1):
    m.append(k^c[i]^c[i+1])

for i in range(len(m)):
    print(long_to_bytes(m[i]).decode(),end='')

# coctf{a53858c6-6a54-4b16-8a63-9a8ec448f27a}

F3 | 最后的晚餐 |

低指数广播攻击+e爆破(当时想了半天怎么处理e,20个e,最后发现是e=13)、

import gmpy2
from functools import reduce
from Crypto.Util.number import*

import libnum

def CRT(mi, ai):
    assert(reduce(gmpy2.gcd,mi)==1)
    assert (isinstance(mi, list) and isinstance(ai, list))
    M = reduce(lambda x, y: x * y, mi)
    ai_ti_Mi = [a * (M // m) * gmpy2.invert(M // m, m) for (m, a) in zip(mi, ai)]
    return reduce(lambda x, y: x + y, ai_ti_Mi) % M

n = [1219424512430240452161708967378571788348299511863149055555975633817956317665900357486835460123063967922201670748161708615668398708813311341458640571866997154236891326003855323487213753043637831876583829856356045385175781048172491262707746981430628512052592894622069784167255295776766933471111747724719109, 1919855336098318638995041778146565216051584582940922857546323342907080931635158957315485905491577575016589393135212257428587710482975343548898926668507151449578246946490913586398032614744273222330093710620296178243242551395586276919524475743740522156894626482790933576793331326002486879966866271880421511, 1622154334601100384111809392705037548973394686404065212677942490843292598292087691859839343830846956061949493743952221278610226285548951534261211995903176612049814023293186231557994447370918991521803694195673484672570472148648146412709770218652531140493534276532606625259030915039292369807207553334523709, 2480513113145818798715263507966829079445910043625025013923809213293157609466121892200271442122354780729995226083281256800702231785079163611426388563644726778323860252173480193100772934211355294301813544273287895209943094664995264402502082846158265964662638725494612874528424439018638924133703533884475843, 1278450090774848187320812012629692040573885199340923815914365820853768814197622536142197287509944797517955304048519499100884355716805210040442141871547898946018286560330901454718261060329936085770672298751506246287805387914319475681947596019440112688048887198879573816513015336286682637245984687980332033, 1750425010925046436708067500795625569042632881184081147754190148640640336243143192801910065402781086409727258184641585548819110174909652639082605658741132587471617520520263649354615937150006789725143237607687552889819998281055736216883696160008916045772994577364404314923956402868451891333087995266294983, 1980420015928704576303616389202660785964799502261436482095129872240591167141962962879745876663273258218503066497124695167312614689278168251928515420332703598019121133942685048023619614324716093827201698212048663826210609553481129776585212402689030444748187851271124792413482838701766962122040153478412713, 1664137894405041299633142286074998401698635259096711815647923013373461676936159069243217647293114639122934141572555591238407843566451171584247636721182851158539368574533981731239837006148936517613630251282693630219410821939178199538683374982366372809451876235909357721974288306505093894206876311257913483]
c = [916726812788635341883840209986104296960900128998850930061855456472248605500457658699716643791629789506477274107526508971952764548117112976613041546859769694129219031800621799276846667293867519416483416919772806118365602868722104992757915039281642307586254256582417524702049716412950818725577480162066000, 1034101042827617402148865269885406378379481443330769284380676698369194182744294857994718274447290677772208751705571847058647887717978787410380938989365820208279603216265638582122834329187300706375159565495622219432243171545069574257321601831283094057178649112814602711247359988110787680038015584224503116, 56016120525062295559040794473244848484153746450915607765062995696873721091718061684295511802274068579176877844291758614076021352008123208843535424006319451988565165984571971759979334533864838471622653728615453431726803668190336563160220323523947925445088030698206403817167684798087409288470567696126927, 2235312929582260981585010565420384824755136354963428104081186146911638484601163325287537545584739277034134455315485971707317938041862877950777767312495805462214173604703309309856260653064351812642315163592230156274555402245480235236783544027909136579946999190818179363353928825063933271172859607140417632, 167691427325045716259205128250600313515888481858395672617480399896319569958581068213749503662645583133461732167162347278500313439949001034677004427247419036416793641866128997767638957480981642668680500982820062656553069593736202673213409215879003957374178138464148927578488725086876105432834961046191927, 855727455668080806995812717505209697019466235169849516942802169094840684520639023893947905855051799076683081447527601876884901780812547479679034064552821943113306505580331450567910642231916777446997493121525053191320878050845368476494622669484988916486385486285614585475393613833614848224267681106081966, 1517394475087399343808582055536875302709383973933978917604667725305578832340362100239754023267001870955879050478871252998908182568245959248042691419485501812098931644943118993537936064575748030665339618988496139991731065115393691056157990322560918407213178805367140226467465668350241849522004762767536742, 137625856412069902606478478206639868506506064218956559248437030323739499509263013617167358662252912981771289342994466458653018819353328056183005692142641418838258148451334178914687871893697311677612922285299784310320650094866100658643984214155841343791834439948194201143828748081099197463015782720821378]
e=13

m=gmpy2.iroot(CRT(n, c), e)[0]
print(long_to_bytes(m))

# b'coctf{23bdf1ce-e807-4b62-87e0-909048cbd205}'

F1 | Caesar_ProMax |

凯撒大帝自从统一两个字母王国后,来到更加广阔的世界,发现还有许多符号王国,于是乎他一鼓作气统一了另外的五个符号王国,鉴于文化差异,他决定这七个王国分开管辖。

根据题目和ASCII表我们可以将可见字符划分为七个区域,一开始没有认真读题,认为是大小写一个偏移,其他字符一个偏移,得到一个单表

def replace_letters(input_string):
    letter_mapping = {
      'A':'O','B':'P','C':'Q','D':'R','E':'S','F':'T',
      'G':'U','H':'V','I':'W','J':'X','K':'Y','L':'Z',
      'M':'A','N':'B','O':'C','P':'D','Q':'E','R':'F',
      'S':'G','T':'H','U':'I','V':'J','W':'K','X':'L',
      'Y':'M','Z':'N',

      'a':'o','b':'p','c':'q','d':'r','e':'s','f':'t',
      'g':'u','h':'v','i':'w','j':'x','k':'y','l':'z',
      'm':'a','n':'b','o':'c','p':'d','q':'e','r':'f',
      's':'g','t':'h','u':'i','v':'j','w':'k','x':'l',
      'y':'m','z':'n',

      ' ':'"','!':'#','"':'$','#':'%','$':'&','%':'\'','&':'(','\'':')','(':'*',')':'+','*':',','+':'-',',':'.','-':'/','.':' ','/':'!',
      '0':'2','1':'3','2':'4','3':'5','4':'6','5':'7','6':'8','7':'9','8':'0','9':'1', 
      ':':'<',';':'=','<':'>','=':'?','>':'@','?':':','@':';',
      '[':']','\\':'^',']':'_','^':'`','_':'[','`':'\\',
      '{':'}','|':'~','}':'{','~':'|'

        #'!':'.','"':'/','#':'!','$':'"','%':'#','&':'$', "'":'%','(':'&',')': "'",'*':'(','+':')',',':'*','-':'+','.':',','/':'-',
        #'0':'8','1':'9','2':'0','3':'1','4':'2','5':'3','6':'4','7':'5','8':'6','9':'7', 
        #':':'?',';':'@','<':':','=':';','>':'<','?':'=','@':'>', 
        #'[':'_','\\':'`',']':'[','^':'\\','_':']','`':'^',
        #'{':'}','|':'~','}':'{','~':'|'
    }

根据开头的coctf可以确定小写字母部分的偏移量,根据{}可以确定相应符号部分的偏移量,但是最后发现不对就回去分析代码。

代码中最重要的是关于key的确定key = random.randint(0, 2**64),及key是0到2^64间的一个随机数,而每位字符都是用这个key,所以之前的思路错误,根据出题脚本写个解密的脚本。

首先根据取值范围我们可以确定七个区间(这里注意ASCII值为32的空格也要算在内,否则%len(Chr_tab1)会少1。

Chr_tab1 = {' ','!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/'}
Chr_tab2 = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
Chr_tab3 = {':', ';', '<', '=', '>', '?', '@'}
Chr_tab4 = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
Chr_tab5 = {'[', '\\', ']', '^', '_', '`'}
Chr_tab6 = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
Chr_tab7 = {'{', '|', '}', '~'}

偏移部分的+key改为-key就可以得到原来的字符。但是key是未知的,所以我们对key进行爆破,并输出开头满足条件coctf{的字符串,输出后由于key的范围太大了,有很多都符合要求,挨着交结果第一个就是,key不是很大。

import random

key = 1

Plaintxt = "oaofr}&'()*#$%{8967=@:;<MNO]^[\mno}~|{"  

Chr_tab1 = {' ','!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/'}
Chr_tab2 = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
Chr_tab3 = {':', ';', '<', '=', '>', '?', '@'}
Chr_tab4 = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
Chr_tab5 = {'[', '\\', ']', '^', '_', '`'}
Chr_tab6 = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
Chr_tab7 = {'{', '|', '}', '~'}

found_flags = []

while True:
    flag = ''
    for c in Plaintxt:
        if c in Chr_tab1:
            c = chr((ord(c) - key - 32) % len(Chr_tab1) + 32)
            flag += c
        elif c in Chr_tab2:
            c = chr((ord(c) - key - 48) % len(Chr_tab2) + 48)
            flag += c
        elif c in Chr_tab3:
            c = chr((ord(c) - key - 58) % len(Chr_tab3) + 58)
            flag += c
        elif c in Chr_tab4:
            c = chr((ord(c) - key - 65) % len(Chr_tab4) + 65)
            flag += c
        elif c in Chr_tab5:
            c = chr((ord(c) - key - 91) % len(Chr_tab5) + 91)
            flag += c
        elif c in Chr_tab6:
            c = chr((ord(c) - key - 97) % len(Chr_tab6) + 97)
            flag += c
        elif c in Chr_tab7:
            c = chr((ord(c) - key - 123) % len(Chr_tab7) + 123)
            flag += c
    if flag.startswith("coctf{"):
        if flag not in found_flags:
            found_flags.append(flag)
        else:
            break

    key += 1

print("Found flags:")
for found_flag in found_flags:
    print(found_flag)

""" 
Found flags:
coctf{ !"#$-./}0189:=>?@ABC[\_`abc{|~}
......
 """

Reverse

F | sign_in |

点击即送flag

Snipaste_2024-05-10_16-50-30

coctf{899ee051-b716-0fdd-c1d3-537d08bd53d1}

F | easy_z3 |

利用z3库进行计算得到flag

from Crypto.Util.number import *
import gmpy2
from z3 import*

s = Solver()
v=Int('v')
w=Int('w')
x=Int('x')
y=Int('y')
z=Int('z')
s.add(v * 23 + w * -32 + x * 98 + y * 55 + z * 90 == 308369)
s.add(v * 123 + w * -322 + x * 68 + y * 67 + z * 32 == 473803)
s.add(v * 266 + w * -34 + x * 43 + y * 8 + z * 32 == 847130)
s.add(v * 343 + w * -352 + x * 58 + y * 65 + z * 5 == 1070419)
s.add(v * 231 + w * -321 + x * 938 + y * 555 + z * 970 == 3118208)

if s.check() == sat:
    print(s.model())

# [x = 940, w = 205, z = 924, v = 2908, y = 1323]
# coctf{{2908_205_940_1323_924}}

F2 | 简单的逻辑 |

根据汇编代码进行反汇编

#include <stdio.h>

void decrypt(char *ciphertext, int length) {
    int var_8 = 0;
    int var_4 = 0;

    for (var_8 = 0; var_8 < length; var_8++) {
        var_4 = 0x40; // '@'
        while (var_4 <= 0x42) { // 'B'
            int edx = var_8;
            int eax = (int)ciphertext + edx;
            int ecx = edx;
            int edx2 = (int)ciphertext + ecx;
            char dl = *(char*)eax;
            int edx3 = var_4;
            char al = (char)(edx3 ^ dl);
            *(char*)edx2 = al;
            var_4++;
        }
    }
}

int main() {
    char ciphertext[] = " , 7%8zwq{uz &n\"'\"!nr%!snr%rsn&{u'rsp{v'zw>";
    int length = sizeof(ciphertext) - 1; // 计算密文的长度,不包括字符串结尾的空字符 '\0'

    decrypt(ciphertext, length);

    printf("Decrypted text: %s\n", ciphertext);

    return 0;
}

// coctf{942869ce-adab-1fb0-1f10-e86d10385d94}

F2 | random | 

题目中有种子srand(0x21C4u),根据种子可以生成一样的随机数,根据汇编语言写出脚本

#include <stdio.h>

void flag(char *a1)
{
  void *v1;
  int v2; 
  int v3;
  char *s1;
  int i;
  int v6;
  int v7;
  int v8; 
  char *s2;

  s1 = a1;
  s2 = (char *)&v3;
  srand(0x21C4u);
  for ( i = 0; i < 13; ++i )
  {
    v2 = rand();
    v7 = v2 % 8 + 1;
    s2[i] = v2 % 8 + 49;
  }
  s2[v6] = 0;
  if (!strcmp(s1, s2))
  {
    printf("Right! The flag is coctf{%s}\n", s2);
    exit(0);
  }
  puts("error!");
  exit(0);
}

int main() 
{
    char v3[88];

    scanf("%80s",&v3);
    flag(v3);
}

在kali中运行得到flag

Snipaste_2024-05-10_18-02-06

coctf{7173857278535}

Web

F | 重生之我不是大宝 |

查看js文件,更改判断部分,使其能够在任意状态下传输加密信息

1

在css文件中发现加密信息被隐藏,修改字体大小

Snipaste_2024-05-12_13-04-08

画面发生改变

Snipaste_2024-05-12_13-04-15

得到flag

coctf{yoU_ve_R34L1Y_mAN_D4_6A0_Bro7heR_3d9eba940e40}

总结

Misc和Crypto部分大部分题比较传统,misc里mc题比较新(可能是见的不多),crypto的Caesar系列很有意思,加深了对Caesar原理的认识。题目大都属于常规考点,没有套娃的题。最后,感谢学长们的精心准备🙏,学长们辛苦啦!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇