2011-02-16 3 views
3

Je mène des recherches déversoirs tampons (sur l'architecture IA32) et je voudrais préciser une chose en particulier avec cet exemple programme:Stack Overflow - Tampon emplacement en mémoire

int main(int argc, char **argv) { 
    char array[512]; 
    if(argc > 1) 
    strcpy(array, argv[1]); 
} 

Je suivais le ebp, inscrivez-vous esp changement au cours de l'exécution du code d'assemblage: Dump de code assembleur pour fonction principale:

0x080483c4 <+0>:  push ebp 
    0x080483c5 <+1>:  mov ebp,esp 
    0x080483c7 <+3>:  sub esp,0x208 
    0x080483cd <+9>:  cmp DWORD PTR [ebp+0x8],0x1 
    0x080483d1 <+13>: jle 0x80483ed <main+41> 
    0x080483d3 <+15>: mov eax,DWORD PTR [ebp+0xc] 
    0x080483d6 <+18>: add eax,0x4 
    0x080483d9 <+21>: mov eax,DWORD PTR [eax] 
    0x080483db <+23>: mov DWORD PTR [esp+0x4],eax 
    0x080483df <+27>: lea eax,[ebp-0x200] 
    0x080483e5 <+33>: mov DWORD PTR [esp],eax 
    0x080483e8 <+36>: call 0x80482f4 <[email protected]> 
    0x080483ed <+41>: leave 
    0x080483ee <+42>: ret 

l'esp, les valeurs de registre ebp étaient les suivants:

program start 
    esp: 0xbffff24c 
    ebp: 0xbffff2c8 

push ebp 
    esp: 0xbffff248 
    ebp: 0xbffff2c8 

mov ebp,esp 
    esp: 0xbffff248 
    ebp: 0xbffff248 

sub esp,0x208 
    esp: 0xbffff040 
    ebp: 0xbffff248 

strcpy call (ebp is overwritten) 
    esp: 0xbffff250 
    ebp: 0x41414141 

lorsque j'ai entré 520 caractères «a», ce qui a entraîné EBP, EIP survolé. Et la mémoire ressemble à ceci:

Lower Memory Addresses 
0xbffff070:  0xbffff078  0xbffff492  0xaaaaaaaa  0xaaaaaaaa 
0xbffff080:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
0xbffff090:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
0xbffff0a0:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
0xbffff0b0:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
... 
0xbffff270:  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa  0xaaaaaaaa 
Higher Memory Addresses 

La chose qui me intéresse est: Pourquoi tampon commence à l'adresse 0xbffff078, si l'ESP pointe à l'adresse 0xbffff040 (lorsque la place variable locale - tampon - est réservé sur la empiler). Le tampon aurait dû être enregistré à l'adresse 0xbffff040. Quelqu'un peut-il expliquer pourquoi ce n'est pas?

+0

Comment vos caractères ''a'' se sont-ils transformés en' 0xaaaaaaaa'? Est-ce que vous nous montrez le programme entier? –

+0

Etes-vous sûr que l'adresse de 'array' était 0xbffff078, pas 0xbffff048? Peut-être que l'postlude de 'strcpy' a essayé de faire des choses de pile qui ont écrasé les 8 octets à 0xbffff070? – aschepler

+0

La mémoire est-elle vidée de la même invocation du programme que la trace du registre? – aaz

Répondre

5

Le compilateur a décidé d'allouer de l'espace à la fois pour la variable locale et les paramètres passés à strcpy() sur la pile en même temps.

sub esp,0x208    # 0x200 for array, 8 for 2 pointers 
... 
mov DWORD PTR [esp+0x4],eax # argv[1], not push 
mov DWORD PTR [esp],eax  # array 

Ainsi, le tableau est en fait à esp+8 (ou ebp-0x200, comme le compilateur y fait référence).

Edit:
esp est différent entre les invocations du programme, notamment en fonction du nombre d'arguments. 0xbffff040 ou 0xbffff070. Le tampon est à 0xbffff048, pas à 0xbffff040. Ou au 0xbffff078, et non 0xbffff070. Demandez au débogueur où il doit vérifier.

Dans le vidage de la mémoire, le tampon a 0xaa (je suppose qu'il s'agit d'une mémoire non initialisée avant l'appel). En face de cela, vous pouvez voir les deux pointeurs qui sont passés à strcpy().

+0

Oui, je fais une erreur, c'est 0xbffff048, mais cela n'explique toujours pas pourquoi il est à 0xbffff078 et pas à 0xbffff048, où il aurait dû l'être (parce que l'espace libre sur la pile lui était réservé). – eleanor

+0

J'ai deviné qu'avant de faire le vidage de la mémoire, vous avez redémarré le programme sans arguments. Ainsi, le cadre de la pile est plus haut et le tampon est rempli de '0xaa' au lieu de' 0x41' ("a"). Est-ce le cas? – aaz

Questions connexes