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 のシンタクスハイライト使てみた。