---
# System prepended metadata

title: PearlCtf2024

---

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()
```



