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.
加载中,请稍侯......
精彩评论