それSP戻せばできるよ(仮)

shinhさんの「ふとイヤなコードを思いつきました」インスパイヤされてみました。

...といいたいところなのですがあまりよいものはできず。

// なかなかポータブルなハローワールド
main() {
  char     _[0x40000000];
  char    __[0x40000000];
  char   ___[0x40000000];
  char  ____[0x3fffff60];
  char _____[0x00000091];
  return puts(*(char**)_____ + 2);
}

環境及び実行結果:

% uname -a
Linux localhost.localdomain 2.6.17-1.2174_FC5 #1 Tue Aug 8 15:30:55 EDT 2006 i686 athlon i386 GNU/Linux
% gcc -v
Target: i386-redhat-linux
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)

% gcc hello.c -o 'hello world!'
% ./hello\ world\!
hello world!
%

まず、引数ナシまたは2引数で呼ぶというネタが一部で確立している気がするputs関数を普通に1引数で呼んでいる時点で敗北しています。最後のサイズ0x91な変数をとっぱらえば引数ナシで呼べそうなものなんですが、自動変数の合計サイズが1GB(多分)をこえていると、gcc様が "error: total size of local objects too large" という見慣れない文句をつけてくるので、ダミーの変数を置き合計サイズが4GBを超えるようにして(size_tな値がwrap aroundするようにして)やらないとだめなのでした。


配列____[]を直接argv[0]の指し先に重ねてしまう方法もありますが、それだとスタック開始位置のランダム化を切らないとだめなんで、とりあえずargv[0]そのものを使うようにしてみたのは多少工夫した点ではあります(がちょっとなー)。なお上記コード、x86_64なgcc-4.1.1でgcc -m32でコンパイルしたらICEしました。なんで。


うーん。内容には関係ありませんが、シゴトで消防士に任命されて焼け死にそうな為、即座にテキトーな事を書けないのも無念。