main 蹂躙

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;
なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h