设为首页 友情链接
在线留言 发表文章
加入收藏 广告联系

刺猬首页

| 专案技术 | 网络技术 | 图形图象 | 网络编程 | 网页设计 | 操作系统 | 服务器 | 技术白皮书 | 在线实验室 | 刺猬论坛 |
小说专版  | 数据库 | 设计赏析 | 存储频道 | 网络安全 | 私服架设 |  Solaris | 网站评估 | PC维护技巧 | 下载中心 | 博 客 |
专   题: | Linux | java | cisco | 防病毒 | 刀片 | SOA | iscsi | ASP.NET | SQL | Oracle |
您现在的位置: IT公社 IT community >> 网络安全 >> 黑客攻防 >> 文章正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
网络黑客新手入门指南
iqst的黑客入门系列教程…
用VB学做“黑客”程序
Windows黑客编程基础(上…
flat使用经验谈
网银被盗案:黑客团伙控…
blackhat 2003 黑客大会…
black hat2003年黑客大会…
黑客技巧:利用Log备份获…
黑客技术教程:安全扫描…
  黑客经验之杂谈PHP4内核Hacking         ★★★★★
黑客经验之杂谈PHP4内核Hacking
 

先大概描述一下PHP内核的情况,PHP内核分为2个部分,ZEND和PHP CORE。ZEND可以说是PHP的内核的内核,他负责与操作系统沟通。分配内存,模块初始化什么什么的,他就负责了,同时把可读的脚本代码系统化。而PHP CORE呢,负责一些外围处理,比如与SAPI沟通。APACHE、IIS啊之类的东西。php.ini他也管。 还负责网络和文件I/O。最后提醒一句,PHP是用C写的,而不是C++,大多数资源,类型,在PHP内核中需要转换。

在C语言中,套接字这样定义:SOCKET socket(int af,int type,int protocol);

在PHP中是:

typedef int PHP_SOCKET; 

typedef struct {        

PHP_SOCKET bsd_socket;

int   type  ;      

int    error;} php_socket;

看起来是一样的。那就来看看一个最简单的网络函数。

PHP_FUNCTION(socket_write)

{

    zval        *arg1;

    php_socket    *php_sock;

    int            retval, str_len;

    long            length;

    char        *str;



    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &str,

 &str_len, &length) == FAILURE)

        return;



    ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name,

 le_socket);



    if (ZEND_NUM_ARGS() < 3) {

        length = str_len;

    }



#ifndef PHP_WIN32

    retval = write(php_sock->bsd_socket, str, MIN(length, str_len));

#else

    retval = send(php_sock->bsd_socket, str, min(length, str_len), 0);

#endif



    if (retval < 0) {

        PHP_SOCKET_ERROR(php_sock, "unable to write to socket", errno);

        RETURN_FALSE;

    }



    RETURN_LONG(retval);

}

先说zval,ZVAL是PHP内核中的结构,里面包含任何数据类型。所以在PHP内核中最好用ZVAL,而少用char *。这样可能会带来一些安全问题。看上面的代码,好象是没问题。其实不然,看char * str。他作为第2个参数被传入。

执行socket_write ( $sock, "hellosdfs35434sdvx.plpop34][[]" );

正常得很。但是如果我们提交一个PHP数组他就会暴错了。为什么呢?虽然说char str[]从某种意义上等于char * str。但是PHP中的数组和C语言可不一样。PHP程序本身这种错误太多了,PHP的开发者可能已经习惯了。

继续PHP SOCK.zend_parse_parameters函数是得到传入参数的,当CHAR类型被传入的时候,必须指定CHAR LEN.ZEND_NUM_ARGS()是得到函数个数的。

那TSRMLS_CC是什么东西。这里得专门讲一下TSRM。他的全称是Thread Safe Resource Management。

PHP是作为网络脚本来使用的,这意味着,成千上万的人在同1秒钟里可能调用同一个页面。客户A请求的是ID1,客户B请求的是ID2,以下省去数万字。

如果没有TSRM的话,单线程的SAPI还好说,像apache,iis这样的话。那么PHP可能乱套。TSRM的作用就是保持变量的中立性。在PHP中,基本上从全局传入参数都要使用TSRM.PHP hacking中也应该使用TSRM。

ZEND_FETCH_RESOURCE(php_sock, php_socket *, &arg1, -1, le_socket_name, le_socket);

相当于是把参数1 当做PHP_SOCK类型在ZEND注册资源。关于SOCKET_WRITE后面都是一些简单的C函数,就不谈了这个了。

关于PHP内核里面建立套接字还有一种方法,那就是用PHP流。PHP流是很强大的,是I/O的代名词。无论是FILE I/O,还是NETWORK I/O。

拿php_stream_open_wrapper API来说,他支持FILE、TCP、UDP、SSL、SCP、HTTP、FTP。

php_stream * stream = php_stream_open_wrapper

