Tôi đã cố gắng bỏ qua hướng dẫn bằng cách thay đổi địa chỉ trả lại thông qua ngăn xếp đập. Đoạn mã sau bỏ qua một ++ trong chính và in một đầu ra của "1 3". Tôi đã thực thi mã này trên máy intel 32 bit.Bỏ qua hướng dẫn sử dụng ngăn xếp đập
#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);
}
Tôi không thể hiểu tại sao địa chỉ trả lại được lưu trữ ở mức dịch chuyển 24 byte từ địa chỉ bắt đầu của buf. Tôi đã thử thực hiện cùng một mã trên một máy intel 32-bit khác nhau và tôi đã phải sử dụng một chuyển 20 byte thay vì 24 byte. Tôi đã đặt sự hiểu biết của tôi trong hình dưới đây. Tôi không chắc chắn về những gì lấp đầy khoảng cách được đại diện bởi "?" trong hình. Gcc có đặt bất kỳ giá trị canary nào hay tôi đang thiếu thứ gì đó?
Liên kết đến hình: http://www.cse.iitb.ac.in/~shashankr/stack.png
Smashing the stack example3.c confusion hỏi những câu hỏi tương tự, nhưng không thể giải thích lý do của việc dịch chuyển nói chung.
Hình dưới đây cho biết chế độ xem của ngăn xếp thu được bằng cách đặt điểm ngắt trong chức năng.
stack content http://www.cse.iitb.ac.in/~shashankr/stack4.png
Sau đây là mã lắp ráp cho vui chính và:
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
Xin lưu ý rằng tôi đã tìm ra giá trị 24 bằng thử và sai. Ngoài ra, giá trị 5 thông qua gdb tháo gỡ chức năng chính. – shashank
Biến 'p' cũng phải nằm trên ngăn xếp, vì vậy bạn có thể thêm 4 byte vào đó, tôi tin. Tôi không chắc phần còn lại đến từ đâu. –
Nhìn lại nó cũng có khả năng là các đối số 'a' và' b' không bao giờ bị loại bỏ khỏi ngăn xếp vì lý do hiệu quả, do đó chiếm phần còn lại của bộ nhớ. –