【picoCTF2022】Crypto部分

basic-mod1

str = '128 63 242 87 151 147 50 369 239 248 205 346 299 73 335 189 105 293 37 214 333 137'
d = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
print(''.join([d[int(x) % 37] for x in str.split(' ')]))

basic-mod2

from gmpy2 import *
from sympy import invert

str = '186 249 356 395 303 337 190 393 146 174 446 127 385 400 420 226 76 294 144 90 291 445 137'
d = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
print(''.join([d[invert(int(x), 41) - 1] for x in str.split(' ')]))

credstuff

str = 'cvpbPGS{P7e1S_54I35_71Z3}'
d = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for i in range(len(d)):
    ans = ''
    for x in str:
        if x.isalpha():
            if x.islower():
                x = x.upper()
                ans += d[(d.find(x) + i) % len(d)].lower()
            else:
                ans += d[(d.find(x) + i) % len(d)]
        else:
            ans += x
    if ans.find('picoCTF') != -1:
        print(ans)

morse-code

image.png

picoCTF{wh47_h47h_90d_w20u9h7}

rail-fence

'''
若知道栏数,则使用decode解密,若不知道,则使用crack_cipher遍历所有可能性
'''


def generate_w(string, n):
    '''将字符排列成w型'''
    array = [['.'] * len(string) for i in range(n)]  #生成初始矩阵
    row = 0
    upflag = False
    for col in range(len(string)):  #在矩阵上按w型画出string
        array[row][col] = string[col]
        if row == n - 1:
            upflag = True
        if row == 0:
            upflag = False
        if upflag:
            row -= 1
        else:
            row += 1
    return array


def encode(string, n):
    '''加密'''
    array = generate_w(string, n)
    msg = []
    for row in range(n):  #将每行的字符连起来
        for col in range(len(string)):
            if array[row][col] != '.':
                msg.append(array[row][col])
    return array, msg


def decode(string, n):
    '''解密'''
    array = generate_w(string, n)
    sub = 0
    for row in range(n):  #将w型字符按行的顺序依次替换为string
        for col in range(len(string)):
            if array[row][col] != '.':
                array[row][col] = string[sub]
                sub += 1
    msg = []
    for col in range(len(string)):  #以列的顺序依次连接各字符
        for row in range(n):
            if array[row][col] != '.':
                msg.append(array[row][col])
    return array, msg


def crack_cipher(string):
    '''破解密码'''
    for n in range(2, len(string)):  #遍历所有可能的栏数
        print(str(n) + '栏:' + ''.join(decode(string, n)[1]))


if __name__ == "__main__":
    string = "Ta _7N6DDEhlg:W3D_H3C31N__883ef sHR053F38N43D1B i33___ND"
    n = 4  #栏数

    #若不知道栏数,则遍历所有可能
    # crack_cipher(string)

    #若知道栏数
    array, msg = decode(string, n)
    # array,msg = encode(string, n)
    for i in array:
        print(i)
    print(''.join(msg))

# ['T', '.', '.', '.', '.', '.', 'a', '.', '.', '.', '.', '.', ' ', '.', '.', '.', '.', '.', '_', '.', '.', '.', '.', '.', '7', '.', '.', '.', '.', '.', 'N', '.', '.', '.', '.', '.', '6', '.', '.', '.', '.', '.', 'D', '.', '.', '.', '.', '.', 'D', '.', '.', '.', '.', '.', 'E', '.']
# ['.', 'h', '.', '.', '.', 'l', '.', 'g', '.', '.', '.', ':', '.', 'W', '.', '.', '.', '3', '.', 'D', '.', '.', '.', '_', '.', 'H', '.', '.', '.', '3', '.', 'C', '.', '.', '.', '3', '.', '1', '.', '.', '.', 'N', '.', '_', '.', '.', '.', '_', '.', '8', '.', '.', '.', '8', '.', '3']
# ['.', '.', 'e', '.', 'f', '.', '.', '.', ' ', '.', 's', '.', '.', '.', 'H', '.', 'R', '.', '.', '.', '0', '.', '5', '.', '.', '.', '3', '.', 'F', '.', '.', '.', '3', '.', '8', '.', '.', '.', 'N', '.', '4', '.', '.', '.', '3', '.', 'D', '.', '.', '.', '1', '.', 'B', '.', '.', '.']
# ['.', '.', '.', ' ', '.', '.', '.', '.', '.', 'i', '.', '.', '.', '.', '.', '3', '.', '.', '.', '.', '.', '3', '.', '.', '.', '.', '.', '_', '.', '.', '.', '.', '.', '_', '.', '.', '.', '.', '.', '_', '.', '.', '.', '.', '.', 'N', '.', '.', '.', '.', '.', 'D', '.', '.', '.', '.']
# The flag is: WH3R3_D035_7H3_F3NC3_8361N_4ND_3ND_D81DB8E3

