at the very beginning there is a struct defined called auth with two element

name( 32 bytes size ) from type char and auth with the type int ( by default on 32 and 64 bit machines the type int has a 4 bytes size )

at the next line we have two pointers auth ( pointer to the auth struct ) and struct

next inside the main function there is this while loop that prints the auth and service pointers and reads a line with a maximum of 128 bytes (this is a secure fgets) , next we have this conditional statements

these if statements are responsible for checking from the input and compare it with the strings or commands (‘auth , reset , service , login’)

and just doing stuff depending on the command specified by user

the first command is auth , this command allocates a memory on the heap with the size of the auth object (32 bytes for name and 4 bytes for auth) , then the next line with the memset function overwrites the whole memory allocated with zeros because on the heap data is constantly allocated or freed and overwriting this chunk of memory here is to make sure it doesn’t have any old data stored in there

next it checks the length of the input ( should be less than 31) this happens to prevent the auth integer from being overwritten

the ’login’ command is interesting , take a look at that part , if you typed login the program will check the integer auth value (which is always null and until now we don’t have any control of it) , and just print ‘you have logged in already’ if it evaluates to TRUE , so clearly our goal is to somehow find a way to write to the location of the auth integer and login ..

lets take a look at the other commands

reset looks also interesting , this command just frees the auth object on the heap , the last command is service , this command use’s strdup function

lets take a look at the man page of the function with man 3 strdup

in the description section it appears that this function allocates memory on the heap with malloc and just copy the string passed to it there.

interacting with the program

after we understood the code lets run the program

at the beginning it just prints the values of the auth and struct pointers which are null before we type the command auth ,

after we type auth and pass the value admin , the auth pointer changed to an address which is the address of the auth object on the heap , now if we tried to login it just says ‘please enter your password’

after that we try the reset command , this will free the auth object , but notice that it still points to same address

now we use the service command with service hack, notice that the service and auth are now pointing to the same address , isn’t this weird? that happened because the auth variable was freed , then service got that free space

lets debug this with gdb

open gdb and define a hook stop to display the heap every time you step through

type auth admin and observe the heap , we see our string admin on the address of the auth variable , but hold on! , why is the length of the chunk is only 0x11? this is not the actual size of auth ! , well that happens when you write bad code and name everything auth

when the program calculated the size of auth it calculated the size of the variable auth not the struct auth , unintended mistake ! this is the essence of the majority of the security flows and bugs

lets try reset and see what will happen

the auth still exists with the same pointer but the name is now empty with null

lets try service

BOOOOOOOOM we changed the auth

how did i got here and changed the auth variable ?

i simply typed service three times in each time i passed one of those sequence of characters AAA,BBB,CCC , the auth value changed because it was overwritten with the value CCC ,this is predictable because as i mentioned before this code is so bad and it allocates a wrong size for the auth ..

another good way to break this is by simply typing service with a long sequence of characters (maybe ‘A’ * 28) and you will get the same result so it wasn’t necessary to free the auth variable , this term called use-after-free and it was kind of the intended way to solve this challenge