2014-09-01 79 views
5

我得到一台新电脑,所以一个朋友和我决定我们想用我们电脑的内存玩俄罗斯轮盘赌。总的前提是我们随机在内存中占据一个位置,并将其分配给一个随机值,并查看哪个计算机发生故障/崩溃最快或最差。我所做的一切都不是想成为一个好主意,所以不安全的做法被接受,甚至在此鼓励。如何编辑随机存储器?

这是我到目前为止有:

#include <iostream> 
#include <stdlib.h> 
#include <time.h> 

// use preprocessor to avoid losing this data during the running of the program 
// 4GB RAM (4 * 2^32 bytes) 
#define NUM_MEMORY_LOCATIONS 4294967296 

int main() 
{ 
    // Intializes random number generator 
    time_t t; 
    srand((unsigned) time(&t)); 

    while (true) 
    { 
     // 4GB RAM (2^32 bytes) 
     /** generate a 31-bit number between 0b0 (0) and 0b111 1111 1111 1111 1111 1111 1111 1111 (4294967295) **/ 
     // generate a 15-bit number between 0b0 (0) and 0b111 1111 1111 1111 (32767) 
     unsigned long int hi = rand() % 32768; 
     // shift the bits 
     hi <<= 16; 
     // generate a 15-bit number between 0b0 (0) and 0b111 1111 1111 1111 (32767) 
     unsigned long int med = rand() % 32768; 
     // shift the bits 
     med <<= 1; 
     // generate a 1-bit number between 0b0 (0) and 0b1 (1) 
     unsigned long int lo = rand() % 2; 
     // combine to make final random number 
     unsigned long int randNum = hi + med + lo; 

     // select a random position in memory 
     void * randomPointer = 0; 
     randomPointer += randNum; 

     // Something like this here to break my computer: 
     //*randomPointer = 0; 
    } 
} 

我不知道我怎么可以设置这个值,甚至只是0。另外,我不知道什么指针类型,我应该使用。 void指针似乎不起作用,但我可能不完全理解C++中不安全内存管理的复杂性。

有谁知道我该怎么做?任何帮助,将不胜感激。

+11

操作系统不会让您的程序访问未分配给您的程序的内存 – 2014-09-01 06:08:19

+3

这不是现代操作系统或现代计算机体系结构在“正常”情况下的工作方式。阅读[虚拟内存](https://en.wikipedia.org/wiki/Virtual_memory),了解为什么随机尝试翻转某些随机内存位置中的某些位不会导致其他程序出现故障。基本上,每个正在运行的程序都有自己的地址空间,所以一个程序的指针值不一定指向另一个程序的内存。由于操作系统对进程的内存使用情况保持非常接近的选项卡,因此最终所做的几乎肯定会使自己的进程崩溃。 – 2014-09-01 06:10:02

+0

答案取决于你的操作系统。 Linux上的root用户可以通过'/ dev/mem'访问随机存储位置,而Windows有一些特权的API调用,它们会给你类似的访问权限。 – cdhowie 2014-09-01 06:10:28

回答

5

你不能用你的代码做到这一点:在x86-64系统上,你会得到一个访问冲突,每个地址都与你的可执行地址空间无关。

操作系统负责决定哪些地址属于给定的进程(它们经历最终决定该地址是否与进程有关的MMU转换过程),以防它通知处理器并且根据操作系统,您可能会遇到访问冲突或分段错误。

在linux系统上,您通常会编辑另一个进程的内存,如ptrace来调试另一个进程。另一种可能性是编辑/dev/mem。对于这两者你都需要root权限。

在Windows系统上,而不是你可以使用ReadProcessMemoryWriteProcessMemory的或直接注入代码为您生成(CreateRemoteThread的),其地址的目标。

反正记住最主要的原因,你不能用你当前的代码完成它:现代操作系统在分页环境中运行你的应用程序,即它们提供一定的(通常唐虚拟地址空间't)映射到物理地址。 你要做的是错误的,因为这些地址不会映射到物理位置。如果你真的想这样做,你将不得不禁用或绕过分割机制,ring3/0保护,分页,涉及MMU的翻译,并可能处理大量有关保留地址和MMIO注册时间间隔的其他问题。

+0

这不完全正确;这很难做到,但这是可能的。即使只是写一个设备驱动程序来获得必要的访问权限。 – ash 2014-09-01 06:12:40

+0

随着OP的代码,它是不可能的,完全不可靠 – 2014-09-01 06:13:10

+1

“你不能这样做”,你的意思是欧普不能用C++代码做到这一点吗?也许我误解了你的回答。 – ash 2014-09-01 06:15:44

1

对于指针,只需使用“int *”即可。

这样说,程序试图访问的内存只是它自己的内存。为了访问所有的计算机RAM(甚至不是所有的虚拟内存),它需要一些特定于操作系统的技巧以及管理权限来访问程序本身以外的内存。

2

由于虚拟内存机制,你试图做的事情不可能像你试图做的那样。您的进程中的内存地址是,由操作系统的虚拟内存管理器(VMM)将映射到实际的物理内存位置。如果您尝试读取或写入VMM未分配给您的进程的地址,则只会导致您自己的进程崩溃(Windows上的访问冲突,Linux上的分段错误等)。

在Linux上,如果您的进程具有root权限,您可以以不同的方式完成此操作;只需打开/dev/mem节点作为文件并寻找一个随机位置,然后写入随机值或零值。 (实际上,您在代码中执行的操作与使用文件I/O操作时相同 - 查找和写入操作 - 而不是取消引用指针)。

4

所有现代桌面操作系统都使用虚拟进程地址空间。这意味着你的进程看到4GB内存(在32位操作系统上;更多在64位系统上),它拥有所有内存本身,并且看不到其他进程或操作系统内核拥有的内存。虚拟地址空间如何映射到物理内存和交换空间取决于操作系统,并随着内存交换进入和退出而随着时间而改变。

因此,从实验中可以预料到的最糟糕的情况是崩溃您编写的程序。要做其他事情,你需要进入内核空间。

+0

在内核模式下,更准确地 – sehe 2014-09-01 07:35:03

+0

注意区分内核模式/用户模式与内核空间/用户空间吗? – Tom 2014-09-01 07:43:58

+0

空间是指内存寻址空间。 _mode_是处理器所处的实际模式(与地址映射存在更多差异的具体不同模式) – sehe 2014-09-01 07:50:56

0

那么,在Windows 95之后,所有更大的操作系统都使用了内置于CPU中的安全功能。在x86系列上,这被称为“保护模式”。有几种不同的技术,但最广泛使用的技术使用“分页”。

寻呼意味着在页面分割内存空间(4K通常情况下),在那里你有代码的一个子集,另一个用于数据等,如果你尝试写你允许的一组数据页的​​东西之外,你会导致一个异常(称为“陷阱”),这将被操作系统拦截。 95后的生活更无聊了。

寻呼的一个优点是所谓的“交换”。这意味着操作系统可以通过将页面放置在磁盘上来卸载RAM,然后在读取/写入它们时拦截并将其重新调用到RAM中。