Having a program vulnerable to stack based buffer overflow with setuid bit set, and want to fill the buffer with ROP gadgets.

If setuid(0) is needed to spawn a shell with root privilege, then '0' would be written in the stack, so setuid() can take it as the unique argument. The 0 breaks the sequence we want to write in the stack so an alternate way to write it is needed.

Reading about printf and format string, i'll fill the buffer with ROP gadgets this way:

        <higher address>
        printf's argument
        setuid's argument          
        addr. of pop\ret
        addr. of setuid() 
        addr. of printf's argument
        addr. of pop\ret
ESP-->  addr. of printf()

When it's time to return to the calling function, what is pointed from ESP is loaded into EIP, so the cpu execute the printf() with its argument and so on.

What i'm not understanding is how printf() plays in writing the 0 in the "setuid's argument" position.

I'm on a 32-bit linux system.

  • "The 0 breaks the sequence we want to write in the stack" not always true, depends on the function that is reading it. But I assume you mean it is using a string function which has this behavior? Aug 29 '20 at 13:36
  • strcpy(buffer,argv[1]) is the function i'm working with
    – Marco_81
    Aug 31 '20 at 7:32

While the program itself may not have a format string vulnerability, you can still use the same technique to abuse printf's ability to write arbitrary data at relative offsets without even knowing the address to write to.

The manpage of printf is your friend here. On x86, arguments are taken from the stack, so if you called printf here with the argument %p %p %p %p, it would print out the next few values on the stack, showing the second half of your payload. The 3rd offset, I believe, should be where you are trying to write 0 for setuid's argument. This parameter could also be accessed directly using the notation %3$x.

The %n specifier tells printf to write the number of bytes already printed to whatever address is provided as an argument. So, if printf has not printed anything yet, and its argument is %3$n, it should write 0 to the 3rd stack offset, achieving your goal.

The only problem you may still have to solve is getting your printf argument into memory at a known address.

An unrelated method; if you have enough ROP gadgets, you may be able to find some combination that allows you to push a 0 onto the stack in the correct place.

  • very well explained, and i was able to test with fine result.
    – Marco_81
    Aug 31 '20 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.