It is pretty clear where the vulnerability is: an user input of arbitrary size is copied to a local buffer of fixed size (32*4096)... a straight stack-based buffer overflow.

Unfortunately our input is encrypted (xored) with a different pseudorandom key obtained from /dev/urandom every time we connect to the service (cipher function). The key is, however, reused within the same session. The output of this encryption is returned to the user.

Since we are in a while loop and we can call multiple times the vulnerable routine, we'll use the first cycle to extract the key (sending just null bytes) and then send our payload encrypted with the same key to exploit the buffer overflow. The cipher routine will actually "decrypt" our payload (how XOR works) allowing us to overwrite EIP with the desired value.

EIP is under control and ESP is pointing to user controlled input. We cannot execute our shellcode directly from the stack due to the Non-Executable Stack policy, but, since the binary is not a PIE we can probably craft a chain of libc function calls (using the GOT) to obtain a shell. Remember also that stdin and stdout are redirected to the socket connection.

The "system()" function is not available, but we have "execve()" which works fine. Since there is no "/bin/sh" string in the binary we must write it ourselves to a writable memory location (bss?) with a bunch of "snprintf()" calls.