堆栈上的内存分配

逆向工程 部件 记忆 堆栈变量
2021-06-13 13:35:01

这是从一个简单的程序逆向工程的示例函数:

main            proc near
var_70          = dword ptr -70h
var_6C          = dword ptr -6Ch
var_68          = dword ptr -68h
i_2             = dword ptr -54h
i               = dword ptr -4
push    ebp
mov     ebp, esp
and     esp, 0FFFFFFF0h
sub     esp, 70h
mov     [esp+70h+i], 0
jmp     short loc_804840A
loc_80483F7:
mov     eax, [esp+70h+i]
mov     edx, [esp+70h+i]
add     edx, edx
mov     [esp+eax*4+70h+i_2], edx
add     [esp+70h+i], 1
loc_804840A:
cmp     [esp+70h+i], 13h
jle     short loc_80483F7
mov     [esp+70h+i], 0
jmp     short loc_8048441
loc_804841B:
mov    eax, [esp+70h+i]
mov    edx, [esp+eax*4+70h+i_2]
mov    eax, offset aADD ; "a[%d]=%d\n"
mov    [esp+70h+var_68], edx
mov    edx, [esp+70h+i]
mov    [esp+70h+var_6C], edx
mov    [esp+70h+var_70], eax
call   _printf
add    [esp+70h+i], 1
loc_8048441:
cmp    [esp+70h+i], 13h
jle     short loc_804841B
mov    eax, 0
leave 
retn
main   endp

C code

#include <stdio.h>
int main() {
    int a[20];
    int i;
    for (i=0; i<20; i++)
        a[i]=i*2;
    for (i=0; i<20; i++)
        printf ("a[%d]=%d\n", i, a[i]);
    return 0;
}

我的问题是:

  1. 为什么内存没有连续分配,为什么内存的某些部分介于两者之间esp + 70h -54h并且esp + 70h -68h没有使用?

  2. 在 中sub esp, 70h,这个数字70h在不同的程序中似乎是一个随机数,而且通常比我们需要的要大。为什么编译器不只分配我们需要的东西?

1个回答

在您的情况下,因为int是 4 个字节并且您需要 20 个元素

int a[20] // --> 20 * 4 = 0x50

所以ii_2 很正常

另一件事是您的编译器没有将printf参数压入堆栈。它预先分配了堆栈位置

var_70 = dword ptr -70h
var_6C = dword ptr -6Ch
var_68 = dword ptr -68h

并像这样调用函数

mov    edx, [esp+eax*4+70h+i_2]
mov    eax, offset aADD ; "a[%d]=%d\n"
mov    [esp+70h+var_68], edx
mov    edx, [esp+70h+i]
mov    [esp+70h+var_6C], edx
mov    [esp+70h+var_70], eax
call   _printf

但是这种事情有两个原因(不是你的情况)......

  1. 出于性能原因和缓存的易用性,编译器对齐缓冲区。此外,未对齐的缓冲区在某些情况下会导致失败,例如 Windows API 调用并使调试变得困难,因此编译器会对齐每个缓冲区以避免此类失败。

  2. 一些安全编译在缓冲区后分配随机数以防止成功利用缓冲区溢出。例如:

    和 esp, 0FFFFFFF0h


是的!正如@DCoder 评论的那样,你之前在这里过。