Zend_Op_Array php解密opcode

Modify by:MG193.7

My Blog

My Github

Base on vld document


Opcode nameExplanationExample (phpdbg)
NOPno operationNOP
ADDAdds "value1" to "value2" and stores the result into "result".ADD 1 2 ~0
$a = 1+2;
SUBSubtracts "value2" from "value1" and stores the result into "result".SUB 2 1 ~0
$a = 2-1;
MULMultiplys "value1" by "value2" and stores the result into "result".MUL 1 2 ~0
$a = 1*2;
DIVDivides "value1" by "value2" and stores the result into "result".DIV 6 3 ~0
$a = 6/3;
MODMakes the value of "result" congruent to "value1" modulo "value2".MOD 6 3 ~0
$a = 6%3;
SLShift bits of value1 to the left value2 steps (each step means "multiply by two")SL 8 2 ~0
$a = 8<<2;
SRShift bits of value1 to the right value2 steps (each step means "divide by two")SR 8 2 ~0
$a = 8>>2;
CONCATConcats string values string1 and string2CONCAT "A" "B" ~0
echo "A"."B";
BW_ORBit-wise or of value1 and value2BW_OR 1 2 ~0
echo 1|2;
BW_ANDBit-wise and of value1 and value2BW_AND 1 2 ~0
echo 1&2;
BW_XORBit-wise xor of value1 and value2BW_XOR 1 2 ~0
echo 1^2;
BW_NOTBit-wise not of "value"BW_NOT 15 ~0
echo ~15;
BOOL_NOTBoolean (logical) not of "value"BOOL_NOT 1 ~0
echo !1;
BOOL_XORBoolean (logical) xor of value1BOOL 1 2 ~0
echo 1 xor 2;
IS_IDENTICALCompares value1 and value2 to see if they are equal AND have the same typeIS_IDENTICAL 1 1 ~0
echo (1===1);
IS_NOT_IDENTICALcompares value1 and value2 to see if they are unequal or of different typesIS_NOT_IDENTICAL 1 1 ~0
echo (1!==1);
IS_EQUALcompares if value1 and value2 are equalIS_EQUAL 1 1 ~0
echo (1==1);
IS_NOT_EQUALcompares if value1 and value2 are not equalIS_NOT_EQUAL 1 1 ~0
echo (1!=1);
IS_SMALLERcompares if value1 is less than value2IS_SMALLER1 1 2 ~0
echo (1 < 2);
IS_SMALLER_OR_EQUALcompares if value1 is less than or equal to value2IS_SMALLER_OR_EQUAL 2 1 ~0
echo (2<=1);
CASTcasts value1 as type value2 (type in extended_value)CAST<4> 1 ~0
echo (int)1;
QM_ASSIGNQuestion Mark Assign, used twice inside a question mark assign to temporarily assign result as value1 (this is followed up with an ASSIGN bytecode)JMPZ 1 J3
QM_ASSIGN 1 ~0
JMP J4
QM_ASSIGN 2 ~0
ECHO ~0
echo (1?1:2);
ASSIGN_ADDAdd value1 to value2 and store in variable indicated by value1ASSIGN_ADD $a 2
$a+=2;
ASSIGN_SUBSubtract value1 from value2 and store in variable indicated by value1ASSIGN_SUB $a 2
$a-=2;
ASSIGN_MULMultiply result by value1 and store in variable indicated by resultASSIGN_MUL $a 2
$a*=2;
ASSIGN_DIVDivide result by value1and store in variable indicated by result.ASSIGN_DIV $a 2
$a/=2;
ASSIGN_MODPerform result mod value1 and store in variable indicated by resultASSIGN_MOD $a 2
$a%=2;
ASSIGN_SLShift result by value1 bits to left and store in variable indicated by resultASSIGN_SL $a 2
$a<<=2;
ASSIGN_SRShift result by value1 bits to right and store in variable indicated by resultASSIGN_SR $a 2
$a>>=2;
ASSIGN_CONCATConcats string values result and value1 and store in variable indicated by resultASSIGN_CONCAT $a 'z'
$a.='z';
ASSIGN_BW_ORPerforms binary OR on result and value1 and stores in variable indicated by result.ASSIGN_BW_OR $a 64
$a|=64;
ASSIGN_BW_ANDPerforms binary AND on result and value1 and stores in variable indicated by result.ASSIGN_BW_AND $a 64
$a &=64;
ASSIGN_BW_XORPerforms binary XOR on result and value1and stores in variable indicated by result.ASSIGN_BW_XOR $a 64
$a ^=64;
PRE_INCincrements variable indicated by value1 by 1 (before performing other operations) and stores in resultPRE_INC $a
++$a;
PRE_DECdecrements variable indicated by value1 by 1 (before performing other operations) and stores in resultsPRE_DEC $a
--$a;
POST_INCincrements variable indicated by value1 by 1 (after performing other operations) and stores in resultPOST_INC $a ~0
$a++;
POST_DECdecrements variable indicated by value1 by 1 (after performing other operations) and stores in resultPOST_DEC $a ~0
$a--;
ASSIGNassigns value1 to resultASSIGN $a $b
$a=$b;
ASSIGN_REFUNKNOW in phpdbg.
Maybe you could refer to ASSIGN_REF
UNKNOW
ECHODump textECHO "hello world"
echo "hello world";
PRINTSame as ECHO?ECHO<1> "hello world"
print 'hello world';
If you want to refer the opcodes in vld,
you could see PRINT
JMPUnconditonally jump to the address#0 IS_EQUAL $a "a" ~0
#1 JMPZ ~0 J4
#2 ECHO 1
#3 JMP J5
#4 ECHO 2
#5 RETURN<-1> 1

