「実行中のプロセスのパス名をチェックする」の話
http://d.hatena.ne.jp/y-hamigaki/20061116#1163680455
で実行時にファイルを移動した場合について調べてくださっています。 (deleted) がつくのが面白いです。これ、以前見たことはある気がしますが、いつだったか覚えてない…
p_flags とか
そういえば昨日は喋った後で kik さんに間違ってるところ無いですか?と聞いて、 write が失敗したら EAX が -1 になっちゃって落ちるんだよ、という話と、 p_flags は下 3bit が 3 か 6 か 7 にしなきゃならんという話を補足してもらいました。後者は苦労するのはわかってたけど、 exit のあとは地味気味なので、説明しなくてもまぁいいかなぁと省略してしまったのでした。スライドだけ見るとそれ書いてないので一応補足をここで。 p_flags はロードするメモリ領域の rwx を指定するわけですが、ヘッダを通ってる最中に EAX 付近をいじってしまうので w が必須で、あと r か x が必要だと思います。で、 p_flags のある位置には "o" があるのですが、これは
irb(main):004:0> "%b"%?o => "1101111"
とのことですから全 bit 立ってますね。
irb とか
irb はバイナリどうこうするツールとして便利…というような話をスライド中の
irb(main):020:0> [0x00210001^0x6C4D6549].pack"L" => "Hell"
の部分で少ししたのですが、もっと色々できるように、ということでとりあえず機械語を命令に変換できるように .irbrc になんか書きました。
require 'tempfile' def disasm(b, arch = 'i386') tmp = Tempfile.new('irb_disasm', '/tmp') if b.class == Array tmp.print(b.pack("C*")) else raise "type mismatch (#{b.class})" end tmp.close print `objdump -m #{arch} -b binary -D #{tmp.path}` nil end
例えば別に push で fall through せんでもいい、と言った e_type, e_machine あたりは逆アセすると、
irb(main):001:0> disasm([2,0,3,0]) /tmp/irb_disasm18351.0: ファイル形式 binary セクション .data の逆アセンブル: 0000000000000000 <.data>: 0: 02 00 add (%eax),%al 2: 03 00 add (%eax),%eax => nil
って感じみたいです。 EAX はどうせ後で 4 入れますしいじっても問題ない、という。
56B の ELF quine
kik さんが簡単だとおっしゃってたので書いてみました。
i@u ~/wrk/binhacks> ls -l quine_small -rwxr-xr-x 1 i i 56 2006-11-16 22:41 quine_small* i@u ~/wrk/binhacks> diff =(./quine_small) ./quine_small i@u ~/wrk/binhacks>
すごそうに見えますが、実はこれは簡単すぎてつまらない…
mov al, 4 ; write = 4 inc ebx ; stdout = 1 mov dl, filesize ; strlen int 0x80 xchg eax, ebx ; exit = 1 xchg ebx, ecx ; exit(0) int 0x80
みたいなコードを magic の下に埋めてやれば 58B => 56B に簡単にできます。命令的にはスカスカですが、 56B がヘッダの位置的にバイナリサイズの限界です。
一応もっと深く ELF ヘッダとプログラムヘッダを重ねるのを検討したのですが、どうにも無理だと私は判断。一応実行開始までいけるパターンはあるんですが。
えーと
他にもなんかあった気がするけど忘れた…
a.out で 63Byte Hello, world!
a.out だったら小さくなるかも、って質問に答えたんですが、 a.out ってファイル内オフセットを指定できないから、ヘッダの空間使えないみたいで、たぶんこんなくらいで限界ぽいというかつまらない…
i@u ~/wrk/binhacks> ls -l hello_aout -rwxr-xr-x 1 i i 63 2006-11-17 05:05 hello_aout* i@u ~/wrk/binhacks> file hello_aout hello_aout: Linux/i386 pure executable (NMAGIC), stripped i@u ~/wrk/binhacks> ./hello_aout Hello, world!
まぁ、 ELF の 58B の方が短いというのは非常にすごいということが再確認できます。
BITS 32 ORG 0 dw 0x108 ; magic db 100 ; 386 db 0 dd textsz dd 0 dd 0 dd 0 dd entry - text dd 0 dd 0 text: db "Hello, world!", 10 entry: lea ebx, [eax+1] xor ecx, ecx lea edx, [eax+14] mov al, 4 int 0x80 mov al, 1 dec ebx int 0x80 textsz equ $ - text
ヘッダ 32B で Hello が 14B で実行コードが 17B 。いくつかどうでもいい知識が身につきました。だいたい a.out なんて私が Linux 触りはじめた時には駆逐されてたしなぁ…