PHPをハックしよう(第二回)

2014-10-22 00:00:00 +0000

PHPのopcodeをいじってPHPの実行環境を別言語から使えるように改造していく連載の第二回目です。

PHP嫌いのハッカーがPHPをハックする連載の第二回目です。 前回はこちら

前回見つけた、opdumperというPHP拡張でopcodeをdumpしてみましょう。

foo.phpとして以下の内容のファイルを作成します。

<?php

function f($a, $b) {
    return $a + $b;
}

echo f(1,2);

このファイルのopcodeをdumpしてみましょう。

$ php -d opdumper.active=1 foo.php
line: 3
opcode: ZEND_NOP
op1_type: UNUSED
op2_type: UNUSED
result_type: UNUSED
op1: UNUSED
op2: UNUSED
result: UNUSED
==============================
line: 7
opcode: ZEND_SEND_VAL
op1_type: CONST
op2_type: UNUSED
result_type: UNUSED
op1: 1
op2: UNUSED
result: UNUSED
==============================
line: 7
opcode: ZEND_SEND_VAL
op1_type: CONST
op2_type: UNUSED
result_type: UNUSED
op1: 2
op2: UNUSED
result: UNUSED
==============================
line: 7
opcode: ZEND_DO_FCALL
op1_type: CONST
op2_type: UNUSED
result_type: VAR
op1: f
op2: UNUSED
result: $4294967264
==============================
line: 7
opcode: ZEND_ECHO
op1_type: VAR
op2_type: UNUSED
result_type: UNUSED
op1: $4294967264
op2: UNUSED
result: UNUSED
==============================
line: 8
opcode: ZEND_RETURN
op1_type: CONST
op2_type: UNUSED
result_type: UNUSED
op1: 1
op2: UNUSED
result: UNUSED
$

ちなみに、失敗する場合にはPHP拡張が読み込めていない可能性があります。 その場合にはphp.iniextension=opdumper.soを追加するなどしてみてください。

opcodeとソースを見比べるとなんとなくわかりますね。 ZEND_SEND_VALで関数の引数をスタックに積んで、ZEND_DO_FCALLで関数を呼び出しているのがわかります。 で、その結果をZEND_ECHOで出力しています。

しかしですね、関数fの定義のopcodeが見当たらない。。。 調べてみると、PHPのコンパイラはtwo-passのコンパイラ、つまり2回ソースをスキャンするタイプのコンパイラなんです。 1回目で関数の宣言とかそういうのをスキャンして、2回目で実際の関数の呼び出しのopcodeを生成しているようです。 つまり、この出力されているのは2回目のスキャンの結果のようです。 1回目のスキャン結果のopcodeはどうやって取得すればよいのやら。。。 どうやらPHPのソースをハックする必要がありそうです。 なんか深みにはまりそうな予感。。。

続きは次回。

関連する記事

将棋DB2
プロ棋士からコンピューター将棋の棋譜まで観られる将棋の棋譜サービス
将棋DB iOS
将棋DB2のiOSアプリ
将棋DB Android
将棋DB2のAndroidアプリ
碁DB
プロ棋士からコンピューター囲碁の棋譜まで観られる囲碁の棋譜サービス