関数ポインタとmprotectを使って関数の領域を上書き2
http://d.hatena.ne.jp/kanbayashi/20081005/p1
とかやってみたついでに遊んでみる。
#includevoid hoge(){
printf("hoge\n");
}void bar(){
printf("bar\n");
}void main(){
bar();
}
こうすると当然
と出力されるわけだけど、ここでbar関数にhoge関数の中身をコピーして、出力される文字列を入れ替えちゃおう。
bar
下調べ
とりあえず、hoge関数とbar関数の中身をobdumpで調べる
objdump -d hoge_bar.out
08048414:
8048414: 55 push %ebp
8048415: 89 e5 mov %esp,%ebp
8048417: 83 ec 08 sub $0x8,%esp
=============================ココ==================================
804841a: c7 04 24 00 86 04 08 movl $0x8048600,(%esp)
===================================================================
8048421: e8 52 ff ff ff call 8048378
8048426: c9 leave
8048427: c3 ret08048428
:
8048428: 55 push %ebp
8048429: 89 e5 mov %esp,%ebp
804842b: 83 ec 08 sub $0x8,%esp
=============================ココ==================================
804842e: c7 04 24 05 86 04 08 movl $0x8048605,(%esp)
===================================================================
8048435: e8 3e ff ff ff call 8048378
804843a: c9 leave
804843b: c3 ret
ヒープにある文字列を取り出すコードは、
関数の先頭+6バイト目から始まる7バイトにあるみたいだから、そこをコピーしてあげればよさそう。
書いてみる
#include
#include
#includevoid hoge(){
printf("hoge\n");
}void bar(){
printf("bar\n");
}void main(){
void (*hoge_p)();
void (*bar_p)();
int *p;
unsigned int p_i;
int i;p = bar;
p_i = p;
/* mprotectに渡すアドレスはページ境界(4K)に合わせる */
p = p_i & 0xFFFFF000;
/* bar関数のマップされている領域を書き込み可能にする */
if(mprotect(p,0x1000,PROT_WRITE | PROT_EXEC) < 0){
perror("mprotect");
}/* 文字列のデータを持ってくるところのみコピー */
memcpy(bar_p+6,hoge_p+6,7);
printf("write succeeded\n");
/* さてどうなるかな */
bar();
}