if($a=="a"){echo 1;}else{echo 2;}
JMPZJump to the address if the value is zeroYou could see the opcodes in JMP
JMPNZJump to the address if the value is not zero...
JMPNZ ~0 JX
...

if($b!=0){...}
JMPZNZJump to the address given in the operands if the value is zero;
jump to the address given in extended data if nonzero.
UNKNOW in phpdbg
You could refer to JMPZNZ
JMPZ_EXJump to the address if the value is zero.#0 JMPZ_EX $a J2 ~0
#1 BOOL true ~0
#2 JMPZ ~0
#3 RETURN<-1> 1

if($a&&true){}
JMPNZ_EXJump to the address if the value is not zero.#0 JMPZ_EX $a J2 ~0
#1 BOOL true ~0
#2 JMPZ ~0
#3 RETURN<-1> 1

if($a||true){}
CASEUNKNOWDo not found CASE opcode in phpdbg,
You could refer to CASE
SWITCH_FREERelease the allocated space of "value"?Do not found SWITCH_FREE in phpdbg,
You could refer to SWITCH_FREE
BRKIt means "break" in vld,
But not found this opcode in phpdbg.
If you want to break in while-loop(or something else),phpdbg will simply use JMP opcode jump out the loop,instead of use "BRK" opcode.
#0 JMP J2
#1 JMP J3
#2 JMPNZ 1 J1
#3 RETURN<-1> 1

while(1){break;}
You also could see BRK
CONTSame as BRK opcode,
this opcode means "continue" in vld,
But not found this opcode in phpdbg.
phpdbg still use JMP to control the flow in loop.
You could refer to CONT
BOOLconvert value to boolean and store in result#0 JMPZ_EX $a J2 ~0
#1 BOOL true ~0
#2 JMPZ ~0
#3 RETURN<-1> 1

if($a&&true){}
ROPE_INITwhen create a string that cotains variable,
this opcode used to init this string and store the string of begining part to result
ROPE_INIT<3> "Test" ~1
ROPE_ADD<1> ~1 $a ~1
ROPE_END<2> ~1 " Test" ~0
ECHO ~0

echo "Test$a Test";
ROPE_ADDafter ROPE_INIT opcode,continue add a variable to string,and store the string to result.Could see ROPE_INIT part
ROPE_ENDafter ROPE_INIT opcode,continue add a string to the whole string,and treat the string just added as the end of the whole string.Could see ROPE_INIT part
FAST_CONCATconcats value1 and value2,than stored it to the resultFAST_CONCAT "Test" $a ~0
ECHO ~0

echo "Test$a";
BEGIN_SILENCEprepare to perform function call without displaying error messagesBEGIN_SILENCE ~0
INIT_FCALL<1> 96 "file"
SEND_VAL"non_existent_file" 1
DO_ICALL @1
END_SILENCE ~0
ASSIGN $a @1
RETURN<-1> 1

