0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C言語 何故main に戻らない?スタック上の戻り先を改変する実験 main→func1→func2

Last updated at Posted at 2025-04-23

func1戻り先のアドレスを知る

使用したサイト

C言語ソース

image.png

アセンブリソース

左側に各命令のアドレスが表示されている
image.png
image.png

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

image.png
image.png

実行結果.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++』 清華大学出版社.

0
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?