赛迪网 > IT技术 IT技术关注 > 文章
  IT资讯搜索
 
IT产品搜索
[程序开发][网管世界][网络安全][数据库技术]
[操作系统][嘉宾聊天·在线访谈][活动集锦]
[精彩专题][Symantec专区][订阅IT技术周刊]
[开发论坛][网管论坛][安全论坛][数据库论坛]
[操作系统论坛][Sybase专区][IBM dW技术专区]
[病毒求助][病毒与漏洞播报][文档·源码下载]

黑客经验之杂谈PHP4内核Hacking

发布时间:2006.12.05 06:42     来源:安全焦点    作者:Darkness

此篇文章记录一下我这些天PHP 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系列处理了。这样就能正常输出了。

(t116)


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· 学生好奇当"黑客" 恶意攻击网吧数百台电脑 (12-04) · 黑客教给你之详解WMI的攻击与防御方法 (12-01)
· 黑客实战录之对一有防火墙机器的渗透 (12-01) · 如何编译一个操作系统内核-Ubuntu方式 (12-01)
· 一黑客侵入他人电脑 窥视其隐私敲诈14万元 (12-01) · 黑客经验谈之SA权限入侵的感悟 (11-30)
· 黑客利用火狐严重漏洞盗取用户密码 (11-30) · 黑客技巧之用QQ皮肤来做后门入侵 (11-27)
· 黑客攻破SQL服务器系统的十种方法 (11-24) · 分析黑客攻击方法建立具体防范措施 (11-24)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
  赛迪推荐  
  手机·资费 ·新品·导购·评测·手机资费·宽带
手机搜索  诺基亚 N73 MOTO Z6
  IT产品 ·笔记本·台式机·服务器·打印·投影
IT产品搜索 
  IT技术 ·开发·网管·安全·数据库·操作系统
  信息化 ·热点·专题·访谈·周刊·方案案例
[政务][电信][金融][农业][制造业][中小企业]
[CIO][ERP][协同][IT管理][中间件][电子商务]
[政策][地方][专家][评估][辞典][博客][社区]
· 专题:一路畅通构想曲——让出行不再遭遇堵车
· CIO工作亲历:企业ERP选型不能忽视"选人关"
· 综述:信息化建设给中国监狱带来的各种变化
· 金融业风险管理和法规遵从有五点需考虑的因素
· 保险业CIO关注:该如何建立统一高效的CRM体系
· 调查显示:多数CIO对IT规划仍存在困惑和误解
  博客·论坛 ·曾剑秋·项立刚·Java学习·网管