四.数组数组是用来存储列表的,与变量不同,它允许在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
1 2 3 4 5
(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
当编写exploit的时候,我们有时需要获取用户的输入数据,比如IP地址,以便使程序根据用户的意图来执行相应的工作。对于这种情况,我们可以使用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
127.0.0.1是目标主机的IP地址,3424是端口号。下面我们举例讲解一下@ARGV的使用,以下代码将输入参数<IP>和<Port>保存在@ARGV数组中,而$0是用来代替被perl解释器所解释的文件名(比如perl riusksk.pl中$0=riusksk.pl):
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 Ca 127.0.0.1 Cp 1234
IP Address: 127.0.0.1, Port is 1234.
以上三种方法以最后一种最为常用了,常用于编写exploit。