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

时间:2014-08-23 15:16:21

标签: c++ c pointers

我知道C / C ++几乎可以使用指针来操作内存空间的任何部分。但是是否可以使用指针访问内存空间的文本或内核部分。看起来应该有一些针对这些部分的安全防范,因为否则就不可能动态地改变编译的程序,这会自动崩溃我认为,或者在改变的情况下使整个系统崩溃内核中的东西?

编辑: 问题仅涉及采用MMU的现代系统。

3 个答案:

答案 0 :(得分:3)

无法从任何程序访问内核内存,甚至不能访问C或汇编程序。现代操作系统采用一种名为virtual memory的技术,它基本上让每个程序假装它拥有自己的所有计算机内存。程序可以看到的所有内存都属于它。

请注意,大多数操作系统都为程序提供了访问内核内存的平均值,但是您的程序需要具有提升的权限级别(例如超级用户/ root /管理员)才能执行此操作。

答案 1 :(得分:2)

计算机中漏洞的安全性和防范取决于几个组件的协作:(1)计算机硬件,(2)操作系统,以及(3)应用程序。由于安全性和防止漏洞需要额外的时间和金钱,大多数计算机的使用,特别是在20世纪80年代和90年代的个人计算机具有相当开放的架构。

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

这个Wikpedia article, x86 Memory Segmentation描述了从内存寻址的角度,从8086到更高版本的英特尔x86处理器系列的演变,例如80286,它开始为地址转换引入硬件支持。

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

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

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

只读区域的另一个用途来自Thompson,UNIX Implementation的本文,其中UNIX术语中的只读区域或文本部分是一次加载并在多个进程之间共享。这是一篇有趣的历史性文章,提供了UNIX中最具影响力的单片(非基于内核)操作系统之一的缩略图,该操作系统非常成功并且被许多其他操作系统模仿。此stackoverflow问题/答案Unix/Linux Loader Process提供了有关加载程序以及进程加载方式的一些其他详细信息。

然而,任何处理过缓冲区溢出问题的人都看到应用程序可以修改自己的内存区域,通常会在应用程序上带来灾难性的结果。

有关英特尔架构的详细信息,请查看Intel 64 and IA-32 Architectures manuals

恶意软件和病毒是在操作系统中使用各种漏洞和漏洞利用的应用程序。 Stuxnet是一个着名的例子(见IEEE Spectrum The Story of Stuxnet以及这篇有线文章How Digital Dectives Deciphered Stuxnet, the Most Menacing Malware in History)和Flame一样,两者似乎都是网络战应用。

另请参阅此关于USB恶意软件的Wired.com文章Why the Security of USB is Fundamentally Broken,该文章通过修改USB固件概述了恶意软件攻击。美国国家安全局在美国正在开展一些工作。

这是一个简单的例子,展示了使用C风格的演员可以在C中完成的任务。此示例将使用Visual Studio 2005进行编译。如果在调试器中运行此示例,您将看到它将点击int 3指令以导致断点命中。

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 :(得分:-2)

操作系统和CPU防止在内存中访问内核和中断表地址 但是如果你的用户在ring0中你可以,比如使用本节但在操作系统之外的bootloader程序,但是如果存在stackoverflow错误或类似于lsass或任何其他具有ring0或更好的其他操作系统中的漏洞(系统)在Windows中)您可以使用安全漏洞访问这些内存区域