NASL的语法同C非常类似,除了移除掉一些C中令人困扰的东西。你不用关心你的变量的类型,也不用关心内存的申请和释放。在使用变量之前也不需要声明。你只需要专注于你的安全测试。
如果你不知道C,那么此篇为C程序员写的教程阅读起来可能会比较困难。不要抱怨,这本手册将来更具可读性。
注释字符是“#”。它仅能注释当前行。 例子:
合法的注释:
a = 1; #let a = 1
#Set b to 2:
b = 2;
非法的注释:
#
set a to 1:
#
a = 1;
a = # set a to 1 #1;
你不要在使用变量之前声明它, 也不需要关心变量类型。NASL解释器在你尝试写一些不符合语法的代码时提示你, 比如把一个IP报文和一个整数相加。你也不需要关心内存分配和包含。NASL中没有包含(从目前最新的nasl脚本来看,还是有包含的:( ),而且内存在需要时会自动分配。
可以使用三种数制类型:十进制,十六进制,以及二进制。
例如:
a = 1024;
b = 0x0A;
c = 0b001010110110;
d = 123 + 0xFF;
字符串必须用引号括起来。和C不一样。NASL不会去解析特殊字符,除非使用string()函数。
例如:
a = "Hello\nI'm Renaud"; # a equals to "Hello\nI'm Renaud"
b = string("Hello\nI'm Renaud"); # b equals to "Hello
# I'm renaud"
c = string(a); # c equals to b
string()函数将在 字符串操作 中解释。
在处理函数参数上,NASL同C有一个不一样的地方。在C中, 你必须知道每一个参数的位置和顺序。当一个函数的参数多达10个以上的时候,你就头疼了。例如,一个组装IP报文的函数,需要茫茫多的参数,如果你要使用它,就需要通过阅读文档来记住参数们的位置和顺序。这太浪费时间了,所以NASL尝试避免这种情况。
所以,当函数参数有不同的类型,且参数顺序很重要的时候, 就要定义一个命名函数了。你必须给每一个参数命名。当你忘记其中一些参数时,在运行时,NASL会给出一些提示。
例如:
forge_ip_packet()函数有很挫的参数。下面这两个调用方式都是对的,且功能是一样的:
forge_ip_packet(ip_hl : 5, ip_v : 4,
ip_p : IPPROTO_TCP);
forge_ip_packet(ip_p : IPPROTO_TCP,
ip_v : 4, ip_hl : 5);
在运行时,用户会被提示缺少参数(ip_len等等)。当然安全测试脚本不能和用户交互,但是方便快速编码和调试。
匿名函数是只有一个参数或者多个相同类型的参数的函数。
例如:
send_packet(my_packet);
send_packet(packet1, packet2, packet3);
这些函数可能会有一些可选项。比如,send_packet()函数在等待目标的响应。如果你觉得没必要等待,可以停用等待加快测试速度:
send_packet(packet, use_pcap:FALSE);
for和while跟c中类似。
for:
for(instruction_start;condition;end_loop_instruction)
{
#
# Some instructions here
#
}
或者
for(instruction_start;condition;end_loop_instruction)function();
while:
while(condition)
{
#
# Some instructions here
#
}
或者
while(condition)function();
例子:
# Count from 1 to 10
for(i=1;i<=10;i=i+1)
display("i : ", i, "\n");
# Count from 1 to 9, and say the type
# of each number (even or odd)
for(j=1;j<10;j=j+1)
{
if(j & 1)
display(j, " is odd\n");
else
display(j, " is even\n");
}
# Do something completely useless :
i = 0;
while(i < 10)
{
i = i+1;
}
NASL现在已经支持自定义函数。一个自定义函数可以像这样定义:
function my_function(argument1, argument2, ....)
自定义函数必须使用命名参数。NASL可以处理递归调用。
例如:
function fact(n)
{
if((n == 0)||(n == 1))
return(n);
else
return(n*fact(n:n-1));
}
display("5! is ", fact(n:5), "\n");
自定义函数中不能包含其他的自定义函数(实际上是可以的,但在这种情况下,NASL解释器会告警)。 注意,如果你想要你的函数返回值(大部分函数的目的), 那么你需要使用return()函数。 因此,return必须使用括号。
下面是一个错误的用法:
function func()
{
return 1; # parenthesis are missing here !
}
标准C中的一些操作符,同样可以用在NASL中,例如: +, -, *, / 以及 %。 目前操作符优先级还不支持,但是以后会更新。除此之外,还支持二进制操作符 | 和 &。另外还有两个C中没有的操作符。
for和while都很实用。但在一些情况下会有性能损失,因为每次迭代中,条件都需要计算。比如你想发送一个SYN风暴或者别的,就比较麻烦了。’x’操作符可以重复相同的函数N次,而且非常快(跟C的速度差不多)。
例如:
send_packet(udp) x 10;
将会发送相同的udp包10次。
‘><’ 是一个布尔操作符。如果A字符被包含在B字符中,则返回true。
例如:
a = "Nessus";
b = "I use Nessus";
if(a >< b)
{
# This will be executed since
# a is in B
display(a, " is contained in ", b, "\n");
}