# PearlCTF
### Baby Message Out
```python3=
#!/usr/bin/env python3
from Crypto.Util.number import getPrime, isPrime, bytes_to_long
from flag import flag
from math import log
import sys
n = pow(10, 5)
sys.setrecursionlimit(n)
def nextPrime(p):
if isPrime(p):
return p
else:
return nextPrime(p + 61)
p = getPrime(256)
q = nextPrime(nextPrime(17*p + 1) + 3)
r = nextPrime(29*p*q)
s = nextPrime(q*r + p)
t = nextPrime(r*s*q)
print(f"{p = }")
print(f"{q = }")
print(f"{r = }")
print(f"{s = }")
print(f"{t = }")
n = p*q*r*s*t
e = 65537
m = bytes_to_long(flag)
c = pow(m, e, n)
print(f"c: {c}")
print(f"n: {n}")
```
```python3=
c: 1838979268925267202615818395622122484893202706167722156383681963142079180161531237936585341507802530813847301831886857107840552940103096671213346624172927405178565892385733216702672851783423891229382579221604596673156151519463795808010572632138076246765227545034269340790242411584582692558549837221897037971538915332866933837117883228953143242965510280921618063635225603250391037969273250144174802927111408106890496901519737395485115788436384012937788617630381389196078818501905993385084557887716148781944416313908553565974546239241287340505018036547080504009483360838747251073440799502791555942879229132369697126614944991347408598924472158561247485575276852356316968119522601927483600978106155875300324966339458896992260918634629607740522754923275555209240690069838566642421234035117257380757518902549668151860260985363114235340791362277047923494577018035035653075155240898800910887230020812289524262582877697129108304758256250595391379019020972909027192107727799235384374670082518555887502478560056865020860127002
n: 485889862688353809145356849681869098056742135790325154633816315764783289109350404808839464043297429168130293002483316664607770068196944445394490388957147529192164743228508084885030734914365245916125607677185307000076761646830755541107131137865984020648243428286711853728051263128076845261298240617545417811431124904304446607845470628505361436115651109768237103000946120781642652665829238385087624612205525857191218811570122228639908283598707567056620352822139985271817003262919597858495812801663331842855143930997258260164422858382713240717739568744168349527025412634588705503126870149875268600539407786323924132037483972529603572727892740460450963315253482630345996561505957763886776070413535287129043703855880444326909520084249767518737040222995586717034060176093473694948961503759770499124924886087468497100053775745634680192678426965540847613838559522315570932873854027804486662281273550134766570419630624914801192395060568099367828616501877701994364906741451132770474154689411119296104818089636891131318495955929
```
Ta thấy rằng, có một hàm sinh số nguyên tố như sau:
```python3=
def nextPrime(p):
if isPrime(p):
return p
else:
return nextPrime(p + 61)
```
Và có 5 số nguyên tố được sinh ra
```python3=
p = getPrime(256)
q = nextPrime(nextPrime(17*p + 1) + 3)
r = nextPrime(29*p*q)
s = nextPrime(q*r + p)
t = nextPrime(r*s*q)
```
Ta thử chạy một code mới và thu được như sau (mình tự chạy với số p khác bài)
```python3=
p = (p)
q = (3 + 17*p + 1037*k1)
r = (29*p*(3 + 17*p + 1037*k1) + 61*k2)
s = ((29*p*(3 + 17*p + 1037*k1) + 61*k2)*(3 + 17*p + 1037*k1) + p + 61*k3)
t = ((29*p*(3 + 17*p + 1037*k1) + 61*k2)*(3 + 17*p + 1037*k1)*((29*p*(3 + 17*p + 1037*k1) + 61*k2)*(3 + 17*p + 1037*k1) + p + 61*k3) + 61*k4)
```
Từ việc khai triển trên, ta thấy được rằng
$$q \approx 17p$$
$$r \approx 29pq \approx 29 \cdot 17p^2$$
$$s \approx qr \approx 17p \cdot 29 \cdot17 p^2 \approx 29 \cdot17^2 p^3 $$
$$t\approx rsq \approx 29 \cdot 17p^2 \cdot 29 \cdot 17^2 p^3 \cdot 17p = 29^2\cdot17^4p^6$$
$$n = pqrst \approx 29^4\cdot17^8p^{13}$$
Từ đó, ta có thể tìm được giá trị sấp xỉ của p bằng cách
$$p \approx \sqrt[13]{\dfrac{n}{29^4\cdot17^8}}$$
Sau đó ta sẽ bruteforce p, sao cho giá trị p là nghiệm của N.
```python3=
from Crypto.Util.number import isPrime, long_to_bytes
from gmpy2 import next_prime, iroot
import sys
n = pow(10, 5)
sys.setrecursionlimit(n)
def nextPrime(p):
if isPrime(p):
return p
else:
return nextPrime(p+61)
n = 485889862688353809145356849681869098056742135790325154633816315764783289109350404808839464043297429168130293002483316664607770068196944445394490388957147529192164743228508084885030734914365245916125607677185307000076761646830755541107131137865984020648243428286711853728051263128076845261298240617545417811431124904304446607845470628505361436115651109768237103000946120781642652665829238385087624612205525857191218811570122228639908283598707567056620352822139985271817003262919597858495812801663331842855143930997258260164422858382713240717739568744168349527025412634588705503126870149875268600539407786323924132037483972529603572727892740460450963315253482630345996561505957763886776070413535287129043703855880444326909520084249767518737040222995586717034060176093473694948961503759770499124924886087468497100053775745634680192678426965540847613838559522315570932873854027804486662281273550134766570419630624914801192395060568099367828616501877701994364906741451132770474154689411119296104818089636891131318495955929
p_approx = iroot(n//(pow(17,8)*pow(29,4)),13)[0]
print(p_approx)
for i in range(p_approx - 10000, p_approx + 10000):
if n % i == 0:
p = i
break
print(p)
q = nextPrime(nextPrime(17*p+1)+3)
r = nextPrime(29*p*q)
s = nextPrime(q*r+p)
t = nextPrime(r*s*q)
phi = (p-1)*(q-1)*(r-1)*(s-1)*(t-1)
e = 65537
d = pow(e,-1,phi)
c = 1838979268925267202615818395622122484893202706167722156383681963142079180161531237936585341507802530813847301831886857107840552940103096671213346624172927405178565892385733216702672851783423891229382579221604596673156151519463795808010572632138076246765227545034269340790242411584582692558549837221897037971538915332866933837117883228953143242965510280921618063635225603250391037969273250144174802927111408106890496901519737395485115788436384012937788617630381389196078818501905993385084557887716148781944416313908553565974546239241287340505018036547080504009483360838747251073440799502791555942879229132369697126614944991347408598924472158561247485575276852356316968119522601927483600978106155875300324966339458896992260918634629607740522754923275555209240690069838566642421234035117257380757518902549668151860260985363114235340791362277047923494577018035035653075155240898800910887230020812289524262582877697129108304758256250595391379019020972909027192107727799235384374670082518555887502478560056865020860127002
m = pow(c,d,n)
print(long_to_bytes(m))
```
**Flag: pearl{7h1s_0n3_w4s_f0r_7h3_k1ds}**
### Security ++
Secure.py
```python3=
flag = b'PearlCTF{day-la-flag}'
key = b'a'*8 + b'b'*8 + b'c'*8 + b'd'*8
from base64 import b64encode
from enc import encrypt_block, pad
def encrypt(data: bytes):
pt = data + flag
pt = pad(pt)
block_count = len(pt) // 16
encText = b''
for i in range(block_count):
if i % 2 == 0:
encText += encrypt_block(pt[i * 16:i * 16 + 16], key[0:16])
else:
encText += encrypt_block(pt[i * 16:i * 16 + 16], key[16:])
return encText
def main():
while 1:
msg = input("\nEnter plaintext: ").strip()
res = encrypt(msg.encode())
print(b64encode(res).decode())
if __name__ == '__main__':
main()
```
enc.py
```python3=
from copy import copy
s_box = (
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
)
def bytes2matrix(text):
return [list(text[i:i + 4]) for i in range(0, len(text), 4)]
def matrix2bytes(m):
plaintext = b''
for row in range(4):
for j in range(4):
plaintext += chr(m[row][j]).encode('latin-1')
return plaintext
def pad(text: bytes):
if len(text) % 16 != 0:
pad_len = ((len(text) // 16) + 1) * 16 - len(text)
else:
pad_len = 0
text = text.ljust(len(text) + pad_len, b'.')
return text
def sub_bytes(state, sbox):
for i in range(len(state)):
for j in range(4):
state[i][j] = sbox[state[i][j]]
return state
def shift_rows(s):
s[1][0], s[1][1], s[1][2], s[1][3] = s[1][1], s[1][2], s[1][3], s[1][0]
s[2][0], s[2][1], s[2][2], s[2][3] = s[2][2], s[2][3], s[2][0], s[2][1]
s[3][0], s[3][1], s[3][2], s[3][3] = s[3][3], s[3][0], s[3][1], s[3][2]
return s
def gmul(a, b):
if b == 1:
return a
tmp = (a << 1) & 0xff
if b == 2:
return tmp if a < 128 else tmp ^ 0x1b
if b == 3:
return gmul(a, 2) ^ a
def mix_col(col):
temp = copy(col)
col[0] = gmul(temp[0], 2) ^ gmul(temp[1], 3) ^ gmul(
temp[2], 1) ^ gmul(temp[3], 1)
col[1] = gmul(temp[0], 1) ^ gmul(temp[1], 2) ^ gmul(
temp[2], 3) ^ gmul(temp[3], 1)
col[2] = gmul(temp[0], 1) ^ gmul(temp[1], 1) ^ gmul(
temp[2], 2) ^ gmul(temp[3], 3)
col[3] = gmul(temp[0], 3) ^ gmul(temp[1], 1) ^ gmul(
temp[2], 1) ^ gmul(temp[3], 2)
return col
def add_round_key(state, round_key):
for i in range(len(state)):
for j in range(len(state[0])):
state[i][j] = state[i][j] ^ round_key[i][j]
return state
def encrypt_block(ptext: bytes, key):
cipher = ptext
rkey = bytes2matrix(key)
for i in range(10):
ctext = bytes2matrix(cipher)
ctext = sub_bytes(ctext, s_box)
ctext = shift_rows(ctext)
temp = copy(ctext)
for j in range(4):
column = [temp[0][j], temp[1][j], temp[2][j], temp[3][j]]
column = mix_col(column)
for k in range(4):
ctext[k][j] = column[k]
ctext = add_round_key(ctext, rkey)
cipher = matrix2bytes(ctext)
return cipher
```
Solve.py
```python3=
#!/usr/bin/python3
from pwn import*
from base64 import*
from string import printable
io = process(["python3", "secure.py"])
brt_char = b''
payload_1 = b'a'*16
flag = b''
for i in range(40):
payload_1 = payload_1[1:] + brt_char
for j in printable:
payload = payload_1 + j.encode() + b'a'*(31-i)
io.recvuntil(b'Enter plaintext: ')
io.sendline(payload)
data = io.recvuntil(b'\n',drop=True).decode()
data = b64decode(data)
if data[:16] == data[32:48]:
flag += j.encode()
brt_char = j.encode()
print(flag)
break
```
### 3 spies
```python3=
#!/usr/bin/env python3
from Crypto.Util.number import getPrime, bytes_to_long
with open('flag.txt', 'rb') as f:
flag = f.read()
n1 = getPrime(512)*getPrime(512)
n2 = getPrime(512)*getPrime(512)
n3 = getPrime(512)*getPrime(512)
e=3
m = bytes_to_long(flag)
c1 = pow(m,e,n1)
c2 = pow(m,e,n2)
c3 = pow(m,e,n3)
with open('encrypted-messages.txt', 'w') as f:
f.write(f'n1: {n1}\n')
f.write(f'e: {e}\n')
f.write(f'c1: {c1}\n\n')
f.write(f'n2: {n2}\n')
f.write(f'e: {e}\n')
f.write(f'c2: {c2}\n\n')
f.write(f'n3: {n3}\n')
f.write(f'e: {e}\n')
f.write(f'c3: {c3}\n')
n1: 125267411676839013904356880992044234494446196964982422223130579882047339346910691451497681975351838034684254305738613386927222900898672184001345811471784343779083336010063097729870079645284178978512325038316112509718505547104307526489798594871208559607331790920412305711830820739308995357441030646151241475357
e: 3
c1: 53377681151597930200174280269480737905892580547675095951568028531545776989476273786562435486230550919422086944133253611872983670236114054374565938184593173194919064517779661178744278071496565181181705071524501841159717567250259220092464925447795412484629687708208662079791459184303259833667333882817260906165
n2: 101985110329687359982214188967281711679876126442294375297547334583432698756724057183438691227371260175904715854057793173086301783390154807726779286131084537704721881438398569476214173211311977143694032174701007005033830070482491565424683664984059187439768982994371382763048098663670188786016786612348042190633
e: 3
c2: 86370003324603283962938004647941072863866893771153362222202759619566185050496089684606274416415418388916028237984708280964054009059814813483639010674182298294505525549842057730933691736372086557397211586739691237738757897947336698446258197604918828646265244195686107866422922575275382813594250335044143485624
n3: 83259448903366278561128205003734328779222118906091604625605804813528274055482582431201682767294594942491788720967344243567819654813240542076250030802111361571504667752481579915864184180358691091092122509649590043074189547962292835856503625214027405901620103615424259796442446412031011575671410630232956892267
e: 3
c3: 25601241268900087228853235319569275926328919786631787991019848828558430219449358810095537362492238844266084660904521793373698736119824512458196492049138821633273765102576368573691391116632126183996786969554104441242376959688329346567745607825277943462236901478944551669406261301309719409165457168678763092118
```
```python3=
from Crypto.Util.number import long_to_bytes
from functools import reduce
from gmpy2 import iroot
n1 = 125267411676839013904356880992044234494446196964982422223130579882047339346910691451497681975351838034684254305738613386927222900898672184001345811471784343779083336010063097729870079645284178978512325038316112509718505547104307526489798594871208559607331790920412305711830820739308995357441030646151241475357
e = 3
c1 = 53377681151597930200174280269480737905892580547675095951568028531545776989476273786562435486230550919422086944133253611872983670236114054374565938184593173194919064517779661178744278071496565181181705071524501841159717567250259220092464925447795412484629687708208662079791459184303259833667333882817260906165
n2= 101985110329687359982214188967281711679876126442294375297547334583432698756724057183438691227371260175904715854057793173086301783390154807726779286131084537704721881438398569476214173211311977143694032174701007005033830070482491565424683664984059187439768982994371382763048098663670188786016786612348042190633
e= 3
c2= 86370003324603283962938004647941072863866893771153362222202759619566185050496089684606274416415418388916028237984708280964054009059814813483639010674182298294505525549842057730933691736372086557397211586739691237738757897947336698446258197604918828646265244195686107866422922575275382813594250335044143485624
n3 = 83259448903366278561128205003734328779222118906091604625605804813528274055482582431201682767294594942491788720967344243567819654813240542076250030802111361571504667752481579915864184180358691091092122509649590043074189547962292835856503625214027405901620103615424259796442446412031011575671410630232956892267
e = 3
c3 = 25601241268900087228853235319569275926328919786631787991019848828558430219449358810095537362492238844266084660904521793373698736119824512458196492049138821633273765102576368573691391116632126183996786969554104441242376959688329346567745607825277943462236901478944551669406261301309719409165457168678763092118
def chinese_remainder(n, a):
sum = 0
prod = reduce(lambda a, b: a*b, n)
for n_i, a_i in zip(n, a):
p = prod // n_i
sum += a_i * mul_inv(p, n_i) * p
return sum % prod
def mul_inv(a, b):
b0 = b
x0, x1 = 0, 1
if b == 1: return 1
while a > 1:
q = a // b
a, b = b, a%b
x0, x1 = x1 - q * x0, x0
if x1 < 0: x1 += b0
return x1
m=chinese_remainder([n1,n2,n3],[c1,c2,c3])
flag = iroot(m,3)
print(flag)
```