Tags: coppersmith crypto re 

Rating: 2.0

# coooppersmith Writeup

### DEFCON 2020 Quals - crypto 130 - 41 solves

> I was told by a cooopersmith that I should send hackers encrypted messages because it is secure. `coooppersmith.challenges.ooo 5000`

#### Observation

[Reversing is done](service.i64). There are two steps to get the flag.

1. `test()`: Guess two consecutive crandom output which seed is `time(NULL)`.
2. `getEncFlag()`: Obtain encrypted flag and decrypt it.

#### Prime generation algorithm

Public modulus `n = p * q` is generated by weird logic. It first gets 60 byte input `seed` from user, and generate 512 bit prime `prime`. Below is the `genPrime()` logic.

```python
def genPrime(seed):
assert len(seed) <= 120
v = int(seed, 16)
l = len(seed)
shift_val = 4 * (128 - l)
v8 = v << shift_val
v7 = 2 ** (shift_val / 2)
v2 = 0
for _ in range(100):
r = randrange(v7)
prime = r + v8
while prime >> shift_val == v:
if isPrime(prime):
v2 = 1
break
prime += 1
if v2:
break
return prime
```

After that, service uses `prime` as seed to generate two 1024 bit primes `p`, `q` using function `genRSAPublicKey()`. It iterates until it generates primes with following contraints, where `x0`, `y0` are 512 bit values.

```
p = 2 * prime * x0 + 1
q = 2 * prime * y0 + 1
n = (2 * prime * x0 + 1) * (2 * prime * y0 + 1)
```

#### Exploit

First send `seed` as value of `'ff' * 60` The entropy of `prime` is controlled by `seed`. If I use maximum value of `seed`, It becomes feasible to brute and find out the value of `prime`. When `seed` has 60 byte length, random `r` for `genPrime()` falls in `range(65536)` and can be easily guessed. Below is the example output of `genPrime()` in hex.

```
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000a0df
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009f61
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000005cb
```

Public modulus `n` satifies `(n - 1) % prime == 0` because of upper prime gen logic. By using this fact, brute and obtain `prime`.

```python
start = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000

while True:
if (n - 1) % start == 0:
print(start)
exit()
start += 1
```

Secondly, guess two 32bit crand values. This is [obvious](https://stackoverflow.com/questions/5574914/srandtimenull-doesnt-change-seed-value-quick-enough) because value of seed is `time(NULL)`. Use ctypes to call `srand()`.

```python
class RandomWrapper():

def __init__(self, delta, seed=None):
self.c = ctypes.CDLL('/lib/x86_64-linux-gnu/libc.so.6')
if seed:
self.seed = seed - delta
else:
self.seed = self.c.time(0) - delta
pwn.log.info('seed: {}'.format(self.seed))
self.c.srand(self.seed)
self.Random = self.c.rand

def Random(self):
return self.Random()

delta = 0
r = RandomWrapper(delta)
s = r.Random()
t = r.Random()
ans = (s + t) & 0xffffffff
```

Now we have `c` and `prime`. To factor `n = (2 * prime * x0 + 1) * (2 * prime * y0 + 1) `, I have to find out `x0` and `y0`. [Bivariate coppersmith](http://www.jscoron.fr/publications/bivariate.pdf) may solve the equation.

By using this [great implementation](https://github.com/ubuntor/coppersmith-algorithm) of Coron's reformulation of Coppersmith's algorithm for finding small integer roots of bivariate polynomial over `n`, I recovered `x0` and `y0`. Below is the polynomial constructed for applicating coppersmith.

```python
X = Y = 2 ** 512 # Estimated size of x0, y0
P.<x, y> = PolynomialRing(ZZ)
pol = (2 * p0 * x + 1) * (2 * p0 * y + 1) - n
x0, y0 = coron(pol, X, Y, k=2, debug=False)[0]
assert n == (2 * p0 * x0 + 1) * (2 * p0 * y0 + 1)
p = 2 * p0 * x0 + 1
q = 2 * p0 * y0 + 1
assert p * q == n
```

Factors known, get the flag!

```
OOO{Be_A_Flexible_Coppersmith}
```

Original binary: [service](service)

Exploit code: [solve.py](solve.py), [coppersmith.sage](coppersmith.sage)

Original writeup (https://github.com/pcw109550/write-up/tree/master/2020/DEFCON/coooppersmith).