func1戻り先のアドレスを知る
使用したサイト
C言語ソース
アセンブリソース
func1のスタックフレーム
低アドレス | |
---|---|
・・・ | |
1 | mov QWORD PTR [rbp-0x10],0x1 |
2 | mov QWORD PTR [rbp-0x8],0x2 |
旧rbpの値 | push rbpによって代入された |
401166 | call func1()の次の命令のアドレス |
・・・ | |
高アドレス |
※上のスタック図は8バイト刻み
スタックにfunc1の戻り先アドレスが積まれていることを確認
スタック図をみるとa[1]の16バイト先に戻り先アドレスが入っている。
この仮説を基にa[3]の値をprintfで出力してみる。
void func1(){
long a[2];
a[0]=1;
a[1]=2;
printf("%lx",a[3]);
}
実行結果.bash
401176
このアドレスは「 mov eax,0x0」命令のアドレスと一致する。
つまりfunc1関数からは「 call 401126 」の次のアドレスに返るということである。
func1の戻りアドレスを別のアドレスに変更
compiler Explorer
実行結果.bash
ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 139
Program terminated with signal: SIGSEGV
compiler Explorer上では安全ではないと判断されたのかエラーを吐いた。
(参考にした本では同じようなコードでも動いていたが。。。)
ローカルgccで確認
test.c
#include<stdio.h>
void func2();
void func1(){
long a[2];
a[0]=1;
a[1]=2;
a[4] = (long)func2;
}
void func2(){
printf("func2");
}
int main(){
func1();
printf("main");
return 0;
}
gcc -fno-stack-protector -no-pie -O0 test.c -o test
実行結果.bash
func2
自分の仮説ではa[3]が戻りアドレスだと思っていたが、a[4]だったようだ。
スタックフレームがどうなっているのか分からない。
詳しい方がおられましたらご教示下さると幸いです。
参考文献
①阿布編程 (2023) 『CPU眼里的C/C++』 清華大学出版社.