classMyRSA2(RSA): defencrypt(self,m:bytes) -> bytes: returnpow(int.from_bytes(m),self.e,self.N).to_bytes(256,'little') defdecrypt(self,c:bytes) -> bytes: m = pow(int.from_bytes(c),self.d,self.N).to_bytes(256,'little') print('Hibiscus is here to trick your decryption result!!') return crystal_trick(m)
menu = ''' Welcome to NCTF 2025 arcahv challenge! --- Menu --- [1] View encrypted flag and hint [2] Play with the decryption orcale [3] Get some random numbers for fun [4] Exit Your Option > '''
print("Since you didn't v Hibiscus 50 on crazy thursday, Hibiscus decided to do some trick on your decryption result!") print(f'Your pubkey:({hex(r2.N)[2:]},{hex(r2.e)[2:]})')
while attempts > 0: ifinput('Do you still want to try decryption(y/[n])?') != 'y': break
c = bytes.fromhex(input(f'You have {attempts} remaining access to decryption orcale!\nYour ciphertext(in hex):')) print(f'Result: {r2.decrypt(c).hex()}') attempts -= 1 if attempts == 0: print('Unfortunately, you are out of decryption attempts! Come back again on nctf2026 ~')
deflcgchal(): lcg = LCG(int.from_bytes(key))
print('Tempering with LCG generator, please wait...') while urandom(1)[0] & 0xff: lcg.next() hexnums = ''.join(hex(lcg.next())[2:] for _ inrange(5)) iflen(hexnums) % 16: hexnums = hexnums.zfill((len(hexnums) // 16 + 1) * 16) idx = 0 whileinput('Do you want another unsigned long long number(y/[n])?') == 'y': print(int(''.join(hexnums[idx:idx+16]),16)) idx = (idx + 16) % len(hexnums)
defbye(): print('Hope you have fun during the challenge XD:)') exit(0)
print("Since you didn't v Hibiscus 50 on crazy thursday, Hibiscus decided to do some trick on your decryption result!") print(f'Your pubkey:({hex(r2.N)[2:]},{hex(r2.e)[2:]})')
while attempts > 0: ifinput('Do you still want to try decryption(y/[n])?') != 'y': break
c = bytes.fromhex(input(f'You have {attempts} remaining access to decryption orcale!\nYour ciphertext(in hex):')) print(f'Result: {r2.decrypt(c).hex()}') attempts -= 1 if attempts == 0: print('Unfortunately, you are out of decryption attempts! Come back again on nctf2026 ~')
值得注意的是这并不是一个普通的RSA加密,因为r2涉及到了一个混淆函数
1 2 3 4 5
defcrystal_trick(m:bytes) -> bytes: m = bytearray(m) for i inrange(len(m)): m[i] = reduce(lambda x,y: x^y^urandom(1)[0],m[:i],m[i]) return m
from Crypto.Util.number import * from util import * from os import getenv from Crypto.Util.Padding import pad from random import Random from Crypto.Cipher import AES from hashlib import md5
string = open('secret.txt').read().strip().encode() flag = getenv('FLAG').encode()
if __name__=='__main__': Keys = [] for m in string: f = FHE() s = long_to_bytes(Random().getrandbits(20000)) for i in s[4:]: Keys.extend(f.encrypt([i]))
for i in s[:4]: Keys.extend(f.encrypt([i * (m & 0x03) % 0x101])) m >>= 2 assertlen(Keys) == 30000
print(f'[+] Your ciphertext: {AES.new(md5(string).digest(),AES.MODE_ECB).encrypt(pad(flag,16)).hex()}') input(f'[+] The keys to retrieve the global internet connection are as follows:') for i inrange(30000): print(f'[+] {Keys[i]}')
defencrypt(self,msg:list[int] | bytes): result = [] for m in msg: tmp = 0 shuffle_base = urandom(16) for i in shuffle_base: x,y = divmod(i,16) tmp += x*self.pubkeys[y] + y*self.pubkeys[x] result.append(tmp + m) return result
from Crypto.Util.number import * from random import * import json from pwn import * from Crypto.Cipher import AES from hashlib import md5 from tqdm import *