function overwrite

Challenge

Story telling class 2/2 You can point to all kinds of things in C. Checkout our function pointers demo program. You can view source here. And connect with it using nc saturn.picoctf.net 55620

Solution

The program lets us input a string/story and then asks us for two numbers. The first number specifies the index of an array and the second number specifies the value to add at that array index. Crucially, only the upper bound of the array index is checked, which means we can go out of bounds and specify a negative number, thus allowing us to write to arbitrary memory locations. This is exactly what we did in PicoCTF 2019's L1im1tL355 challenge.
We are able to write to the array fun:
void (*check)(char*, size_t) = hard_checker;
int fun[10] = {0};
Notice that the check pointer is right above the fun array. Therefore, that pointer will be the first thing we encounter when tracing backwards through memory with negative array indices. This is important because we will be able to set the check pointer to easy_checker instead of hard_checker. easy_checker calls the calculate_story_score function and checks if the output is 1337 before printing the flag while hard_checker checks for the value 1337 which is not obtainable because the program does not let us input enough characters.
The score is calculated by converting each character to an integer using ascii encoding and then taking the sum. With a little trial and error we see that aaaaaaaaaaaaa will get a score of 1261. So, we just need 1337-1261=76 more points. Looking at an ascii table, 76 corresponds to L. So, we can use the string aaaaaaaaaaaaaL to get a score of 1337.
Now, we need to replace the check pointer with easy_checker's address. It currently points to hard_checker's address and the value we specify will added to the current value. Therefore, we need to add the difference like so exe.symbols["easy_checker"] - exe.symbols["hard_checker"]. This will subtract from hard_checker the difference between easy_checker and hard_checker, thus making check point to easy_checker.
Finally, we just need to brute force the offset. Basically, we will trying writing the address delta to fun[-1] and then to fun[-2] etc until the flag is printed.
Fun the solution script.py to get the flag.

Flag

picoCTF{0v3rwrit1ng_P01nt3rs_529bfb38}
Copy link
Edit on GitHub