c - 如何使用 C 中的指针检测缓冲区溢出?
问题描述
我正在研究缓冲区溢出,到目前为止,我已经看到了很多使用数组的示例,但是我对以下代码有疑问:
void foo(){
struct {
char a[4];
char b[16];
char *p;
} s;
scanf("%s", s.p);
printf("flag: %s", s.p);
}
int main(){
foo();
}
s.p
作为参数的scanf会导致缓冲区溢出吗?如果是,我如何预测在 scanf 中写入的字符串保存在哪里(那么我必须写多少才能覆盖保存的指令指针,并使漏洞利用工作?)。
我已经用 gdb 分析了代码,我可以看到在 scanf 中插入的字符串从数组的位置开始覆盖a[]
,但是我不知道这种情况是否总是发生,或者字符串是否保存在“随机”位置。
解决方案
“缓冲区溢出”意味着您正在写入已经属于您的数组的末尾并破坏紧随其后的任何内容。
您要问的问题是不同的,因为 的初始值s.p
是不确定的- 它可能根本不对应于可写地址,在这种情况下,您(很可能)会触发段错误。这不是缓冲区溢出,它只是试图访问进程空间中的随机地址。指针值无效(意味着它在该对象的生命周期内不指向程序中的对象),但是没有(好的、标准的、可移植的)方法来判断非NULL
指针值是否有效。
就像写入数组末尾一样,尝试通过无效指针读取或写入的行为是undefined,这意味着编译器和运行时环境都不需要以任何特定方式处理它。不保证行为是可预测或可重复的;它甚至可以在同一环境中运行与运行相同的二进制文件(尽管在实践中往往是一致的)。如果你不破坏任何“重要”的东西,你的代码将不会出现明显的问题。
出于这个原因,几乎不可能检测到缓冲区溢出或从缓冲区溢出中恢复,或者事后通过无效指针进行写入。您的时间最好花在防止缓冲区溢出和通过无效指针写入首先发生的事情上。
推荐阅读
- mongodb-query - 如何在 C# 中使用逗号分隔的字符串从 mongo 集合中查找
- android - 完成动画时如何将小部件和该小部件的功能传递给 main.dart?
- azure-devops - 在 azure devOps 中部署项目期间编辑 sql 文件以保护凭据
- apache-spark - IBM Analytics Engine - 如果我将 Ambari 配置作为高级选项的一部分传递,则集群创建失败
- javascript - 滚动动画技能栏不起作用
- android - 服务 media.camera 没有启动
- mqtt - 使用 MQTT 消息控制 picamera 的问题
- python - 在条形图上使用 yerr() 绘制标准误差(std/sqrt(N))
- jmeter - JMETER 5.2.1:为什么在某些请求中禁用参数选项卡以及在这种情况下如何处理请求
- javascript - 为什么 fs.exists 不是 react js 中的函数?怎么了?