【问题标题】:What string operations do the 0x0d and 0xff (from a terminator canary) protect against0x0d 和 0xff(来自终结者金丝雀)可以防止哪些字符串操作
【发布时间】:2015-08-07 04:52:04
【问题描述】:

据说here:

终结符金丝雀包含 NULL(0x00)、CR (0x0d)、LF (0x0a) 和 EOF (0xff) -- 应该终止大多数字符串操作的四个字符,呈现 溢出尝试无害。

我知道 null (0x00) 可以帮助防止 strcpy、strncpy、stpcpy 和 strcat。 LF (0x0A) 也可以用于 get 和 fget。

0x0D 和 0xFF 对停止有什么好处?

【问题讨论】:

  • 0x0d == \r == CR 是 Apple 世界中的行终止符。
  • @DrKoch 大约 15 年前,它行终止符。没有了。
  • 如引用的文字中所指出的,0xFF是EOF,所以有些程序会认为已经到了文件的末尾而停止处理。
  • EOF 实际上是-1(但有些程序认为是0xff)。
  • @ThomasDickey 0xff 如果您将其解释为二进制补码表示的有符号 8 位整数,则为 -1。(许多常见 C 实现中的 char

标签: c linux assembly stack-overflow libc


【解决方案1】:

“金丝雀”的目的是检测缓冲区何时溢出。它被放置在堆栈的返回地址之前,在当前堆栈帧中分配的任何缓冲区之后。如果它的值发生变化,那么堆栈检查代码就会知道缓冲区已经溢出,并在程序造成任何损害之前中止程序。

这样做的问题是,如果攻击者使用与之前相同的值覆盖金丝雀,则不会检测到缓冲区溢出。为了使这更加困难,要么使用随机数作为金丝雀,因此攻击者无法预测它,要么使用您询问的特殊“终结者金丝雀”值。选择构成终结器金丝雀的字节值是因为它们将终止程序使用的各种复制操作。如果这些值在字符串(“shellcode”)中,攻击者用来尝试覆盖返回值,那么大多数复制字符串的代码将在覆盖返回值之前停止。

如果终止金丝雀出现在源输入中,以下是内存复制操作的示例,这些操作将在覆盖返回值之前终止:

NUL 终止

char buf[10];

strcpy(buf, src);

上面的例子是最常见的情况。任何复制 C 字符串的操作都会停止源字符串中的第一个 NUL (0) 字节。

EOL 终止

char buf[10];

gets(buf);

使用gets 是初学者常见的错误,通常不会出现在生产代码中,但编写更复杂的代码来读取一行但不注意不溢出缓冲区并不难。什么标志着行尾取决于约定。通常的 Unix 约定是使用单个换行符(LF,0x0A),但 Windows 使用回车换行(CR LF,0x0D 0x0A)序列。由于终止符金丝雀包含 CR 和 LF 字节值,因此两个 EOL 终止符都存在于金丝雀中。任何复制单行的操作都会在覆盖返回值之前停止。

EOF 终止中断

char buf[10];
char *dest = buf;

while(1) {
    char c = getchar();
    if (c == EOF) {
        break;
    }
    *dest++ = c;
}

这里 EOF 终止符的工作原理比其他两个示例更难理解和解释。除了缓冲区溢出错误之外,此代码还包含另一个导致 0xFF 被解释为 EOF 的错误。就像使用gets 一样,这也是一个新手错误,但在生产代码中更常见。该错误是由使用char c 而不是int c 引起的。

getchar 返回的值实际上是int 而不是char。这使得可以将有效的字节值与特殊的 EOF 返回值区分开来,在大多数系统上是 -1。从文件中读取的字节值作为unsigned char 值转换为int 返回。所以文件中的字节值'\xFF'作为int值255返回。当它被分配给char变量c时,它被截断为(在当今大多数系统上)一个32位有符号整数值为 8 位有符号整数值。这会将 32 位有符号整数值 255 转换为 8 位有符号整数值 -1。此转换还将 32 位有符号整数值 -1 (EOF) 转换为 8 位有符号整数值 -1。

因为 '\xFF' 和 EOF 最终都被转换为 -1,所以它们最终都比较等于 EOF。这意味着在上面的示例代码中,当getchar 返回任一值时,循环将终止。任何出现此类错误的代码都将在源输入中的第一个 '\xFF' 字节处停止复制。但是,正确使用 getchargetcfgetc 或类似函数的代码,将返回值分配给 int,将继续复制任何 '\xFF' 字节。

总结

终结器金丝雀使得攻击者无法利用代码中的给定缓冲区溢出,如果溢出代码使用 NUL (0)、EOL (0x0D 和/或 0x0A) 或损坏的 EOF (0xFF) 比较终止复制。我的猜测是大多数缓冲区溢出的情况都是由于 NUL 在终结者金丝雀中而无法利用的。许多剩余部分将受到 EOL 字符的保护,而损坏的 EOF 字节可能根本没有太多适用性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多