We need 28 characters of padding and 4 bytes to modify the variable which is 32 bytes at total and equal to the size parameter of read. Now, we know that we can modify it, let’s disassemble the secretFunc function.

puts("Your name was encrypted using the best encryption in the world");

printf("This is your new name: ");

printf((constchar*)buf);

fflush(stdout);

if(retaddr!=(void*)retAddr)

exit(1);

return0;

}

It asks for an input and reads it with read again. This time the size parameter is 27 and the buffer’s size is 28.

After reading the input, it puts a null byte at the end of it. Then, it iterates through the buffer and reads chunks of 4 bytes except the last chunk and convert them 32-bit integers. Next, it xors them with 0x5F7B4153 and overwrite the original chunk with the result. Finally, it prints this new string using printf. Since it uses xor to encrypt the string, if we give an encrypted string to it, it will decrypt it correctly. We can prepare a format string exploit and send its encrypted version to the server and it will get decrypted. However, before returning from the function, it also verifies the return address. Instead of overwriting the return address of this function, we can overwrite the [email protected]since the main functions calls exit(0) at the end.

There exists another function named superSecretFunc at 0x08048596. Here is the decompilation of it.

1

2

3

4

5

6

intsuperSecretFunc()

{

printf("Here is your flag: ");

fflush(stdout);

returnsystem("cat flag");

}

This function prints the flag from the server. Therefore, we need to call this function by overwriting the [email protected].