Johnny 写的文章,因为没有整理,所以比较乱。
参考文章
1.现在的几家dezend系统都基于VLD制作
#tar -xzf vld-0.8.0.tgz
#mv vld-0.8.0 vld
#cd -R vld ../php-4.3.8/ext //复制vld目录到
php的源码下的ext中
#cd php-4.3.8
#rm configure
#./buildconf
#./configure –with-mysql –with-apxs2=/usr/www/bin/apxs –enable-vld
#make
#make install
据说运行
zend过的
文件,查看
源代码就可以看到了
2.Vulcan Logic Disassembler
http://derickrethans.nl/vld.php
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.
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:
1. Unpack the tarball: tar -xzf vld-0.8.0.tgz.
2. cd into the newly created directory.
3. Create the configure script: phpize
4. 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
注意:
1)debian 下要安装php4-dev或者php5-dev才有phpize
2)PHP 5.1 有一个宏
定义是取消了的,要将其注释掉, 网上有补丁
这里给出我修改的
复制内容到剪贴板
代码:
diff -u srm_oparray.c vld-0.8.0/srm_oparray.c
--- srm_oparray.c 2005-01-19 19:59:54.000000000 +0800
+++ vld-0.8.0/srm_oparray.c 2006-10-29 09:47:04.000000000 +0800
@@ -351,6 +351,7 @@
op->op2.op_type = VLD_IS_OPLINE;
break;
+#ifdef ZEND_JMP_NO_CTOR
case ZEND_JMP_NO_CTOR:
flags = OP2_USED;
if (op->op1.op_type != IS_UNUSED) {
@@ -361,6 +362,7 @@
#endif
op->op2.op_type = VLD_IS_OPLINE;
break;
+#endif
#ifdef ZEND_ENGINE_2
case ZEND_FETCH_CLASS:<!--code2-->3.截获PHP读取文件并装载至缓存的过程
zend/zend_ini_scanner.c
4. xfocus.net 2006大会
先说一段题外话
目前国内掌握了dezend的似乎有
lkq 此人应该是国内最早完整掌握了该
技术的人
http://www.qinvent.com/
===============================
airsupply/segfault.cn
此人是
https://0x557.org
成员,在安全焦点2006大会做了dezend的报告
他应该是受了 qinvent的启发,才开始着手做这个事情的
===============================
3 dot
http://3.999ye.com/
他也认为基于vld可以做出来
===============================
看看他们之间的一段争论
lkq (
lkq@kali.com.cn)
稍微读一下vld的源代码,就可以知道它什么事也没干。无非是从ram中的一点点信息打印出来而已。充其量是一个极烂的debug程序而已。(只能打印最低版encoder编译的一小部分opcode而已)
就和在dos下用debug显示汇编指令一样,那跟反编译或源代码没有一点关系。
segfault (
airsupply@segfault.cn) 2006-8-31
事实上 vld 甚至可以反汇编 Zend Guard 4.01 加密的 php,注意是"反汇编"。
当然需要稍稍修改几行代码。 要做到这一步花几个小时就够了。
需要的只是一个在这基础上的反编译
引擎。 这个比较复杂,算是大量体力劳动。
lkq:
vld只是从内存中dump一小部分opcode的一小部分信息(
变量名、数组、类成员等信息丢失),function和class中的opcode无法dump。对于3.x以上由于opcode是加密的,所以dump出来的opcode是完全错误的。
所以vld离反汇编器还差的远了,充其量只是一个baby级的dump工具。
segfault:
vld 可以完全 dump 出 op_array 中所有的 opcode,也包括 function 和 class 中的 opcode.
可能你用的版本老?
我说了,对 4.01 的 Zend Guard, vld 修改几行代码就能 dump 了。
lkq(2006-8-31 20:43)
呵呵,很多版本zend的function和class中的opcode无法dump。对于加密后的opcode也无法dump,各种变量名、函数名、类名也无法dump,zend_op中很多信息也无法dump。
对于一般情况,要打印出opcode其实非常简单,随便写几十行代码就可以。但各种版本各种选项以及各种php语法有数不清的情况,不经过特殊处理根本无法获得所需的全部op信息。得到了包含完整信息的op也离获得PHP源码差的远了。这就是为什么除了deZender,到目前还没有出现第2个真正可用的 PHP反编译器。
segfault(2006-9-1 09:45)
简单测了 Zend Encoder 3.01 和 Zend Guard 4.01 加密后 php, vld 都几乎能完整 dump 出所有 opcode. 除了对 3.01 的 DO_FCALL 识别不出来。
当然,没有做大量的测试。
所以,对写反编译器,vld 还是有很大价值。只需添加一行代码就能 dump Zend Encoder 3.01 和 Zend Guard 4.01加密的 opcode.
它提供了原始的思路,方法和代码基础。而不是像楼上一些人说的是“垃圾”或一无用处。
确实,对不同版本的 Encoder 必然在细节上要做不同的修正,这个工作比较琐碎。从 opcode 到 php source,工作量也比较浩大。
lkq:
对于要想获得PHP源码的人,vld就是垃圾。vld做的事就是从内存中dump少部分 opcode。对于少数版本的简单PHP文件可以dump出完整的opcode,但一个op除了opcode以外,还包含了很多信息,vld遗漏了许多这样的信息。而对于opcode加密的情况,绝非添加一行或几行代码就能实现解密的,何况不同版本的Zend加密算法有所不同,不对zend所采用的加密算法进行透彻的研究怎么可能破解他的加密算法呢。
我们知道,一个反汇编器,需要针对各种情况得出完整的汇编代码(对于zend可以理解为op),仅仅能得到一部分opcode(不是op)和一些简单的参数信息,并且对于很多情况连opcode也无法得出。这能叫反编译器吗?在开发人员看来,vld只是一个dump工具,并且是一个玩具级的dump工具。
vld做的事情是用几十行代码就能完成的事情,编写一个真正能用的PHP反编译器需要几万行代码并且需要对各种数不尽的特殊情况进行识别和大量的测试。vld做的事情不到整个PHP反编译器工作的1%。
对于普通的PHP程序员,不可能用vld得到一行PHP源码,花大量时间精力去学习如何安装vld和编译PHP源码是不值得的;
对于专业人士(精通C和PHP并立志要写一个PHP反编译器),正确的第1步是研究编译原理和Zend Engine。如此简单的vld根本无任何参考价值。相反对于准备写PHP反编译器的人来说有误入歧途之嫌。
对于介于上述2种人之间的,有大量时间并懂
linux和会编译PHP源码的人,体验一下vld到底能干什么也无可厚非。
segfault:
对 3.01 和 4.01 Zend Encoder 加密过的 opcode (我手头只有这两个版本), 确实可以用添加同样的一行代码来解密。
写反编译器,Zend 引擎和编译原理当然需要熟悉。
另外,其实 vld 使用很简单,根本不需要编译 php 源码。
lkq:
对于解密的代码,可否麻烦把这行代码贴出来?不在透彻研究加密算法的基础上做解密,是不专业和不严谨的,并没有实际运用价值,只能作为业余玩玩。
写反编译器,要研究透Zend 引擎和编译原理,而不是简单的熟悉就可以了。而且这也只是写反编译器的准备工作而已。
对于绝大多数甚至连linux都没有使用过的PHP程序员,要成功安装使用vld并不是件容易的工作。一个成熟的
软件,应该能让绝大多数没有相关专业知识的人方便使用。
另外,我所知道的vld是源码,需要编译到php代码中。可能你已经找到了一个全新的vld版本,可否在此共享你的安装方法和程序。以让广大非专业人士体验一下。
segfault:
我用的就是 vld 0.8.0,不需要编译到 php 中,作为一个 php 扩展单独编译。
参考:
http://derickrethans.nl/vld.php
解密代码暂时不打算公开。我想看看我能在反编译方面走多远,纯粹作为技术挑战,呵呵。
如果将来觉得难度太大,或者没兴趣了,再公开所有成果。
我不知道 Dezender 是怎么做的。如果是独立读入加密过的 php,解压,再构造 opcode array,
然后再解密,那么这时候解密就比较复杂了,不是一行代码能完成的。我估计是这么做的。
还有其它的思路,可以完全绕过上面的解压,构造 opcode array,和解密三个过程。这就是
vld 提供的思路。显然能减少不少工作量,代码量和不同版本 Encoder 兼容性问题。
总之,使用 vld 只花了两个晚上就能完成 opcode 解密和 dump (事实上我到目前位置只做了
这么久,本周才开始对这方面感兴趣,对 php 也只了解一点点,zend 引擎完全没接触过)。
如果不用 vld, 才用上述独立读入解压解密方式做,我估计需要 1-2 周才行。所以,vld 有没有
价值很显然。
lkq:
有多少PHP程序员懂如何编译vld 0.8.0?
显然老兄对vld或zend加密编译过程了解的不是太多。我们之所以最终认为vld是垃圾,是基于我们前期对zend engine和vld深入研究基础之上得出的。对于一个想要写出有实用性的PHP反编译器的人,以vld的思路走下去是完全行不通的,举个例子:很多 Zend加密后的文件都有时间、IP或域名等限制,以PHP扩展库的方式根本无法解决对这些文件的反编译。当你着手编写反编译器的时候,有许多问题用 vld的思路是无法解决的,你会发现vld不但无用,更让人误入歧途,浪费时间。当你研究完Zend Engine后再回过头来看vld,你甚至还会发现vld太小儿科,并且存在一些严重的理解错误。如果你纯粹为了好玩或想挑战一下自己,浪费点时间倒也无妨。
deZender已经推出了近1年了,期间不断地进行完善。在这一年中,有不少人都想挑战自己编写一个类似的PHP反编译器,包括我们在MSN上也遇到过许多俄国和美国的个人和组织,也表达了他们的决心和要求我们提供一些支持。但到目前为止第2个真正能用的PHP反编译器还没有出来。可想要做一个PHP反编译器是技术和毅力上的双重考验。
另外,vld并没有解决加密PHP文件的加载读入问题,你只需要花半小时时间仔细读一下vld就知道它所干的那些事情只是将内存中的最容易得到的 opcode打印出来而已。如果你了解了Zend engine后,在Zend engine的适当位置加十几行代码就能实现同样的事情,并且还能比vld干的更好。
segfault:
不见得是浪费时间,毕竟过程中能学到不少东西。 比如 Zend Encoder 对加密后 php 文件格式的组织,使用自定义字典做
压缩,都很新颖。其它如 Zend 引擎生成和解释执行 opcode 数组的过程,对我的工作本身很有参考价值。
不过最大的挑战是反编译引擎的组织。没有一个合适的
框架,那么多类 opcode 处理起来会一团糟。
lkq:
是的,任何经历都可以认为是学到了东西,哪怕走错了路也一样可以学到东西。但对于不是要挑战自己而是要用最经济最可行的方法得到PHP源码的人来说,花时间在vld上就是浪费时间。何况对于一个真正要写PHP反编译器的人来说,阅读zend engine比从vld上学到的东西要多得多,做技术的人都懂得:在前人的经验上做事情是非常重要的。以我们的经验,如果你真的要测试一下自己的能力,想写一个PHP反编译器证明一下,与其在vld上浪费时间,不如把精力花在研究zend engine上,你的收获会更多。从zend engine的代码中,你才能真正体会到专业严谨的思维方式和技术方法。希望你能坚持不懈达到自己的目标。
segfault:
在 vld 上只花了不到一晚上时间。其实主要时间花在跟踪 opcode 解密上了。vld 就那么一点代码,不需要花费多少时间。
个人并不喜欢 Zend 引擎代码。从软件工程观点看,它的代码不好。首先,注释很少;其次,宏使用太多。对其它人阅读和维护代码很不利。
lkq:
不知你读过其他开源
项目的源码没有,Zend Engine在开源项目中在软件工程化方面算是不错了。而且代码逻辑清晰、命名规范、结构关联较少。大量使用宏定义正是为了增强代码的可读性和可维护性,这些都是软件开发工程化的必备因素,比起很多开源项目,甚至商业程序的工程化程度都高。
segfault:
类似 EG,EX 这样的宏命名能增加可读性?
打开一个文件,满眼都是 EG,EX 这样不知道什么东西,立刻就晕了
lkq

2006-9-1 17:55)
之所以定义EG, EX宏,是为了针对各种不同情况使代码体现一致性,并简化代码,增强可读性。而不把它定义成函数,是为了提升zend engine的性能。至于在命名上为何和其他宏相比显得过于简单,我想可能是Zend考虑要和低版本源码保持一致,或其他一些原因。
Zend engine中的绝大部分变量、宏、函数、文件等的命名都是规范化的。我想我们不应该对任何软件太吹毛求疵。目前,任何软件在工程化方面远未达到完美的程度,比起很多开源项目和商业程序,Zend engine算是比较符合当今软件工程的要求的。一个多人参与的大项目,不走工程化道路是很难保证质量和进度要求的。
实际上软件可以说是工程和艺术的结合体,即需要集体的协作也少不了个人的创造。之所以当今世界如此突出软件工程的作用,那是因为以前软件开发过程太过艺术化、太讲究个人英雄主义的创造和发挥,我们不能矫枉过正。我想,也许软件开发永远也无法实现如同在生产线上按部就班的生产一辆汽车那样的高度工程化。软件同样离不开个人的创新和创造。
[
本帖最后由 flyindance 于 2007-6-19 18:50 编辑 ]