The Vulcan Logic Disassembler hooks into the Zend Engine and dumps all the opcodes (execution units) of a script. It was written as as a beginning of an encoder, but I never got the time for that. It can be used to see what is going on in the Zend Engine.
New Features in 0.8
PHP 5.0 / PHP 5.1 support.
vld will only show opcodes if the setting vld.active is set to 1.
New Features in 0.6
Class methods info is only dumped if they contain some user defined functions.
Clean up the framework for better opcode display.
Print extended value for function calls (# of args in that case).
Op code elements are only printed when they are actually used.
Download and Installation Instructions
The extension is not totally finished yet, but it works fine for me. If you have questions, feel free to send me an e-mail (but read this first) at derick at php dot net. If you like this piece of software, feel free to checkout my wishlist or Andrei's. This improves chances that we will be continuing developing VLD.
You can download the source here or get it from CVS. The CVS root is "srmread@cvs.vl-srm.net:/repository", the module is "vle" (not "vld") and the password is "srmread".
It's not hard to use this extension, but it might not work with all PHP versions. Here are the instructions to get it to work:
Unpack the tarball: tar -xzf vld-0.8.0.tgz.
cd into the newly created directory.
Create the configure script: phpize
Now run "./configure" followed by "make install".
That's it, if you now run PHP from the command line and add the -dvld.active=1 parameter VLD will spit out the opcodes:
php -dvld.active=1 program.php
deZender,PHP decoder, PHP decompiler, decode Zend/ionCube/SourceGuardian.
现在的几家dezend系统都基于VLD制作,有需要的朋友研究下吧
使用方法(只适用于Linux操作环境)
执行
[Copy to clipboard]CODE:
#tar -xzf vld-0.8.0.tgz //解压
#mv vld-0.8.0 vld //重命名
#cp -R vld ../php-4.4.2/ext //拷贝vld目录到php源码的解压目录下的ext中
#cd php-4.4.2 //进入PHP源码目录
#rm configure //刪除configure,因为下面的buildconf会重新生成新的configure
#./buildconf --force //如果出现错误,就按提示加上相应的参数
#./configure --enable-vld --with-apxs2=/httpd/bin/apxs --enable-track-vars --enable -force-cgi-redirect --enable-pic --enable-inline-optimiation --with-config -file-path=/etc --enable-sysvmsg --enable-sockets --enable-sysvshm -- enable-sysvsem --enable-gd-native-ttf --with-gd=/usr/local/lib --with- zlib-dir=/usr/local/lib --with-ttf=/usr/lib --with-tiff-dir=/usr/lib - -with-jpg-dir=/usr/local/lib --with-png-dir=/usr/local/lib --with-freetype -dir=/usr/local/lib --with-mysql --with-xml --with-gdbm-dir=/usr/lib --with-ftp --disable-debug --with-gettext=/usr/lib --enable-bcmath -- enable-wddx --enable-thread-safety --enable-calendar --enable-mbstring =cn //重新配置php
#make && make install 编译安装PHP
服务器必须先安装ZendOptimizer
运行Zend后的文件,查看源代碼就可以看到了.
例:运行下面的命令就可以得到program.php的源代码
php -dvld.active=1 program.php
phpdecode(deZend)tools collection下载地址:
方法二:
只要你有Linux主機,再装一个程序,就能浏览源码了.
[复制PHP代码]PHP代码如下:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_vld.h"
#include "srm_oparray.h"
static zend_op_array* (*old_compile_file)(zend_file_handle* file_handle, int type TSRMLS_DC);
static zend_op_array* vld_compile_file(zend_file_handle*, int TSRMLS_DC);
static void (*old_execute)(zend_op_array *op_array TSRMLS_DC);
static void vld_execute(zend_op_array *op_array TSRMLS_DC);
function_entry vld_functions[] = {
{NULL, NULL, NULL}
};
zend_module_entry vld_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"vld",
vld_functions,
PHP_MINIT(vld),
PHP_MSHUTDOWN(vld),
PHP_RINIT(vld),
PHP_RSHUTDOWN(vld),
PHP_MINFO(vld),
#if ZEND_MODULE_API_NO >= 20010901
"0.8.0",
#endif
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_VLD
ZEND_GET_MODULE(vld)
#endif
ZEND_BEGIN_MODULE_GLOBALS(vld)
int active;
int skip_prepend;
int skip_append;
int execute;
ZEND_END_MODULE_GLOBALS(vld)
ZEND_DECLARE_MODULE_GLOBALS(vld)
#ifdef ZTS
#define VLD_G(v) TSRMG(vld_globals_id, zend_vld_globals *, v)
#else
#define VLD_G(v) (vld_globals.v)
#endif
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("vld.active", "0", PHP_INI_SYSTEM, OnUpdateBool, active, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.skip_prepend", "0", PHP_INI_SYSTEM, OnUpdateBool, skip_prepend, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.skip_append", "0", PHP_INI_SYSTEM, OnUpdateBool, skip_append, zend_vld_globals, vld_globals)
STD_PHP_INI_ENTRY("vld.execute", "1", PHP_INI_SYSTEM, OnUpdateBool, execute, zend_vld_globals, vld_globals)
PHP_INI_END()
static void vld_init_globals(zend_vld_globals *vld_globals)
{
vld_globals->active = 0;
vld_globals->skip_prepend = 0;
vld_globals->skip_append = 0;
vld_globals->execute = 1;
}
PHP_MINIT_FUNCTION(vld)
{
ZEND_INIT_MODULE_GLOBALS(vld, vld_init_globals, NULL);
REGISTER_INI_ENTRIES();
old_compile_file = zend_compile_file;
old_execute = zend_execute;
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(vld)
{
UNREGISTER_INI_ENTRIES();
zend_compile_file = old_compile_file;
zend_execute = old_execute;
return SUCCESS;
}
PHP_RINIT_FUNCTION(vld)
{
if (VLD_G(active)) {
zend_compile_file = vld_compile_file;
if (!VLD_G(execute)) {
zend_execute = vld_execute;
}
}
return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(vld)
{
zend_compile_file = old_compile_file;
zend_execute = old_execute;
return SUCCESS;
}
PHP_MINFO_FUNCTION(vld)
{
php_info_print_table_start();
php_info_print_table_header(2, "vld support", "enabled");
php_info_print_table_end();
}
static int vld_check_fe (zend_op_array *fe, zend_bool *have_fe TSRMLS_DC)
{
if (fe->type == ZEND_USER_FUNCTION) {
*have_fe = 1;
}
return 0;
}
static int vld_dump_fe (zend_op_array *fe TSRMLS_DC)
{
if (fe->type == ZEND_USER_FUNCTION) {
fprintf(stderr, "Function %s:
", fe->function_name);
vld_dump_oparray(fe);
fprintf(stderr, "End of function %s.
", fe->function_name);
}
return ZEND_HASH_APPLY_KEEP;
}
#ifdef ZEND_ENGINE_2
static int vld_dump_cle (zend_class_entry **class_entry TSRMLS_DC)
#else
static int vld_dump_cle (zend_class_entry *class_entry TSRMLS_DC)
#endif
{
zend_class_entry *ce;
zend_bool have_fe = 0;
#ifdef ZEND_ENGINE_2
ce = *class_entry;
#else
ce = class_entry;
#endif
if (ce->type != ZEND_INTERNAL_CLASS) {
zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) vld_check_fe, (void *)&have_fe TSRMLS_CC);
if (have_fe) {
fprintf(stderr, "Class %s:
", ce->name);
zend_hash_apply(&ce->function_table, (apply_func_t) vld_dump_fe TSRMLS_CC);
fprintf(stderr, "End of class %s.
", ce->name);
} else {
fprintf(stderr, "Class %s: [no user functions]
", ce->name);
}
}
return ZEND_HASH_APPLY_KEEP;
}
/* {{{ zend_op_array vld_compile_file (file_handle, type)
* This function provides a hook for compilation */
static zend_op_array *vld_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
{
zend_op_array *op_array;
if (!VLD_G(execute) &&
((VLD_G(skip_prepend) && PG(auto_prepend_file) && PG(auto_prepend_file)[0] && PG(auto_prepend_file) == file_handle->filename)
(VLD_G(skip_append) && PG(auto_append_file) && PG(auto_append_file)[0] && PG(auto_append_file) == file_handle->filename)))
{
zval nop;
ZVAL_STRINGL(&nop, "RETURN ;", 8, 0);
return compile_string(&nop, "NOP" TSRMLS_CC);;
}
op_array = old_compile_file (file_handle, type TSRMLS_CC);
if (op_array) {
vld_dump_oparray (op_array);
}
zend_hash_apply (CG(function_table), (apply_func_t) vld_dump_fe TSRMLS_CC);
zend_hash_apply (CG(class_table), (apply_func_t) vld_dump_cle TSRMLS_CC);
return op_array;
}
/* }}} */
/* {{{ void vld_execute(zend_op_array *op_array TSRMLS_DC)
* This function provides a hook for execution */
static void vld_execute(zend_op_array *op_array TSRMLS_DC)
{
// nothing to do
}
/* }}} */