首先用hello world试手一下。
下载php源码包,ext目录就是扩展目录了里面有2个重要的文件是ext_skel以及ext_skel_win32.php.
下载cygwin.有了这个就可以方便的在windows下创建php扩展了。
下载中。。。
下载完后用php ext_skel_win32.php --extname=hello来编译生成我们的扩展开发目录hello
然后开始写测试程序hello world
在hello.c文件里添加函数定义以及函数注册语句:
函数注册语句:
const zend_function_entry hello_functions[] = { PHP_FE(confirm_hello_compiled, NULL) PHP_FE(sayHello,NULL)//这句是我们手动添加的 {NULL, NULL, NULL} };
函数定义:
PHP_FUNCTION(sayHello){ php_printf("Hello C extension"); }
好像说是一定要以PHP_FUNCTION出现的宏形式,因为如果直接裸写c代码可能会发生命名冲突或是其他的冲突。
然后在php_hello.h里面添加函数声明语句:
PHP_FUNCTION(sayHello);
写好测试程序,编译结果出现
../main/config.w32.h': No such file or directory
网上查了一下,好像是要下载额外的包。。。麻烦啊
http://www.php.net/extra/bindlib_w32.zip
http://www.php.net/extra/win32build.zip
将这两个包放在一起,我把它们放在win32/build目录下
然后执行php源码包根目录下的buildconf.bat(最好在命令行运行,不然显示结果会一闪而过)
然后把bison.exe(在刚下载的包里面)所在的目录设置为环境变量,再运行configure.bat。完后就生成/main/config.w32.h这个文件了。
然后再次编译刚才hello项目结果出现一大推错误。
形如:
..\..\main\streams/php_stream_transport.h(85) : error C2143: syntax error : missing ')' before '*'
..\..\main\streams/php_stream_transport.h(85) : error C2081: 'socklen_t' : name in formal parameter list illegal
网上说是由于找不到宏定义才会这样,那应该是socklen_t这个宏没定义了,但是它具体的宏定义应该是怎么样的呢,总不能随便写一个吧。
所以打开\main\streams/php_stream_transport.h发现应该是个类型别名,而且是个int ,因为有socklen_t addrlen;addrlen按字面应该是存储长度的值。
所以在这个文件中添加typedef int socklen_t;保存
在编译刚才的项目,错误少了很多,但是还有7个,经检查发现是输入了中文符号。改正再编译。。。还有一个错误:
LINK : fatal error LNK1181: cannot open input file "php5ts.lib"
于是将寻找php5ts.lib这个文件并将它放到项目目录下或是VC6 lib文件默认搜索目录下也可以。找啊找啊找。。。
tmd,用windows搜索找了好久都没找到。百度是说在php二进制代码包里面。所以先下个同版本的二进制代码包(应该就是平时写php所必须下载的那个包吧)
这里先说下环境吧windows+vc6+php5.3.5(二进制代码包和源码包)+cygwin
下载完毕,找到,复制 ,编译,成功!
但是出现了一个很严重的问题,dll文件没出来,,,我哭
创建出来的是php_hello.exp和php_hello.lib。怎么会是静态的呢??
其实已经生成了,只是不在本目录下的Release_TS目录下,而是在ext上级的Release_TS目录下。
然后测试。哈哈,说是未定义函数,有没可能是测试的php版本和我扩展的php版本不一样的关系呢?
测试了一下也不是,只要在ini里一设置加载php_hello.dll重启apache就会出现内存不能读的错误。
总觉得代码没有问题,应该还是前面配置编译的时候有问题。
经过一番又一番的测试发现时php二进制包下错了我下了vc9的应该下vc6的。
接下来要开始写加密和解密了。加密解密算法本身不是这里的重点,重点是如何在zend层用zend本身的接口结合c来编程,在zend编译源文件之前将文件解密(当然文件之前要是有加过密的)。为了使用的方便。我的想法是像php_screw一样生成dll的同时,生成一个加密的可执行文件,这加密的可执行文件由我们手动执行,传入目录参数,能够对该目录下的所有文件进行加密。
在网上找了一堆资料后,再看看php_screw的代码,还有有些吃力,所以决定根据自己的思路来写。当然有些地方时会借鉴php_screw的代码
首先是先写一个对文件进行解密的函数。这个函数利用我们现成的解密算法对文件内容进行解密。
这个函数应该有一个参数用来接收当前请求文件的句柄(貌似是zend_compile_file这个东西,百度之,确认一下,几篇文章说是函数指针,我看了下源代码确实是函数指针)extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
那么要如何得到当前请求文件的文件指针呢?或许和zend_compile_file函数指针所指函数的作用有关。在源代码中发现了zend_compile_file = compile_file;该函数的定义在zend_language_scanner.c,不过要看懂该函数有点难度,网上的说法是:
-------------
zend_compile_file负责将要执行的脚本文件编译成由ZE的基本指令序列构成的op codes 。
PHP执行这段代码会经过如下4个步骤:
1. Scanning (Lexing) ,将PHP代码转换为语言片段(Tokens)
2. Parsing , 将Tokens转换成简单而有意义的表达式
3. Compilation , 将表达式编译成Opocdes
4. Execution , 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。
-------------
所以我们应该要在这个四个步骤之前将文件解密。
想法是重写一个函数a判断在文件被compile之前先将它解密,然后再调用默认的complie函数。定义好函数a后,应该在请求初始化的时候将函数a传递给函数指针zend_compile_file
PHP_MINIT_FUNCTION(dencrypt){ old_comlie_file = zend_complie_file;//保留默认的compile,以便等一下调用 zend_complie_file = 函数a; return SUCCESS; }
ZEND_API zend_op_array *a(zend_file_handle *file_handle,int type TSRMLS_DC){//这里的TSRMLS_DC是一个宏类似于,...(宏的定义暂时找不到)总之是跟多线程环境下全局变量的线程安全有关系的,以后再深究
解密代码。。。
old_comlie_file(file_handle); .... }
但是问题还是没有解决,因为我们还是不知道如何获取到文件指针。我看php_screw里面的解密步骤挺长的,参考之。。。找到了fp = fopen(file_handle->filename, "r");原来file_handle里面有文件名的信息(其实如果找到file_handle的结构体定义语句也就知道了)。
但是php_screw里面还有这么一段
char fname[32]; memset(fname, 0, sizeof fname); if (zend_is_executing(TSRMLS_C)) {//TSRMLS_C获得全局变量 if (get_active_function_name(TSRMLS_C)) {//获取当前调用函数的名字(当前调用函数?哪里的函数?php函数?想想当然是zend里面的函数。而不是php层的函数,因为现在都还没编译,更没执行呢) strncpy(fname, get_active_function_name(TSRMLS_C), sizeof fname - 2); } } if (fname[0]) { if ( strcasecmp(fname, "show_source") == 0//也就是说如果当前是这两个函数则不解密也不编译了。恩,看样子没错。 || strcasecmp(fname, "highlight_file") == 0) { return NULL; } }
所以这段还是必要的,不然遇到以上两个函数就没法实现了,compile_file函数里面应该也有这步才对。所以这里主要是不要让它被解密,而是直接显示密文。
还有这么一段
fp = fopen(file_handle->filename, "r"); if (!fp) {//如果打开失败则直接调用默认compile函数 return org_compile_file(file_handle, type); } fread(buf, PM9SCREW_LEN, 1, fp);//一下5句的作用是:如果发现时未加密的文件则不进行解密。 if (memcmp(buf, PM9SCREW, PM9SCREW_LEN) != 0) { fclose(fp); return org_compile_file(file_handle, type); } if (file_handle->type == ZEND_HANDLE_FP) fclose(file_handle->handle.fp);//判断文件句柄类型,应用相应的关闭函数。 if (file_handle->type == ZEND_HANDLE_FD) close(file_handle->handle.fd); file_handle->handle.fp = pm9screw_ext_fopen(fp);//调用解密文件的函数,并用file_handle里面的fp接收函数返回结果 file_handle->type = ZEND_HANDLE_FP;//将句柄类型设置为文件指针类型 file_handle->opened_path = expand_filepath(file_handle->filename, NULL TSRMLS_CC);//这里有点不懂,猜想是不是接受当前文件的路径呢?一路追踪找到了expand_filepath_ex这个函数这个函数的最后一句是return real_path;看样子应该就是返回当前要编译文件的路径吧。但是为什么要有上面那两步呢?就是设置类型和路径这两部。如果我们不做解密操作就不用这两步,我的猜想是因为fclose(file_handle->handle.fp)这里改变了file_handle的状态,所以才需要重新设置吧! //(但是有一个疑问是,这样做是Compilation之前解密,还是在Scanning之前解密?我初步认为从语义上来讲是在Compilation之前解密,但是从实际情况来看应该是要在Scanning之前解密,这边后期可以验证,事实证明后者是对的,因为compile_file函数里有对open_file_for_scanning函数的调用,也就是说在compile_file函数里执行了前面所说的123步)
入口点有了(还有4分之3的问题需要解决)。
接下来开始写解密文件的函数
需要考虑的问题有,解密文件后的明文代码,并不需要写入文件,那么如何取得这些明文的文件指针呢?用临时文件来做?但是如果每个请求都用不同的临时文件那会生成很多临时文件(显然不可行),如果对同一个php文件的不同请求只用一个临时文件,也会出现资源等待的问题(显然也不可行)。能不能直接在内存中指定一个文件指针呢?先看看php_screw的做法,调用tmpfile()产生临时文件,但是在程序退出时便会自动删除!其实我认为的在内存中的文件也是这样实现的。
直接下来把之前用php写的可逆加解密算法用c来实现,可是c并没有现成了md5和base64函数,看来只能抛弃这2个了。
写好后就开始编译了,遇到了一些错误也都改过来了。
然后链接的时候出现了错误:error LNK2001: unresolved external symbol _zend_compile_file
搜索了一下,貌似是因为函数编译方式的不一样所导致的找不到函数加入
BEGIN_EXTERN_C() ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); END_EXTERN_C()
即可
生成dll文件成功,但是不知道如何生成用于加密的可执行文件,当然最简单的解决方法就是另外建一个项目。看来只好先这样了,因为对vc的一些编译机制还有参数设置也不是很熟悉(以后再研究程序员的自我修炼好像有讲这个的)
之后又遇到c的指针传递问题(很久没弄,一些基础的都忘了,最后用二级指针来解决指针作为参数回传的问题)
又遇到了链接时找不到_zend_compile_file符号的问题(跟zend_api宏有关dllimport\dllexport)
然后又遇到读写文件的问题,其实没错,只是我把写入文件的密文手动复制内容到另一个文件中去测试,结果会出错,如果直接复制文件,或直接操作该原始文件则正确。
最后又遇到了内存不能读的错误。。。
总觉得代码没有问题,应该还是前面配置编译的时候有问题。
经过一番又一番的测试发现时php二进制包下错了我下了vc9的应该下vc6的。
相关推荐
这里的“php加密的两个扩展”指的是ytCRYPT.dll和yntCRYPT2.dll这两个动态链接库文件,它们可能是用于PHP源代码加密的工具。由于你提到这些是由国外大牛制作,且算法未知,这暗示了它们可能采用了高级或定制的加密...
"如何加密PHP源代码.zip"这个文件包显然关注的是PHP源代码的加密技术,特别是使用了ioncube工具来实现这一目标。以下是关于PHP源代码加密的一些关键知识点: 1. **PHP源代码保护**:PHP是一种解释性语言,其源码...
1. **代码混淆**:通过改变代码的可读性,使得源代码难以理解,降低被盗版或逆向工程的可能性。PHP有多种混淆工具,如Zend Guard、IonCube等。 2. **数字签名**:使用RSA等非对称加密算法为代码签名,验证软件的...
压缩包内的文件名未给出具体细节,但通常会包含PHP源代码文件、配置文件、可能的样式表(CSS)和脚本(JavaScript)文件,以及可能的示例数据或测试用例。开发者可以通过阅读源码来理解其工作原理,学习如何实现类似...
这些工具通常会将源代码转换为无法直接阅读的格式,并需要对应的解密扩展来运行。 接下来,我们关注解密工具。标题中的"php代码加密的解密工具"可能指的是用于对抗上述加密方法的工具,它们可能能够反混淆、反编码...
解密过程需要确保在不影响代码正常执行的前提下,正确还原出原始的PHP源代码。 3. 在线版的实现:该实例可能提供了一个Web接口,允许用户上传加密的PHP文件,并在线进行解密操作。这通常涉及到服务器端的处理逻辑,...
前一些PHP代码为了自我保护项目方都会对源代码进行一些加密处理,加密的方法中较为常见的一种就是Zend加密,分享一个Seay大佬写的Zend解密的工具—SeayDzend,该工具可以完美解密Zend 5.2~5.4直接的加密代码,而且是...
在PHP中,代码加密通常指的是将PHP源代码转换为难以理解或无法直接运行的形式,以保护知识产权。这种扩展是专门设计用来在PHP7环境中进行代码加密的工具,旨在提高加密效率,同时确保能够在不同的操作系统和服务器...
这样,开发者就可以使用 sodium 扩展模块来实现高级的加密和解密功能。 安装 sodium 扩展模块需要安装 libsodium 依赖项,编译 PHP 源代码,生成扩展模块,并配置扩展模块的路径和名称。这样,开发者就可以使用 ...
在压缩包中的`RSA`文件可能是这个类库的源代码,包含了实现RSA和AES加密解密功能的PHP类。这些类可能提供了如`encrypt()`和`decrypt()`等方法,方便开发者在项目中调用,无需关心底层加密算法的细节。 总的来说,`...
解密通常涉及使用特定的工具或服务,这些工具可以解析ionCube加密格式并将其还原为可读的PHP源代码。 在进行ionCube解密时,你可能会遇到以下步骤: 1. **确认环境**:首先,确保你的服务器环境是PHP 5.6,并已...
【cpp-tonyenc】是一个专为PHP7设计的高性能、跨平台代码加密扩展,它使得开发者能够更加安全地保护自己的源代码,防止未经授权的访问和使用。这个扩展使用了C++进行开发,充分利用了C++的高效性能和灵活性,同时...
了解这些内容有助于用户在使用过程中少走弯路,特别是在使用加密工具时,了解支持的PHP版本、系统环境要求、加密解密流程以及兼容性问题等细节尤为重要。 威盾PHP源码加密专家的出现,为广大PHP开发者提供了一种不...
在实际的压缩包中,这可能是一个包含所有源代码文件的主目录,或者是一个具体的PHP源代码文件,比如类库、函数集或者示例脚本。 在PHP中,字符串加密通常涉及以下几个核心知识点: 1. **对称加密**:使用相同的...
在提供的"132687511133603578"文件中,可能是源代码或者数据文件。如果是一个PHP脚本,它可能包含了上述加密解密过程的实现,例如定义了自定义的加密解密函数,或者使用了PHP的内置函数。而"使用须知.txt"文件则可能...
标题中的“【站长亲测】兽语爱语文字在线加密解密PHP网站”指的是一个基于PHP编程语言构建的在线服务,允许用户对文字、字母、数字、代码和标点符号等进行加密和解密操作。这个系统经过了网站管理员的实际测试,证明...
常用的加密方法有多种,其中一种是使用编码转换,比如base64编码,可以将PHP源代码转化为不可读的字符串。但这种方法并不安全,因为熟悉base64的开发者可以轻易地将其还原。更安全的加密方式是使用混淆技术,如PHP ...
在压缩包中的文件“screw-plus-master”可能是一个Git仓库的克隆,通常包含项目的源代码、构建脚本、文档和其他资源。用户需要展开这个文件,进入目录,然后按照README或其他相关文档的指示来编译和安装这个PHP加密...
本文将介绍三种通过自定义函数实现PHP源代码加密的方法,这些方法能够对文本内容进行二进制加密与解密。 #### 方法一:基于字符串替换的加密方式 此方法通过使用两个随机密钥,并结合`base64_encode`和`strtr`函数...
这可能涉及到特殊的编译器插件或IDE扩展,使得在开发过程中源代码能在保持加密状态下被处理。 4. **动态解密**:在运行时,源代码可能需要动态解密后执行。这种方式称为“白盒加密”,它将密钥安全地嵌入到程序中,...