[C]リターンアドレスの詐称
後で役に立つかもしれないからここにメモっておく。
gcc 4.1.2 + Linux kerner2.6 で動作確認済み。(Windows環境で動くかどうかは知りません。スタックの実装が違うと動かないかもしれない。)
追記: 調べたらスタックの実装はOSレベルじゃなくてCPUのアーキテクチャレベルで行われているらしいので、Winでも(x86 CPUなら)動くかと。
コード
#include <stdio.h>
#include <stdlib.h>
void test2(){
puts("Hello");
exit(1);
}
void test(int a){
*((&a)-1) = (int)test2;
return;
}
void main(){
test(1);
puts("test(1) has been returned.");
}
実行結果
Hello
説明
main関数からtest(1)を呼ぶ。
testでは、スタックに
リターンアドレス→1個目の引数
と積まれることを利用して、aのアドレスから1(&aは int* 型であるので、実際には4バイト)戻ったところにリターンアドレスが書いてあると予想し、
そこをtest2のアドレスに書き換える。
んでリターンすると、見事mainではなくtest2に飛んだ。
ちなみに、test2のexitをはずすとSegmentation Faultが発生した。
(test2にはリターンアドレスが設定されていないので、適当なアドレスにリターンしようとしてエラーを起こした?)
以上。