Pearl Ctf 2024 Writeup by Fai
I have participanted in Pearl Ctf 2024 with Students Taking Flags Society and we achieved 8th/601. The below writeup is the chals I solved
**OSINT**
- Noob Hacker
This is the Osint series-2, after series-1, from the youtube comments we got the github page of shenoyharry. we can found a repo named PGP, which is an encryption system used for both sending encrypted emails and encrypting sensitive files. After base64 decoding the given file we found his email.
pearl{shenoyharry@proton.me}
- Bomb Trace
Still in shenoyharry's github page, we can find a whatsapp chat screenshot from 'cool', after accessing the url inside the screenshot we found a image, which an AI generated art museum ticket and a geometric location attached in it. Googling it show us the result of virginia.
pearl{virginiamuseumoffinearts}
- lost letter
Since the organization is from india, I immediately search all the states and city which start with T and J, after few attempts I got the flag.
pearl{jagtial_telangana}
**Crypto**
- Baby's Message Out
```
#!/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)
n = p*q*r*s*t
e = 65537
m = bytes_to_long(FLAG.encode())
c = pow(m, e, n)
print(f"c: {c}")
print(f"n: {n}")
```
This chals is about multi-prime RSA.
from the source code we can see that all primes and some relations and can all be written as p. since p is a large prime, for every next/fore prime it makes a big change towards n. And the difference between p^n^ and p^n-1^ is small.
Hence, we could try to write q,r,s,t as a*p^b, where a and b is a constant.
after calculation, we got n = 17^8^ * 29^4^ * p^13^. so p = (n/(17^8^ * 29^4^))^(1/13)^.
```
def nextPrime(p):
if isPrime(p):
return p
else:
return nextPrime(p + 61)
def primegen(p):
q = nextPrime(nextPrime(17*p + 1) + 3)
r = nextPrime(29*p*q)
s = nextPrime(q*r + p)
t = nextPrime(r*s*q)
return q*r*s*t*p
def find_p(papprox, n):
while True:
print(papprox)
try:
n_approx = primegen(papprox)
except:
continue
papprox = gmpy2.iroot(n//(pow(17, 8)*pow(29, 4)), 13)[0]
p = find_p(papprox, n)
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)
d = inverse(e, phi)
pt = long_to_bytes(pow(c, d, n))
print(pt)
```
- 3 spies
```
#!/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')
```
since the e is small and used to generate three different cipher, it is under broadcast attack.
```
n = [n1, n2, n3]
c = [c1, c2, c3]
d = c1*c2*c3
m = gmpy2.iroot(d, e)[0]
```
- Rick Roll
lost the source of this chals, basically just vigenre cipher + ROT13.
**Misc**
- Excel Mayhem
treat the excel as zip and unzip it, we can found the flag in sharedstrings.xml
- TooRandom
The chals is bugged and can get the flag right away.
- i^2 = -1
We solved this chals in the competition time actually but none of us spotted that, we found it out after competition end :(
```
car1_complex = car1.astype(np.int16)
imwrite("unknown.png", car1_complex[..., 0].astype(np.float64) / 4)
```
By doing this we can saw the flag in the shadow of car.
**Web**
- rabbithole
By access to robots.txt we can see it disallowed /w0rk_h4rd, after accessing to it is show us a bold text about **s3cr3t1v3_m3th0d**. So if we raise a request as `s3cr3t1v3_m3th0d /w0rk_h4rd` we can get the flag.
**Reversing**
- input-validator
```
def reverse():
var3 = [1102, 1067, 1032, 1562, 1612, 1257, 1562, 1067, 1012, 902, 882, 1397, 1472, 1312, 1442, 1582, 1067,
1263, 1363, 1413, 1379, 1311, 1187, 1285, 1217, 1313, 1297, 1431, 1137, 1273, 1161, 1339, 1267, 1427]
str2 = "oF/M5BK_U<rqxCf8zWCPC(RK,/B'v3uARD"
for i in range(34):
var3[i] -= 1337
var2 = []
for i in range(34):
var2.append(0)
for i in range(17):
var2[1+2*i] = var3[i]//5
var2[2*i] = var3[i+17]//2
for i in range(34):
var2[i] += ord(str2[33-i])
print(var2)
str1 = ''
for i in range(34):
str1 += chr(bytes_to_long(xor(var2[i], ord(str2[i]))))
print(str1)
var1 = ""
var2 = "oF/M5BK_U<rqxCf8zWCPC(RK,/B'v3uARD"
var3 = "pearl{aaaaaaaaaaaaaaaaaaaaaaaaaaa}"
reverse()
```