("http://www.php.net", "rb", REPORT_ERRORS, NULL);

if (stream) {

    while(!php_stream_eof(stream)) {

        char buf[1024];



        if (php_stream_gets(stream, buf, sizeof(buf))) {

            printf(buf);

        } else {

            break;

        }

    }

    php_stream_close(stream);

}

看了上面的代码,可以知道的是。C语言的FILE操作函数那些 加上php_stream便可以操作php i/o了。这是官方给的一个例子。有一点错误,PHP中printf是不能输出到网页的,要用php_printf或者zend_printf,php_write。

继续socket的话题。在php i/o中有一个API,可以把C语言的SOCKET劫持到PHP中。

php_stream * php_stream_sock_open_from_socket ( int socket, int persistent )

这样比起php_sock方便一些。

再谈谈PHP内核中的管道与命令执行。

编写API

{

建立管道

创建进程

返回输出管道

}

函数

{

传入参数处理

执行API

转换API管道为PHP流 

读取PHP流

输出流

}

我看了一下SYSTEM,PASSTHRU的代码,都是由popen来完成。POPEN又由popen_ex来完成。

TSRM_API FILE *popen_ex(const char *command, const char *type,

 const char *cwd, char *env)

{

             FILE *stream = NULL;

             int fno, str_len = strlen(type), read, mode;

             STARTUPINFO startup;

             PROCESS_INFORMATION process;

             SECURITY_ATTRIBUTES security;

             HANDLE in, out;

             char *cmd;

             process_pair *proc;

             TSRMLS_FETCH();



             security.nLength= sizeof(SECURITY_ATTRIBUTES);

             security.bInheritHandle = TRUE;

             security.lpSecurityDescriptor= NULL;



             if (!str_len || !CreatePipe(&in, &out, &security, 2048L)) {

                          return NULL;

             }

             

             memset(&startup, 0, sizeof(STARTUPINFO));

             memset(&process, 0, sizeof(PROCESS_INFORMATION));



             startup.cb= sizeof(STARTUPINFO);

             startup.dwFlags= STARTF_USESTDHANDLES;

             startup.hStdError= GetStdHandle(STD_ERROR_HANDLE);



             read = (type[0] == 'r') ? TRUE : FALSE;

             mode = ((str_len == 2) && (type[1] == 'b')) ? O_BINARY : O_TEXT;





             if (read) {

                          in = dupHandle(in, FALSE);

                          startup.hStdInput     = GetStdHandle(STD_INPUT_HANDLE);

                          startup.hStdOutput = out;

             } else {

                          out = dupHandle(out, FALSE);

                          startup.hStdInput     = in;

                          startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);

             }



             cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c "));

             sprintf(cmd, "%s /c %s", TWG(comspec), command);

             if (!CreateProcess(NULL, cmd, &security, &security, 

security.bInheritHandle, NORMAL_PRIORITY_CLASS, env, cwd, &startup, &process))

 {

                          return NULL;

             }

             free(cmd);



             CloseHandle(process.hThread);

             proc = process_get(NULL TSRMLS_CC);



             if (read) {

                          fno = _open_osfhandle((long)in, _O_RDONLY | mode);  

                          CloseHandle(out);

             } else {

                          fno = _open_osfhandle((long)out, _O_WRONLY | mode);

                          CloseHandle(in);

             }



             stream = _fdopen(fno, type);

             proc->prochnd = process.hProcess;

             proc->stream = stream;

             return stream;

}

process_pair是一个结构体,HANDLE和FILE。这段代码好象是一个标准的CMDSHELL。他建立了并返回了管道(文件)流。

这可是用C语言建立的管道啊,PHP并不懂的。要用PHP的一个未公开的API来完成转换。说到未公开,PHP的内核好多东西都是"未公开"的。这方面的文档少得很。

php stream * pipe  = php_stream_fopen_from_file_pipe(fp,"rb");

接下来就交给php_stram系列处理了。这样就能正常输出了。

 

责任编辑 赵毅 zhaoyi#51cto.com TEL:(010)68476636-8001



频道声明:本频道的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出出处和原始作者 文章版权归本频道与文章作者所有.对于被频道转载文章的个人和网站,我们表示深深的谢意。

原始作者:佚名 录入时间:2006-12-22 17:09:21
信息来源:不详 投稿信箱:itqoo@126.com
文章录入:itqoo    责任编辑:itqoo 
  • 上一个文章:

  • 下一个文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    - 关于我们 - 合作伙伴 - 友情链接 - 广告刊登 - 投稿热线 - 在线留言版权声明联系方式 -
    IT公社版权所有 粤ICP备05127012号
    Copyrigh@2005-2006 itqoo.com.Inc All Rights Reserved  推荐分辨率 1024*768
    联系站长:E-Mail:itqoo@126.com     MSN:urchincc@hotmail.com    QQ:点击这里给我发消息
    特别感谢:亿太网络提供空间支持