.

BOF

<<

shafiee01

Newbie
Newbie

Posts: 1

Joined: Sat Dec 10, 2011 2:45 pm

Post Sat Dec 10, 2011 2:50 pm

BOF

Hi,
I want to get shell by exploiting a BOF vulnerability in a simple c code. My problem is that there is a canary guard in the code which does not let to change the memory from buffer -> "ret" address of function just like classic BOF exploits. However, I think there is another mistake in this code. The author has not used the global variable (I mean 'i') therefore, i is copied above the stack like buffer and other arguments. Thus, by changes both the canary and i variable the check should be bypassed!(This is what I think and may be wrong!). I tried to write an exploit for this code but the value of i does not change. If(as I think) the stack is like this:
[ buffer ][canary][sfp][ret][*arg][i]
then by overwriting a string of 600 or longer the value of i should be changed! but it does not change!! :o

  Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/ptrace.h>

int vulnerable(char *arg, unsigned char i)
{
    unsigned char canary;
    char buffer[512];
    canary = i;
    strcpy(buffer,arg);
    if (canary!=i)
    {
        printf("Stack protection!\n\n");
        exit(200);
    }

    return 0;
}

int main(int argc, char *argv[])
{
    unsigned char i=0;

    srand(time(NULL));
    i = rand() % 10;

    if (argc<2)
    {
        fprintf(stdout,"Synopsis: vuln <message>\n\n");
        exit(1);
    }

    vulnerable(argv[1],i);
    printf("End.\n");

    return 0;
}
<<

unicityd

User avatar

Full Member
Full Member

Posts: 170

Joined: Wed Sep 03, 2008 5:33 pm

Post Sun Dec 11, 2011 2:47 am

Re: BOF

The most likely explanation for the value of i not changing is that the compiler is loading i into a register when it assigns "canary = i" and that it does not use that register again before it needs to check "if (canary != i)".  In the C code, i is not used again so there is no reason to copy the parameter off the stack again unless it needs to use the register for something else.  The call to strcpy() won't affect it because it will push the registers onto the stack before the function call and pop them back off when it returns.  

Note: when I talk about the compiler loading a variable into a register, I'm talking about the assembly language or machine instructions the compiler generates during compilation.

So, the code for "canary = i" might load canary into register ebx.  Then the program calls strcpy after which canary is still in the ebx register.  Then it checks the value of i against canary ("if (canary!=i)") by comparing to the ebx register without copying canary from the stack a second time.  If this is the case, you can overwrite canary on the stack with impunity because the compiler optimized away the security check.  If you overwrite both i and canary, you're better off if the compiler doesn't keep canary in a register so that you can overwrite both of them with a new value.

You can also beat the canary check without changing i because the canary value isn't very random.  Look at the code below:

i = rand() % 10;    

The canary is set to a value between 0 and 9.  So, when you do the overflow, you can overwrite that byte with any value between 1 and 9 and have a 1/10 chance of it working.  You can't overwrite it with 0 unless you want strcpy() to terminate on that byte.  I'd just overwrite it with a 1 and try the exploit until 1 turns out be a correct guess.

The better way to implement canaries is in the compiler itself so that a canary is automatically added into the stack frame for each function and checked on return.  There are ways to beat this as well (if you can guess/reproduce the canary or direct a pointer right at the saved instruction pointer thus bypassing the canary entirely), but it's stronger and may prevent exploitation entirely (depending on the circumstances).

While I don't think it's happening here, there is another reason for you not to be able to change a passed parameter with a buffer overflow.  In some cases, parameters are passed in registers in which case you cannot modify i with a buffer overflow.  This is common when compiling 64-bit code since extra registers are available to the compiler.  I don't think you'll see this in 32-bit code unless the function is declared with fastcall:

__attribute__((fastcall)) int vulnerable(char *arg, unsigned char i);

I hope this helps.

Best regards,

Steven

Edit: cleaned this up to make a little more sense.
Last edited by unicityd on Tue Dec 13, 2011 1:31 am, edited 1 time in total.
BS in IT, CISSP, MS in IS Management (in progress)
<<

unicityd

User avatar

Full Member
Full Member

Posts: 170

Joined: Wed Sep 03, 2008 5:33 pm

Post Tue Dec 13, 2011 1:24 am

Re: BOF

I tested some similar code today with VC++ and gcc.  With VC++, the generated assembly code copies the canary from the stack before making the comparison, but gcc with -O3 (I didn't try lesser optimizations) does keep the canary value in a register so it will check out okay even if the canary on the stack gets overwritten.
BS in IT, CISSP, MS in IS Management (in progress)

Return to Programming

Who is online

Users browsing this forum: No registered users and 1 guest

.
Powered by phpBB® Forum Software © phpBB Group.
Designed by ST Software