LakeCTF 2022 Writeups

scoreboard

LakeCTF event was hosted by the top team polygl0ts of EPFL University. This time I couldn’t spend much time so I just solved 3 challenges, achieving the 58 position out of 191 teams.

scoreboard

The challenges I solved are from categories ‘pwn’ and ‘rev’. Apart from these three challenges, I spent most of my time trying the web challenge called ‘People’. I’m excited to read writeups of this challenge because I know that I was going in good direction but I got stuck on the final part of the challenge.

scoreboard

Attack on Canary [pwn][56 solves]


Keywords: BoF, Canary

canary

As the name suggest, this challenge involves the bypass of the protection Stack Canaries. ‘Checksec’ tool allows us to check the security protection of the binary. In this case, the two most important protection’s for this challenge are Canary and PIE. The challenge has PIE Protection disabled so if we find a BoF we could easily change the ret address to point anywhere we want.

canary

Binary is not stripped so it would be easier to analyze the assembly. If we check the functions of the binary, there are two function names that attract our attention (‘win’ and ‘vulnerable’). Let’s take a look using ghidra decompiler.

canary

“Win” function is just a wrapper to spawn a shell, so this is the function we will use to get the flag. We need to find a vulnerability (in “vulnerable” function), to overwrite the return address to this function.

canary

Before searching the security flaw in the “vulnerable” function, I extracted the win address (Little Endian b’\x37\x08\x40’). Remember PIE is disabled.

canary

“Vulnerable” function provides us with two possible commands. If we send the command “0” we are able to read 8 bytes from a particular offset of the stack. If we make a simple calculation (initial_buffer_addres + (our_input « 3)) we are able to read whatever 8 bytes we want, like for example, Canary ;)

In the second part of the function, the binary allows us to write on the buffer. The message printed on the screen says that we are able to write a maximum of 8 bytes. However, if we check the read syscall, our input is provided as the size. This security flaw allows us to write all the bytes we want. In this moment, the idea of changing the ret address of the “vulnerable” function to point to “win” function has to pop up in our minds.

canary

GDB debugger allows us to execute the binary in order to know the exact offset’s we need to take care of. We can use GDB breakpoint’s in order to know the exact position of the canary or return address. If we put a breakpoint in the syscall that prints some bytes of the stack, we can see that the canary is right after the 88 bytes of the buffer. With this in mind, the payload will be: 88 bytes of buffer, 8 bytes of canary, 8 bytes of RBP, 8 bytes of ret address that we are going to replace to ret into “win” function.

canary
canary

To summarize, in the reading phase we have to exfiltrate the canary and use that canary in order to overwrite the return address to point to “win” function. In order to exfiltrate the canary (check again ghidra), we need to calculate the offset we want to provide. In the writing phase, we need to use the payload to overwrite the return address to point “win” function, using the exfiltrated canary.

canary

Finally, I automatized the process using the popular library pwntools. In the following image you can check the completed exploit. After executing the exploit, a shell (of “win” function syscall) will be spawned that allows to read the flag.

canary
canary

Fun fact: When I printed the flag I thought the flag was incorrect and the challenge involved also some Privilege Escalation phase. After spending a couple of minutes checking the system, I just tried to enter that flag.

Way too simple [pwn][47 solves]


Keywords: Format String

formatstring

“Way too simple” was a challenge that involved a format string. At the beggining, I tried to execute the binary but I couldn’t so I started checking strings of the binary.

formatstring

While I was checking strings on the binary I found one “…flag…”. In that moment, I opened GHidra and I checked in which function was referenced. After a bit of reversing (renaming functions…), I realized that there was a format string in the function.

formatstring
formatstring

In order to check the binary behavior, I connected to the server. Furthermore, I noticed that the binary executes the vulnerable function we reversed. I checked the format strings vulnerability entering a format character, in this case “%x” to print hexadecimal. After submitting our test, the server returns bytes from the stack. I found two great articles explaining this type of vulnerability [Link 1, Link 2] that I used as a walkthrough.

formatstring

The first message that the server prints is the memory location of the flag. To summarize, we need to put that memory location and use the format “%s” to follow that memory and exfiltrate the flag. Before starting to code the exploit, we need to find in which position we are writing our input. In this case, the position is the 7th.

formatstring

Finally, parsing the flag address and using the format “%s” we are able to exfiltrate the flag. In the following screenshot you can see the final exploit to exfiltrate the flag.

formatstring
formatstring

Baby rev [rev][77 solves]


formatstring

Baby rev was the first challenge I solved. First of all, I checked if the binary was stripped, in this case it wasn’t stripped so the reversing was much simpler.

formatstring

In my case I used GHidra to rev the binary. GHidra provide us with a really nice decompilation of binaries. In this particular binary, it was easy to find where the “reversing” part was. The binary receives an input of a number and this number is compared to the resulting value of some calculation.

formatstring

To resolve this challenge I just created a bruteforcer script of the possible values. In almost 30 the script prints one of the possible solutions for this challenge. In this challenge, there were some people that used a SMT Solver (e.g., Z3) to calculate the number. Finally we just need to submit this value to the server and the flag is going to be printed.

formatstring
formatstring

Conclusions


LakeCTF was a really enjoyable event and I liked the challenges I tried to solve. I’m really excited to read the writeups of some of the challenges I couldn’t even try. Thanks to the organizers and the author’s of the challenges for this event. Congratulations to the winners of the CTF.

Thanks for reading!

Alberto Fernandez-de-Retana
Alberto Fernandez-de-Retana
PhD Student

Kaixo! PhD Student at University of Deusto under supervision of Igor Santos-Grueiro and Pablo G. Bringas. My research interests include web security & privacy. In my free time I love to be pizzaiolo.