假设我有一个 C 字符数组char buf[15]。假设变量int set_me = 0将其数据直接存储在char buf[15]. 如果我溢出buf与串"aaabbbcccdddeee\xef\xbe\xad\xde",将set_me的数据类型的变化从一个整数的字符阵列?
Bob*_*Bob 33
不。
变量的“数据类型”仅与源代码相关(甚至仅与某些语言相关)。它告诉编译器如何处理变量。
这些高级数据类型在编译(本机)代码中不存在。它们会影响编译器生成的指令,但指令本身并不关心数据是表示字符还是数字。
硬件中不存在变量。在硬件中,您有内存位置和对它们进行操作的指令。
一个变量可以被看作是一个内存位置的数据视图——如果你眯着眼睛看同一个内存略有不同(不同类型的不同变量引用同一位置),相同的二进制值可能有不同的含义.
例如,字节 0x41 可以解释为 UTF-8 编码的字符A。它也可以解释为单字节整数65。它也可以解释为多字节整数或浮点数中的一个字节,或多字节字符编码中的一个字节。它可能是 bitset 0b1000001。全部来自同一内存位置中的同一字节。在 C 语言中,您可以通过强制转换为这些不同的类型来看到这种效果。
当您遇到“缓冲区溢出”时,您所做的事情超出了您的编译器或语言的预期范围。但是,就硬件而言1,您正在将字节(无论是单个还是多个)写入内存位置。内存位置没有“类型”。事实上,硬件甚至不知道任何特定的字节集在您的代码中构成一个数组或缓冲区。
无论您下次在代码中的何处访问该内存位置,指令都将按照最初定义的方式运行。例如,如果他们在那里期待一个数字,他们会像处理数字一样处理任何字节的数据。
要使用您的示例,假设您int是一个有符号的 4 字节(32 位)整数:
+-------------+--------------------------------------------+-----------+
| Source code | char[15] | int |
+-------------+--------------------------------------------------------+
| Memory |61|61|61|62|62|62|63|63|63|64|64|64|65|65|65|EF|BE|AD|DE|
+-------------+--------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
您可以看到int的内存位置现在包含0xEFBEADDE,假设是大端系统2。这是有符号的 32 位 int -272716322。现在,如果您将相同的内存解释为 unsigned int ( uint),则4022250974相反。对于内存中完全相同的数据,其含义完全取决于您如何查看它。
1有一些机制会阻止您写入受保护的内存区域,并且如果您尝试这样做会使您的程序崩溃。
2 x86 实际上是 little-endian,这意味着您可以向后解释构成较大值的字节。因此,在 x86 上,您将改为使用0xDEADBEEFSigned-559038737或 unsigned 3735928559。
| 归档时间: |
|
| 查看次数: |
2036 次 |
| 最近记录: |