スタックスマッシングによってリターンアドレスを変更して、命令をスキップしようとしています。次のコードは、メインのa ++をスキップし、「13」の出力を出力します。このコードを32ビットのIntelマシンで実行しました。
#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);
}
bufの開始アドレスから24バイトの変位でリターンアドレスが格納される理由がわかりません。別の32ビットIntelマシンで同じコードを実行しようとしましたが、24バイトではなく20バイトの変位を使用する必要がありました。私は次の図に私の理解を入れました。「?」で表されるギャップを何が埋めているのかわかりません。図では。gccはカナリアの値をそこに入れますか、それとも何かが足りませんか?
図へのリンク:http ://www.cse.iitb.ac.in/~shashankr/stack.png
スタックexample3.cの混乱を壊すことは同じ質問をしましたが、一般的に変位の理由を説明することができませんでした。
次の図は、関数にブレークポイントを配置することによって取得されたスタックを示しています。
(出典:www.cse.iitb.ac.inのshashankr)
以下は、mainとfunのアセンブリコードです。
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 <__stack_chk_fail@plt>
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 <printf@plt>
0x080484c5 <+84>: leave
0x080484c6 <+85>: ret