我在C中遇到过指向指针(不确定这是正确的术语)的指针,例如:
*(长*)p = 10;我永远不会为我的生活理解它的含义,或者另一个例子:
*(void *)NULL,或*(char *)0;我只是无法绕过它,有人可以向我解释这一点,并拯救我免受部分脑损伤吗? :)
由于
(P.S下面显示了这种用法的一个例子)
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); }
答案 0 :(得分:3)
首先打破声明:
long *q = (long*)p;
*q = 10;
p += 4;
p参数的类型为char*
,您只能通过该指针一次读取或写入1个字节。转换为long*
会创建一个指针,您可以通过该指针一次从/向同一地址读取或写入4个字节。赋值写入字节0x00,0x00,0x00,0x0A。同样的事情:
*p = 10;
p++;
*p = 0;
p++;
*p = 0;
p++;
*p = 0;
取决于字节顺序。在赋值之后,p需要增加4,因为写了4个字节。
这个技巧在包含非字节数据的字节缓冲区中很常见。
答案 1 :(得分:2)
*(long *) p = -4;
意思是:p是“指向long的指针”,我试图将值赋给那里引用的内存。我们这样做是因为最初我们说p是一个char指针,我们想在访问时改变它的行为。
答案 2 :(得分:1)
在(long *)之前放置*称为“解除引用”指针。正如@GrayWizardx所说,这意味着你正在修改指针所指向的内存中的值。
答案 3 :(得分:1)
codepad.org/iz2TSDfa
此代码将四个字节的数据写入内存中的零地址。这不是常见或接受的做法,并不适用于一般情况。换句话说:黑魔法。
我猜它会触发某种处理器中断。
如果您想了解它,我建议您学习汇编/此代码所针对的计算机体系结构。
答案 4 :(得分:0)
第一颗星实际上取消引用了铸造指针。因此,*(long *)p = 10表示将p转换为指向long的指针并将-4指定给解除引用的位置。将您的示例与* p = 10进行比较。
答案 5 :(得分:0)
它的指针算法,基于指针类型,即它的char * cPtr或int * nPtr,当你递增cPtr ++时将移动一个字节而nPtr ++将移动4个字节(assumimg char占用一个字节,int占用4个字节)
答案 6 :(得分:0)
当您理解示例代码背后的动机时,您可能会更轻松。
代码正在处理4字节值,这就是p
被强制转换为long *
的原因。构造* (long *) p = -4;
允许您使用单个赋值将4个字节设置为0xFFFFFFFC
。如果您将p
作为char *
离开,则需要进行四次单独的分配,并且还需要担心平台的endianness。
那么为什么不首先简单地将p
声明为long *
?因为代码使用指针算法来计算目标地址:p += sizeof(shellcode) + 64 - 4;
使用char *
指针算法很容易,因为向指针添加1将使其前进到下一个字节,就像您期望的那样。指向其他数据类型的指针不是这样!如果p
被声明为long *p;
,那么p += 4
会将 4 * sizeof(long)
添加到p
。
为什么呢?因为这样可以轻松遍历long
变量列表:
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;
}
因此,在您的示例中,将p
定义为char *
可以很容易地按字节数进行指针运算,并将其转换为long *
使分配更容易。