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;