17

我目前正在反汇编一些用 Visual Studio 2012 Express 制作的小型 C 程序,并且我注意到二进制文件中的一种趋势。

在 main 函数中执行的第一组指令总是:

SUB ESP,154                       ; Doesn't have to be 0x154.
.....
.....
.....
LEA EDI,DWORD PTR SS:[EBP-154]
MOV ECX,55                        ; Also doesn't have to be 0x55.
MOV EAX,CCCCCCCC
REP STOS DWORD PTR ES:[EDI]

那么,为什么机器会用这个 0xCCCCCCCC 填充堆栈呢?我读过它被 VC++ 或其他东西用作未初始化空间的标记?

然后假设我要在我的缓冲区中放入一些东西......编译器或处理器决定将它放在这个空间内的某个随机点,但我不明白为什么它会把它放在那里......

EBP-90   > CCCCCCCC  ÌÌÌÌ
EBP-8C   > CCCCCCCC  ÌÌÌÌ
EBP-88   > CCCCCCCC  ÌÌÌÌ
EBP-84   > 00000001  ...  ; Why this place?
EBP-80   > CCCCCCCC  ÌÌÌÌ
EBP-7C   > CCCCCCCC  ÌÌÌÌ
EBP-78   > 41414141  AAAA ; Why this far from both the top and bottom of the stack?
EBP-74   > CCCCCC00  .ÌÌÌ
EBP-70   > CCCCCCCC  ÌÌÌÌ
EBP-6C   > CCCCCCCC  ÌÌÌÌ

和...

EBP-14   > CCCCCCCC  ÌÌÌÌ
EBP-10   > CCCCCCCC  ÌÌÌÌ
EBP-C    > 00000000  ....  ; Why here?
EBP-8    > CCCCCCCC  ÌÌÌÌ
EBP-4    > 7EA7D069  iЧ~  ; I think this is some stack cookie stuff.
EBP ==>  >/0017FEA8  ¨þ.   ; Saved EBP.

授予 1 和 0 dwords 存储在这里是因为一些 if 语句,但我只是想知道为什么它们被放置在它们所在的位置。如果它背后有任何逻辑。

谢谢你。

4

2 回答 2

26

当您使用 /RTC 选项时,您只会看到 MSVC 编译器生成的代码。启用运行时检查,在调试版本中默认打开。值 0xcccccccc 很神奇,当你使用未初始化的指针时,它非常擅长使你的程序崩溃。或者生成一个奇怪的int值。或者当你的代码崩溃并开始像代码一样执行数据时崩溃。0xcc 是 INT 3 的 x86 指令,它调用调试器中断。

“为什么这个地方”是您从 /RTC 获得的诊断的一部分。它使编译器在局部变量之间分配额外的空间。充满了神奇的价值。这使得诊断缓冲区溢出导致的堆栈损坏变得非常简单,它只需要检查函数返回时魔术值是否仍然存在。

于 2013-07-14T23:32:02.727 回答
3

我不能代表 Visual Studio,但我编写的某些环境故意用预定值(例如 0xcccccccc)填充堆栈。这样做是为了可以扫描堆栈(从底部开始)以确定有多少尚未使用。在内存量可能相当有限的嵌入式系统上,这在开发过程中非常有用,因此可以优化内存使用。

希望这可以帮助。

于 2013-07-14T22:37:29.500 回答