$a = @file("non_existent_file");
END_SILENCEno longer surpress error messagesSee BEGIN_SILENCE part
INIT_FCALLinit a function going to callINIT_FCALL<1> 96 "abs"
SEND_VAL 2 1
DO_ICALL

abs(2);
INIT_DYNAMIC_CALLcall to function dynamiclyASSIGN $x "phpinfo"
INIT_DYNAMIC_CALL $x
DO_FCALL

$x = 'phpinfo';
$x();
INIT_FCALL_BY_NAMEcall to functionINIT_FCALL_BY_NAME "test"
DO_FCALL @1
ASSIGN $a @1

$a = test();
DO_FCALLCall a function.
If the result of called function was stored to a variable,this opcode must take a result!
See INIT_DYNAMIC_CALL and INIT_FCALL_BY_NAME part
DO_FCALL_BY_NAMECall a function by name.UNKNOW in phpdbg,
You could see DO_FCALL_BY_NAME
RETURNReturn value from a funciton.RETURN 1
return 1;
RECVReceive the number of functoin argumentsRECV 1 $a
RETURN<-1> null

function test($a){}
RECV_INITInitialize a function argument with "value" if not received from caller.
Otherwise same as RECV.
RECV_INIT 1 "test" $t
RETURN<-1> null

function a($t="test"){}
SEND_VALPass the constant value as an actual parameter to a function.INIT_FCALL<2> 112 "hello"
SEND_VAL "world" 1
SEND_VAL "ok" 2
DO_FCALL

hello("world","ok");
SEND_VAL_EXPass the constant value as an actual parameter to a function.Same as SEND_VAL_EXINIT_FCALL_BY_NAME<2> "hello"
SEND_VAL_EX "world" 1
SEND_VAL_EX "ok" 2
DO_FCALL

hello("world","ok");
SEND_VARPass the variable value as an actual parameter to a function.ASSIGN $a 1
INIT_FCALL<1> 96 "abs"
SEND_VAR $a 1
DO_ICALL

$a=1;abs($a);
SEND_VAR_EXPass the variable value as an actual parameter to a function.Same as SEND_VAR.ASSIGN $a 1
INIT_FCALL_BY_NAME<1> "test"
SEND_VAR_EX $a 1
DO_ICALL

$a=1;test($a);
SEND_REFPass the reference value as an actual parameter to a function.INIT_FCALL<1> 96 "each"
SEND_REF $a 1
DO_ICALL

@each($a);
NEWConstruct an instance of "type" and store the reference to the object into "result".NEW<2> "A" @1
SEND_VAL_EX "a" 1
DO_FCALL
FREE @1

new A("a");
INIT_NS_FCALL_BY_NAMENo sample in vld or phpdbg.UNKNOW
FREERelease the allocated space of the value.Could see NEW part
INIT_ARRAYAllocate a new array with elem-value as the first element of the array.UNKNOW in phpdbg,
You could refer to INIT_ARRAY
ADD_ARRAY_ELEMENTAdd elem-value as an element to array-valueUNKNOW in phpdbg,
You could refer to ADD_ARRAY_ELEMENT
INCLUDE_OR_EVALInclude the file specified by filename and eval it.INCLUDE_OR_EVAL<2> "test.php"
INCLUDE_OR_EVAL<1> "echo 1;"

include "test.php";
eval("echo 1;");
UNSET_CVUnset the variable.UNSET_CV $A
unset($A);
UNSET_VARUnset the variable.ASSIGN $A "x"
UNSET_VAR<4> $A

$A="x";
unset($$A);
UNSET_DIMUnset the entry of array-value, which is specified by indexUNSET_DIM $A 0
unset($A[0]);
UNSET_OBJUnset the property of the current objectUNSET_OBJ<8> $A "test"
unset($A->test);
FE_RESET_RInitialize an iterator on array-value. If the array is empty, jump to address.#0 ASSIGN $a array(3)
#1 FE_RESET_R $a J5 @1
#2 FE_FETCH_R<96> @1 $num
#3 ECHO<1> $num
#4 JMP J2
#5 FE_FREE @1

