//------------------------------------------------ //--- 010 Editor v7.0 Binary Template // // File: OPCache.bt // Authors: Ian Bouchard // License: MIT // Version: 0.1 // Purpose: Parse cache files generated by OPcache for PHP files on an x86 platform. // Category: Programming // File Mask: *.php.bin // ID Bytes: 4F 50 43 41 43 48 45 // OPCACHE // History: // 0.1 2016-06-07 ib: Initial release. //------------------------------------------------ // Structs // typedef struct { char magic[8]; char system_id[32]; int mem_size; int str_size; int script_offset; time_t timestamp; int checksum; } _meta; typedef struct zend_string { unsigned int64 gc; unsigned long h; unsigned long len; char val[len]; } _string ; string _string_read(_string &s) { if (s.len == 0) return "[EMPTY]"; return s.val; } typedef struct zval_struct { int value; int value2; union { struct { unsigned char type; unsigned char type_flags; unsigned char const_flag; unsigned char reserved; } v; int type_info; } u1; unsigned int flags; if (u1.v.type == 6) { local int curr_pos = FTell(); FSeek(value + sizeof(_meta)); _string real_value; FSeek(curr_pos); } } _zval; typedef struct zend_try_catch_element { unsigned int try_op; unsigned int catch_op; unsigned int finally_op; unsigned int finally_end; } _try_catch_element; typedef struct zend_live_range { unsigned int var; unsigned int start; unsigned int end; } _live_range; typedef union node_op { unsigned int constant; unsigned int var; unsigned int num; unsigned int opline_num; } _node_op; string show_val_node_op(_node_op &n) { if (n.num > 0) { int string_pos = ReadInt(n.num + sizeof(_meta)); string s = ReadString(string_pos + 16 + sizeof(_meta)); if (Strlen(s) == 0) return "[N/A]"; return s; } else return "void"; } typedef struct zend_arg_info { // Name pos int name_pos; // Name if (name_pos != 0) { local int curr_pos = FTell(); FSeek(name_pos + sizeof(_meta)); _string name; FSeek(curr_pos); } // Class name pos int class_name_pos; // Class name if (name_pos != 0) { curr_pos = FTell(); FSeek(class_name_pos + sizeof(_meta)); _string class_name; FSeek(curr_pos); } unsigned char type_hint; unsigned char pass_by_reference; unsigned char allow_null; unsigned char is_variadic; } _arg_info; typedef struct zend_op { unsigned int handler; _node_op op1; _node_op op2; _node_op result; unsigned int extended_value; unsigned int lineno; unsigned char opcode; unsigned char op1_type; unsigned char op2_type; unsigned char result_type; } _op; string show_pseudo_op(_op &o) { string s; SPrintf(s, "(%d)%s = %d((%d)%s, (%d)%s)", o.result_type, show_val_node_op(o.result), o.opcode, o.op1_type, show_val_node_op(o.op1), o.op2_type, show_val_node_op(o.op2)); return s; } typedef struct zend_op_array { byte type; byte arg_flags[3]; int fn_flags; // Function name pos int function_name_pos; // Function name if (function_name_pos != 0) { local int curr_pos = FTell(); FSeek(function_name_pos + sizeof(_meta)); _string function_name; FSeek(curr_pos); } // Scope pos int scope_pos; // Prototype pos int prototype_pos; int num_args; int required_num_args; // Args Info pos int arg_info_pos; curr_pos = FTell(); FSeek(arg_info_pos + sizeof(_meta)); _arg_info arg_infos[num_args]; FSeek(curr_pos); int refcount; int this_var; int last; // Opcodes pos int opcodes_pos; curr_pos = FTell(); FSeek(opcodes_pos + sizeof(_meta)); _op opcodes[last]; FSeek(curr_pos); int last_var; int T; // Vars int vars_pos; curr_pos = FTell(); FSeek(vars_pos + sizeof(_meta)); int var_pos[last_var]; local int i; for (i = 0; i < last_var; i++ ) { FSeek(var_pos[i] + sizeof(_meta)); _string vars; } FSeek(curr_pos); int last_live_range; int last_try_catch; // Live range int live_range_pos; curr_pos = FTell(); FSeek(live_range_pos + sizeof(_meta)); _live_range live_range[last_live_range]; FSeek(curr_pos); // Try catch array int try_catch_array_pos; curr_pos = FTell(); FSeek(try_catch_array_pos + sizeof(_meta)); _try_catch_element try_catch_array[last_try_catch]; FSeek(curr_pos); // Static variables pos int static_variables_pos; // Filename pos int filename_pos; // Filename curr_pos = FTell(); FSeek(filename_pos + sizeof(_meta)); _string filename ; FSeek(curr_pos); int line_start; int line_end; // Doc comments pos int doc_comments_pos; // Doc comments curr_pos = FTell(); FSeek(doc_comments_pos + sizeof(_meta)); _string doc_comments ; FSeek(curr_pos); int early_binding; int last_literals; // Literals pos int literals_pos; int cache_size; int runtime_cache; int reserved[4]; // Literals curr_pos = FTell(); FSeek(literals_pos + sizeof(_meta)); for (i = 0; i < last_literals; ++i) _zval literals; FSeek(curr_pos); } _op_array; typedef struct _Bucket { _zval val; unsigned long h; int key_pos; local int curr_pos = FTell(); FSeek(key_pos + sizeof(_meta)); _string key; FSeek(val.value + sizeof(_meta)); _op_array op_array; FSeek(curr_pos); } Bucket; typedef struct _HashTable { int64 gc; int flags; unsigned int nTableMask; unsigned int bucket_pos; unsigned int nNumUsed; unsigned int nNumOfElements; unsigned int nTableSize; unsigned int nInternalPointer; long nNextFreeElement; unsigned int pDestructor; curr_pos = FTell(); FSeek(bucket_pos + sizeof(_meta)); Bucket buckets[nNumUsed]; FSeek(curr_pos); } HashTable; typedef struct script { local int curr_pos; // Filename pos int filename_pos; // Filename curr_pos = FTell(); FSeek(filename_pos + sizeof(_meta)); _string filename ; FSeek(curr_pos); // Main Op Array _op_array main_op_array; // Function table HashTable function_table; HashTable class_table; } _script; _meta meta; _script cached_script;