首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以使用C中的指针访问文本或内核部分?

是否可以使用C中的指针访问文本或内核部分?
EN

Stack Overflow用户
提问于 2014-08-23 15:16:21
回答 3查看 1.2K关注 0票数 2

我知道C/C++允许使用指针操作内存空间的几乎任何部分。但是是否可以使用指针访问内存空间的文本或内核部分。看起来应该有一些安全防护措施来防范这些部分,否则就不可能动态地更改编译后的程序,这会自动使它崩溃,或者在内核中发生更改时使整个系统崩溃吗?

编辑:问题只是指使用MMU的现代系统。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-08-23 16:22:53

计算机漏洞的安全和防范取决于几个组件的配合:(1)计算机硬件,(2)操作系统,(3)应用程序。由于安全和防止脆弱性需要额外的时间和金钱,大多数计算机的使用,特别是1980年代和1990年代的个人计算机,都有一个相当开放的架构。

例如,使用Intel 8080或8086的IBM PC或克隆机将运行MSDOS操作系统或某些变体。许多应用程序将修改BIOS区域内的各种区域和表以及MSDOS操作系统。这是可能的,因为CPU的体系结构将内存呈现为一个单一的共享资源,而操作系统非常简单,提供了最低限度的安全性和漏洞保护。硬件不支持虚拟内存或地址转换,因此所有运行的应用程序都必须有良好的行为和自我约束。关于如何链接中断处理程序,以便多个应用程序能够共存于同一个物理内存区域,并被告知他们正在寻找的事件或中断,有公认的指导方针。

Wikpedia文章,x86内存分割从内存寻址的角度描述了英特尔x86处理器系列从8086到较晚版本的演变,如80286,它开始引入对地址转换的硬件支持。

然而,任何复杂的现代CPU都提供了多种安全机制来支持虚拟内存和管理虚拟内存隔离应用程序。与原来的IBM及其克隆机一起,所有应用程序都共享物理内存。现代CPU为每个应用程序提供虚拟内存空间,CPU将虚拟内存空间内的单个内存访问转换为实际的物理内存位置。结果是,应用程序在自己的虚拟内存空间中运行,它需要操作系统机制来允许协同应用程序(每个应用程序运行在自己的虚拟内存空间中)具有一个共享内存区域。

这些机制的目标是尽可能地隔离单个应用程序,以便如果它们做了一些愚蠢的事情,唯一受影响的应用程序是应用程序本身,而不是可能正在运行的其他应用程序。最重要的工作是确保应用程序不会影响操作系统,这样即使单个应用程序崩溃,操作系统也能保持正常运行。

没有什么可以阻止单个应用程序修改自身。这样做的想法是,如果应用程序想要修改自己,那么应该允许它这样做,只要结果仅限于应用程序本身。在某些情况下,虚拟存储器的区域可以标记为只读区域,如果试图修改只读区域中的数据或程序代码,则会导致异常。

只读区域的另一种用法来自于汤普森,UNIX实现的论文,在这篇文章中,UNIX中的只读区域或文本部分是加载一次,并在多个进程之间共享。这是一篇有趣的历史论文,提供了一个缩略图,描述了当前最有影响力的单块(非基于内核)操作系统之一,UNIX,它变得相当成功,并被许多其他操作系统所模仿。这个堆栈溢出问题/答案,Unix/Linux加载程序,提供了一些关于加载程序和进程如何加载的附加细节。

但是,任何处理过缓冲区溢出问题的人都会发现,应用程序可以修改自己的内存区域,通常会给应用程序带来灾难性的后果。

有关英特尔体系结构的详细信息,请看一下英特尔64和IA-32建筑手册

恶意软件和病毒是在操作系统中使用各种漏洞和漏洞的应用程序。Stuxnet是一个著名的例子(请参阅IEEE频谱: Stuxnet的故事以及这篇连线文章数字解码如何破译史上最具威胁的恶意软件Stuxnet)和Flame一样,这两者似乎都是网络战应用程序。

还可以看到这篇关于USB恶意软件的Wired.com文章,USB的安全性为什么会被彻底破坏概述了通过修改USB固件进行的恶意软件攻击。这与美国国家安全局正在做的一些工作有关。

下面是一个简单的例子,展示了在C中使用C风格的铸造可以做什么.此示例将使用Visual 2005进行编译。如果在调试器中运行此命令,您将看到它将命中int 3指令,从而导致断点命中。

代码语言:javascript
复制
int jjFunc (void)
{
    int i = 3;

    return i;
}

// 0xCC is an int 3 instruction for causing a break point.
unsigned char xxFunc [] = {0xcc,0,0,0,0};

int _tmain(int argc, _TCHAR* argv[])
{
    int (*xx)(void) = jjFunc;

    char *p = (char *)xx;

    // point to my tiny program in memory
    xx = (int (*)(void))&xxFunc[0];

    xx ();

    jjFunc ();
    *p = 0;
    jjFunc();

    return 0;
}
票数 2
EN

Stack Overflow用户

发布于 2014-08-23 15:25:57

不可能从任何程序访问内核内存,甚至连C或汇编程序都不可能访问。现代操作系统采用了一种叫做虚拟存储器的技术,它本质上可以让每个程序假装自己拥有计算机的所有内存。程序所能看到的所有内存都属于它。

请注意,大多数操作系统为程序访问内核内存提供了一种手段,但您的程序需要有更高的权限级别(例如超级用户/根/管理员)才能这样做。

票数 3
EN

Stack Overflow用户

发布于 2014-08-23 15:27:01

操作系统和CPU阻止访问内存中的内核和中断表地址,但如果您的用户在ring0中,则可以访问这些内存区域,就像使用本节但在操作系统之外的引导加载程序一样,但是如果存在堆栈溢出漏洞或类似os服务(如lsass )或任何其他具有ring0或更好(windows中的系统)权限的漏洞,则可以使用安全漏洞访问这些内存区域。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25463394

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档