$a = array(1,2,3);
foreach($a as $num){
print $num;
}
FE_FETCH_RFetch an element from iterator.
If no element is available, jump to the address that FE_RESET_R opcode setted.
Could see FE_RESET_R part.
EXITExit running after dumping "message".EXIT "foo"
die("foo");
FETCH_Rfetch Variable variables.ASSIGN $a "x"
FETCH_R<4> $a ~1
ECHO ~1

$a="x";
echo $$a;
FETCH_DIM_Rfetch value of variables by index.FETCH_R<4> $a ~1
FETCH_DIM_R ~1 0 ~2
ECHO ~2

echo $$a[0];

FETCH_DIM_R $x 0
$x[0];
FETCH_OBJ_Rfetch property value of Variable variablesFETCH_R<4> $a ~1
FETCH_OBJ_R ~1 "test" ~2
ECHO ~2

echo($$a->test);
FETCH_Wfetch Variable variables and make it writable.ASSIGN $x 1
ASSIGN $a "x"
FETCH_W<4> $a @2
ASSIGN @2 2

$x=1;
$a="x";
$$a=2;
FETCH_DIM_Wfetch Variable variables by index and make it writable.FETCH_DIM_W $x 0 @0
ASSIGN_DIM @0 1
OP_DATA 2

$x[0][1]=2;
FETCH_OBJ_Wfetch property value of Variable variables and make it writable.FETCH_OBJ_W $x "t" @0
ASSIGN_OBJ<16> @0 "test"
OP_DATA 1

$x->t->test=1;
FETCH_RWfetch value of Variable variables.FETCH_RW<4> $a @0
POST_INC @0;

$$a++;
FETCH_DIM_RWfetch value of Variable variables by index.FETCH_DIM_RW $a 0 @0
POST_INC @0

$a[0]++;
FETCH_OBJ_RWfetch property value of Variable variablesFETCH_OBJ_RW $a "b" @0
POST_INC_OBJ<16> @0 "c"

$a->b->c++;
FETCH_ISFetch the value from variable which is to be used to test if it is set or not, through isset()/isempty().FETCH_IS<2> "_GET" ~0
ISSET_ISEMPTY_DIM_OBJ ~0 0

isset($_GET[0]);
FETCH_DIM_ISNo php sample.
FETCH_OBJ_ISNo php sample.
FETCH_FUNC_ARGfetch value of Variable variables as arg of functionINIT_FCALL_BY_NAME<1> "test"
CHECK_FUNC_ARG 1
FETCH_FUNC_ARG<4> $a @0
SEND_FUNC_ARG @0 1
DO_FCALL

test($$a);
FETCH_DIM_FUNC_ARGfetch value of variable by index as arg of functionINIT_FCALL_BY_NAME<1> "test"
CHECK_FUNC_ARG 1
FETCH_DIM_FUNC_ARG $a 0 @0
SEND_FUNC_ARG @0 1
DO_FCALL

test($a[0]);
FETCH_OBJ_FUNC_ARGfetch property value of variable as arg of functionINIT_FCALL_BY_NAME<1> "test"
CHECK_FUNC_ARG 1
FETCH_OBJ_FUNC_ARG $a "b" @0
SEND_FUNC_ARG @0 1
DO_FCALL

test($a->b);
FETCH_UNSETFetch a variable for the purpose of unset() operation.FETCH_UNSET<4> $A @1
UNSET_DIM @1 0

unset($$A[0]);
FETCH_DIM_UNSETFetch a variable by index for the purpose of unset() operation.FETCH_DIM_UNSET $a 0 @0
UNSET_OBJ @0 "b"

unset($a[0]->b);
FETCH_OBJ_UNSETFetch a property value of variable for the purpose of unset() operation.FETCH_OBJ_UNSET $a "b" @0
UNSET_OBJ<16> @0 "c"

unset($a->b->c);
FETCH_LIST_RFetch array list.FETCH_LIST_R array(2) 0 @0
ASSIGN $x @0
FETCH_LIST_R array(2) 1 @2
ASSIGN $b @2

list($x,$b) = array("x","b");
FETCH_DIM_TMP_VARNo php sample in phpdbgYou could refer to FETCH_DIM_TMP_VAR
FETCH_CONSTANTfetch value by const name.FETCH_CONSTANT "A" ~0
ECHO ~0

