Rating:

Idea is we pivot to data section, which has a constant address despite ASLR. Moreover, it is not data NX, only stack NX, so we can write shellcode there.
Then, our shellcode will increment the byte in the code (since code is not RO) which checks input for bounds. That allows us to input an "invalid" request for the factory to output the key. To deal with ASLR/Cookie we notice that the random seed is only seeded once from the random syscall. But it's only 32bits and it goes through an LCG to produce some output we observe. So we just undo the LCG to derive the seed, and likewise the ASLR base and cookie.

Original writeup (https://github.com/perfectblue/ctf-writeups/tree/master/csaw-ctf-2018-finals/overlord).