substitution0

quipqiup - cryptoquip and cryptogram solver

image.png

substitution1

image.png

substitution2

记得填上数字

image.png

transposition-trial

str = 'heTfl g as iicpCTo{7F4NRP051N5_16_35P3X51N3_VE1A1D3D}B'
ans = ''
# 小于间隔继续
for i in range((len(str) + 3 - 1) // 3):
    ans += str[3 * i + 2] + str[3 * i + 0] + str[3 * i + 1]
print(ans)

Vigenere

str = 'rgnoDVD{O0NU_WQ3_G1G3O3T3_A1AH3S_d0db78b8}'
str = str.upper()
key = 'CYLAB'
ans = ''
index = 0
for ch in str:
    if ch.isalpha():
        ans += chr((ord(ch) - ord(key[index % len(key)]) + 26) % 26 + ord('a'))
        index += 1
    else:
        ans += ch
print(ans)

diffie-hellman

a = 'H98A9W_H6UM8W_6A_9_D6C_5ZCI9C8I_DI9D987F'
b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
ans = ''
for i in a:
    if i == '_':
        ans += i
    else:
        ans += (b[(b.find(i) - 5) % len(b)])

print('picoCTF{' + ans.lower() + '}')

Very Smooth

import gmpy2
from Crypto.Util.number import *


def Pollards_p_1(N):
    a = 2
    n = 2
    while True:
        a = pow(a, n, N)
        res = gmpy2.gcd(a - 1, N)
        if res != 1 and res != N:
            print('n =', n)
            print('p =', res)
            return res
        n += 1


e = gmpy2.mpz(0x10001)
n = gmpy2.mpz(
    0x809fbd8b667d664f01fe1b0387e0b424efe2035e2dec4d249ace30563d0e1a50050020880c2f01bad63b22e21125d780d887cffdb1165268e6be788cd49ad8a9a1d27482f1a8ccbb37adc0deee65d09f312ebaab854782e2411d917181fef63d478b7e25391ac10d0330cafcb5c8d859ee1e403be029ce5dd75f864deabe5a65645b099afb7af4ed84dd75d1e4b966e2a0662ece5409feeacb2a277ddf05b72153ff6f36524f7693cc432269b56bd8ab3d601844aef6a6130eaaec08f92f9816ed0e7781a23a043570364807bef579c1e9175e3fe2b1d8f52356230feea244ce1b88b2342c9e40b25583a1fe558bdfb3a7115a4c71a6f06b706419ce8e21a3e1
)
c = gmpy2.mpz(
    0x74ce97c4712bc3827a9f6021089c093a7540a6280330a9ec7c6f446a88093c33a6b9a0a1fdf2cad96e32344970adbf26601d9baf2c4e9892dde435dc994bde4754fddbac47a475b3907a455c6f671484b473b5481080224406b1d48d48da5ba0d9fccdc5732cb64c0f02c32ddc1413f66bd95b8e5a929e5b1f14843bd8f5d4747a4aabcc64217a187db6913facce48f2019b5524633153ee40a4376960b7f669f331da29227fa9a8c09a58a6f3db7453dd89a6093c062ff95502cc7cca5ee497c8ec6265413f5d05d1b720b4eb620875b6f6d2a7958e2391835497a106f4c280cd1ca8b9605bbef5952b54dffc028c160c1495e5cd2957f6f2bbb2e868823b6a
)
p = Pollards_p_1(n)
q = n // p
assert p * q == n
d = gmpy2.invert(e, (p - 1) * (q - 1))
m = pow(c, d, n)
print(long_to_bytes(m))

Sequences

import hashlib
import sys
import functools
from gmpy2 import *

ITERS = int(2e7)
VERIF_KEY = "96cc5f3b460732b442814fd33cf8537c"
ENCRYPTED_FLAG = bytes.fromhex(
    "42cbbce1487b443de1acf4834baed794f4bbd0dfe08b5f3b248ef7c32b")
P = mpz(10**10000)


# This will overflow the stack, it will need to be significantly optimized in order to get the answer :)
def m_func(i):
    if i == 0: return 1
    if i == 1: return 2
    if i == 2: return 3
    if i == 3: return 4
    m = [
        [mpz(0), mpz(1), mpz(0), mpz(0)],
        [mpz(0), mpz(0), mpz(1), mpz(0)],
        [mpz(0), mpz(0), mpz(0), mpz(1)],
        [mpz(55692), mpz(-9549), mpz(301),
         mpz(21)],
    ]
    m = quickMatrix(m, i - 3)
    ans = mpz(0)
    for i in range(4):
        ans += ((m[3][i] * m_func(i)) % P)
    return ans


def mulMatrix(x, y):
    ans = [[0 for i in range(4)] for j in range(4)]
    for i in range(4):
        for j in range(4):
            for k in range(4):
                ans[i][j] += ((x[i][k] * y[k][j]) % P)
    return ans


def quickMatrix(m, n):
    ans = [[0 for i in range(4)] for j in range(4)]
    for i in range(4):
        ans[i][i] = 1
    while (n):
        if n % 2 != 0:
            ans = mulMatrix(ans, m)
        m = mulMatrix(m, m)
        n >>= 1
    return ans


# Decrypt the flag
def decrypt_flag(sol):
    sol = sol % (10**10000)
    sol = str(sol)
    sol_md5 = hashlib.md5(sol.encode()).hexdigest()

    if sol_md5 != VERIF_KEY:
        print("Incorrect solution")
        sys.exit(1)

    key = hashlib.sha256(sol.encode()).digest()
    flag = bytearray([char ^ key[i]
                      for i, char in enumerate(ENCRYPTED_FLAG)]).decode()

    print(flag)


if __name__ == "__main__":
    sol = m_func(ITERS)
    decrypt_flag(sol)

Sum-O-Primes

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

e = 65537
x = 0x1603fc8d929cb31edf62bcce2d06794f3efd095accb163e6f2b78941bd8c646d746369636a582aaac77c16a9486881a9e3db26d742e48c4adcc417ef98f310a0c5433ab077dd872530c3c3c77fe0c080d84154bfdb4c920df9617e986999104d9284516c7babc80dc53718d59032aefdf41b9be53957dea3f00a386b2666d446e
n = 0x75302ba292dc4bf47ffd690b8edc70ef1fcca5e148b2b9c1b60227788afcfe77a0097929ed3789fe51ac66f678c558244890a09ae4af3e7d098fd366a1c859edabbff1c9e164d5354968798107ae8518fcaab3743de58a141ffd26c1e16cb09fed1f6b0d68536ec7fba744ed120fea8c3a7ac1ebfa55d664d2f321fb44e814650147a9031f3bfa8f69d87393c7d88976d28d147398a355020bcb8e5613f0b29028b77db710e163ca1019fd3c3a065465ea457adec45243c385d12d3a1de3178f6ca05964be92e8b5bc24d420956de96ccc9ce39e70705660eb6b2f4e675aac7d6d7ba45c84223fc5819b37aa85beff1382f1c2c3b97603150f30c17f7e674441
c = 0x562888c70ce9a5c5ed9a0be1b6196f854ba2efcdb6dd0f79319ee9e1142659f90a6bae67481eb0f635f445d3c9889da84639beb84ff7159dcf4d3a389873dc90163270d80dbb9503cbc32992cb592069ba5b3eb2bbe410a3121d658f18e100f7bd878a25c27ab8c6c15b690fce1ca43288163c544bfce344bcd089a5f4733acc7dc4b6160718e3c627e81a58f650281413bb5bf7bad5c15b00c5a2ef7dbe7a44cce85ed5b1becd5273a26453cb84d327aa04ad8783f46d22d61b96c501515913ca88937475603437067ce9dc10d68efc3da282cd64acaf8f1368c1c09800cb51f70f784bd0f94e067af541ae8d20ab7bfc5569e1213ccdf69d8a81c4746e90c1
phi = n - x + 1
d = invert(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

NSA Backdoor

使用了 Pohlig-Hellman algorithm

离散对数 - CTF Wiki (ctf-wiki.org)

先用 Very Smooth 的代码分解 n 有

p = 133120514134071565184901374403906104857402594315193452979400334844456988039351029748429497538981454221984106135005043996378098395846705709422658663585864970394230279241392567216599860405945469882804839379543093459226432299183847151658790842646530907008354991523758458009950957111989465047584759069188272154703
q = 107878320716069936845347261730222923402619282584236808136469656719645067255143372538361375857163594280233925663413568686520703251291382637679919197208920902793419007945364505474185442005931731898039583502138819092649272834779913753377381462765827012568092442233669634217190652686190269458879367972776287369087

在 sagemath 上用 discrete_log 就行(这个 discrete_log 包含了好多算法,强强)

image.png

image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值