echo A;
GOTONo sample in phpdbg and vld,
phpdbg use JMP opcode to control flow.

EXT_STMTNo php sample
EXT_FCALL_BEGINNo php sample
EXT_FCALL_ENDNo php sample
EXT_NOPNo php sample
TICKS
TICKS<100>
declare(ticks=100);
SEND_VAR_NO_REFNo php sample
CATCHcatch when Exception get throw.#0 THROW $t
#1 JMP J4
#2 CATCH<1> "A" $e
#3 ECHO "catch"
#4 RETURN<-1> 1

try{throw $t}
catch(A $e){echo "catch";}
THROWthrow some Exception.THROW $t
throw $t;
FETCH_CLASSfetch static classFETCH_CLASS $obj @0
FETCH_CLASS_CONSTANT @0 "a"

$obj::a;
FETCH_CLASS_CONSTANTfetch static constant from classCould see FETCH_CLASS part.
FETCH_STATIC_PROP_Rfetch static property value from classFETCH_CLASS $obj @0
FETCH_STATIC_PROP_R "a" @0 ~1

$obj::$a;
FETCH_STATIC_PROP_RWfetch static property value from class,same as FETCH_STATIC_PROP_R but make it readable and writable.FETCH_CLASS $obj @0
FETCH_STATIC_PROP_RW "a" @0 @1
POST_INC @1 ~2

$obj::$a++;
FETCH_STATIC_PROP_Wfetch static property value from class AND make it writable.FETCH_CLASS $obj @0
FETCH_STATIC_PROP_W "a" @0 @1
ASSIGN @1 1

$obj::$a=1;
CLONEclone an objectCLONE $t ~0
clone $t;
RETURN_BY_REFNo sample in phpdbg
INIT_METHOD_CALLPrepare for a method call. Followed by DO_FCALL.INIT_METHOD_CALL $obj "a"
DO_FCALL

$obj->a();
INIT_STATIC_METHOD_CALLPrepare for a static method call. Followed by DO_FCALL.FETCH_CLASS $obj @0
INIT_STATIC_METHOD_CALL @0 "a"
DO_FCALL

$obj::a();
ISSET_ISEMPTY_CVcheck wether a variable is setted and store the result.ISSET_ISEMPTY_CV $a ~0
isset($a);
ISSET_ISEMPTY_VARcheck wether a variable is setted and store the result.ISSET_ISEMPTY_VAR<4> $a ~0
isset($$a);
ISSET_ISEMPTY_DIM_OBJcheck wether a variable is setted by its index and store the result.ISSET_ISEMPTY_DIM_OBJ $a 0 ~0
isset($a[0]);
ZEND_SEND_VAL_EX
Could see SEND_VAL_EX part.
ZEND_SEND_VAR
Could see SEND_VAR part.
ZEND_INIT_USER_CALL

ZEND_SEND_ARRAY

ZEND_SEND_USER

STRLENget length of string and store the resultSTRLEN $a
strlen($a);
DEFINED

ZEND_TYPE_CHECK

ZEND_VERIFY_RETURN_TYPE

ZEND_FE_RESET_RW

ZEND_FE_FETCH_RW

ZEND_FE_FREE

ZEND_INIT_DYNAMIC_CALL

ZEND_DO_ICALL

ZEND_DO_UCALL

ZEND_DO_FCALL_BY_NAME

PRE_INC_OBJSame as PRE_INC but operate to an objectPRE_INC_OBJ $obj "a"
++$obj->a;
PRE_DEC_OBJSame as PRE_DEC but operate to an objectPRE_DEC_OBJ $obj "a"
--$obj->a;
POST_INC_OBJSame as POST_INC but operate to an objectPOST_INC_OBJ $obj "a" ~0
$obj->a++;
POST_DEC_OBJSame as POST_DEC but operate to an objectPOST_DEC_OBJ $obj "a" ~0
$obj->a--;
ASSIGN_OBJfetch an object and wait for OP_DATA opcode.ASSIGN_OBJ $obj "a"
OP_DATA $t

$obj->a=$t;
INSTANCEOF
INSTANCEOF $a "A" ~0
$a instanceof A;
DECLARE_CLASSdeclare a class by nameJMPZ true JX
DECLARE_CLASS "a" @0

