window.onload=function(){ /*页面加载完成之后生成博客目录*/ BlogDirectory.createBlogDirectory("cnblogs_post_body","h2","h3",20); }

XYCTF 2024 出题记录

MISC

美妙的歌声

题目描述:

这首歌能深深地打动你吗?

我的解答:

频谱图查看密码

分析题目描述:深深地打动?想到 deepsound 隐写

密码就是:XYCTF_1s_w3ll

XYCTF{T0uch_y0ur_he3rt_d55ply!!}

疯狂大杂烩!九转功成

题目描述:

你能突破九大关卡修成神仙吗?

题目提示:

1.压缩包密码为比赛名称+8位什么来着?忘了。哈哈哈!

2.flag格式:XYCTF{md5(flag)}

3.第三层非夏多,看看交点

4.第六层键盘画图,狼蛛键盘最新版你值得拥有!

我的解答:

根据提示:压缩包密码为比赛名称+8位什么来着?忘了。哈哈哈!

掩码爆破或猜测可知密码为 XYCTF20240401

第一层–炼气

hint:

这是什么东西?

曰:玉魔命灵天观罗炁观神冥西道地真象茫华茫空吉清荡罗命色玉凶北莽人鬼乐量西北灵色净魂地魂莽玉凶阿人梵莽西量魄周界

天书解码:First_layer_simple

解压压缩包

png 宽高修改

