実行回数を記憶している実行ファイル

http://d.hatena.ne.jp/alohakun/20061113

を見てて、騙されてはいけない! id:yupo5656 さんは僕らの自由を奪う詐欺師だっ…とか思ったので適当に。

ELFヘッダは e_ident という 16Byte のメンバから始まっています。ここは magic を記録する場所です。 magic については Binary Hacks #4 見てね☆とかそんな感じで。

でまぁ、最初の 4Byte 、 "\x7fELF" までは、無いと動きませんし、しぶしぶつけるわけですが、残りの 12Byte は "Hello world\n" を埋めるための空間です…と思ってたらなんか プロゴルファーは実行コード埋めてた というようなのが今までの粗すぎる粗筋なのですが、たしか高林さんがファイルのパーミッションか時刻情報あたりでカウンタ実現してたなぁ(でもURL見つからないなぁ)ということを思い出して、実行回数を自分自身の magic に記録する実行ファイルを作ってみました。

i@u ~/wrk/binhacks> gcc counter.c
i@u ~/wrk/binhacks> ./a.out
1
i@u ~/wrk/binhacks> ./a.out
2
i@u ~/wrk/binhacks> readelf -h a.out | head -2
ELF ヘッダ:
  マジック:   7f 45 4c 46 01 01 01 00 02 00 00 00 00 00 00 00
i@u ~/wrk/binhacks> for i in {0..999}; do; ./a.out >& /dev/null; done
i@u ~/wrk/binhacks> readelf -h a.out | head -2
ELF ヘッダ:
  マジック:   7f 45 4c 46 01 01 01 00 ea 03 00 00 00 00 00 00
i@u ~/wrk/binhacks> ./a.out
1003

こんな感じ。 12Byte もあるわけですがうち 8Byte を使って 64bit カウンタにしてあります。そう簡単にカンストしません。

でまぁ、そんな ELF Golf がどうとかそういう話を SEA & FSIJ 合同フォーラム というところで話すみたいです。目下の課題はスライド作ってみたら多すぎたこと。 58Byte の Hello world! を 12枚のスライドを使って語るような、そんな感じのヒドい状態になる予定です。というか最初から最後まで Hello world! の話なような。

あ、最後にコード。別にどうでもいいけど。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    long long *valp;
    FILE *fp;
    char *tmp, *buf;
    long len;

    fp = fopen(argv[0], "r");
    fseek(fp, 0, SEEK_END);
    len = ftell(fp);
    buf = (char *)malloc(len);
    fseek(fp, 0, SEEK_SET);
    fread(buf, 1, len, fp);
    fclose(fp);

    valp = (long long *)(buf+8);
    (*valp)++;

    tmp = "counter.tmp";
    fp = fopen(tmp, "w");
    fwrite(buf, 1, len, fp);
    fclose(fp);

    chmod(tmp, 0755);
    rename(tmp, argv[0]);

    printf("%lld\n", *valp);
    return 0;
}
なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h