2012-11-11 14 views
5

Yığın parçalama yoluyla dönüş adresini değiştirerek bir talimatı atlamaya çalışıyorum. Aşağıdaki kod bir ++ değerini ana olarak atlar ve "1 3" çıkışını yazdırır. Bu kodu 32 bitlik bir intel makinede çalıştırdım.Yığın parçalamayı kullanarak bir talimatın atlanması

#include<stdio.h> 
void fun(int a,int b) { 
    // buffer 
    char buf[8]; 
    char *p; 
    p = (char *)buf+24; 
    *p=*p+5; 
    return; 
} 

int main() { 
    int a=1,b=2; 
    fun(a,b); 
    a++; 
    b++; 
    printf("%d %d",a,b); 
} 

ben iade adresi buf adresini başlatılmasını 24 bayt yer değiştirme saklanır anlamak kuramıyorum. Aynı kodu farklı bir 32 bitlik bir intel makinesinde çalıştırmayı denedim ve 24 bayt yerine 20 bayt deplasman kullanmak zorunda kaldım. Anlayışımı aşağıdaki şekilde koymuştum. "?" Ile temsil edilen boşluğu doldurduğundan emin değilim. Şekilde. Gcc herhangi bir kanarya değerini koydu mu yoksa bir şey mi özlüyorum? rakama

Bağlantı:

Smashing the stack example3.c confusionhttp://www.cse.iitb.ac.in/~shashankr/stack.png aynı soruyu sordu ama genel olarak yer değiştirme nedenini açıklamak olabilir.

Aşağıdaki şekil, işlevde bir kesme noktası yerleştirerek elde edilen yığının bir görünümünü vermektedir. Cevabın bir şey değildir inanıyoruz

Dump of assembler (fun): 
0x08048434 <+0>: push %ebp 
0x08048435 <+1>: mov %esp,%ebp 
0x08048437 <+3>: sub $0x18,%esp 
0x0804843a <+6>: mov %gs:0x14,%eax 
0x08048440 <+12>: mov %eax,-0xc(%ebp) 
0x08048443 <+15>: xor %eax,%eax 
0x08048445 <+17>: lea -0x14(%ebp),%eax 
0x08048448 <+20>: add $0x18,%eax 
0x0804844b <+23>: mov %eax,-0x18(%ebp) 
0x0804844e <+26>: mov -0x18(%ebp),%eax 
0x08048451 <+29>: movzbl (%eax),%eax 
0x08048454 <+32>: add $0x5,%eax 
0x08048457 <+35>: mov %eax,%edx 
0x08048459 <+37>: mov -0x18(%ebp),%eax 
0x0804845c <+40>: mov %dl,(%eax) 
0x0804845e <+42>: mov -0xc(%ebp),%eax 
0x08048461 <+45>: xor %gs:0x14,%eax 
0x08048468 <+52>: je  0x804846f <fun+59> 
0x0804846a <+54>: call 0x8048350 <[email protected]> 
0x0804846f <+59>: leave 
0x08048470 <+60>: ret  


Dump of assembler (main) 
0x08048471 <+0>: push %ebp 
0x08048472 <+1>: mov %esp,%ebp 
0x08048474 <+3>: and $0xfffffff0,%esp 
0x08048477 <+6>: sub $0x20,%esp 
0x0804847a <+9>: movl $0x1,0x18(%esp) 
0x08048482 <+17>: movl $0x2,0x1c(%esp) 
0x0804848a <+25>: mov 0x1c(%esp),%eax 
0x0804848e <+29>: mov %eax,0x4(%esp) 
0x08048492 <+33>: mov 0x18(%esp),%eax 
0x08048496 <+37>: mov %eax,(%esp) 
0x08048499 <+40>: call 0x8048434 <fun> 
0x0804849e <+45>: addl $0x1,0x18(%esp) 
0x080484a3 <+50>: addl $0x1,0x1c(%esp) 
0x080484a8 <+55>: mov $0x80485a0,%eax 
0x080484ad <+60>: mov 0x1c(%esp),%edx 
0x080484b1 <+64>: mov %edx,0x8(%esp) 
0x080484b5 <+68>: mov 0x18(%esp),%edx 
0x080484b9 <+72>: mov %edx,0x4(%esp) 
0x080484bd <+76>: mov %eax,(%esp) 
0x080484c0 <+79>: call 0x8048340 <[email protected]> 
0x080484c5 <+84>: leave 
0x080484c6 <+85>: ret  
+0

Deneme ve hata ile değeri 24 anladım. Ayrıca, ana fonksiyonun 5 gdb demontajı ile değeri. – shashank

+0

'p' değişkeni yığında da olmalı, böylece 4 bayt ekleyebilirsiniz, inanıyorum. Kalanın nereden geldiğinden emin değilim. –

+0

Geriye doğru bakıldığında, 'a' ve 'b' argümanlarının hiçbir zaman verimlilik nedenleriyle yığından çıkarılmadığı, dolayısıyla hafızanın geri kalanını muhasebeleştirdiği de muhtemeldir. –

cevap

2

: Aşağıdaki

stack content http://www.cse.iitb.ac.in/~shashankr/stack4.png

ana ve eğlence için montaj kodudur. Farklı gcc sürümleri mi yaşıyorsunuz? Her neyse, bir derleyicinin gerekenden daha fazla bir yığın ayırmasına izin verilir. Belki de, değişkenlerin sayısına dayanan ancak herhangi bir değişkeni bir kayda taşımasına izin verilen optimizasyon aşamaları ile azaltılmayan ilk "tahmin" dir. Veya alt rutinin ihtiyaç duyması durumunda ekx, ebp veya diğer yazmaçları saklamak için bir miktar rezervuardır. bir:

sorunu aşmak için bir sabit adres değişkeni zaten var. Dönüş adresi = & a [-1].

+0

Evet, makinelerin farklı gcc sürümleri var. Gcc'in yığında biraz fazla alan ayırma konusunda haklı olabilirsiniz. İkinci makinede aynı kodu çalıştırdığımda, yığın çerçevesinin boyutunun düştüğünü fark ettim. Ayrıca, ilk makinede kullanılan gcc'nin kanarya değeri olduğu için de olabilir. Arabellek taşması için bir strcpy yaptığımda, ilk makinede bir yığın şut hatası aldım.Bu ikinci makinede gcc eski sürümde olmadı ve belki de kanarya değeri kullanmadı. Ayrıca, adresin adresini kullanarak iade adresinin yerini bulmak için bir geçici çözüm önerdiğiniz için teşekkür ederiz. – shashank

İlgili konular