# BUUCTF - Crypto babyrsa task_4

题目如下:

from Crypto.Util.number import *
from flag import flag
def gen_prime(n):
    res = 1
    for i in range(15):
        res *= getPrime(n)
    return res
if __name__ == '__main__':
    n = gen_prime(32)
    e = 65537
    m = bytes_to_long(flag)
    c = pow(m,e,n)
    print(n)
    print(c)
# 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
# 14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595

利用在线网站可以将所给的 n 分解素数为以下 15 个:

2217990919
2338725373
2370292207
2463878387
2706073949
2794985117
2804303069
2923072267
2970591037
3207148519
3654864131
3831680819
3939901243
4093178561
4278428893

公钥如上

n = 以上公钥相乘

phi = 17290065983330319066216184030777067976382697670733255200004943703459332462321021486252411405242719735544959857825124088104221030960082400051200

e = 65537

d * e mod phi = 1 即 由相关数学概念可知,d 是 e 的逆元,标记为 e1e^{-1},

利用 扩展欧几里得算法 和 求解逆元算法

def extended_gcd(a, b):
    if b == 0:
        return a, 1, 0
    gcd, x, y = extended_gcd(b, a % b)
    return gcd, y, x - (a // b) * y
def inverse_modulo(x, p):
    gcd, inverse, _ = extended_gcd(x, p)
    if gcd != 1:
        raise ValueError("The inverse does not exist.")
    return inverse % p

代码如下:

def extended_gcd(a, b):
    if b == 0:
        return a, 1, 0
    gcd, x, y = extended_gcd(b, a % b)
    return gcd, y, x - (a // b) * y
def inverse_modulo(x, p):
    gcd, inverse, _ = extended_gcd(x, p)
    if gcd != 1:
        raise ValueError("The inverse does not exist.")
    return inverse % p
def fastExpMod(b, e, m):               #快速幂
    result = 1
    while e != 0:
        if (e&1) == 1:
            # ei = 1, then mul
            result = (result * b) % m
        e >>= 1
        # b, b^2, b^4, b^8, ... , b^(2^n)
        b = (b*b) % m
    return result
n1 = 2217990919
n2 = 2338725373
n3 = 2370292207
n4 = 2463878387
n5 = 2706073949
n6 = 2794985117
n7 = 2804303069
n8 = 2923072267
n9 = 2970591037
n10 = 3207148519
n11 = 3654864131
n12 = 3831680819
n13 = 3939901243
n14 = 4093178561
n15 = 4278428893
phi = (n1-1)*(n2-1)*(n3-1)*(n4-1)*(n5-1)*(n6-1)*(n7-1)*(n8-1)*(n9-1)*(n10-1)*(n11-1)*(n12-1)*(n13-1)*(n14-1)*(n15-1)
e = 65537
d = inverse_modulo(e, phi)
print(f"The inverse of {e} modulo {phi} is {inverse}.")
n = 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
c = 14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595
m = fastExpMod(c,d,n)
print(long_to_bytes(m))

flag 为: flag{us4_s1ge_t0_cal_phI}

# BUUCTF - Crypto small d task_5

原题目如下:

image-20230928143400881

from secret import flag
from Crypto.Util.number import *
p = getPrime(1024)
q = getPrime(1024)
d = getPrime(32)
e = inverse(d, (p-1)*(q-1))
n = p*q
m = bytes_to_long(flag)
c = pow(m,e,n)
print(c)
print(e)
print(n)
# c = 6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248
# e = 8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825
# n = 19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433

从题目可以看出,其名称为 Small d,并给出了一个人名 **Michael J. Wiener**,该攻击针对 RSA,当 d 很小时,攻击使用连分数法来暴露私钥 d。

我们直接用 rsactftool 脚本跑

https://github.com/RsaCtfTool/RsaCtfTool
python3 RsaCtfTool.py -n 19873634983456087520110552277450497529248494581902299327237268030756398057752510103012336452522030173329321726779935832106030157682672262548076895370443461558851584951681093787821035488952691034250115440441807557595256984719995983158595843451037546929918777883675020571945533922321514120075488490479009468943286990002735169371404973284096869826357659027627815888558391520276866122370551115223282637855894202170474955274129276356625364663165723431215981184996513023372433862053624792195361271141451880123090158644095287045862204954829998614717677163841391272754122687961264723993880239407106030370047794145123292991433 -e 8614531087131806536072176126608505396485998912193090420094510792595101158240453985055053653848556325011409922394711124558383619830290017950912353027270400567568622816245822324422993074690183971093882640779808546479195604743230137113293752897968332220989640710311998150108315298333817030634179487075421403617790823560886688860928133117536724977888683732478708628314857313700596522339509581915323452695136877802816003353853220986492007970183551041303875958750496892867954477510966708935358534322867404860267180294538231734184176727805289746004999969923736528783436876728104351783351879340959568183101515294393048651825 --uncipher 6755916696778185952300108824880341673727005249517850628424982499865744864158808968764135637141068930913626093598728925195859592078242679206690525678584698906782028671968557701271591419982370839581872779561897896707128815668722609285484978303216863236997021197576337940204757331749701872808443246927772977500576853559531421931943600185923610329322219591977644573509755483679059951426686170296018798771243136530651597181988040668586240449099412301454312937065604961224359235038190145852108473520413909014198600434679037524165523422401364208450631557380207996597981309168360160658308982745545442756884931141501387954248 --attack wiener

得出以下内容:

image-20230928152305659

所以 flag 为: flag{learn_some_continued_fraction_technique#dc16885c}

# BUUCTF - Crypto babyxor task_3 简单的异或

题目:

from secret import *
ciphertext = []
for f in flag:
    ciphertext.append(f ^ key)
print(bytes(ciphertext).hex())
# e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2

利用在线转换工具将十六进制转换为二进制,得到前 5 个字符的二进制为:

11101001 11100011 11101110 11101000 11110100

我们可以猜测 前五个字母应该是 flag {,利用 ASCII 转二进制可以知道为:

01100110 01101100 01100001 01100111 01111011

异或:

10001111 10001111

可以知道异或密钥为 10001111。然后先利用 16 进制转 2 进制网站,将密文转换为 2 进制;再利用异或在线解密将密文转换为明文;最后用 2 进制转换为 ASCII 码,得到正确答案,flag: flag{x0r_15_symm3try_and_e4zy!!!!!!}

# BUUCTF - Crypto babyencoding task_3.txt

题目如下所示:

part 1 of flag: ZmxhZ3tkYXp6bGluZ19lbmNvZGluZyM0ZTBhZDQ=
part 2 of flag: MYYGGYJQHBSDCZJRMQYGMMJQMMYGGN3BMZSTIMRSMZSWCNY=
part 3 of flag: =8S4U,3DR8SDY,C`S-F5F-C(S,S<R-C`Q9F8S87T`

第一行就是 Base64 编码,解码得到:

flag{dazzling_encoding#4e0ad4

第二行使用 Base64 编码解码得到乱码:

1?  ?P  ? ?Q1  0?P0?  ??1?? ?R1?? ?

尝试使用 Base32 工具解码得到:

f0ca08d1e1d0f10c0c7afe422fea7

第三行应该是 UUencode,解码后得到:

c55192c992036ef623372601ff3a}

把答案拼起来试试:

flag{dazzling_encoding#4e0ad4f0ca08d1e1d0f10c0c7afe422fea7c55192c992036ef623372601ff3a}

结果正确。

# BUUCTF - Crypto Affine task_2 Caesar with multiplication

题目如下:

from flag import flag, key
modulus = 256
ciphertext = []
for f in flag:
    ciphertext.append((key[0]*f + key[1]) % modulus)
print(bytes(ciphertext).hex())
# dd4388ee428bdddd5865cc66aa5887ffcca966109c66edcca920667a88312064

该题目为 仿射 ,提示是 凯撒和乘法

先将密文前五位 16 进制转为 10 进制:

221 67 136 238 66

根据 modulus 为 256,判断密文应该是对应的 扩展的 ASCII 码。前五位字符原先应该是 flag{ ,其所对应的十进制数为:

102 108 97 103 123

进行暴力破解,我们知道 k0 的逆元 和 k1 的值一定不会大于 256:

modulus = 256
x = [221,67,136,238,66]   #密文
y = [102,108,97,103,123]    
for k0 in range(1,257):
    for k1 in range(1,257):
        y_ = []
        for i in range(len(x)):
            y_.append((k0*( x[i] - k1)) % modulus)
        if y_ == y:
            print('k0为:',k0)
            print('k1为:', k1)
            print('y_为',y_)
            break

破解结果为:

k0的逆元 为: 241
k1为: 23

利用求逆元函数得到,k0 为 17 (没有什么用了)

根据密文转化为 10 进制数带入上述式子,得到明文 10 进制数为:

[102, 108, 97, 103, 123, 52, 102, 102, 49, 110, 101, 95, 99, 49, 112, 104, 101, 114, 95, 105, 53, 95, 118, 101, 114, 121, 95, 51, 97, 122, 121, 125]

再将其转化为 ASCII 码得到 flag: flag{4ff1ne_c1pher_i5_very_3azy}

# BUUCTF - Crypto babyaes task_1 了解下 aes 是什么

题目如下:

from Crypto.Cipher import AES
import os
from flag import flag
from Crypto.Util.number import *
def pad(data):
    return data + b"".join([b'\x00' for _ in range(0, 16 - len(data))])
def main():
    flag_ = pad(flag)
    key = os.urandom(16) * 2
    iv = os.urandom(16)
    print(bytes_to_long(key) ^ bytes_to_long(iv) ^ 1)
    aes = AES.new(key, AES.MODE_CBC, iv)
    enc_flag = aes.encrypt(flag_)
    print(enc_flag)
if __name__ == "__main__":
    main()
# 3657491768215750635844958060963805125333761387746954618540958489914964573229
# b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'

该题目为 AES 加密,使用了一个密钥 key 和初始化向量 iv,选择的 CBC 模式加密。

先分析一下题目中的几个关键函数和方法:

urandom:

语法  os.urandom(size)
参数:
	size:字符串随机字节的大小
	返回值:该方法返回一个字符串,该字符串表示适合加密使用的随机字节。
例 os.urandom(1)
输出:b'\x91'
二进制:10010001 (8bits)
AES.new(key, mode, *args, **kwargs)

param key(参数密钥):
在对称密码中使用的秘密密钥。

它必须为16、24或32个字节长(分别用于AES-128, AES-192或AES-256)。

mode(模式)
模式(支持的MODE_*常量之一)–用于加密或解密的链接模式。
学习链接:https://pycryptodome.readthedocs.io/en/latest/src/cipher/aes.html

Keyword Arguments(关键字参数):
IV(字节,字节组,memoryview) - (只适用于MODE_CBC,MODE_CFB,MODE_OFB,和MODE_OPENPGP模式)。

用于加密或解密的初始化向量。

对于MODE_CBC,MODE_CFB和MODE_OFB它必须是16个字节。

解题思路:
解密 flag 我们需要获取到 key 和 iv 的值,由条件:
key=os.urandom(16)*2
iv=os.urandom(16)
可知:key 是 32bytes,256bits ;iv 是 16bytes ,128bits

key^iv ,那么只有 iv 与 key 的低 128 位相异或,所以 key 的高 128 位是固定不变的。所以输出结果的高 128bits, 就是 key 的高 128bits, 进而可以得到 key 的所有值 256bits。之后 key 的低 128bits,与输出结果的低 128bits 相异或,所得结果就是 iv 的值了。key,iv 得到后直接 aes.decrypt () 解密就 ok 了。
代码如下:

from Crypto.Cipher import AES
import os
from gmpy2 import*
from Crypto.Util.number import*
xor = 3657491768215750635844958060963805125333761387746954618540958489914964573229
enc_flag = b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'
out = long_to_bytes(xor)
key = out[:16]*2
print('key为:',key)
iv = bytes_to_long(key[16:])^bytes_to_long(out[16:])
# print(iv)
iv = long_to_bytes(iv)
print('iv为:',iv)
aes = AES.new(key,AES.MODE_CBC,iv)
flag = aes.decrypt(enc_flag)
print(flag)

运行后得到: b'firsT_cry_Aes\x00\x00\x01' ,其中 firsT_cry_Aes 是我们需要的内容,其余部分只是填充使字符串长度达到 16。所以最终的 flag 为 flag{firsT_cry_Aes}

更新于

请我喝[茶]~( ̄▽ ̄)~*

Yanagi-Kon 微信支付

微信支付

Yanagi-Kon 支付宝

支付宝

Yanagi-Kon 贝宝

贝宝