http://d.hatena.ne.jp/yupo5656/20060828/p1
素敵なのでマネしてみます。
色々常識が足りないけど、一応 main は呼んであげる。
main; __attribute__((constructor, destructor)) static x() { if (main) puts("world!"); else puts("hello", main = 195); }
実行時に急造された上に world 起き場になる main。
main[30]; __attribute__((constructor)) static x() { if (main[0]) { main[0] = 0x6c726f77; main[1] = 0x0a2164; __asm__("movl $1, %%ebx \n" "movl %0, %%ecx \n" "movl $7, %%edx \n" "movl $4, %%eax \n" "int $0x80 \n" :: "r"(main)); } else { puts("hello"); memcpy(main, x, 120); } }
hello に到達しない。 main を .data セクションに置けば main の自己書き換えが容易に。
__attribute__((section (".data"))) main() { unsigned char *p = main; while (*p / 2 != 116) p++; *p++ = 0xb8; *p++ = 1; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0xcd; *p++ = 0x80; puts("hello world!"); }
こっちの方がはるかにラクか…
__attribute__((section (".data"))) main() { unsigned char *p = &&h; *p++ = 0xb8; *p++ = 1; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0xcd; *p++ = 0x80; h: puts("hello world!"); }
追記: 元リンクの追記がまた面白い!最初、え、なんでわざわざ .text に置くんだ?と。もう私ではちょっと解読しないとすぐにはわからないです。ちなみに手元では GCC3 系では hello hello になる模様。そっちの方がコンパイラの気持ちとしてはわかる気もします。 inner-function を下に出してやれば hello world になりましたが、少しさみしいですね。あと思ったんですけどこういう遊びは RISC の方が面白げですね。
せっかくなのでもうひとつ。時代は C++ ですぞ。面倒なのでwoさんの丸パクリ。
struct _ { int a, b, c, d, e, f, g, h, i; _() : a(0x0a2e6f68), b(0x65486800), c(0xe1896c6c), d(0x4b8), e(0x1bb00), f(0x7ba0000), g(0xcd000000), h(0x8c48380), i(0x909090c3) {} }; _ main;