News:

So the widespread use of emojis these days kinda makes forum smileys pointless, yeah?

Main Menu

Help with C pointers

Started by mynameistmp, November 12, 2005, 05:13:58 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

mynameistmp

I found this brief piece of code that I don't really understand. Obviously there is some major concept that I am missing. I was hoping someone here could explain it a little bit. This guy stores shellcode in a char array then executes the shellcode. If you run the program it works, but I don't understand why. Here is the code:


char shellcode[] = "blahblah";

int main()
{
      int *ret;
      ret = (int *)&ret + 2;
      (*ret) = (int)shellcode;
}


I don't really understand how that results in the shellcode being executed. Thanks in advance.


   


iago

Heya, no problem!  The trick is that he's writing to a memory address on the stack (the return address), obviously.  I'll explain how he manages to do that:

char shellcode[] = "blahblah";

int main()
{
      /* Declare a variable on the stack. */
      int *ret;

      /* &ret is the address of the variable ret, which is a stack location.  It's incremented by 2*sizeof(int) (pointers
       * always increment by sizeof(datatype)).  &ret+1 would be the saved frame pointer, and +2 would be the
       * saved return address.  Don't forget that the stack grows downward, so you increment to move back on
       * it.  Assign the location of the saved return address to ret. */
      ret = (int *)&ret + 2;

      /* Set the memory pointed to by ret (which happens to be the return address) to the shellcode. */
      (*ret) = (int)shellcode;

      /* When the function returns, it pops off the saved ebp, which wasn't modified.  Then it pops off the return
       * address, writing it to EIP.  Since the return address now points to the shellcode string, the shellcode is
       * executed. */
      return;
}



mynameistmp

Ah. He's using the integer variable ret as a reference to find ret on the stack, then using the integer variable again as a vector for overwriting it. Thanks.

iago

Correct.  I was going to point out that he's using it for different things, but I figured you'd catch on :)

MyndFyre

There might be one other thing that is confusing that I wanted to point out.  It deals with these two lines:

char shellcode[] = "blahblah";

      (*ret) = (int)shellcode;

I just wanted to remind everyone the type of shellcode is actually char*, and so when you cast it to an int, you're not losing any data.  If the value of shellcode is a pointer to the memory location 0x50348520, then cast as an int it will be 0x50348520.  Since we're assigning to a dereferenced int*, the value needs to be cast as a value and not just a pointer.  If you forgot to dereference it, you'd probably end up with "blah" in the return address, which would likely crash you.  :)  Otherwise you'd get a compile-time error.
Quote from: Joe on January 23, 2011, 11:47:54 PM
I have a programming folder, and I have nothing of value there

Running with Code has a new home!

Quote from: Rule on May 26, 2009, 02:02:12 PMOur species really annoys me.

mynameistmp

Quote
Since we're assigning to a dereferenced int*, the value needs to be cast as a value and not just a pointer.  If you forgot to dereference it, you'd probably end up with "blah" in the return address, which would likely crash you. 

Hmmm... you don't need to cast at all if you don't want.


      (*ret) = shellcode;


That works just fine. And if you didn't dereference it you'd just wind up having ret point to shellcode[0].