• [DownUnderCTF 2022] crypto部分复现


    一个良心的比赛,赛完后给出wp,都是挺好的题,有必要都试一下

    1 baby-arx

    签到题,直接给了加密算法和密文,逐位的进行异或移位操作,这个东西都可以爆破

    1. class baby_arx():
    2. def __init__(self, key):
    3. assert len(key) == 64
    4. self.state = list(key)
    5. def b(self):
    6. b1 = self.state[0]
    7. b2 = self.state[1]
    8. b1 = (b1 ^ ((b1 << 1) | (b1 & 1))) & 0xff
    9. b2 = (b2 ^ ((b2 >> 5) | (b2 << 3))) & 0xff
    10. b = (b1 + b2) % 256
    11. self.state = self.state[1:] + [b]
    12. return b
    13. def stream(self, n):
    14. return bytes([self.b() for _ in range(n)])
    15. FLAG = open('./flag.txt', 'rb').read().strip()
    16. cipher = baby_arx(FLAG)
    17. out = cipher.stream(64).hex()
    18. print(out)
    19. # cb57ba706aae5f275d6d8941b7c7706fe261b7c74d3384390b691c3d982941ac4931c6a4394a1a7b7a336bc3662fd0edab3ff8b31b96d112a026f93fff07e61b

    爆破

    1. #!/usr/bin/env python3
    2. def b_cust(b1, b2):
    3. c1 = (b1 ^ ((b1 << 1) | (b1 & 1))) & 0xff
    4. c2 = (b2 ^ ((b2 >> 5) | (b2 << 3))) & 0xff
    5. b = (c1 + c2) % 256
    6. return b
    7. out = 'cb57ba706aae5f275d6d8941b7c7706fe261b7c74d3384390b691c3d982941ac4931c6a4394a1a7b7a336bc3662fd0edab3ff8b31b96d112a026f93fff07e61b'
    8. enc = bytes.fromhex(out)
    9. flag = 'D'
    10. for i in range(len(enc) - 1):
    11. for code in range(32, 127):
    12. b = b_cust(ord(flag[-1]), code)
    13. if b == enc[i]:
    14. flag += chr(code)
    15. break
    16. print(flag)
    17. #DUCTF{i_d0nt_th1nk_th4ts_h0w_1t_w0rks_actu4lly_92f45fb961ecf420}
    '
    运行

    当然也可以不爆破,用z3可以直接出.

    2 oracle-for-block-cipher-enthusiasts

    AES的OFB模式加密,可以交互两次,用户提供IV给出加密结果

    1. #!/usr/bin/env python3
    2. from os import urandom, path
    3. from Crypto.Cipher import AES
    4. FLAG = open(path.join(path.dirname(__file__), 'flag.txt'), 'r').read().strip()
    5. MESSAGE = f'Decrypt this... {urandom(300).hex()} {FLAG}'
    6. def main():
    7. key = urandom(16)
    8. for _ in range(2):
    9. iv = bytes.fromhex(input('iv: '))
    10. aes = AES.new(key, iv=iv, mode=AES.MODE_OFB)
    11. ct = aes.encrypt(MESSAGE.encode())
    12. print(ct.hex())
    13. if __name__ == '__main__':
    14. main()
    15. #nc 2022.ductf.dev 30009

    OFB的加密方式为先用iv=z0加密得到z1然后用m0⊕z1得到c0,也就是用iv得到的加密流z1,z2,...与明文异或得到密文。所以如果把z1作为iv得到的加密的就是z2,z3,z4...这些z与上边的z相同。

    由于第1段明文已知,那么第一次随意输入一个iv得到密文c0,然后用已知的第1断明文和c0的第1段得到z1,第2次输入iv为z1得到c1,同样通过c1与已知明文异或得到z2,然后用z2和c0的第2段异或得到第2段明文,最后得到flag

    1. #!/usr/bin/env python3
    2. from pwn import *
    3. from os import urandom, path
    4. from Crypto.Cipher import AES
    5. #FLAG = open(path.join(path.dirname(__file__), 'flag.txt'), 'r').read().strip()
    6. #MESSAGE = f'Decrypt this... {urandom(300).hex()} {FLAG}'
    7. def main():
    8. key = urandom(16)
    9. for _ in range(2):
    10. iv = bytes.fromhex(input('iv: '))
    11. aes = AES.new(key, iv=iv, mode=AES.MODE_OFB)
    12. ct = aes.encrypt(MESSAGE.encode())
    13. print(ct.hex())
    14. #nc 2022.ductf.dev 30009
    15. '''
    16. m0 m1 m2 m3
    17. iv z1 z2 z3 z4 ...
    18. c0 c1 c2 c3
    19. m0 m1 m2 m3
    20. z1 z2 z3 z4 z5 ...
    21. x0 x1 x2 x3
    22. OFB模式每轮只对iv加密,然后由c=m^z
    23. 第1次随意输入
    24. 第2次输入由第1次得到的z1
    25. 这样循环 m0^x0 => z2得到下一轮的z, c1^z2 => m1 得到下一块明文
    26. '''
    27. m = [b'Decrypt this... ']
    28. iv = b'\x00'*16
    29. context.log_level = 'debug'
    30. p = remote('2022.ductf.dev', 30009)
    31. #由已知明文得到z(i)
    32. p.sendlineafter(b'iv: ', iv.hex().encode())
    33. c0 = unhex(p.recvline()[:-1])
    34. z0 = xor(c0[:16],m[0])
    35. z = [z0]
    36. #以z(i)为iv,由已知明文0得到z(i+1)
    37. p.sendlineafter(b'iv: ', z0.hex().encode())
    38. c1 = unhex(p.recvline()[:-1])
    39. for i in range(0, len(c0), 16):
    40. #c(i+1) xor z(i+1) => m(i)
    41. z.append(xor(m[-1], c1[i: i+16]))
    42. m.append(xor(z[-1], c0[i+16: i+16+16]))
    43. print(b''.join(m))
    44. #DUCTF{0fb_mu5t_4ctu4lly_st4nd_f0r_0bvi0usly_f4ul7y_bl0ck_c1ph3r_m0d3_0f_0p3ra710n_7b9cb403e8332c980456b17a00abd51049cb8207581c274fcb233f3a43df4a}
    45. '''
    46. C:\2022_DownUnderCTF\crypto_2_oracle-for-block-cipher-enthusiasts>py a.py
    47. [x] Opening connection to 2022.ductf.dev on port 30009
    48. [x] Opening connection to 2022.ductf.dev on port 30009: Trying 34.87.217.252
    49. [+] Opening connection to 2022.ductf.dev on port 30009: Done
    50. [DEBUG] Received 0x4 bytes:
    51. b'iv: '
    52. [DEBUG] Sent 0x21 bytes:
    53. b'00000000000000000000000000000000\n'
    54. [DEBUG] Received 0x5f9 bytes:
    55. b'c5d2cc11722803d1c34f2b0d59938a06f58c4f0e2b7acbd08f30115bb58e08f8726c4226c125282faa8a50687573f8aac72d58f83b531cff4a
    56. 8264bb7dbdfce9839165ec3b943ceaf7a8da0234e100f720407004441b28bb82cbe48cc4f017b4385783468e239391ffe8aad14fdfb37e5685d31a6a
    57. 234830b7d032bfa8f82543616bc6be663b7d098a46e3c147b51f1bbded127a303dc6d762a3429aa2f05d6526dff55799179f33e4e2062850be1b26dd
    58. dc471b010b15bca6aa5b7ba802cd16d69cd34ac959f7042919d6ed88804c4253f298328b5cd0f6f4ba9aff14eea8d7b0dc728780fa895dc52c9cd083
    59. 08f4c1c75e8d529f8cee054df4e1e615c50798b06b95439152d8a90778afa5c17944cdf3dd753147245f1331fc84c18111ca4a13013150acee86bbb5
    60. 8cd16fa9371f570b23f80269443e1bf7d58bd2dde86217ddd6ce40f9c67308ac9c870c9901e14874bdd608ba6cde6ef662e7b0683458fae41cee5d8c
    61. e565f7add226c7379359c0b0853dc56199971ad924b04033e3969905acf68ba3bdb21331df811edbb3dda90b4bff4413ccd0164f72e83e1e4312ff12
    62. bcd5fc3ea4af22955c229d90113813cba196afe84492331c880761a6d0dd3fcaa881dda419826f8bc42bbd834d1f5247621547f1d325c5716b086ba6
    63. b841092ad451decdfd50590e2b767af754c4ae271cea75e4ffbd6a1a255a2f2f93dac2291b1c814a34395c0ee6cb9b45dd1ad925ff4db46a2a61c06f
    64. dbe256c62dc26cff7907757eddb5855fd1e8dd4f2ae6df0a08f48799b5e0ffcc62fcaee4f9a73598190677d7e6235598cc383c2f9b01e1cb47523f3e
    65. f733700ee7ab7ff5fadce14000ca46b671346796573781232069743733e6be7a16838b837d8ea9371d6b4174ff29362f8061168f71cbf7b7cce5d83c
    66. f5e1cd3f47450d8ccf521a44cea4ef83f8a2c8cb25a30a31c6987c1b6f5dcee3579c44a8907bfec9fa20a55aa1cfedf7dd0a3242da1481eeff93fc8b
    67. 7d1ff848314ca0df57756a28ae2d6bfa1d09adced1340b85ea3fa6a3330daec73a9226e5030f31dbfae51a2c43\n'
    68. b'iv: '
    69. [DEBUG] Sent 0x21 bytes:
    70. b'81b7af630b5877f1b727427e77bda426\n'
    71. [DEBUG] Received 0x5f5 bytes:
    72. b'd7df494e346bdbc7c26c1e49a29211ed706e45759377747da78c0e6a7b70fdfac22f0dff3b5046a218826fbc7deaafbdda9364b93fc166e0a5
    73. a8880566bf57f529127255154626bfd59db7df95f114b13c53d5418e29979effeffdd21dd5bf2906d6804e3e204b3eb28562bea8ae7844603fc2b66b
    74. 692d06d949e3c045b51d48bcea45213b6d96dd34a81490f6ad0c6322dff5049c1d9d60beb4062654b61473dd8e411a000544e4aaf80c78ab53c51181
    75. 9fd34a980ca7592b16d4ef8dd04c1100a5cb37db5cd4f1f3b39ba845edaf80ed8d7587d4ac8f5f977ecad3d259fac19b538e54ccdebd024df3e2b112
    76. 940b99ed36934398528faa532eacf195731090f2d922374d245e4f62aed693d01c9b424e066706aebb82b1e6d8813afa341955597daa026d443810f9
    77. d18ed5dde632468fdace14afc57603f5ccd954990ee51a74ead15abe6fd839f560e9b9683159f2e046ea5ad9b234aafdd326c665c4589cb3dd3c9430
    78. 99c21adc27b24067e3c69b57a8ab8cf6eeb24b628a8c1ed8e3dcf90c1ef64846cad5451376e73b4f4715fb14bbd2a068a2fe279c092298c4126f409b
    79. a793fced1797601cdc5564f4d788389faf818cf41cda328f9478e8d41e4b5712361414a3d42a9d753d0b6fa5ba470b2dd050df9ca8540c5d7d772ff6
    80. 00c3a97818be23e5f4bd3f4a26562b2dc1d891214c49d7183c3a5e59b294cb428a4cd876ab1be338236097688eb4549e20966bad2f51707ed1b28959
    81. d7ee8f4627b4dd5e5aa183ceb9eea59034faacedfea061c94b067186bb2c0195ce3b3d22cb52bdc8110c6d3fa663200bb4f97cf0ae8bea45059416e3
    82. 226165867103f6465020766235dfb53e45c4b0975aaf9f57377c084dee026f34d14a2f8b60e0b2e1d6e09116f5f9800e452e1ed08a747544d4fdbc9d
    83. d4ad80e42ba40d029cd1474a5c5dcbd7388f46aa997fbda6f94ff60bc79ce99cdd496408881082bda8f4fbdd714af84d361ef5d705243c7ea6256ff7
    84. 4b5df7cdd6620e8dba3ef0a1365bf99c6bc32db1005930d0afe01c7a0ac01e9aa4b18a27f9f3315197ec12b680\n'
    85. b'Decrypt this... f6e2fad794fa9275d4ba438e428c712ea67f40b8f23d7fa184630e8242ace8631f4ba866cd2049565bbea229cce3f39ae11151
    86. 17f652fedfde598ca85953def5ebbb3312c2c90873abb1693a9dc7408fa0d077b956447a0a63d0fb2d79662102ed756b6c007ac27e8505b40abbab2c
    87. 9ed8331fcfbeb5525d9e538f4e63aaa8a98ab52f59ea330501ef4c031365cfc66378fc437881fac8fbe4f7b023aa89c7b0ecaef34dbc60c2c8a9eb3d
    88. e92b611ebdbad3bd097a41ee2f0e94770ad491f5367008b15280647142177d47d71e61c2caa1271dad11d4156f462faa995a7affbcab353f6a174eed
    89. daff24b324ba50d0cf9bfbc82a2b94fba51534101ce6fda574baecc904bc0f98c3073fc578de640511defb499b8306926e57fded6651374be96a86d5
    90. ff0ba416223dff1f3d DUCTF{0fb_mu5t_4ctu4lly_st4nd_f0r_0bvi0usly_f4ul7y_bl0ck_c1ph3r_m0d3_0f_0p3ra710n_7b9cb403e8332c98045
    91. 6b17a00abd51049cb8207581c274fcb233f3a43df4a}C~\xf7\xa7YCA\xca\x92\x05b\xf3\x8a&\xd7\xfdd\x87\x04\x96\x08\xd4'
    92. '''

    3 cheap-ring-theory

    这是个脑筋急转弯的题。题目是一个很难计算的算式C = A^n * B^m 给出3组解,然后让输入3组解使式子成立

    1. p = 55899879511190230528616866117179357211
    2. V = GF(p)^3
    3. R. = PolynomialRing(GF(p))
    4. f = x^3 + 36174005300402816514311230770140802253*x^2 + 35632245244482815363927956306821829684*x + 10704085182912790916669912997954900147
    5. Q = R.quotient(f)
    6. def V_pow(A, n):
    7. return V([a^n for a in list(A)])
    8. n, m = randint(1, p), randint(1, p)
    9. A = Q.random_element()
    10. B = Q.random_element()
    11. C = A^n * B^m
    12. print(' '.join(map(str, list(A))))
    13. print(' '.join(map(str, list(B))))
    14. print(' '.join(map(str, list(C))))
    15. phi_A = V(list(map(int, input().split())))
    16. phi_B = V(list(map(int, input().split())))
    17. phi_C = V(list(map(int, input().split())))
    18. check_phi_C = V_pow(phi_A, n).pairwise_product(V_pow(phi_B, m))
    19. if phi_C == check_phi_C:
    20. print(open('./flag.txt', 'r').read().strip())

    但是这个算式有两个特殊解0,1当ABC都是0或者都是1时算式恒成立,所以直接输入1组即可

    1. $ nc 2022.ductf.dev 30012
    2. 47778318564842784566021875964043407448 14225130399845907372219257728746212147 8574612587622189283548244260000651099
    3. 54562657673431046093572570377554257218 13201212589661363040860414827784708283 6559649814714882162760393923770035994
    4. 42068356418631381456403302803023702216 2953351887187401071583384926766279486 28509402046235153374884180763878587638
    5. 0 0 0
    6. 0 0 0
    7. 0 0 0
    8. DUCTF{CRT_e4sy_as_0ne_tw0_thr3e}
    9. $ nc 2022.ductf.dev 30012
    10. 14202332705912194922737102630420425225 25456741823861199641984966822367393116 49401604133125475446972443244172984778
    11. 35742550950811340910151890855042975986 30127926032118592751540416970212811542 37792889060452965734274017750212553062
    12. 4755274484612010897449319953362032907 33809699771879943330968717144050513513 20099247008524376332197577971971190549
    13. 1 1 1
    14. 1 1 1
    15. 1 1 1
    16. DUCTF{CRT_e4sy_as_0ne_tw0_thr3e}

    4 rsa-interval-oracle-i

    以下4道都是RSA oracle的题,以前见到的都是LSB,这个第一回见,学习了。

    第1题比较简单,给一N,e,c 然后可以输入密文,反回明文是否在区间内,区间自己输入。

    1. #!/usr/bin/env python3
    2. import signal, time
    3. from os import urandom, path
    4. from Crypto.Util.number import getPrime, bytes_to_long
    5. FLAG = open(path.join(path.dirname(__file__), 'flag.txt'), 'r').read().strip()
    6. N_BITS = 384
    7. TIMEOUT = 20 * 60
    8. MAX_INTERVALS = 384
    9. MAX_QUERIES = 384
    10. def main():
    11. p, q = getPrime(N_BITS//2), getPrime(N_BITS//2)
    12. N = p * q
    13. e = 0x10001
    14. d = pow(e, -1, (p - 1) * (q - 1))
    15. secret = bytes_to_long(urandom(N_BITS//9))
    16. c = pow(secret, e, N)
    17. print(N)
    18. print(c)
    19. intervals = []
    20. queries_used = 0
    21. while True:
    22. print('1. Add interval\n2. Request oracle\n3. Get flag')
    23. choice = int(input('> '))
    24. if choice == 1:
    25. if len(intervals) >= MAX_INTERVALS:
    26. print('No more intervals allowed!')
    27. continue
    28. lower = int(input(f'Lower bound: '))
    29. upper = int(input(f'Upper bound: '))
    30. intervals.insert(0, (lower, upper)) #从头部插入,如果判断时成功则返回0,不成功会返回上一次成功的位置>1,全部不成功才返回-1
    31. elif choice == 2:
    32. queries = input('queries: ')
    33. queries = [int(c.strip()) for c in queries.split(',')]
    34. queries_used += len(queries)
    35. if queries_used > MAX_QUERIES:
    36. print('No more queries allowed!')
    37. continue
    38. results = []
    39. for c in queries:
    40. m = pow(c, d, N)
    41. for i, (lower, upper) in enumerate(intervals):
    42. in_interval = lower < m < upper
    43. if in_interval:
    44. results.append(i)
    45. break
    46. else:
    47. results.append(-1)
    48. print(','.join(map(str, results)), flush=True)
    49. time.sleep(MAX_INTERVALS * (MAX_QUERIES // N_BITS - 1))
    50. elif choice == 3:
    51. secret_guess = int(input('Enter secret: '))
    52. if secret == secret_guess:
    53. print(FLAG)
    54. else:
    55. print('Incorrect secret :(')
    56. exit()
    57. else:
    58. print('Invalid choice')
    59. if __name__ == '__main__':
    60. signal.alarm(TIMEOUT)
    61. main()

    解决办法:对于同样的c,划定m的区间这样就能通过区间确定m的大小,利用二分法每次确定1位。

    1. from pwn import *
    2. p = remote('2022.ductf.dev', 30008)
    3. #context.log_level = 'debug'
    4. N = int(p.recvline())
    5. c = int(p.recvline())
    6. N_BITS = 384
    7. border = [-1, 2<<(N_BITS//9*8)]
    8. def sendborder(low,high):
    9. p.sendlineafter(b'> ', b'1')
    10. print(low)
    11. print(high)
    12. p.sendlineafter(b'Lower bound: ', str(low).encode())
    13. p.sendlineafter(b'Upper bound: ', str(high).encode())
    14. def get_v():
    15. p.sendlineafter(b'> ', b'2')
    16. p.sendlineafter(b'queries: ', str(c).encode())
    17. res = int(p.recvline())
    18. return res
    19. def get_flag(sec):
    20. p.sendlineafter(b'> ', b'3')
    21. p.sendlineafter(b'Enter secret: ', str(sec).encode())
    22. flag = p.recvline()
    23. return flag
    24. for i in range(N_BITS//9*8):
    25. tb = (border[0]+border[1])//2 #检测下半区是否命中
    26. sendborder(border[0], tb)
    27. res = get_v()
    28. print(i,'RES:' , res)
    29. if res != 0: #命中时返回i==0,其它-1,2,3,4都是未命中
    30. border[0] = tb-1 #未命中的情况, 值在上半区,更新下边界
    31. else:
    32. border[1] = tb #命中,在本区更新上边界
    33. context.log_level = 'debug'
    34. print(get_flag(border[0]+1))

    5 rsa-interval-oracle-ii

    第2题在第1题的程序上改动了输入区间的次数为1,也就是只允许输入1次区间。那么这个区间就输入是固定的,难度就象羊了个羊第2关。

    我理解是输入一个分数比如4/3m就会落在大于1的范围上,但在有限域上不能输入分数。就得用比较复杂的办法来模拟,但由于精度不够,在最后还需要爆破24位

    1. from pwn import *
    2. from gmpy2 import invert, c_div
    3. p = remote('2022.ductf.dev', 30011)
    4. context.log_level = 'debug'
    5. N = int(p.recvline())
    6. c = int(p.recvline())
    7. e = 0x10001
    8. N_BITS = 384
    9. border = [-1, 2<<(N_BITS//9*8)]
    10. def sendborder(low,high):
    11. p.sendlineafter(b'> ', b'1')
    12. #print(low)
    13. #print(high)
    14. p.sendlineafter(b'Lower bound: ', str(low).encode())
    15. p.sendlineafter(b'Upper bound: ', str(high).encode())
    16. def get_v(fc):
    17. p.sendlineafter(b'> ', b'2')
    18. p.sendlineafter(b'queries: ', str(fc).encode())
    19. res = int(p.recvline())
    20. return res
    21. def get_flag(sec):
    22. p.sendlineafter(b'> ', b'3')
    23. p.sendlineafter(b'Enter secret: ', str(sec).encode())
    24. flag = p.recvline()
    25. return flag
    26. '''
    27. #local
    28. from os import urandom
    29. from Crypto.Util.number import getPrime, bytes_to_long
    30. N_BITS = 384
    31. p = 0xbe103afbae6d9ef1bf866a9fe44da3a9c3b2818e315de13b
    32. q = 0xf206c05bd9f2cb28822f84874b94b2dbbf0e3e625426c2f5
    33. N = p*q
    34. e = 0x10001
    35. d = pow(e, -1, (p - 1) * (q - 1))
    36. print('d = ', hex(d))
    37. secret = 0x1ad7dbd636f2eb28c75bd0e70a08e6a16a75ae540f3bced8c33e091bd588bf5c406e152431973476f930
    38. c = pow(secret, e, N)
    39. print('N =', hex(N))
    40. print('secret =',hex(secret))
    41. #发送tc 返回是否命中 0命中,-1未命中(本地模拟)
    42. def get_v(tc):
    43. tm = pow(tc, d, N)
    44. print(hex(tm).rjust(100, ' '))
    45. print(hex(border[1]).rjust(100, ' '))
    46. if border[0] < tm < border[1]:
    47. return 0
    48. else:
    49. return -1
    50. def get_flag(s):
    51. if s == secret:
    52. return "flag{test OK}"
    53. else:
    54. return "Fail "+hex(secret)
    55. '''
    56. def oracle(f):
    57. return get_v(c * pow(f,e,N) % N )
    58. #1,secret长度384//9*8=336 边界设置为 B = 336+40
    59. B = 1<<336+40
    60. border = [-1, B]
    61. sendborder(border[0], border[1])
    62. #2,查询secret到B前0的个数
    63. f1 = 1<<40
    64. while oracle(f1) == 0:
    65. f1 <<=1
    66. f1>>=1
    67. #3, ((N+B)/B + delta)*f1*m 是否在边界内
    68. f2 = (N + B)//B * f1
    69. while oracle(f2) == -1:
    70. f2 += f1
    71. #4,
    72. low = c_div(N, f2)
    73. high= (N + B)//f2
    74. while high > low:
    75. tmp = (2*B)//(high - low)
    76. i = c_div(tmp * low, N)
    77. f3 = c_div(i*N, low)
    78. if oracle(f3) == -1:
    79. low = c_div(i*N+B, f3)
    80. else:
    81. high = (i*N+B)//f3
    82. #5 test
    83. assert high - low < (1<<24)
    84. for f4 in range(low, high+1):
    85. if pow(f4,e,N) == c:
    86. print(get_flag(f4))
    87. break
    88. '''
    89. [DEBUG] Received 0x30 bytes:
    90. b'1. Add interval\n'
    91. b'2. Request oracle\n'
    92. b'3. Get flag\n'
    93. b'> '
    94. [DEBUG] Sent 0x2 bytes:
    95. b'3\n'
    96. [DEBUG] Received 0xe bytes:
    97. b'Enter secret: '
    98. [DEBUG] Sent 0x67 bytes:
    99. b'131648374553052306210268283842344617331957330884679611956409650994486668851589013872428584385213442659\n'
    100. [DEBUG] Received 0x24 bytes:
    101. b'DUCTF{Manger_w0uld_b3_pr0ud_0f_y0u}\n'
    102. '''

    6 rsa-interval-oracle-iii

    这个又变了,sleep的时间更长,总timeout变小了,这个有一个工具集lbc_toolkit这里边有个hidden_number_problem 这里输入4个区间,每个差1位,然后输入4700个随机数,当某个数字落在这个区间内就会返回0,1,2,3不在区间内返回-1,当这个题至少50个的时候就可以很快算出m

    1. from pwn import *
    2. #from collections import Counter
    3. # https://github.com/josephsurin/lattice-based-cryptanalysis
    4. from lbc_toolkit import ehnp
    5. def add_interval(lower, upper):
    6. conn.sendlineafter(b'> ', b'1')
    7. conn.sendlineafter(b'Lower bound: ', str(lower).encode())
    8. conn.sendlineafter(b'Upper bound: ', str(upper).encode())
    9. def query_oracle(cts):
    10. conn.sendlineafter(b'> ', b'2')
    11. conn.sendlineafter(b'queries: ', ','.join(map(str, cts)).encode())
    12. r = list(map(int, conn.recvline().decode().split(',')))
    13. return r
    14. N_BITS = 384
    15. MAX_INTERVALS = 4
    16. MAX_QUERIES = 4700
    17. e = 0x10001
    18. #context.log_level = 'debug'
    19. # conn = process('./rsa-interval-oracle-iii.py')
    20. def go():
    21. global conn
    22. conn = remote('2022.ductf.dev', 30010)
    23. N = int(conn.recvline().decode())
    24. secret_ct = int(conn.recvline().decode())
    25. print("N = ", N)
    26. print("secret_ct = ", secret_ct)
    27. for i in range(8, 8 + MAX_INTERVALS):
    28. add_interval(0, 1<<(N_BITS - i))
    29. rs = [randint(1, N) for _ in range(MAX_QUERIES)]
    30. cts = [pow(r, e, N) * secret_ct for r in rs]
    31. query_res = query_oracle(cts) #测试4700个随机数
    32. #print(Counter(query_res))
    33. rs_and_Us = [(r, N_BITS - (MAX_INTERVALS - i + 7)) for r, i in zip(rs, query_res) if i != -1]
    34. ell = len(rs_and_Us)
    35. print('ell:', ell)
    36. if ell < 50:
    37. conn.close()
    38. print("Fail")
    39. return False
    40. print('rs_and_Us = ', rs_and_Us)
    41. open('data.py', 'w').write(f'ell = {ell}\nsecret_ct = {secret_ct}\nN = {N}\nrs_and_Us = {rs_and_Us}')
    42. print(f'e = {e}\nell = {ell}\nsecret_ct = {secret_ct}\nN = {N}\nrs_and_Us = {rs_and_Us}')
    43. conn.sendlineafter(b'> ', b'3')
    44. conn.interactive()
    45. '''
    46. xbar = 0
    47. Pi = [0]
    48. Nu = [336]
    49. Alpha = [r for r, _ in rs_and_Us]
    50. Rho = [[1]] * ell
    51. Mu = [[U] for _, U in rs_and_Us]
    52. Beta = [0] * ell
    53. print(xbar, N, Pi, Nu, Alpha, Rho, Mu, Beta)
    54. sol = ehnp(xbar, N, Pi, Nu, Alpha, Rho, Mu, Beta, delta=1/10**22, verbose=True)
    55. secret = -sol % N
    56. print('secret = ', secret)
    57. print('c = ', pow(secret,e,N))
    58. context.log_level = 'debug'
    59. conn.sendlineafter(b'> ', b'3')
    60. conn.sendlineafter(b'Enter secret: ', str(secret).encode())
    61. flag = conn.recvline().decode()
    62. print(flag)
    63. if 'DUCTF' in flag:
    64. conn.close()
    65. return True
    66. '''
    67. while not go():
    68. pass
    69. #DUCTF{rsa_1nt3rv4l_0r4cl3_1s_n0_m4tch_f0r_y0u!}

    由于网站运行很慢,程序到最后提交的时候总是报错,我把运算的部分单出来,到生成超过50时,由另外一个程序运行,最后再把结果粘回来。

    1. from lbc_toolkit import ehnp
    2. from data import *
    3. e = 0x10001
    4. xbar = 0
    5. Pi = [0]
    6. Nu = [336]
    7. Alpha = [r for r, _ in rs_and_Us]
    8. Rho = [[1]] * ell
    9. Mu = [[U] for _, U in rs_and_Us]
    10. Beta = [0] * ell
    11. print(xbar, N, Pi, Nu, Alpha, Rho, Mu, Beta)
    12. sol = ehnp(xbar, N, Pi, Nu, Alpha, Rho, Mu, Beta, delta=1/10**22, verbose=True)
    13. secret = -sol % N
    14. print('secret = ', secret)
    15. print('c = ', pow(secret,e,N))

    7 rsa-interval-oracle-iv

    这个题在上题基础上给了固定的区间,因为都是预期用同一个程序解,所以区间跟上一题一样。只不过不用输入而已,不过这题用那个官方程序和上边验证过的都试过,结果不正确。不知道原因。

    8 time-locked

    这个到最后也没看懂,先保留一下吧。应该是关于矩阵快速幂的,基本上纯数学问题。给的是一个可以出flag的程序,但由于n非常大,每次减1 不可能实现。这就需要一个简化的方法。

    1. from hashlib import sha256
    2. from Crypto.Util.Padding import unpad
    3. from Crypto.Cipher import AES
    4. ct = bytes.fromhex('85534f055c72f11369903af5a8ac64e2f4cbf27759803041083d0417b5f0aaeac0490f018b117dd4376edd6b1c15ba02')
    5. p = 275344354044844896633734474527970577743
    6. a = [2367876727, 2244612523, 2917227559, 2575298459, 3408491237, 3106829771, 3453352037]
    7. α = [843080574448125383364376261369231843, 1039408776321575817285200998271834893, 712968634774716283037350592580404447, 1166166982652236924913773279075312777, 718531329791776442172712265596025287, 766989326986683912901762053647270531, 985639176179141999067719753673114239]
    8. def f(n):
    9. if n < len(α):
    10. return α[n]
    11. n -= len(α) - 1
    12. t = α[::-1]
    13. while n > 0:
    14. x = sum([a_ * f_ for a_, f_ in zip(a, t)]) % p
    15. t = [x] + t[:-1]
    16. n -= 1
    17. return t[0]
    18. n = 2**(2**1337)
    19. key = sha256(str(f(n)).encode()).digest()
    20. aes = AES.new(key, AES.MODE_ECB)
    21. flag = unpad(aes.decrypt(ct), 16)
    22. print(flag.decode())

    官方结果

    1. from Crypto.Util.number import long_to_bytes
    2. from hashlib import sha256
    3. from Crypto.Util.Padding import unpad
    4. from Crypto.Cipher import AES
    5. ct = bytes.fromhex('85534f055c72f11369903af5a8ac64e2f4cbf27759803041083d0417b5f0aaeac0490f018b117dd4376edd6b1c15ba02')
    6. p = 275344354044844896633734474527970577743
    7. a = [2367876727, 2244612523, 2917227559, 2575298459, 3408491237, 3106829771, 3453352037]
    8. α = [843080574448125383364376261369231843, 1039408776321575817285200998271834893, 712968634774716283037350592580404447, 1166166982652236924913773279075312777, 718531329791776442172712265596025287, 766989326986683912901762053647270531, 985639176179141999067719753673114239]
    9. M = Matrix(GF(p), [a])
    10. M = M.stack(Matrix.identity(len(a) - 1).augment(Matrix.column([0] * (len(a) - 1))))
    11. order = prod([p^len(a) - p^k for k in range(0, len(a))])
    12. n = int(pow(2, 2^1337, order)) - 6
    13. fn = (M^n * vector(α[::-1]))[0]
    14. key = sha256(str(fn).encode()).digest()
    15. aes = AES.new(key, AES.MODE_ECB)
    16. flag = unpad(aes.decrypt(ct), 16)
    17. print(flag.decode())

    虽然题都不会,不过把sage安上了,可以直接在sage里from pwn import *了,还算是有收获的。

    马上放假了,可以有时间把pwn都过一遍了。

  • 相关阅读:
    Go语言躲坑经验总结
    [elastic 8.x]java客户端连接elasticsearch与操作索引与文档
    软件开发人员 Kubernetes 入门指南|Part 1
    【Leetcode】 416. 分割等和子集
    2022年《数据结构试验》上机考试一(计科2103,2105班+数据2101,2102班)题解
    Java中Xml4j的使用
    JavaScript-DOM按钮事件
    13_Nginx_listen指令
    C++11重写muduo网络库——预备知识
    pycharm+python研究生招生智能问答系统django+vue
  • 原文地址:https://blog.csdn.net/weixin_52640415/article/details/127108092