首页 -> 安全研究

安全研究

绿盟月刊
绿盟安全月刊->第8期->安全文摘
期刊号: 类型: 关键词:
RPC/XDR/NFS系列之----RPC编程初战(2)

主页:http://www.nsfocus.com
日期:2000-04-12


作者:scz < mailto: scz@nsfocus.com >
主页:http://www.nsfocus.com
      
测试:

    RedHat6.0

程序:

/*
File Name: rpcscan.c
Author   : unknown
Test     : Linux 2.2.5
Compile  : gcc -pipe -O3 -o rpcscan rpcscan.c
Date     : 2000/02/22
*/

#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <signal.h>
#include <rpc/rpc.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>

void doNothing ( int arg )
{
    return;
}  /* end of doNothing */

u_long resolveHost ( char * host )
{
    struct hostent * he;
    unsigned long    ip;

    if( ( he = gethostbyname( host ) ) == NULL )
    {
        ip = inet_addr( host );  /* 网络字节顺序 */
        if ( ip == INADDR_NONE )
        {
            ip = 0;
        }
    }
    else
    {
        bcopy( he->h_addr_list[0], &ip, sizeof( unsigned long ) );
    }
    return( ip );
}  /* end of resolveHost */

int rpcServerDump ( char * host, char * rpcServerName )
{
    struct sockaddr_in server_addr;
    struct pmaplist *  head      = NULL;
    int                rpcsocket = RPC_ANYSOCK;
    struct timeval     minutetimeout;
    register CLIENT *  clientHandle;
    struct rpcent *    rpc;

    server_addr.sin_addr.s_addr = resolveHost( host );  /* 获得远程主机IP地址 */
    server_addr.sin_family      = AF_INET;              /* 只能是这个地址族 */
    server_addr.sin_port        = htons( PMAPPORT );    /* 111端口 */
    minutetimeout.tv_sec        = 15;
    minutetimeout.tv_usec       = 0;

    /* cause clnttcp_create uses connect() */
    signal( SIGALRM, doNothing );
    alarm( 15 );
    /* 创建句柄 */
    if ( ( clientHandle = clnttcp_create( &server_addr, PMAPPROG,
           PMAPVERS, &rpcsocket, 50, 500 ) ) == NULL )
    {
        alarm( 0 );
        signal( SIGALRM, SIG_DFL );
        return( 0 );
    }
    alarm( 0 );
    signal( SIGALRM, SIG_DFL );
    /* portmapper本身是一个rpc server,提供远程过程PMAPPROC_DUMP */
    if ( clnt_call( clientHandle, PMAPPROC_DUMP, ( xdrproc_t )xdr_void, NULL,
       ( xdrproc_t )xdr_pmaplist, ( caddr_t )&head, minutetimeout ) != RPC_SUCCESS )
    {
        return( 0 );
    }
    if ( head != NULL )
    {
        for ( ; head != NULL; head = head->pml_next )
        {
            if ( ( rpc = getrpcbynumber( head->pml_map.pm_prog ) ) )  /* 可以考虑修改这里 */
            {
                if ( strcmp( rpc->r_name, rpcServerName ) == 0 )
                {
                    return( 1 );
                }
            }
        }
    }
    return( 0 );
}  /* end of rpcServerDump */

void rpcServerScan ( char * inputFileName, char * rpcServerName )
{
    FILE * inputFile;
    char   buffer[512];

    if ( ( inputFile = fopen( inputFileName, "rt" ) ) == NULL )
    {
        return;
    }
    while ( fgets ( buffer, 512, inputFile ) != NULL )
    {
        if ( buffer[ strlen( buffer ) - 1 ] == '\n' )
        {
            buffer[ strlen( buffer ) - 1 ] = '\0';
        }
        if ( rpcServerDump( buffer, rpcServerName ) )
        {
            buffer[ strlen( buffer ) + 1 ] = '\0';
            buffer[ strlen( buffer ) ]     = '\n';
            fprintf( stderr, "%s", buffer );
        }
    }  /* end of while */
    fclose( inputFile );
    return;
}  /* end of rpcServerScan */

int main ( int argc, char * argv[] )
{
    if ( argc < 3 )
    {
        fprintf( stderr, "Usage: %s <hostListFile> <rpcServerName>\n", argv[0] );
        exit( -1 );
    }
    rpcServerScan( argv[1], argv[2] );
    return( 0 );
}  /* end of main */

[scz@ /home/scz/src/rpc]> gcc -pipe -O3 -o rpcscan rpcscan.c
[scz@ /home/scz/src/rpc]> strip rpcscan
[scz@ /home/scz/src/rpc]> ./rpcscan
Usage: ./rpcscan <hostListFile> <rpcServerName>
[scz@ /home/scz/src/rpc]> ./rpcscan hostlist rpcbind
higgs.*.*.*
server.*.*.*
[scz@ /home/scz/src/rpc]>

原理:

    signal和alarm函数的使用就不用我解释了吧,W.Richard.Stevens的经典著作
    看得还不够么,尤其是华南木棉站socket版的朋友,你一定不要问我这个程序
    怎么理解,否则要倒。

    前面的系列中我们已经再三强调,portmapper本身就是一个rpc server。
    程序利用了portmapper提供的远程过程PMAPPROC_DUMP。实际上rpcinfo -p就是这样实现的。
    然后在dump出来的远程主机上的rpc server注册信息中根据关键字查找我们所关心的特定
    的rpc server。这和先用rpcinfo -p后用grep的道理是一致的。

    远程过程PMAPPROC_DUMP,顾名思义,就是dump出所有rpc server注册信息。

    hostListFile的格式如下:

    server.*.*.*
    higgs.*.*.*
    192.168.67.152
    192.168.67.124

    至于命令行上的rpcServerName如何指定,你用rpcinfo -p先看看就知道了。rpcbind正是
    portmapper本身的rpc server name。

    可以写出各种各样的rpc scan程序,后面的系列中还会给出一些,完全可以根据自己的需
    要适当修改加以利用。

    注意,一切rpc scan都是非常容易暴露自己的扫描过程,除非敢保证敌人没有条件过来修
    理你,否则还是悠着好。作为网络管理人员,一旦发现rpc scan,应该警惕,rpc scan
    是rpc remote attack的前奏,这种攻击的危害性相当大。比如前段时间攻击日本站点,
    大量使用过的rpc.cmsd,chat* sigh
版权所有,未经许可,不得转载