75B ELF @ FreeBSD

昨日は b2con でした。発表者の皆さんおつかれさまでした。とても楽しかったです。

dankogaiさんFreeBSD で ELF ゴルフは制約が多いと教えてくださったのでやってみました。確かに制約は厳しい感じでした。 75Byte 。

http://shinh.skr.jp/binary/hello_freebsd4.asm

環境は以下の通り。要するにさくらサバ。

hamaji@www491 ~> uname -srm
FreeBSD 4.10-RELEASE-p24r1 i386

適当に説明と備忘。

BITS 32
        org     0x00000000
        db      0x7F            ; e_ident
        db      "ELF"
; ここが必須になっている。
; 32bit(1), 2の補数リトルエンディアン(1), ELFバージョン(1), FreeBSD(9)
; 余計なことをっ…と思うけど、 OS のタイプ識別とかちゃんと
; してるからエミュレーションが動くって話らしいのでしょうがない。
        db      1,1,1,9
; ここのコードは _start の後で見てね
code:
; なんでもいいから一つ push する呼び出し規約らしい
; ここでは次に備えて 0 を push している
        push    EBX
; write システムコール発行
        int     0x80
; AL を 1 にして exit システムコールを指定
        mov     AL, 1
; なんでもいいから push しておく
        push    EAX
; exit システムコール発行
; ここで、さっき次の備えて 0 を push したので exit(0) になる
        int     0x80
        dw      2               ; e_type
        dw      3               ; e_machine
; e_version は Linux と違って必須
        dd      1               ; e_version
        dd      _start          ; e_entry
        dd      phdr - $$       ; e_phoff
; この位置でのオーバーラップは Linux では不可能
phdr:   dd      1               ; e_shoff, p_type
        dd      0               ; e_flags, p_offset
; FreeBSD では e_phentsize が 32 じゃなくて良いみたい
; Linux だとここがひっかかるのでこのオーバーラップはできない
        dd      $$              ; e_ehsize, p_vaddr
                                ; e_phentsize
        dw      1               ; e_phnum, p_paddr
; ゆとり
        dw      42
        dd      filesize        ; e_shentsize, p_filesz
                                ; e_shnum
_start:
; strlen("Hello world!\n")
        push    byte 13
; 空いた 1B で 1 の入ってるレジスタを作っておく
        inc     ESI
; 以下の2命令は add AL, 4 でもある。
; EAX に 4 を指定して write システムコールを選択している
; また、 p_memsz のこの位置は大きな値だとメモリがあふれる
; また、 p_flags のこの位置は 3bit 目が立っていないといけない
        db      4               ; e_shstrndx, p_memsz
        db      4               ; p_flags
; "Hello world!\n" を push
        push    byte hello
; さっき用意した 1 を push
; 用意してあったおかげで 1B で push できる
        push    ESI
; 上に行く。 short code と書きたかったという話が
        jmp short code
; 他に適切な置き場が見当たらず
; e_ident は FreeBSD だと 8B しか無いし、
; p_memsz と重なるとメモリがあふれる。
hello:  db      "Hello world!", 10
filesize equ    $ - $$

それなりに考えたけどそれなりなので、まだしぼれるかも。上から走るパターンとか他のパターンだと、どうも p_memsz と p_flags の部分をもてあます感じ。

あと他環境でも動くかは知りません。今度確認しようと思います。

なんか微妙かなぁと思ったけど asm のシンタクスハイライト使てみた。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h