VIP de Programming

   

気になった発言とか簡易まとめ
ある程度まとまったらwikiにうpしよう!
レス集

tags C 2008/01/24

[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にはリターンアドレスが設定されていないので、適当なアドレスにリターンしようとしてエラーを起こした?)

以上。

Permalink
Comments (View)
blog comments powered by Disqus