XYCTF{T3e_c0mb1nation_

第二层–筑基

hint:

xihak-minoh-zusok-humak-zurok-gulyk-somul-nenel-dalek-nusyh-zumek-sysuk-zelil-fepak-tysok-senax

BubbleBabble 解码:The_second_layer_is_also_simple

lsb 隐写

ZmxhZzLvvJowZl9jcnlwdDBfYW5kXw==

base64 解码

flag2:0f_crypt0_and_

第三层–结丹

hint:

不是夏多密码,看交点是摩斯。四个交点代表”-” 三个交点代表空格 两个交点代表”.”

得到:the_third

解压压缩包得到 flag.zip 010 文件尾发现:5a+G56CB57uZ5L2g5Y+I5oCO5qC377yaMTIzNDU2

base64 解码提示密码 123456

但本身压缩包就是损坏的应该是伪加密但不完全是其实是伪加密后真加密了,改一个地方就行如下图:

保存解压得到:MZWGCZZT566JU3LJONRV6MLTL5ZGKNTMNR4V6ZTVNYQSC===

base32 解码:

flag3:misc_1s_re6lly_fun!!

第四层–元婴

hint:

都 2024 年了不会还有人解不出 U2FsdGVkX1+y2rlJZlJCMnvyDwHwzkgHvNsG2TF6sFlBlxBs0w4EmyXdDe6s7viL 吧

TripleDES 解码:The_fourth_floor_is_okay

解压发现两个文件 hint.txt 和 MSG0.db

hint.txt

wqk:1m813onn17o040358p772q37rm137qpnqppqpn38nr704m56n2m9q22po7r05r77

随波逐流凯撒解码得到:

key1 #12: key:1a813cbb17c040358d772e37fa137edbeddedb38bf704a56b2a9e22dc7f05f77

数据库文件搜索得知是微信聊天记录文件

搜索解密脚本

input_pass = '1a813cbb17c040358d772e37fa137edbeddedb38bf704a56b2a9e22dc7f05f77'
input_dir = r'文件夹路径。例如: C:\\xxx\\xxx\\xxx\\xxx\\xxx\\元婴\\第四层\\第四层'
 
import ctypes
import hashlib
import hmac
from pathlib import Path
from Crypto.Cipher import AES
 
SQLITE_FILE_HEADER = bytes('SQLite format 3', encoding='ASCII') + bytes(1)
IV_SIZE = 16
HMAC_SHA1_SIZE = 20
KEY_SIZE = 32
DEFAULT_PAGESIZE = 4096
DEFAULT_ITER = 64000
password = bytes.fromhex(input_pass.replace(' ', ''))
def decode_one(input_file):
    input_file = Path(input_file)
    with open(input_file, 'rb') as (f):
        blist = f.read()
    print(len(blist))
    salt = blist[:16]
    key = hashlib.pbkdf2_hmac('sha1', password, salt, DEFAULT_ITER, KEY_SIZE)
    first = blist[16:DEFAULT_PAGESIZE]
    mac_salt = bytes([x ^ 58 for x in salt])
    mac_key = hashlib.pbkdf2_hmac('sha1', key, mac_salt, 2, KEY_SIZE)
    hash_mac = hmac.new(mac_key, digestmod='sha1')
    hash_mac.update(first[:-32])
    hash_mac.update(bytes(ctypes.c_int(1)))
    if hash_mac.digest() == first[-32:-12]:
        print('Decryption Success')
    else:
        print('Password Error')
    blist = [
        blist[i:i + DEFAULT_PAGESIZE]
        for i in range(DEFAULT_PAGESIZE, len(blist), DEFAULT_PAGESIZE)
    ]
    with open(input_file.parent / f'decoded_{input_file.name}', 'wb') as (f):
        f.write(SQLITE_FILE_HEADER)
        t = AES.new(key, AES.MODE_CBC, first[-48:-32])
        f.write(t.decrypt(first[:-48]))
        f.write(first[-48:])
        for i in blist:
            t = AES.new(key, AES.MODE_CBC, i[-48:-32])
            f.write(t.decrypt(i[:-48]))
            f.write(i[-48:])
if __name__ == '__main__':
    input_dir = Path(input_dir)
    for f in input_dir.glob('*.db'):
        decode_one(f)
# 62914560
# Decryption Success

解开之后打开数据库文件

L1u_and_K1cky_Mu

第五层–化神

hint:

enc = ‘key{liu*****’
md5 = ‘87145027d8664fca1413e6a24ae2fbe7’

md5 爆破:

import hashlib
enc = 'key{liu'
md5 = '87145027d8664fca1413e6a24ae2fbe7'
 
for x in range(0,127):
    for y in range(0,127):
        for z in range(0,127):
            for k in range(0,127):
                temp1 = hashlib.md5(str(enc + chr(x) + chr(y) + chr(z) + chr(k) + "}").encode("utf-8"))
                temp2 = temp1.hexdigest()
                if(md5 == temp2):
                    print(enc + chr(x) + chr(y) + chr(z) + chr(k) + "}") 
#key{liuyyds}

解压得到 flag.txt 和 serpent.txt

flag.txt无结果。看另一个txt文件名发现是serpent隐写。。密码就是 liuyyds

记事本打开此文件:

     这是一个非常神奇的故事    ‌ ​,至于它神奇在哪?嘿嘿    ‌     ​!我也不知道              ‌​     。         ​    ‌ ‌    ‌    ​    ​​   

一眼丁真,零宽隐写:

_3re_so_sm4rt!

第六层–炼虚

hint:

wszrdc 
fgtrfvb 
ghytgbn 
rfctg 
yhju
frtg
uyhbghj
6yhn
uyhjujmn
tgvvghb
yhnmghj
4rfv
derf
iujkikmn
 

键盘密码画图,根据每行字母走向刻画出密码为:keeponfighting

好多文件逐一分析发现 flag 都是假的。。还有一个 jpg,猜测可能是某种隐写,先试一波 steghide,密码是啥?

这里有个脑洞:观察上面的文件名是数字,密码可能就是顺序或者逆序排列的。

steghide extract -sf yuanshen.jpg
Enter passphrase: 98641
wrote extracted data to "flag.txt".

In_just_a_few_m1nutes_

第七层–合体

hint:

密文:Tig+AF8-viakubq+AF8-vphrz+AF8-xi+AF8-uayzdyrjs

听说维吉尼亚 key 大残

首先对密文进行 UTF-7 解码。熟悉此类编码的都懂(直接就看出来了。)

接下来的操作就挺新颖的。我们知道维吉尼亚 key 都是字母。因此大残即全选。之前做过 BUU 的 NewStar 的应该有印象,当时好像有个 misc 题是 R 通道大残。

这样一来我们解码即可:

The_seventh_level_is_difficult

接下来根据颜色找对应数字。

164 150 145 171 137 167 145 162 145 137 164 150 162 60 165 147 150 41

观察数字发现是八进制。随波逐流八进制转字符得到 flag:

they_were_thr0ugh!

第八层–大乘

hint8.py

from Crypto.Util.number import bytes_to_long, getPrime
flag=b"password{xxxxx}"
p,q= getPrime(1024),getPrime(1024)
n = p * q
e = 65537
m = bytes_to_long(flag)
c = pow(m,e,n)
print("n=",n)
print("c=",c)
print("p^q=",p^q)
'''
n= 22424440693845876425615937206198156323192795003070970628372481545586519202571910046980039629473774728476050491743579624370862986329470409383215065075468386728605063051384392059021805296376762048386684738577913496611584935475550170449080780985441748228151762285167935803792462411864086270975057853459586240221348062704390114311522517740143545536818552136953678289681001385078524272694492488102171313792451138757064749512439313085491407348218882642272660890999334401392575446781843989380319126813905093532399127420355004498205266928383926087604741654126388033455359539622294050073378816939934733818043482668348065680837
c= 1400352566791488780854702404852039753325619504473339742914805493533574607301173055448281490457563376553281260278100479121782031070315232001332230779334468566201536035181472803067591454149095220119515161298278124497692743905005479573688449824603383089039072209462765482969641079166139699160100136497464058040846052349544891194379290091798130028083276644655547583102199460785652743545251337786190066747533476942276409135056971294148569617631848420232571946187374514662386697268226357583074917784091311138900598559834589862248068547368710833454912188762107418000225680256109921244000920682515199518256094121217521229357
p^q= 14488395911544314494659792279988617621083872597458677678553917360723653686158125387612368501147137292689124338045780574752580504090309537035378931155582239359121394194060934595413606438219407712650089234943575201545638736710994468670843068909623985863559465903999731253771522724352015712347585155359405585892
 
'''

普通的剪枝算法,exp:

from Crypto.Util.number import *
import gmpy2
import sys  # 导入sys模块
sys.setrecursionlimit(3000)  # 将默认的递归深度修改为3000
 
n = 22424440693845876425615937206198156323192795003070970628372481545586519202571910046980039629473774728476050491743579624370862986329470409383215065075468386728605063051384392059021805296376762048386684738577913496611584935475550170449080780985441748228151762285167935803792462411864086270975057853459586240221348062704390114311522517740143545536818552136953678289681001385078524272694492488102171313792451138757064749512439313085491407348218882642272660890999334401392575446781843989380319126813905093532399127420355004498205266928383926087604741654126388033455359539622294050073378816939934733818043482668348065680837
seed = 14488395911544314494659792279988617621083872597458677678553917360723653686158125387612368501147137292689124338045780574752580504090309537035378931155582239359121394194060934595413606438219407712650089234943575201545638736710994468670843068909623985863559465903999731253771522724352015712347585155359405585892
#seed即p^q
 
def findp(p, rp):
    l = len(p)
    if l == 1024:
        rp.append(int(p, 2))
    else:
        pp = int(p, 2)
        qq = (seed ^ pp) % 2 ** l
        if pp * qq % 2 ** l == n % 2 ** l:
            findp('1' + p, rp)
            findp('0' + p, rp)
 
rp = []
findp('1', rp)
for i in rp:
    if n%i==0 & isPrime(int(i)):
        print(i)
#145805499551351837545170670839798336872366414383311042018386386595288060139791135454980413014693924866953972662266748526407954492877610429602886244372924035960962307198910659475639333945895922717307291255423855616274924584270570126180050363106535962473049107576556315461013755859097114552522187755171423621071
#153796947048270429510444756458855481287460639468563001213489907625132438953570738468181770925091867439727519074685449940618659583114338501872698220745473531199063071421852521618805765627999106188015431567625318850899895052130157037822960945909520973243793507740817436707504505709194025074527084803054107605547
 
 
p=145805499551351837545170670839798336872366414383311042018386386595288060139791135454980413014693924866953972662266748526407954492877610429602886244372924035960962307198910659475639333945895922717307291255423855616274924584270570126180050363106535962473049107576556315461013755859097114552522187755171423621071
q=n//p
c=1400352566791488780854702404852039753325619504473339742914805493533574607301173055448281490457563376553281260278100479121782031070315232001332230779334468566201536035181472803067591454149095220119515161298278124497692743905005479573688449824603383089039072209462765482969641079166139699160100136497464058040846052349544891194379290091798130028083276644655547583102199460785652743545251337786190066747533476942276409135056971294148569617631848420232571946187374514662386697268226357583074917784091311138900598559834589862248068547368710833454912188762107418000225680256109921244000920682515199518256094121217521229357
e=65537
phi = (p-1) * (q-1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
#password{pruning_algorithm}

解压得到 txt 文本,里面是 no 和 yes 组成的。想到 01 画图。no 代表 0,yes 代表 1

但要知道坐标才行,010 分析压缩包文件尾:

5rOi6YCQ5rWB5rSq5rWB5rOi5rOi5rSq5rWB5rOi6ZqP5rSq5rWB6YCQ6ZqP5rWq5rWB5rOi5rOi5rWB5rSq5rWB5rOi5rWB5rSq5rWB6ZqP6YCQ5rSq6YCQ6ZqP6ZqP5rWq5rOi6YCQ5rOi6YCQ5rWq5rOi6YCQ5rWB6ZqP5rWq5rOi6YCQ6ZqP5rOi5rWq5rOi6YCQ5rOi5rWB5rSL5rOi6YCQ6YCQ6ZqP6ZqP5rWB5rWB6ZqP5rSL5rOi5rOi5rWB5rWB6ZqP6ZqP5rWB5rWB5rSL5rOi6ZqP5rWB5rWB6YCQ6ZqP6YCQ5rWB5rSL5rOi5rOi6YCQ5rOi6YCQ6ZqP6ZqP6YCQ5rSL5rWB5rWB5rWB5rWB6ZqP5rOi6YCQ6YCQ5rWq5rOi6ZqP6ZqP5rOi5rWq5rOi6YCQ6ZqP5rOi5rSq5rWB6ZqP5rOi5rWq5rOi6YCQ6ZqP5rOi5rWq5rOi6YCQ6ZqP5rOi5rWq5rOi5rOi5rWB5rWB5rWq5rOi6YCQ6ZqP5rOi5rSq5rWB6ZqP5rOi5rWq5rOi6YCQ6ZqP5rOi5rWq5rOi5rOi5rWB5rWB5rWq5rOi6YCQ6ZqP5rOi5rWq5rOi6YCQ6ZqP5rOi5rWq5rOi6YCQ6ZqP5rOi5rWq5rOi5rOi5rWB5rWB5rWq5rOi6YCQ6ZqP5rOi5rWq5rOi6YCQ6ZqP5rOiCg==

base64 解码得到:

波逐流洪流波波洪流波随洪流逐随浪流波波流洪流波流洪流随逐洪逐随随浪波逐波逐浪波逐流随浪波逐随波浪波逐波流洋波逐逐随随流流随洋波波流流随随流流洋波随流流逐随逐流洋波波逐波逐随随逐洋流流流流随波逐逐浪波随随波浪波逐随波洪流随波浪波逐随波浪波逐随波浪波波流流浪波逐随波洪流随波浪波逐随波浪波波流流浪波逐随波浪波逐随波浪波逐随波浪波波流流浪波逐随波浪波逐随波

随言随语密码,随波逐流解码即可:

548×72 flag 格式例如:Aa1aa_a1a_aaa_aa

坐标和 flag 格式都有了,接下来进行画图:

from PIL import Image
MAX1 = 548
MAX2=72
pic = Image.new("RGB",(MAX1, MAX2))
str = ""
i = 0
for y in range (0,MAX2):
    for x in range (0,MAX1):
        if(str[i] == '1'):
            pic.putpixel([x,y],(0, 0, 0))
        else:
            pic.putpixel([x,y],(255,255,255))
        i = i+1
pic.show()
pic.save("flag.png")

这是什么?好像是一种文字编码。百度一下发现是须弥沙漠文。

须弥沙漠文

对照并根据 flag 格式可以得到:Sm3rt_y0u_can_do

第九层–渡劫

hint9.py

from Crypto.Util.number import *
from random import randint
 
p = getPrime(512)
q = getPrime(512)
n = p * q
e = 65537
 
list = []
for _ in range(2):
    a, b = randint(0, 2**8), randint(0, 2**256)
    list.append(a * p + b * q)
 
password = b"xxxxx"
c = pow(bytes_to_long(password), e, n)
print(f'{n = }')
print(f'{c = }')
print(f'{list = }')
 
 
#n = 107803636687595025440095910573280948384697923215825513033516157995095253288310988256293799364485832711216571624134612864784507225218094554935994320702026646158448403364145094359869184307003058983513345331145072159626461394056174457238947423145341933245269070758238088257304595154590196901297344034819899810707
#c = 46049806990305232971805282370284531486321903483742293808967054648259532257631501152897799977808185874856877556594402112019213760718833619399554484154753952558768344177069029855164888168964855258336393700323750075374097545884636097653040887100646089615759824303775925046536172147174890161732423364823557122495
#list = [618066045261118017236724048165995810304806699407382457834629201971935031874166645665428046346008581253113148818423751222038794950891638828062215121477677796219952174556774639587782398862778383552199558783726207179240239699423569318, 837886528803727830369459274997823880355524566513794765789322773791217165398250857696201246137309238047085760918029291423500746473773732826702098327609006678602561582473375349618889789179195207461163372699768855398243724052333950197]

爆破 a 求 q (使用笛卡尔积)

我们知道

h1 = a1p + b1q

h2 = a2p + b2q

而其中的 a1 和 a2 很小,所以爆破一下可求

a2h1 – a1h2 = (a2b1 – a1b2) q

发现是 q 的倍数,然后和 n 进行 gcd 即可。

exp:

from Crypto.Util.number import *
from itertools import product
from math import gcd
import gmpy2
 
n = 107803636687595025440095910573280948384697923215825513033516157995095253288310988256293799364485832711216571624134612864784507225218094554935994320702026646158448403364145094359869184307003058983513345331145072159626461394056174457238947423145341933245269070758238088257304595154590196901297344034819899810707
c = 46049806990305232971805282370284531486321903483742293808967054648259532257631501152897799977808185874856877556594402112019213760718833619399554484154753952558768344177069029855164888168964855258336393700323750075374097545884636097653040887100646089615759824303775925046536172147174890161732423364823557122495
list = [618066045261118017236724048165995810304806699407382457834629201971935031874166645665428046346008581253113148818423751222038794950891638828062215121477677796219952174556774639587782398862778383552199558783726207179240239699423569318, 837886528803727830369459274997823880355524566513794765789322773791217165398250857696201246137309238047085760918029291423500746473773732826702098327609006678602561582473375349618889789179195207461163372699768855398243724052333950197]
h1, h2 = list
 
for a, b in product(range(2**8), repeat=2):
    q = gcd(a * h1 - b * h2, n)
    if q != 1 and q < n:
        print(q, n)
        break
q = 12951283811821084332224320465045864899191924765916891677355364529850728204537369439910942929239876470054661306841056350863576815710640615409980095344446711
 
p = n // q
e = 65537
d = pow(e, -1, (p - 1) * (q - 1))
m = pow(c, d, n)
print(long_to_bytes(m))
#game_over

解压得到:

你相信我吗.txt

压缩包里的图片真的有东西吗?不如看向外面

我们的小秘密嘿嘿.zip

看到提示说:压缩包里的图片真的有东西吗?不如看向外面

那应该是不让你分析图片,图片可能啥也没有。那就分析压缩包呗!尝试很多方法没什么思路,再看看文件名?我们的小秘密?oursecret? 试一下感觉是这个。密码是 game_over

分离得到 flag.txt:

_nine_turns?}

最终把九段 flag 拼接得到:

XYCTF{T3e_c0mb1nation_0f_crypt0_and_misc_1s_re6lly_fun!!L1u_and_K1cky_Mu_3re_so_sm4rt!In_just_a_few_m1nutes_they_were_thr0ugh!Sm3rt_y0u_can_do_nine_turns?}

md5 加密上述结果,最终 flag 为:

XYCTF{b1bdc6cf06a28b97c91c1c12f0d3bc00}

又是个签到

题目描述

也许你能在QQ群里签上到

asrmorfe.txt

😸🙍👭🙅🙇👔🙊👙👺🙂👌👪😫🙈😰😳🙃🙃🙄🙊🙎👐😱🙆👮👡👚👷😵👫🙇👏🙊👲😶👤🙉👫😰😷👹🙇👨👸👓👏🙋🙋👲🙈👳😲🙎👭👨🙉😰👰👙🙇👑👸👦🙎🙊👹🙊👮👗👩🙁😹🙃👧👡👸🙁😱👤👩👣👷👕🙅👨👙👗🙄👵👐👡👢😫😸👔😳👤👬😵😯👦👱😵👭🙎🙂🙃👓😲👐👶👥😷👰😵😹😷👘👗👪👬👥👬👒👱👰😶👕👳😵😯🙇👺😳👹😱😰👵🙉🙁😽😽

签到.txt

HWXj+kI2pS+5pSJhDS0oAzlQmziosSr7gUvdXppjSt8BNUTz8oLfE57NkCrVwBBgGul5hHzCcKqyG7U5LWMOXYtzloMsVvdZdPbMZyb+EgYF17+W/S1oLDgQcjGmP6CSHWXj+kI2pS+5pSJhDS0oA3fVDcJt/sEYpz9U0yQTrgxTN0kF5G4xTJ5IKqYil2gK3Ml6usGZsucJXa6pCovoeaGSyZNq6T3aX1NOlb5Gt4gF17+W/S1oLDgQcjGmP6CSHWXj+kI2pS+5pSJhDS0oAzlQmziosSr7gUvdXppjSt8PPIU/UwIkvINgvGw+oQMCCaOmO7bDsiSxD/r9w3RKRQEfMm/fv+a/5v/NWgauEpoF17+W/S1oLDgQcjGmP6CSHWXj+kI2pS+5pSJhDS0oA2QV+Gu05V1J2eVrbGhHB487Ns8HTVNYrll8P/Xve17NCaOmO7bDsiSxD/r9w3RKRQEfMm/fv+a/5v/NWgauEpoF17+W/S1oLDgQcjGmP6CS1yISnL45ZHzPjs5BGSboyDJXscweSL6g0ptOqql5vhY7Ns8HTVNYrll8P/Xve17NlyvQj9HulYK3sIMIiNTVrv/QYgLgLF9uO3y6uH800Gy0VvmX5a5S5ZEDlkBSgVrDb/KxZEoU9d83Nbzm7yH80p9xX+50C/29uVc+H6gx1gOTPv9mT6A8qfJoby4BoCS3by65j7WFf6d/XZX0KskX4t1SAjnDpnC8qWVbU6l6Zs9zWhqP0E6UVZEUMUcRZB43hzoYB6fvcRSs8WPoArwl6dY0JrIccPz30xmtzuOLZRKpeJ5IPHFZw5l6Zo68xW/fiYggRz/KqtgFCLvPQ+Lj+6YY1X0zgl8a3xzz5EI9efUoZd30RstP6oPDy17QzTwoaA1OLHZfyIntyJiT9r3x0kLELrvwIFczyH339IGVYqE4qA/Xsd3t/I+jStXiGGCnKCWoqABdtqk7Z22cIzn0lPAiqi9i3hd/IIgrlkygiofpTmBc34UjLRWWFjQgmDQZ8em1hDlVfgd+/93D4BVIn36xgcg2RtYCx2GmXmg5JwRj5pxcBzyOVie5m0U4zHD6Rt0T8GAvCiCf9hhYkBi7lVHe4Sb7op9fpgfXrNunluSOwxS0NlaBKwa1gvE6/BNy2CI2Uv2y4jlPTdIuCNnWbCJsTSczfPJg5PVfyXykQtg4qA/Xsd3t/I+jStXiGGCnKCWoqABdtqk7Z22cIzn0lLw/priteJqeyg6psALOE5HEboNbEbOkupEDq1HXrfGn2CI2Uv2y4jlPTdIuCNnWbCJsTSczfPJg5PVfyXykQtg4qA/Xsd3t/I+jStXiGGCnctoLlIFVYoOgnQM/2Rz5g4eIxaKQoZ+9cRB51n5yxl/BJQA5860fCnVVFSyvS40JdaogrK4AcB+C0gsnUbXVyeX1Kq+MwIHo812Z/0GIAiR+HkJQwgmO7qkogz1vcP4+q7EHUnfXquRurKvZ5jMHz4eIxaKQoZ+9cRB51n5yxl9g/v4Djdoq+YadpY2vIGrZ2CI2Uv2y4jlPTdIuCNnWbDVfnXQwmbz3jY+JyZm4sKgHDLAxJSG/IIAKk2q5C0f6l6L6v86Nra6TiDC3FBOzBEMzapQz6v9XkJfLFhywMtFLbz4PXsEvXiaFbSooHN8xVDDfRmWQyINRSNJguwiY9ElfGZnb6gHT2U5ENwxhxpxW+5Jnwn3zMCBub7HDwqyOSl5l8hKoU5obcdof5SuB3A==

我的解答:

颜文字解密,密码为文件名逆过来看:65537

432000023200001320000211000003200004320000313000021100001130000113000034200003320000

可以看到上面的字符串基本都是后面4个0然后前面3位在变化,显然7个一组,类似ASCII,根据数字范围基本确定是五进制,计算一下

strs="432000023200001320000211000003200004320000313000021100001130000113000034200003320000"

for i in range(len(strs)//7):
    num=strs[7*i:7*i+7]
    n=0
    for j in range(7):
        # print(num[-j])
        n=n+int(num[-(j+1)])*(5**j)
    print(chr(n),end="")

得到了乱码,但是结果是有的,把密文逆一下试试

str="432000023200001320000211000003200004320000313000021100001130000113000034200003320000"
strs = str[::-1]
for i in range(len(strs)//7):
    num=strs[7*i:7*i+7]
    n=0
    for j in range(7):
        # print(num[-j])
        n=n+int(num[-(j+1)])*(5**j)
    print(chr(n),end="")
    # DIQQ SEA BCE

已经可以看到结果了:ECB AES QQID

得知是AES(ECB模式加密),后面的QQID应该是key。结合题目描述可知QQID = 798794707

对附件密文签到.txt进行解密:

看到解密后末尾出现提示:Have you heard of Malbolge?

百度可找到此解密网址:https://malbolge.doleczek.pl/

XYCTF{It's_Easy!_Special_Signature}

Crypto

babyRSAMAX

题目

听说你们数学很好,我不信我不信;)

from Crypto.Util.number import *
from gmpy2 import *
from random import choice
 
flag = b'XYCTF{******}'
e = '?'
def getBabyPrime(nbits):
    while True:
        p = 1
        while p.bit_length() <= nbits:
            p *= choice(sieve_base)
        
        if isPrime(p+1):
            return p+1
 
p = getBabyPrime(512)
q = getBabyPrime(512)
n = p*q
gift1 = (pow(p,e,n)-pow(q,e,n)) % n
gift2 = pow(p+q,e,n)
 
t = 65537
x = bytes_to_long(e)
y = pow(x, t, n)
 
m = bytes_to_long(flag)
c = powmod(m, e, n)
 
print(f'n = {n}')
print(f'gift1 = {gift1}')
print(f'gift2 = {gift2}')
print(f'c = {c}')
print(f'y = {y}')
 
'''
n = 39332423872740210783246069030855946244104982381157166843977599780233911183158560901377359925435092326653303964261550158658551518626014048783435245471536959844874036516931542444719549997971482644905523459407775392702211086149279473784796202020281909706723380472571862792003687423791576530085747716706475220532321
gift1 = 4549402444746338327349007235818187793950285105091726167573552412678416759694660166956782755631447271662108564084382098562999950228708300902201571583419116299932264478381197034402338481872937576172197202519770782458343606060544694608852844228400457232100904217062914047342663534138668490328400022651816597367310
gift2 = 111061215998959709920736448050860427855012026815376672067601244053580566359594802604251992986382187891022583247997994146019970445247509119719411310760491983876636264003942870756402328634092146799825005835867245563420135253048223898334460067523975023732153230791136870324302259127159852763634051238811969161011462
c = 16938927825234407267026017561045490265698491840814929432152839745035946118743714566623315033802681009017695526374397370343984360997903165842591414203197184946588470355728984912522040744691974819630118163976259246941579063687857994193309554129816268931672391946592680578681270693589911021465752454315629283033043
y = 1813650001270967709841306491297716908969425248888510985109381881270362755031385564927869313112540534780853966341044526856705589020295048473305762088786992446350060024881117741041260391405962817182674421715239197211274668450947666394594121764333794138308442124114744892164155894256326961605137479286082964520217
 
'''

我的解答:

考点:p-1 光滑数、高次 Rabin、不互素问题 + 公式推导

首先,p-1 光滑攻击解 e

然后,高次 Rabin 解 flag,注意:gift1 和 gift2 不互素

exp:

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

#part1: p-1光滑攻击解e
n = 39332423872740210783246069030855946244104982381157166843977599780233911183158560901377359925435092326653303964261550158658551518626014048783435245471536959844874036516931542444719549997971482644905523459407775392702211086149279473784796202020281909706723380472571862792003687423791576530085747716706475220532321
t = 65537
y = 1813650001270967709841306491297716908969425248888510985109381881270362755031385564927869313112540534780853966341044526856705589020295048473305762088786992446350060024881117741041260391405962817182674421715239197211274668450947666394594121764333794138308442124114744892164155894256326961605137479286082964520217
a = 2
m = 2
while True:
    a = powmod(a, m, n)
    p = gcd(a-1, n)
    if p != 1 and p != n:
        break
    m += 1
 
q = n // p
 
phi = (p-1)*(q-1)
d = invert(t, phi)
e = powmod(y, d, n)
print(long_to_bytes(e))
#b'XYCTF{e==4096}'

#part2: 高次Rabin解flag,注意gift1和gift2不互素
from Crypto.Util.number import *
import gmpy2
 
gift1 = 4549402444746338327349007235818187793950285105091726167573552412678416759694660166956782755631447271662108564084382098562999950228708300902201571583419116299932264478381197034402338481872937576172197202519770782458343606060544694608852844228400457232100904217062914047342663534138668490328400022651816597367310
gift2 = 111061215998959709920736448050860427855012026815376672067601244053580566359594802604251992986382187891022583247997994146019970445247509119719411310760491983876636264003942870756402328634092146799825005835867245563420135253048223898334460067523975023732153230791136870324302259127159852763634051238811969161011462
n= 39332423872740210783246069030855946244104982381157166843977599780233911183158560901377359925435092326653303964261550158658551518626014048783435245471536959844874036516931542444719549997971482644905523459407775392702211086149279473784796202020281909706723380472571862792003687423791576530085747716706475220532321
c= 16938927825234407267026017561045490265698491840814929432152839745035946118743714566623315033802681009017695526374397370343984360997903165842591414203197184946588470355728984912522040744691974819630118163976259246941579063687857994193309554129816268931672391946592680578681270693589911021465752454315629283033043
e = 4096
p = gmpy2.gcd((gift1+gift2)//3,n)
q = n//p
print(p)
print(q)
p = 166353789373057352195268575168397750362643822201253508941052835945420624983216456266478176579651490080696973849607356408696043718492499993062863415424578199
q = 236438400477521597922950445153796265199072404577183190953114805170522875904551780358338769440558816351105253794964040981919231484098097671084895302287425479
pp = p%4
qq = q%4
print(pp)
print(qq)
#3
#3
 
n = p*q
def rabin(c):
    mp = pow(c, (p + 1) // 4, p)
    mq = pow(c, (q + 1) // 4, q)
 
    yp = inverse(p,q)
    yq = inverse(q,p)
 
    r = (yp * p * mq + yq * q * mp) % n
    r_ = n - r
    s = (yp * p * mq - yq * q * mp) % n
    s_ = n - s
    return r,r_,s,s_
 
cs = [c] #把c放入列表里面
#[16938927825234407267026017561045490265698491840814929432152839745035946118743714566623315033802681009017695526374397370343984360997903165842591414203197184946588470355728984912522040744691974819630118163976259246941579063687857994193309554129816268931672391946592680578681270693589911021465752454315629283033043]

#循环12次罗宾算法
for i in range(12):
    ps = []  #设置一个空列表用来存放最后结果
 
    for c2 in cs:
        r,r_,s,s_ = rabin(c2)
        if r not in ps:
            ps.append(r)
        if r_ not in ps:
            ps.append(r_)
        if s not in ps:
            ps.append(s)
        if s_ not in ps:
            ps.append(s_)
   # print(ps)
    cs = ps
 
for i in range(len(cs)):
    print(long_to_bytes(cs[i]))
#XYCTF{Rabin_is_so_biggggg!}

fakeRSA

题目

无描述就是最好的描述,嘿嘿!

from Crypto.Util.number import *
 
flag = b'XYCTF{******}'
n = ZZ(bytes_to_long(flag))
p = getPrime(int(320))
print(p)
 
G = Zmod(p)
 
def function(X, Y, Z):
    def part(a, b, c):
        return vector([9 * a - 36 * c, 6 * a - 27 * c, b])
    def parts(n):
        Gx.<a, b, c> = G[]
        if n == 0: return vector([a, b, c])
        mid = parts(n // 2)
        result = mid(*mid)
        if n % 2 == 0: return result
        else: return part(*result)
    return parts(n)(X, Y, Z)
 
print(function(69, 48, 52))
 
 
#1849790472911267366045392456893126092698743308291512220657006129900961168811898822553602045875909
#(1431995965813617415860695748430644570118959991271395110995534704629241309597572003500157255135707, 1011565891130611736600822618382801465506651972373410962205810570075870804325974377971089090196019, 784497518859893244278116222363814433595961164446277297084989532659832474887622082585456138030246)

我的解答:

考点:矩阵相似对角化、jordan

题目给了一个 function ,输入的有 n 和三个常数 X Y Z 而 n 就是我们要的 flag。

part 函数对于三个输入 a,b,c 输出一个向量 [9a – 36c, 6a – 27c, b]。而且计算都是在 Fp 下运算的

parts 函数对于输入 n 使用 symbolic 的 a,b,c 做一些运算。仔细观察会发现这其实是一个很单纯的快速幂。

我们假设 part 代表一个未知的转换 T,mid = parts (n // 2) 计算 T[n/2] 然后 mid (*mid) 就是 ( T[n/2] )2

然后再看 n 的奇偶性考虑要不要再乘 T,因此 parts (n) 其实代表的就是 Tn(x)

而 part 代表的 T 本身其实很容易看出来是个矩阵乘法:

因此这道题简单来说就是给予 v = Anu 求 n,这有点像 discrete log。

要求矩阵的次方我们想到的第一件事是对角化看看,不过很容易就能发现,A 不可对角化。我们只能算 jordan form ,也就是求 A = PJP-1 其中 J 是一个上三角矩阵。

另外,我们知道:

因此 v = Anu 可以化成 v‘ = Jnu’ 其中 v‘ = P-1v 和 u’ = P-1u

而这道题的 J 我们可以算出来是:

上三角矩阵的次方很容易推出其通项公式,懒得手算了,直接用 WolframAlpha 来解吧

所以有:

其中的 a,b,c 和 a’,b’,c’分别是 u’,v’的三个维度,都是已知的值。由于 3n-2/2 未知,因此我们设成 k 方便处理。后面可以消掉。

两式相除得到

所以

exp:

from Crypto.Util.number import *
 
p = 1849790472911267366045392456893126092698743308291512220657006129900961168811898822553602045875909
G = Zmod(p)
A = matrix(G, [[9, 0, -36], [6, 0, -27], [0, 1, 0]])
u = vector(G, (69, 48, 52))
v = vector(
    G,
    (
        1431995965813617415860695748430644570118959991271395110995534704629241309597572003500157255135707, 
        1011565891130611736600822618382801465506651972373410962205810570075870804325974377971089090196019, 
        784497518859893244278116222363814433595961164446277297084989532659832474887622082585456138030246,
    ),
)
J, P = A.jordan_form(transformation=True)
# A^n*v=u
# A=PJP^-1
# J^n*vv=uu
print(J)
vv = ~P * v
uu = ~P * u
a, b, c = uu
aa, bb, cc = vv
n = (18 * bb * c - 18 * b * cc) / (6 * c * cc)
print(n)
#11248090436223445352625693407089269386223255468324240386169564292825656540049141991068475773
print(long_to_bytes(int(n)))
#XYCTF{y0u_finally_f0und_t3h_s3cr3ts!!}

factor3

题目:

这个 e 咋比 n 还大啊 * 逆天!* 逆天!

from Crypto.Util.number import *
import random
 
flag = b'XYCTF{*****}'
m = bytes_to_long(flag)
def gainPrime():
    while True:
        x = random.getrandbits(256)
        y = random.getrandbits(256)
 
        if y % 2 == 0:
            continue
 
        p = x ** 3 + 3 * y ** 3
        if p.bit_length() == 768 and p % 2 == 1 and isPrime(p):
            return p
 
p, q = gainPrime(), gainPrime()
N = p * q
phi = (p ** 2 + p + 1) * (q ** 2 + q + 1)
d = getPrime(320)
e = inverse(d, phi)
c = d**2^m
 
print(f"N: {N}")
print(f"e: {e}")
print(f"c: {c}")
 
N: 913125842482770239379848062277162627509794409924607555622246822717218133091223291889541294440266178282194506242444509803611492259403578922020590849630191477864719052980160940803309686069818208833547621252544423652489179493083138385424424384165228024273745733240109761707533778691158938848158094054261174692601673435971526522219273943464877956131040249169850420336023942653021547841666224446678539579529590840999008107782784268926145671962239929431694391039559247
e: 494518390582436635999115147756676313570637682518235195828939117782099618734167908630788943568232122157772909140885391963441876427590731524706959546524212914108888799081844320513851526790475333924396837458796755678072486028072639014677580265244176441153444956871730684233063789931539669072735599696830757690822185323538738397827461580678488181113667710378657058297572328491762536595872579603698945272140918157163640403488075948987156585480146162739943419183496337465468187233821931312507662218106713861638334075899266373256620752680354704533272722692596941861606161634082613228896420520465402725359166156632884432690715903666803067996854084671477445131853993177110154928274312496230096270510089973592664248613332000290545537840595645944390047611474888693558676781309912289044962293014118087259307560444929227407113819165713213046898243995956550944640168932947118400215917515277554126694376415569909534496134700668701465649939
c: 4450931337369461482106945992542133557585962894030505065110870389112565329875502952762182372926117037373210509516570958483606566274369840551132381128665744266165792377925899683228751870742727716

我的解答:

考点:coppersmith-bounds、论文

我们有:

注意到 d 只有 320bits,非常小,所以说不定能透过以

去近似 phi,用 wiener attack 得到 k/d,不过实际上测试这个方法只有在 200 bits 的 d 才会成功。这样算不可举。

我们可以先推得

然后根据

得到:

设 s = p + q,然后 mod e 之后有:

这边的 k 和 d 都是同样大小 320bits, s = p + q 约 768-769bits 左右,一个容易被忽略的盲点是 phi 是 3072bits,所以 e 也是差不多的长度,所以 k,s 的大小符合 coppersmith 的 bounds,所以用 coppersmith 解出 s 后就能直接分解拿 d 了

exp:

from Crypto.Util.number import *
 
n = 913125842482770239379848062277162627509794409924607555622246822717218133091223291889541294440266178282194506242444509803611492259403578922020590849630191477864719052980160940803309686069818208833547621252544423652489179493083138385424424384165228024273745733240109761707533778691158938848158094054261174692601673435971526522219273943464877956131040249169850420336023942653021547841666224446678539579529590840999008107782784268926145671962239929431694391039559247
e = 494518390582436635999115147756676313570637682518235195828939117782099618734167908630788943568232122157772909140885391963441876427590731524706959546524212914108888799081844320513851526790475333924396837458796755678072486028072639014677580265244176441153444956871730684233063789931539669072735599696830757690822185323538738397827461580678488181113667710378657058297572328491762536595872579603698945272140918157163640403488075948987156585480146162739943419183496337465468187233821931312507662218106713861638334075899266373256620752680354704533272722692596941861606161634082613228896420520465402725359166156632884432690715903666803067996854084671477445131853993177110154928274312496230096270510089973592664248613332000290545537840595645944390047611474888693558676781309912289044962293014118087259307560444929227407113819165713213046898243995956550944640168932947118400215917515277554126694376415569909534496134700668701465649939
c = 4450931337369461482106945992542133557585962894030505065110870389112565329875502952762182372926117037373210509516570958483606566274369840551132381128665744266165792377925899683228751870742727716
 
P = PolynomialRing(Zmod(e), "k,s")
kk, ss = P.gens()
f = 1 + kk * (n ^ 2 + ss * (ss + n + 1) - n + 1)
load("coppersmith.sage")
k, s = small_roots(f, (2 ** 320, 2 ** 769), m=3, d=4)[0]  # take ~1min
k, s = ZZ(k), ZZ(s)
print(k)
print(s)
 
sol = solve(x ^ 2 - s * x + n, (x,))
p = ZZ(sol[0].rhs())
q = ZZ(sol[1].rhs())
print(p)
print(q)
assert p * q == n
d = inverse_mod(e, (p ^ 2 + p + 1) * (q ^ 2 + q + 1))
print(d)
 
#k = 1251257306657373659654605739485817595695717202438149781637777849635371292306024253248630690054410
#s = 1925420229022578583406139554581551835655011964695773657501082158233633376833949737222087944109022904389943420455209060081354234597292378923627336957822763834975165642898757928184306157864510241547740313972548801708249946480791494352
#p = 1079692686288325812308630934214667048073665141240195252583556389192093937087035206847129125872559936616225942097278411602071282941911673739879515157769270737229378250560113256396308250699296075273110248314981762673299506406938725953
#q = 845727542734252771097508620366884787581346823455578404917525769041539439746914530374958818236462967773717478357930648479282951655380705183747821800053493097745787392338644671787997907165214166274630065657567039034950440073852768399
#d = 2109723047551375043305134722302342646596769444055829710618826161103186815230448177424794300667429
 
m = c^^d**2
print(long_to_bytes(m))
#b'XYCTF{I_love_to_read_the_crypto_paper_and_try_to_ak_them}'

coppersmith.sage

import itertools
 
def small_roots(f, bounds, m=1, d=None):
	if not d:
		d = f.degree()
 
	if isinstance(f, Polynomial):
		x, = polygens(f.base_ring(), f.variable_name(), 1)
		f = f(x)
 
	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 []

 

posted @ 2024-04-25 19:28  Kicky_Mu  阅读(768)  评论(2编辑  收藏  举报