if(true){class A{}}
DECLARE_INHERITED_CLASSwhen declare a class by name,if declared class extends other class,will execute this opcode.JMPZ true JX
DECLARE_INHERITED_CLASS "a" "C" @0

if(true){
class a extends C{}
}
DECLARE_FUNCTIONdeclare function by nameJMPZ true JX
DECLARE_FUNCTION "test"

if(true){
function test(){}
}
RAISE_ABSTRACT_ERROR

DECLARE_CONSTdeclare a const valueDECLARE_CONST "a" 1
const a=1;
ADD_INTERFACEwhen declare class by name,if declared class implements other interface,will execute this opcode.JMPZ true JX
DECLARE_CLASS "a" @0
ADD_INTERFACE @0 "C"
VERIFY_ABSTRACT_CLASS @0

if(true){
class a implements C{}
}
DECLARE_INHERITED_CLASS_DELAYED

VERIFY_ABSTRACT_CLASS
Could see ADD_INTERFACE part.
ASSIGN_DIMset value of variable by index,followed by OP_DATA.ASSIGN_DIM $x 0
OP_DATA 2

$x[0]=2;
OP_DATAset value after "ASSIGN" opcodes(such as ASSIGN_DIM,ASSIGN_OBJ...) executed.Could see ASSIGN_DIM part.
ISSET_ISEMPTY_PROP_OBJcheck wether a property value of an object is setted and store the resultISSET_ISEMPTY_PROP_OBJ $a "b" ~0
isset($a->b);
HANDLE_EXCEPTION

USER_OPCODE

ZEND_ASSERT_CHECK

JMP_SETset the variable if value is not zero,otherwise jump to addressJMP_SET $b JX ~0
QM_ASSIGN 2 ~0
ASSIGN $t ~0

$t=$b?:2;
DECLARE_LAMBDA_FUNCTION
DECLARE_LAMBDA_FUNCTION "\000{clousre}C:\\"+ ~0
INIT_DYNAMIC_CALL ~0
DO_FCALL

(function(){return "phpinfo";})();
ADD_TRAITfollowed by BIND_TRAITSDECLARE_CLASS "a" @0
ADD_TRAIT @0 "B"
BIND_TRAITS @0

class A{
use B;
}
BIND_TRAITSbind trait in class.Could see ADD_TRAIT part.
ZEND_SEPARATE

ZEND_FETCH_CLASS_NAME

ZEND_CALL_TRAMPOLINE

ZEND_DISCARD_EXCEPTION

ZEND_YIELD

ZEND_GENERATOR_RETURN

ZEND_FAST_CALL

ZEND_FAST_RET

ZEND_RECV_VARIADIC

ZEND_SEND_UNPACK

ZEND_POW

ZEND_ASSIGN_POW

ZEND_BIND_GLOBAL(vld)
BIND_GLOBAL
declare an global variableBIND_GLOBAL $a "a"
global $a;
ZEND_COALESCE

ZEND_SPACESHIP

ZEND_DECLARE_ANON_CLASS

ZEND_DECLARE_ANON_INHERITED_CLASS

ZEND_FETCH_STATIC_PROP_R

ZEND_FETCH_STATIC_PROP_W

ZEND_FETCH_STATIC_PROP_RW

ZEND_FETCH_STATIC_PROP_IS

ZEND_FETCH_STATIC_PROP_FUNC_ARG

ZEND_FETCH_STATIC_PROP_UNSET

ZEND_UNSET_STATIC_PROP

ZEND_ISSET_ISEMPTY_STATIC_PROP

ZEND_FETCH_CLASS_CONSTANT

ZEND_BIND_LEXICAL

ZEND_BIND_STATIC

ZEND_FETCH_THIS

ZEND_SEND_FUNC_ARG

ZEND_ISSET_ISEMPTY_THIS

ZEND_SWITCH_LONG

ZEND_SWITCH_STRING

ZEND_IN_ARRAY

ZEND_COUNT

ZEND_GET_CLASS

ZEND_GET_CALLED_CLASS

ZEND_GET_TYPE

ZEND_FUNC_NUM_ARGS

ZEND_FUNC_GET_ARGS

ZEND_UNSET_CV


暂无留言,赶快评论吧

欢迎留言