# Cyber Apocalypse 2024: Hacker Royale {%hackmd @themes/orangeheart %} ## Dynastic ![image](https://hackmd.io/_uploads/Byt1RFTT6.png) source.py ```python= from secret import FLAG from random import randint def to_identity_map(a): return ord(a) - 0x41 def from_identity_map(a): return chr(a % 26 + 0x41) def encrypt(m): c = '' for i in range(len(m)): ch = m[i] if not ch.isalpha(): ech = ch else: chi = to_identity_map(ch) ech = from_identity_map(chi + i) c += ech return c with open('output.txt', 'w') as f: f.write('Make sure you wrap the decrypted text with the HTB flag format :-]\n') f.write(encrypt(FLAG)) ``` **output.txt** ``` Make sure you wrap the decrypted text with the HTB flag format :-] DJF_CTA_SWYH_NPDKK_MBZ_QPHTIGPMZY_KRZSQE?!_ZL_CN_PGLIMCU_YU_KJODME_RYGZXL ``` Đọc source code ta có: `ech = chr((ord(m[i]) - 0x41)+i) % 26 + 0x41)` --> `ord(ech) - 0x41 = ord(m[i]) - 0x41 + i - k*26` --> `ord(m[i]) = ord(ech) - i + k*26` **script:** ```python= from random import randint c = 'DJF_CTA_SWYH_NPDKK_MBZ_QPHTIGPMZY_KRZSQE?!_ZL_CN_PGLIMCU_YU_KJODME_RYGZXL' p = '' for i in range(len(c)): if not c[i].isalpha(): p=p+c[i] else: for k in range(5): tmp = chr(ord(c[i]) + k*26 - i) if tmp.isalpha(): p = p + tmp break print(p) ``` Flag: `HTB{DID_YOU_KNOW_ABOUT_THE_TRITHEMIUS_CIPHER?!_IT_IS_SIMILAR_TO_CAESAR_CIPHER}` Một số challange tiếp theo khá đơn giản nên mình sẽ lướt qua luôn nhé !!! **Blunt:** Tìm share_secret trong Diffie-Hellman Elliptic Curves. Mình chỉ cần sử dụng logarit rời rạc để tính được khóa bí mật của Bob hoặc Alice đều được. **Makeshift:** Mã hóa bằng cách hoán vị từng 3 kí tự một. Để giải mã ta chỉ cần làm ngược lại khá là đơn giản :))))). ## Arranged Đây là sourcecode **main.sage** ```python3= from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.number import long_to_bytes from hashlib import sha256 from secret import FLAG, p, b, priv_a, priv_b F = GF(p) E = EllipticCurve(F, [726, b]) G = E(926644437000604217447316655857202297402572559368538978912888106419470011487878351667380679323664062362524967242819810112524880301882054682462685841995367, 4856802955780604241403155772782614224057462426619061437325274365157616489963087648882578621484232159439344263863246191729458550632500259702851115715803253) A = G * priv_a B = G * priv_b print(A) print(B) C = priv_a * B assert C == priv_b * A # now use it as shared secret secret = C[0] hash = sha256() hash.update(long_to_bytes(secret)) key = hash.digest()[16:32] iv = b'u\x8fo\x9aK\xc5\x17\xa7>[\x18\xa3\xc5\x11\x9en' cipher = AES.new(key, AES.MODE_CBC, iv) encrypted = cipher.encrypt(pad(FLAG, 16)) print(encrypted) ``` **output.txt** ```python3= (6174416269259286934151093673164493189253884617479643341333149124572806980379124586263533252636111274525178176274923169261099721987218035121599399265706997 : 2456156841357590320251214761807569562271603953403894230401577941817844043774935363309919542532110972731996540328492565967313383895865130190496346350907696 : 1) (4226762176873291628054959228555764767094892520498623417484902164747532571129516149589498324130156426781285021938363575037142149243496535991590582169062734 : 425803237362195796450773819823046131597391930883675502922975433050925120921590881749610863732987162129269250945941632435026800264517318677407220354869865 : 1) b'V\x1b\xc6&\x04Z\xb0c\xec\x1a\tn\xd9\xa6(\xc1\xe1\xc5I\xf5\x1c\xd3\xa7\xdd\xa0\x84j\x9bob\x9d"\xd8\xf7\x98?^\x9dA{\xde\x08\x8f\x84i\xbf\x1f\xab' ``` Target ở bài này là mình cần phải đi tìm được các giá trị còn lại của đường cong. Mình đã có 3 điểm trên đường cong và `a`. Để tìm được `b` thì chỉ cần thay một điểm vào và giải phương trình thì ta tìm được ngay. Ta có: $y^2 = x^3 + a*x + b \pmod p$, tức là đường cong này được xác định trên trường $F_p$ suy ra: $y^2 - x^3 - a*x - b = k*p$, với 3 điểm có sẵn mình lần lượt thay thế vào thì mình có 3 cái bội của `p`. Tiếp đến sử dụng GCD để tìm ước chung của 3 cái bội đó thì ta tìm được p. Sau khi đã có các dữ kiện cần thiết mình chỉ cần đi tìm share_secret và nhận flag thôi. **script:** ```python3= from sage.all import * x1 = 926644437000604217447316655857202297402572559368538978912888106419470011487878351667380679323664062362524967242819810112524880301882054682462685841995367 y1 = 4856802955780604241403155772782614224057462426619061437325274365157616489963087648882578621484232159439344263863246191729458550632500259702851115715803253 x2 = 6174416269259286934151093673164493189253884617479643341333149124572806980379124586263533252636111274525178176274923169261099721987218035121599399265706997 y2 = 2456156841357590320251214761807569562271603953403894230401577941817844043774935363309919542532110972731996540328492565967313383895865130190496346350907696 x3 = 4226762176873291628054959228555764767094892520498623417484902164747532571129516149589498324130156426781285021938363575037142149243496535991590582169062734 y3 = 425803237362195796450773819823046131597391930883675502922975433050925120921590881749610863732987162129269250945941632435026800264517318677407220354869865 a = 726 #b = var('b') #solve(y2**2 - x2**3 - a*x2 - b, b) b = -235389841633113518256718847719878733250125469551464659906955192105157068458892240496251208387305226684383977028692545364635616542911806071089784509634298138989466830088876060296948154657939206289908022191050803100386883123914692738193940269023567868365152264359631600117242932969716150281155438233466191095095609214364837462241270538753838231525244229345683421423856137208707912136351137768367596194932966862290676506665434291342481388359433898092926158324340379 K1 = (y1**2 - x1**3 - a*x1 - b) K2 = (y2**2 - x2**3 - a*x2 - b) K3 = (y3**2 - x3**3 - a*x3 - b) p = gcd(gcd(K1, K2), K3) F = GF(p) E = EllipticCurve(F, [726, b]) G = E([x1, y1]) A = E([x2, y2]) B = E([x3, y3]) a = G.discrete_log(A) S = a*B S ``` ```python3= from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.number import long_to_bytes from hashlib import sha256 secret = 926644437000604217447316655857202297402572559368538978912888106419470011487878351667380679323664062362524967242819810112524880301882054682462685841995367 ciphertext = b'''V\x1b\xc6&\x04Z\xb0c\xec\x1a\tn\xd9\xa6(\xc1\xe1\xc5I\xf5\x1c\xd3\xa7\xdd\xa0\x84j\x9bob\x9d"\xd8\xf7\x98?^\x9dA{\xde\x08\x8f\x84i\xbf\x1f\xab''' hash = sha256() hash.update(long_to_bytes(secret)) key = hash.digest()[16:32] iv = b'u\x8fo\x9aK\xc5\x17\xa7>[\x18\xa3\xc5\x11\x9en' cipher = AES.new(key, AES.MODE_CBC, iv) flag = cipher.decrypt(ciphertext) print(flag) # b'HTB{0rD3r_mUsT_b3_prEs3RveD_!!@!}\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' ``` ## Iced Tea **source.py** ```python3= import os from Crypto.Util.Padding import pad from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b from enum import Enum from pwn import xor class Mode(Enum): ECB = 0x01 CBC = 0x02 class Cipher: def __init__(self, key, iv=None): self.BLOCK_SIZE = 64 self.KEY = [b2l(key[i:i+self.BLOCK_SIZE//16]) for i in range(0, len(key), self.BLOCK_SIZE//16)] self.DELTA = 0x9e3779b9 self.IV = iv if self.IV: self.mode = Mode.CBC else: self.mode = Mode.ECB def _xor(self, a, b): return b''.join(bytes([_a ^ _b]) for _a, _b in zip(a, b)) def encrypt(self, msg): msg = pad(msg, self.BLOCK_SIZE//8) blocks = [msg[i:i+self.BLOCK_SIZE//8] for i in range(0, len(msg), self.BLOCK_SIZE//8)] ct = b'' if self.mode == Mode.ECB: for pt in blocks: ct += self.encrypt_block(pt) elif self.mode == Mode.CBC: X = self.IV for pt in blocks: enc_block = self.encrypt_block(self._xor(X, pt)) ct += enc_block X = enc_block return ct def encrypt_block(self, msg): m0 = b2l(msg[:4]) m1 = b2l(msg[4:]) K = self.KEY msk = (1 << (self.BLOCK_SIZE//2)) - 1 s = 0 for i in range(32): s += self.DELTA m0 += ((m1 << 4) + K[0]) ^ (m1 + s) ^ ((m1 >> 5) + K[1]) m0 &= msk m1 += ((m0 << 4) + K[2]) ^ (m0 + s) ^ ((m0 >> 5) + K[3]) m1 &= msk m = ((m0 << (self.BLOCK_SIZE//2)) + m1) & ((1 << self.BLOCK_SIZE) - 1) # m = m0 || m1 return l2b(m) def decrypt_block(self, msg): m = b2l(msg) m0 = (m >> (self.BLOCK_SIZE//2)) & ((1 << (self.BLOCK_SIZE//2)) - 1) m1 = m & ((1 << (self.BLOCK_SIZE//2)) - 1) K = self.KEY msk = (1 << (self.BLOCK_SIZE//2)) - 1 s = 0xC6EF3720 for i in range(32): m1 -= ((m0 << 4) + K[2]) ^ (m0 + s) ^ ((m0 >> 5) + K[3]) m1 &= msk m0 -= ((m1 << 4) + K[0]) ^ (m1 + s) ^ ((m1 >> 5) + K[1]) m0 &= msk s -= self.DELTA return l2b(m0) + l2b(m1) def decrypt(self, msg): msg = pad(msg, self.BLOCK_SIZE//8) blocks = [msg[i:i+self.BLOCK_SIZE//8] for i in range(0, len(msg), self.BLOCK_SIZE//8)] ct = b'' if self.mode == Mode.ECB: for pt in blocks: ct += self.decrypt_block(pt) elif self.mode == Mode.CBC: X = self.IV for pt in blocks: enc_block = self.decrypt_block(self._xor(pt, X)) ct += enc_block X = pt return ct if __name__ == '__main__': key = bytes.fromhex("850c1413787c389e0b34437a6828a1b2") cipher = Cipher(key) Ciphertext = "b36c62d96d9daaa90634242e1e6c76556d020de35f7a3b248ed71351cc3f3da97d4d8fd0ebc5c06a655eb57f2b250dcb2b39c8b2000297f635ce4a44110ec66596c50624d6ab582b2fd92228a21ad9eece4729e589aba644393f57736a0b870308ff00d778214f238056b8cf5721a843" c = bytes.fromhex(Ciphertext) ct = cipher.decrypt(c) print(c) ``` **output.txt** ``` Key : 850c1413787c389e0b34437a6828a1b2 Ciphertext : b36c62d96d9daaa90634242e1e6c76556d020de35f7a3b248ed71351cc3f3da97d4d8fd0ebc5c06a655eb57f2b250dcb2b39c8b2000297f635ce4a44110ec66596c50624d6ab582b2fd92228a21ad9eece4729e589aba644393f57736a0b870308ff00d778214f238056b8cf5721a843 ``` Mình mò trên mạng thì biết được đây là [Tiny Encryption Algorithm](https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm). Một loại block cipher đơn giản các bước mã hóa cũng đơn giản không kém. Mình có luôn hàm decrypt. ```python= import os from Crypto.Util.Padding import pad, unpad from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b from enum import Enum class Mode(Enum): ECB = 0x01 CBC = 0x02 class Cipher: def __init__(self, key, iv=None): self.BLOCK_SIZE = 64 self.KEY = [b2l(key[i:i+self.BLOCK_SIZE//16]) for i in range(0, len(key), self.BLOCK_SIZE//16)] self.DELTA = 0x9e3779b9 self.IV = iv if self.IV: self.mode = Mode.CBC else: self.mode = Mode.ECB def _xor(self, a, b): return b''.join(bytes([_a ^ _b]) for _a, _b in zip(a, b)) def encrypt(self, msg): msg = pad(msg, self.BLOCK_SIZE//8) blocks = [msg[i:i+self.BLOCK_SIZE//8] for i in range(0, len(msg), self.BLOCK_SIZE//8)] ct = b'' if self.mode == Mode.ECB: for pt in blocks: ct += self.encrypt_block(pt) elif self.mode == Mode.CBC: X = self.IV for pt in blocks: enc_block = self.encrypt_block(self._xor(X, pt)) ct += enc_block X = enc_block return ct def encrypt_block(self, msg): m0 = b2l(msg[:4]) m1 = b2l(msg[4:]) K = self.KEY msk = (1 << (self.BLOCK_SIZE//2)) - 1 s = 0 for i in range(32): s += self.DELTA m0 += ((m1 << 4) + K[0]) ^ (m1 + s) ^ ((m1 >> 5) + K[1]) m0 &= msk m1 += ((m0 << 4) + K[2]) ^ (m0 + s) ^ ((m0 >> 5) + K[3]) m1 &= msk m = ((m0 << (self.BLOCK_SIZE//2)) + m1) & ((1 << self.BLOCK_SIZE) - 1) # m = m0 || m1 return l2b(m) def decrypt_block(self, ct): c0 = b2l(ct[:4]) c1 = b2l(ct[4:]) K = self.KEY msk = (1 << (self.BLOCK_SIZE//2)) - 1 s = 0xC6EF3720 for i in range(32): c1 -= ((c0 << 4) + K[2]) ^ (c0 + s) ^ ((c0 >> 5) + K[3]) c1 &= msk c0 -= ((c1 << 4) + K[0]) ^ (c1 + s) ^ ((c1 >> 5) + K[1]) c0 &= msk s -= self.DELTA c = ((c0 << (self.BLOCK_SIZE//2)) + c1) & ((1 << self.BLOCK_SIZE) - 1) return l2b(c) def decrypt(self, ct): blocks = [ct[i:i+self.BLOCK_SIZE//8] for i in range(0, len(ct), self.BLOCK_SIZE//8)] msg = b'' if self.mode == Mode.ECB: for ct in blocks: msg += self.decrypt_block(ct) elif self.mode == Mode.CBC: X = self.IV for ct in blocks: msg += self._xor(self.decrypt_block(ct), X) X = ct return msg ``` chỉ cần chạy đoạn code trên và lấy flag thôi!!! ## Tsayaki source.py ```python= from tea import Cipher as TEA from secret import IV, FLAG import os ROUNDS = 10 def show_menu(): print(""" ============================================================================================ || I made this decryption oracle in which I let users choose their own decryption keys. || || I think that it's secure as the tea cipher doesn't produce collisions (?) ... Right? || || If you manage to prove me wrong 10 times, you get a special gift. || ============================================================================================ """) def run(): show_menu() server_message = os.urandom(20) print(f'Here is my special message: {server_message.hex()}') used_keys = [] ciphertexts = [] for i in range(ROUNDS): print(f'Round {i+1}/10') try: ct = bytes.fromhex(input('Enter your target ciphertext (in hex) : ')) assert ct not in ciphertexts for j in range(4): key = bytes.fromhex(input(f'[{i+1}/{j+1}] Enter your encryption key (in hex) : ')) assert len(key) == 16 and key not in used_keys used_keys.append(key) cipher = TEA(key, IV) enc = cipher.encrypt(server_message) if enc != ct: print(f'Hmm ... close enough, but {enc.hex()} does not look like {ct.hex()} at all! Bye...') exit() except: print('Nope.') exit() ciphertexts.append(ct) print(f'Wait, really? {FLAG}') if __name__ == '__main__': run() ``` Challenge này sử dụng TEA đã được nói đến ở chall trước. Việc chúng ta cần làm là gửi đến `target ciphertext`. Sau đó gửi 4 key liên tiếp sao cho chúng mã hóa `server_mesage` thành `target ciphertext`. Vượt qua được 10 rounds thì lụm flag. Đọc [link](https://www.tayloredge.com/reference/Mathematics/VRAndem.pdf) này mình đã tìm ra cách xử lí. Ở phần 3.5 **Equivalent Key** Đây là trường hợp các khóa tương đương của mã hóa TEA. Từ một khóa ban đầu ta có thể tạo thêm được 3 khóa tương đương. Nghĩa là nếu cùng sử dụng 4 khóa này thì sẽ cho ra cũng một ciphertext. ![image](https://hackmd.io/_uploads/BksXxTw0p.png) Đầu tiên mình cần tìm được IV để lấy `target ciphertext`. Giả sử ta gửi đến server một `key` và `target ciphertext` lại sai (lúc này đã biết được ciphertext đâu). Thì server sẽ trả về cho ta ciphertext sau khi mã hóa `plaintext` của server. Cùng nhìn lại hàm decrypt: ```python def decrypt(self, ct): blocks = [ct[i:i+self.BLOCK_SIZE//8] for i in range(0, len(ct), self.BLOCK_SIZE//8)] msg = b'' if self.mode == Mode.ECB: for ct in blocks: msg += self.decrypt_block(ct) elif self.mode == Mode.CBC: X = self.IV for ct in blocks: msg += self._xor(self.decrypt_block(ct), X) X = ct return msg ``` Ta chỉ cần lấy `msg` xor lại với `ct` thì có IV. ```python= c = bytes.fromhex("8c0acbde4a1af63579313db874ab79a991fbaad4a459e4a5") key = bytes.fromhex("9d6e095e19614e4f0bade6546f99d105") msg = bytes.fromhex("0bc8f872e85a549c9815e69e1be5774631837362") cipher = Cipher(key) from pwn import xor block1 = cipher.decrypt(c[:8]) iv = xor(block1, msg[:8]) print(iv) # iv = b'\r\xdd\xd2w<\xf4\xb9\x08' ``` Tiếp đến mình viết hàm để tạo thành các key tương đương: ```python= CONST = bytes.fromhex("80000000") def gen_key(): keys = [] key = os.urandom(16) key1, key2, key3, key4 = [key[i:i+4] for i in range(0, 16, 4)] keys = [ b''.join([key1, key2, key3, key4]), b''.join([key1, key2, xor(key3, CONST), xor(key4, CONST)]), b''.join([xor(key1, CONST), xor(key2, CONST), key3 , key4 ]), b''.join([xor(key1, CONST), xor(key2, CONST), xor(key3, CONST), xor(key4, CONST)]) ] return keys ``` **script** ```python= import os from Crypto.Util.Padding import pad, unpad from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b from enum import Enum class Mode(Enum): ECB = 0x01 CBC = 0x02 class Cipher: def __init__(self, key, iv=None): self.BLOCK_SIZE = 64 self.KEY = [b2l(key[i:i+self.BLOCK_SIZE//16]) for i in range(0, len(key), self.BLOCK_SIZE//16)] self.DELTA = 0x9e3779b9 self.IV = iv if self.IV: self.mode = Mode.CBC else: self.mode = Mode.ECB def _xor(self, a, b): return b''.join(bytes([_a ^ _b]) for _a, _b in zip(a, b)) def encrypt(self, msg): msg = pad(msg, self.BLOCK_SIZE//8) blocks = [msg[i:i+self.BLOCK_SIZE//8] for i in range(0, len(msg), self.BLOCK_SIZE//8)] ct = b'' if self.mode == Mode.ECB: for pt in blocks: ct += self.encrypt_block(pt) elif self.mode == Mode.CBC: X = self.IV for pt in blocks: enc_block = self.encrypt_block(self._xor(X, pt)) ct += enc_block X = enc_block return ct def encrypt_block(self, msg): m0 = b2l(msg[:4]) m1 = b2l(msg[4:]) K = self.KEY msk = (1 << (self.BLOCK_SIZE//2)) - 1 s = 0 for i in range(32): s += self.DELTA m0 += ((m1 << 4) + K[0]) ^ (m1 + s) ^ ((m1 >> 5) + K[1]) m0 &= msk m1 += ((m0 << 4) + K[2]) ^ (m0 + s) ^ ((m0 >> 5) + K[3]) m1 &= msk m = ((m0 << (self.BLOCK_SIZE//2)) + m1) & ((1 << self.BLOCK_SIZE) - 1) # m = m0 || m1 return l2b(m) def decrypt_block(self, ct): c0 = b2l(ct[:4]) c1 = b2l(ct[4:]) K = self.KEY msk = (1 << (self.BLOCK_SIZE//2)) - 1 s = 0xC6EF3720 for i in range(32): c1 -= ((c0 << 4) + K[2]) ^ (c0 + s) ^ ((c0 >> 5) + K[3]) c1 &= msk c0 -= ((c1 << 4) + K[0]) ^ (c1 + s) ^ ((c1 >> 5) + K[1]) c0 &= msk s -= self.DELTA c = ((c0 << (self.BLOCK_SIZE//2)) + c1) & ((1 << self.BLOCK_SIZE) - 1) return l2b(c) def decrypt(self, ct): blocks = [ct[i:i+self.BLOCK_SIZE//8] for i in range(0, len(ct), self.BLOCK_SIZE//8)] msg = b'' if self.mode == Mode.ECB: for ct in blocks: msg += self.decrypt_block(ct) elif self.mode == Mode.CBC: X = self.IV for ct in blocks: msg += self._xor(self.decrypt_block(ct), X) X = ct return msg from pwn import remote, xor import os CONST = bytes.fromhex("80000000") IV = b'\r\xdd\xd2w<\xf4\xb9\x08' def gen_key(): keys = [] key = os.urandom(16) key1, key2, key3, key4 = [key[i:i+4] for i in range(0, 16, 4)] keys = [ b''.join([key1, key2, key3, key4]), b''.join([key1, key2, xor(key3, CONST), xor(key4, CONST)]), b''.join([xor(key1, CONST), xor(key2, CONST), key3 , key4 ]), b''.join([xor(key1, CONST), xor(key2, CONST), xor(key3, CONST), xor(key4, CONST)]) ] return keys io = remote('83.136.254.223', 32915) io.recvuntil(b'Here is my special message:') server_message = io.recvuntil(b'\n', drop = True).decode() def payload(key): cipher = Cipher(key, IV) enc = cipher.encrypt(bytes.fromhex(server_message)) return enc.hex() for i in range(10): keys = gen_key() io.recvuntil(b'Enter your target ciphertext (in hex) : ') io.sendline(payload(keys[0]).encode()) for key in keys: io.recvuntil(b'Enter your encryption key (in hex) : ') io.sendline(key.hex().encode()) io.recvlines() ``` ## Partial Tenacity source.py ```python= from secret import FLAG from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP class RSACipher: def __init__(self, bits): self.key = RSA.generate(bits) self.cipher = PKCS1_OAEP.new(self.key) def encrypt(self, m): return self.cipher.encrypt(m) def decrypt(self, c): return self.cipher.decrypt(c) cipher = RSACipher(1024) enc_flag = cipher.encrypt(FLAG) with open('output.txt', 'w') as f: f.write(f'n = {cipher.key.n}\n') f.write(f'ct = {enc_flag.hex()}\n') f.write(f'p = {str(cipher.key.p)[::2]}\n') f.write(f'q = {str(cipher.key.q)[1::2]}') ``` output.txt ``` n = 118641897764566817417551054135914458085151243893181692085585606712347004549784923154978949512746946759125187896834583143236980760760749398862405478042140850200893707709475167551056980474794729592748211827841494511437980466936302569013868048998752111754493558258605042130232239629213049847684412075111663446003 ct = 7f33a035c6390508cee1d0277f4712bf01a01a46677233f16387fae072d07bdee4f535b0bd66efa4f2475dc8515696cbc4bc2280c20c93726212695d770b0a8295e2bacbd6b59487b329cc36a5516567b948fed368bf02c50a39e6549312dc6badfef84d4e30494e9ef0a47bd97305639c875b16306fcd91146d3d126c1ea476 p = 151441473357136152985216980397525591305875094288738820699069271674022167902643 q = 15624342005774166525024608067426557093567392652723175301615422384508274269305 ``` Đọc đoạn code trên mình nhận thấy p và q đã bị khuyết các số. Nó kiểu như này: ```python= leak_p = "1?5?1?4?4?1?4?7?3?3?5?7?1?3?6?1?5?2?9?8?5?2?1?6?9?8?0?3?9?7?5?2?5?5?9?1?3?0?5?8?7?5?0?9?4?2?8?8?7?3?8?8?2?0?6?9?9?0?6?9?2?7?1?6?7?4?0?2?2?1?6?7?9?0?2?6?4?3" leak_q = "?1?5?6?2?4?3?4?2?0?0?5?7?7?4?1?6?6?5?2?5?0?2?4?6?0?8?0?6?7?4?2?6?5?5?7?0?9?3?5?6?7?3?9?2?6?5?2?7?2?3?1?7?5?3?0?1?6?1?5?4?2?2?3?8?4?5?0?8?2?7?4?2?6?9?3?0?5?" ``` Cách mà mình hay sử dụng để giải quyết các bài kiểu như thế này đó chính là dựa vào: - Cho 2 số a, b với a*b = n, ta có: Số chữ số cuối của a * số chữ số cuối của b = số chữ số cuối của n. **script:** ```python= from Crypto.Util.number import long_to_bytes from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP # p = "151441473357136152985216980397525591305875094288738820699069271674022167902643" # leak_p = '' # for i in p: # leak_p += i + '?' # q = "15624342005774166525024608067426557093567392652723175301615422384508274269305" # leak_q = '' # for i in q: # leak_q += '?' + i # print(leak_p) # print(leak_q) leak_p = "1?5?1?4?4?1?4?7?3?3?5?7?1?3?6?1?5?2?9?8?5?2?1?6?9?8?0?3?9?7?5?2?5?5?9?1?3?0?5?8?7?5?0?9?4?2?8?8?7?3?8?8?2?0?6?9?9?0?6?9?2?7?1?6?7?4?0?2?2?1?6?7?9?0?2?6?4?3" leak_q = "?1?5?6?2?4?3?4?2?0?0?5?7?7?4?1?6?6?5?2?5?0?2?4?6?0?8?0?6?7?4?2?6?5?5?7?0?9?3?5?6?7?3?9?2?6?5?2?7?2?3?1?7?5?3?0?1?6?1?5?4?2?2?3?8?4?5?0?8?2?7?4?2?6?9?3?0?5?" n = 118641897764566817417551054135914458085151243893181692085585606712347004549784923154978949512746946759125187896834583143236980760760749398862405478042140850200893707709475167551056980474794729592748211827841494511437980466936302569013868048998752111754493558258605042130232239629213049847684412075111663446003 ct = "7f33a035c6390508cee1d0277f4712bf01a01a46677233f16387fae072d07bdee4f535b0bd66efa4f2475dc8515696cbc4bc2280c20c93726212695d770b0a8295e2bacbd6b59487b329cc36a5516567b948fed368bf02c50a39e6549312dc6badfef84d4e30494e9ef0a47bd97305639c875b16306fcd91146d3d126c1ea476" e = 65537 def guess(a, b, i, p, q): conditon = 1 if b == '?': a, b = b, a p, q = q, p conditon = 0 for _ in range(10): if str(int(str(_) + str(p)) * int(str(b) + str(q)))[-i:] == str(n)[-i:]: a = str(_) break if conditon: return a + p, b + q else: return b + q, a + p p = '' q = '' index = 1 for i, j in zip(leak_p[::-1], leak_q[::-1]): p, q = guess(i, j, index, p, q) index += 1 p = int(p) q = int(q) assert p * q == n phi = (p-1)*(q-1) d = pow(e, -1, phi) private_key = RSA.construct([n, e, d]) cipher = PKCS1_OAEP.new(private_key) m = cipher.decrypt(bytes.fromhex(ct)) print(m) ```