【问题标题】:c++ -successfully printing out of range string indexesc++ - 成功打印超出范围的字符串索引
【发布时间】:2018-09-02 18:33:34
【问题描述】:

我是 C++ 新手,我正在玩 string 类。当我使用 GNU 编译器在 CodeBlocks 中运行以下代码时,我意识到:

#include <iostream>

using namespace std;

int main()
{
    string test = "hi";
    cout<<"char is : "<<test[100];
    return 0;
}

我实际上得到了一个价值。我玩索引(我尝试从 100 到 10000),我可能会得到其他字符,或者我可能会得到空值。这是否意味着您可以通过这种方式读取您不应该读取的部分内存?你能用它来剥削吗?还是只是我的想法是幻觉?

【问题讨论】:

  • 未定义的行为是未定义的be.havior
  • C++ 没有边界检查。越界导致undefined behavior 可能是(或至少曾经是)大多数程序安全问题的最常见原因。
  • 你告诉 C++ 从最初的起点到第 100 个条目,它会很乐意这样做,不管它是否是“你的记忆”。会发生什么?你不知道,我不知道,没有人能告诉你。这就是未定义的行为,而 C++ 是极少数存在这种概念的语言之一。
  • 详细说明@Someprogrammerdude 的评论——C++ 不要求 对字符串的operator[] 进行边界检查。对程序做什么没有要求,正式地称为“未定义的行为”。语言定义不禁止边界检查;允许为越界访问抛出异常是允许的,因为行为是未定义的。一些实现在调试模式下这样做。
  • @TheEngineer -- 因为我认为这是不安全且可利用的! -- 这就是为什么您有责任使用安全/安全的编码实践。您不会将数组的大小声明为 N,然后随便从超出N 的用户那里获取输入,然后将其插入您的数组访问中。您负责任何边界检查,除非您使用函数显式检查越界访问。 C++ 旨在通过进行访问检查来不妨碍编程性能——这落在您的肩上。

标签: c++ string segmentation-fault exploit


【解决方案1】:

答案很简单——未定义的行为。不,您不能相信此信息,强烈不推荐。不要这样做..

【讨论】:

    【解决方案2】:

    这是未定义的行为,所以任何事情都可能发生。编译器可以优化掉该行、插入 abort() 或执行其他任何操作。

    如果编译器没有对代码进行大的更改,并且std::string 实现了短字符串优化,那么test[100] 将访问调用main() 的函数之一的堆栈帧。

    这些函数负责加载共享库、安排环境变量、构造std::cout等全局对象,以及创建argc、argv并将其传递给main()。这段代码窥探了这些函数的堆栈。在具有内存保护的系统(例如 Linux 或 Windows)上,如果有足够多的越界访问,应用程序就会崩溃。

    不要依赖它,因为编译器可以用它做一些完全出乎意料的事情。

    是的,它会导致剥削。如果越界取决于用户输入,那么该用户可能能够读取或写入他们不应该读取的数据。这是蠕虫或病毒可能传播的方式之一:它们读取密码,或编写将在函数返回时执行的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      • 2016-02-19
      • 2012-03-02
      • 2016-02-10
      • 2021-01-30
      相关资源
      最近更新 更多