Nessus安全測試插件編寫教程(1)

作者:Renaud Deraison(Nessus最主要的編寫者,法國人)
 翻譯:nixe0n
 版本:1.0.0pre2

1.簡介

  1.1.什麼是NASL?

  NASL是一個爲網絡安全掃描工具Nessus開發的腳本語言。通過它,任何人都可以方便快速地針對新出現的漏洞編寫出測試插件,也便於不同操作系統的用戶分享測試腳本。除此之外,NASL還可以保證編寫的腳本只能用於針對目的主機的測試,使編寫者難以使用編寫的腳本用於惡意用途。


  使用NASL,你可以很容易地打造IP報文,或者發送通常的報文。NASL中還有一些專門的函數用於向FTP和WEB服務器發送數據。另外,NASL還可以保證:

   除了目標主機之外,不向任何的主機發送報文。
   不允許在本地系統執行任何命令。

  1.2.What NASL is not

  NASL不是一種功能很強大的腳本語言。它的目的只是用於安全測試。因此,別指望使用這種腳本語言寫出第三代的WEB服務器或者文件轉換工具,要編寫此類軟件還是使用Perl、Python或者其它的腳本語言吧。用它們編寫要比使用NASL快100倍。

  另外,由於NASL的設計有些倉促,在語法上還有一些需要改進的地方。

  1.3.爲什麼不在Nessus中使用Perl、Python、tcl或者其它腳本語言

  我知道有很多功能非常強大的腳本語言,和它們相比NASL功能要弱很多。不過,雖然這些語言都非常強大,但是它們都不×××全。使用這些語言,你可以非常容易地編寫出***檢測插件,泄露你的信息,讓第三者知道你是一個Nessus用戶,甚至會把一些敏感信息(例如:密碼文件)發送到第三方主機。

  使用這些語言還有另外一個問題,它們都會消耗大量的系統資源,尤其是內存。這非常令人頭疼。以Perl爲例,Perl非常棒,並且非常優美。但是,如果要使用它編寫Nessus的測試插件,你需要消耗大量的時間安裝必須的模塊,Net::RawIP就是其中之一。

  與此相反,NASL根本不會消耗大料的內存。因此,即使沒有256M內存,你也可以同時啓動20個nessusd線程。而且,對於編寫檢測插件,NASL本身就足夠了,你不必爲了爲了編寫新的安全檢測插件而安裝大量的軟件包。

  1.4.爲什麼你應該自己編寫安全測試插件

  你可能會盤算爲了自己編寫Nessus安全測試插件而在學習一種腳本語言是否值得?但是,你要知道:

   * NASL爲Nessus做過專門的優化,因此使用NASL編寫的安全測試插件效率很高。
   * 在很多方面,NASL和C非常類似,因此你沒有必要擔心很難掌握。
   * NASL非常適合編寫安全測試插件。
   * NASL的移植性很好。在M$版本的Nessus發佈之後,所有的安全測試插件根本勿需修改,就可以使用。

  1.5.這個教程會教你一些什麼東西

  這個教程的目的是教你如何使用NASL編寫自己的Nessus安全測試插件。

  1.6.NASL的侷限

  我在上面講過,NASL不是一種強大的腳本語言。它最大的侷限是:

   結構(structure)。目前NASL還不支持結構,可能在不久的將來可以支持。
   一個調試程序。NASL還沒有一個合適的debug程序。不過,有一個單獨的解釋程序nasl可以暫時用於排錯。

  1.7.感謝

  下面這些人爲NASL的設計提出了高貴的意見,作者在此致謝:

   Denis Ducamp([email protected])
   Fyodor([email protected])
   Noam Rathaus([email protected])

2.NASL基礎:語法

  在語法上,NASL非常類似於C,只是去掉了一些煩人的東西。你勿需顧及對象的類型,也不用爲它們分配和釋放內存;在使用變量之前不必事先聲明。這樣,你就可以只致力於安全測試插件的的編寫。

  如果你以前不懂C語言,讀這個教程可能要費點勁,如果你對C語言已經很精通,讀本教程將非常輕鬆。

  2.1.註釋

  在NASL中,註釋符是#。它只對當前行有效,例如:

  有效的註釋:

   a = 1 ; #let a = 1
   #set b to 2
   b = 2;

  無效的註釋:

   #
   set a to 1
   #
   a = 1;
   a = # set a to 1 # 1;

  2.2.變量、變量類型、內存分配和包含(include)

  與C語言不同,在使用變量之前,你不用事先聲明,也不用關心它們的類型。如果你的操作錯誤(例如:把一個IP報文和一個整數相加),NASL就會提醒你。你也不必關心C語言中經常遇到的內存分配和包含(include)等問題,在NASL中沒有include,而且內存是在需要時自動分配。

  2.3.數字和字符串

  NASL中的數字可以使用三種進制:十進制、十六進制和二進制。例如:

   a = 1204;
   b = 0x0A;
   c = 0b001010110110;
   d = 123 + 0xFF;

  數組必須使用引號。注意:和C語言不同,除非使用string()函數,否則NASL解釋器將不解釋特殊字符(例如:\n)。例如:

   a = "Hello\nI'm Renaud"; #a等於Hello\nI'm Renaud",\n沒有特殊含義
   a = string("Hello\nI'm Renaud");#b等於"Hello
   # I'm Renaud"
   c = string(a); #c等於b

   string()函數將在“字符串處理”中詳細討論。

  2.4.匿名/非匿名參數

  非匿名函數(Non-anonymous Function)

  NASL對函數參數的處理方式也C語言也不相同。在C語言中,程序員必須只參數的位置。

  如果一個函數的參數超過10個,就非常讓人頭疼。例如,一個構造IP報文的函數就可能有很多參數。如果你需要使用這個函數,就得記住參數的確切次序,這非常浪費時間。

  在NASL中儘量避免出現這種情況。

  在NASL中,當函數的參數次序比較重要,並且當這個函數不同的參數是不同的類型,這個函數就是一個非匿名函數。也就是,你必須給出元素名。如果你忘記了某些元素,在運行時NASL會給你錯誤提示。例如:

   forge_ip_packet()函數有很多參數。以下兩種調用方式都有效並且執行相同的操作:

    forge_ip_packet(ip_hl:5,ip_v:4,ip_p:IPPROTO_TCP);
    forge_in_packet(ip_p:IPPROTO_TCP,ip_v:4,ip_hl:5);

  在運行時,用戶會被提示缺少參數(ip_len等)。

  匿名函數(Anonymous function)

  如果函數只有一個參數,或者所有參數的類型是相同的,這種函數就叫做匿名函數。例如:

   send_packet(my_packet);
   send_packet(packet1,packet2,packet3);

  這些函數可以有選項。例如:在使用send_packet()函數時,你可以決定是否等待迴應。如果你感覺沒有必要接收目標的迴應,你可以使用如下調用形式來加速安全測試速度:

   send_packet(packet,use_pcap:FALSE);

  2.5.for和while

  在NASL中也存在for和while兩種循環控制,和C語言的幾乎完全相同,其語法格式如下:

   for(instruct_start;condition;end_loop_instruction)
    {
     #
     #需要執行的代碼
     #
    }

  或者

   for(instruction_start;condition;end_loop_instruction)fuction();

  While的格式:

   while(condition)
    {
     #
     #執行的代碼
     #
    }

  或者:

  while(condition)function();

  例如:

   # 顯示從1到0
   for(i=1;i〈=10;i=i+1)display("i : ",i,"\n");

   # 顯示從1到9以及它們是奇數還是偶數
   for(j=1;j〈=10;j=j+1)
    {
     if (j&1)display(j," is odd\n");
      else display(j," is even\n");
    }

   # 使用while
   i = 0;
   while(i〈10)
    {
     i=i+1;
    }

  2.6.用戶定義的函數

  NASL允許用戶定義自己的函數。用戶可以使用如下的語法定義自己的函數:

   function my_func(argument1,argment2,....)

  用戶定義的函數必須使用非匿名(non-anonymous)參數,NASL能夠處理遞歸調用。例如:

   function fact()
    {
     if((n==0)││(n==1))
      return(n);
     else
      return(n*fact(n:n-1));
    }

   display("b! is ",fact(n:5),"\n);

  另外,用戶自己定義的函數不能調用其它的用戶定義函數(實際上是可以的但是遇到這種情況,NASL解釋器會向你發出警告)。

  注意:如果你需要讓自己的函數返回一個值,需要使用return()函數。因爲return()是一個函數,因此需要有括號,下面這種寫法就是錯誤的:

   function func()
    {
     return 1; #這種寫法在C語言中是可以的,但是在NASL中不性
    }

  2.7.操作符

  一些標準的C語言操作符也可以用於NASL,包括:+、-、*、/和%。目前,NASL還不支持操作符的優先級,但是以後版本將會支持操作符的優先級。另外,NASL也支持C語言的二進制操作符│和&。

  除此之外,NASL還有兩個獨有的操作符:

  x操作符

  對於某些簡單的循環使用for或者while非常不便,而且每次循環還需要對條件進行檢查,造成效率的下降。因此NASL引入了一個x操作符來簡化某些循環代碼。例如:如果你需要發出10次UDP報文,使用x操作符,只要下面一行代碼就可以了:

   send_packet(udp)x10;

  〉〈操作符

  〉〈操作符是一個布爾型操作符,表示如果一個字符串A包含在另一個字符串B中,就返回真,例如:

   a = "Nessus"'
   b = "I like Nessus";
   if(a〉〈b)
    {
     #結果爲真
     display(a " is contained in ",b,"\n");
    }

3.網絡相關函數

  3.1.套接字處理

  套接字是使用TCP或者UDP協議和其它主機通訊的途徑。在NASL中不允許你直接打開一個和測試目標通訊的套接字,因此你只能使用NASL提供的函數打開套接字。

  3.1.1.如何打開一個套接字

  在NASL中,函數open_sock_tcp()和open_sock_udp()分別用於打開一個TCP或者UDP套接字。這兩個函數使用匿名(anonymous)參數。當前,你每次智能打開一個端口,將來的版本將解決這個問題。例如:你可以使用如下代碼分別打開一個TCP和UDP套接字:

   #在80端口打開一個TCP套接字
   soc1=open_sock_tcp(80);

   #在123端口打開一個UDP套接字
   soc2=open_sock_udp(123);

  如果無法和遠程主機建立連接,這兩個函數會返回0。不過,通常open_sock_udp()不會失敗,因爲沒有辦法確定遠程主機的UDP端口是否開放,對於open_sock_tcp(),如果遠程主機的端口是關閉的,它就會返回0。

  open_sock_tcp()可以用於對TCP端口的簡單掃描,例如:

   start = prompt("First port to scan?"); #輸入開始的端口
   end = prompt("Last port to scan?"); #輸入結束的端口
   for(i=start;i〈end;i=i+1)
    {
     soc=open_sock_tcp(i);
     if(soc)
      {
       display("Port ",i," is open\n");
       close(soc);
      }
    }

  3.1.2.關閉一個端口

  關閉一個端口使用close()函數,在close()內部,關閉端口之前,它首先會調用shutdown()函數。

  3.1.3.讀寫套接字

  根據被讀寫的套接字類型,可以選擇使用如下函數完成這兩項操作:

   recn(socket:〈socketname〉,length:〈length〉 [,timeout:〈timeout〉])

  從套接字〈socketname〉讀取〈length〉個字節,這個函數可以用於TCP和UDP。超時(timeout)參數是可選的,以秒爲單位。

   recv_line(socket:〈socketname〉,length:〈length〉 [,timeout:〈timeout〉])

  這個函數和recv()函數類似,只是如果遇到換行(\n)操作終止。這個函數只能用於TCP套接字。

   send(socket:〈socket〉,data:〈data〉 [,length:〈length〉])

  從套接字〈socket〉發送數據〈data〉。可選參數length告訴函數發送〈length〉字節。如果沒有設置length,發送操作就在遇到NULL時終止。

  如果沒有設置超時參數,讀函數(recv()和recv_line())就使用默認的超時時間5秒。如果時間到,它們就返回FALSE。例如:

   # 以下代碼用於顯示遠程主機的banner信息
   soc = open_sock_tcp(21);
   if(soc)
    {
     data = recv_line(socket:soc,length:1024);
     if(data)
      {
       display("The remote FTP banner is : \n",data,"\n");
      }
     else
      {
       display("The remote FTP server seems to be tcp-wrapper\n");
      }
     close(soc);
    }

  3.1.4.高層操作

  NASL有一些針對FTP和WWW協議的函數,用於簡化對這兩個應用層協議的某些操作。

   ftp_log_in(socket:〈soc〉,user:〈login〉,pass:〈pass〉)

  嘗試通過〈soc〉套接字登錄到遠程FP主機。如果用戶名〈login〉和密碼〈pass〉都正確,就返回TRUE,否則返回FALSE。

  ftp_get_pasv_port(socket:〈soc〉)

  向遠程FTP服務器發出一個PASV命令,獲得連接的端口。NASL腳本可以通過這個端口從FTP服務器下載數據。如果發生錯誤函數將返回FALSE。

  is_cgi_installed(〈name〉)

  測試遠程WEB服務器是否安裝了名爲〈name〉的CGI程序。這個函數向遠程WEB服務器發出GET請求實現這個目的。如果〈name〉不是以斜槓(/)開頭,就認爲它是相對於/cgi-bin/。

  這個函數也可以用於確定某個文件是否存在。

  示例腳本:

   #
   # 針對WWW服務器的測試
   #
   if(is_cgi_installed("/robots.txt"))
    {
     display("The file /robots.txt is present\n");
    }

   if(is_cgi_installed("php.cgi"))
    {
     display("The CGI php.cgi is installed in /cgi-bin/\n");
    }

   if(!is_cgi_installed("/php.cgi"))
    {
     display("There is no php.cgi in the remote web root\n");
    }

   #
   # 針對FTP服務器的測試
   #
   # 打開一個連接
   soc = open_sock_tcp(21);
   # 匿名登錄到遠程FTP主機
   if(ftp_log_in(socket:soc,user:"anonymous",pass:"joe@"))
    {
     # 打開一個被動傳輸模式的端口
     port = ftp_get_pasv_port(socket:soc);
     if(port)
      {
       soc2 = open_sock_tcp(port);
       #嘗試獲得遠程系統的/etc/passwd文件
       data = string("RETR /etc/passwd\r\n");
       send(socket:soc,data:data);
       password_file = recv(socket:soc2,length:10000);
       display(password_file);
       close(soc2);
      }
     close(soc);
    }

  3.2.原始報文處理

  NASL允許用戶構造自己的IP報文,而且報文的定製是以一種智能的方式進行的。例如,如果你改變了一個TCP報文的某個參數,就會造成其TCP校驗和發生改變,但是你不必爲此費心,NASL會自動完成。

  所有的原始報文構造函數都使用非匿名(non-anonymous)參數。參數的名字都是來自BSD的包含文件。因此一個IP報文的長度域叫做ip_len而不是length。

  3.2.1.構造IP報文

  在NASL中,你可以使用forge_ip_packet()函數構造一個新的IP報文;使用set_ip_element()函數獲得報文某個域的值;使用set_ip_element()函數改變現有IP跋文某個域的值。forge_ip_packet函數的原形如下:

   〈return_value〉=forge_ip_packet(
     ip_hl :〈ip_hl〉,
     ip_v :〈ip_v〉,
     ip_tos :〈ip_tos〉,
     ip_len :〈ip_len〉,
     ip_id :〈ip_id〉,
     ip_off :〈ip_off〉,
     ip_ttl :〈ip_ttl〉,
     ip_p :〈ip_p〉,
     ip_src :〈ip_src〉,
     ip_dst :〈ip_dst〉,
     [ip_sum :〈ip_sum〉]);

  其中,ip_sum參數是可選的,如果沒有使用,NASL會自動計算報文的校驗和。ip_p參數可以是一個整數值,或者是IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP、IPPROTO_IGMP或者IPPROTO_IP等常量中的某個值。

  get_ip_element()函數的原型如下:

   〈element〉=get_ip_element(
     ip :〈ip_varible〉,
     element :"ip_hl"│"ip_v"│ip_tos"│"ip_len"│
     "ip_id"│"ip_off"│"ip_ttl"│"ip_p"│
     "ip_sum"│"ip_src"│"ip_dst");

  get_ip_element()將返回報文中的某個域的值。element參數必須是"ip_hl"、"ip_v"、ip_tos"、"ip_len"、"ip_id"、"ip_off"、"ip_ttl"、"ip_p"、"ip_sum"、"ip_src"、"ip_dst"中的一個,而且引號是必不可少的。

  set_ip_elements()函數的原型如下:
   set_ip_elements(
    ip :〈ip_variable〉,
    [ip_hl :〈ip_hl〉,]
    [ip_v :〈ip_v〉,]
    [ip_tos :〈ip_tos〉,]
    [ip_len :〈ip_len〉,]
    [ip_id :〈ip_id〉,]
    [ip_off :〈ip_off〉,]
    [ip_ttl :〈ip_ttl〉,]
    [ip_p :〈ip_p〉,]
    [ip_src :〈ip_src〉,]
    [ip_dst :〈ip_dst〉,]
    [ip_sum :〈ip_sum〉]
   );

  這個函數可以改變IP報文〈ip_varible〉的值,如果你沒有修改ip_sum域的值,它會自動重新計算。這個函數沒有構造報文的能力,因此需要把它放在forge_ip_packet()函數之後。

  最後,還有一個函數dump_ip_packet()需要說明一下,這個函數能夠以可讀的方式把IP報文的內容輸出到屏幕。這個函數應該只用於調試目的。

  3.2.2.構造一個TCP報文

  forge_tcp_packet()用來構造TCP報文。函數原型如下:

   tcppacket = forge_tcp_packet(
    ip :〈ip_packet〉,
    th_sport :〈source_port〉,
    th_dport :〈destination_port〉,
    th_flags :〈tcp_flags〉,
    th_seq :〈sequence_number〉,
    [th_x2 :〈unused〉],
    th_off :〈offset〉,
    th_win :〈window〉,
    th_urp :〈urgent_pointer〉,
    th_sum :〈checksum〉,
    [data :〈data〉]);

  其中,標誌參數th_flags必須是TH_SYN、TH_ACK、TH_FIN、TH_PUSH或者TH_RST,這些標誌可以使用│操作符結合到一塊。th_flags還可以使用一個整數值。ip_packet必須首先由forge_ip_packet()函數產生或者使用send_packet()、pcap_next()函數得到的返回值。

  函數set_tcp_elements()能夠修改TCP報文的內容,其原型如下:

   set_tcp_elements(
    tcp :〈tcp_packet〉,
    [th_sport :〈source_port〉,]
    [th_dport :〈destination_port〉,]
    [th_flags :〈tcp_flags〉,]
    [th_seq :〈sequence_number〉,]
    [th_ack :〈acknowledgement_number〉,]
    [th_x2 :〈unused〉,]
    [th_off :〈offset〉,]
    [th_win :〈window〉,]
    [th_urp :〈urgent_pointer〉,]
    [th_sum :〈checksum〉,]
    [data :〈data〉]);

  除非你自己設置th_sum參數,否則函數會自動計算報文的校驗和。

  函數get_tcp_element()用來設置TCP報文的內容,其原型如下:

   element = get_tcp_elements(
    tcp :〈tcp_packet〉,
    element :〈element_name〉);

  element_name必須是"tcp_sport"、"th_dport"、"th_flags"、"th_seq"、"th_ack"、"th_x2"、"th_off"、"th_win"、"th_urp"、"th_sum"其中之一。注意:引號是不可缺少的。

  3.2.3.構造UDP報文

  UDP報文構造函數forge_udp_packet()和TCP構造函數極爲類似,其原型如下:

   udp = forge_udp_packet(
    ip :〈ip_packet〉,
    uh_sport :〈source_port〉,
    uh_dport :〈destination_port〉,
    uh_ulen :〈length〉,
    [uh_sum :〈checksum〉,]
    [data :〈data〉]);

  而set_udp_elements()和get_udp_elements()函數和TCP報文對應的處理函數用法也相同。

  3.2.4.構造ICMP報文
  3.2.5.構造IGMP報文
  3.2.6.發送報文

  構造報文的操作完成之後,你可以使用send_packet()函數將它們發送出去,其原型如下:

   reply = send_packet(packet1,packet2,....,packetN,
    pcap_active:〈TRUE│FALSE〉,
    pcap_filter:〈pcap_filter〉);

  如果pcap_active參數爲TRUE,這個函數就會等待目標的迴應。pcap_filter用來設置你需要得到的報文類型,詳情請參考pcap或者tcpdump的手冊頁。

  3.2.7.讀取報文

  你可以使用pcap_next()函數讀取一個報文,其原型如下:

   reply = pcap_next();

  這個函數將從你使用的最後一個接口讀取一個報文,報文的類型取決於最後設置的pcap類型。

  3.3.工具函數

  NASL還提供了一些工具函數以簡化你的編程。

   this_host()

  獲得運行腳本的主機IP地址,沒有參數。

   get_host_name()

  返回當前被測試主機的主機名,沒有參數。

   get_host_ip()

  返回當前被測試主機的IP地址,沒有參數。

   get_host_open_port()

  獲得遠程主機打開的第一個端口號,沒有參數。這個函數對於某些腳本(例如:land)非常有用,有些TCP序列號分析程序需要通過這個函數獲得遠程主機一個打開的端口。

   get_port_stat(〈portnum〉)

  如果TCP端口〈portnum〉打開或者其狀態是未知,就返回TRUE。

   telnet_init(〈soc〉)

  在一個打開的套接字上初始化一個telnet會話,並且返回telnet數據的第一行。例如:

   soc = open_sock_tcp(23);
   buffer = telnet_init(soc);
   display("The remote telnet banner is ",buffer,"\n");
   tcp_ping()

  如果遠程主機應答TCP ping請求(發送一個設置ACK標誌的TCP報文),本函數就返回TRUE,沒有參數。

   getrpcport()

  獲得遠程主機的RPC端口號,原型爲:

   result = getrpcport(program :〈program_number),
    protocol :〈IPPROTO_TCP│IPPROTO_UDP,
    [version :〈version〉]);

  如果遠程主機的〈program_number〉程序沒有在RPC portmap監控進程中註冊就返回0。

4.字符串處理函數

  NASL允許你象處理數字一樣處理字符串。因此,你能夠安全地使用==、〈和〉等操作符。

  例如:
   
   a = "version 1.2.3";
   b = "version 1.4.1";
   if(a〈b)
    {
     #因爲version 1.2.3比version 1.4.1低
     #因此,開始執行這裏的代碼
    }
   c = "version 1.2.3";
   if(a == c)
    {
     #兩個字符串相等
     #因此執行這裏的代碼
    }

  在NASL中,也可以獲得一個字符串的某個字符,和C語言完全相同,例如:

   a = "test";
   b = a[1]; #b等於"e"

  你也可以在一個字符串中加、減一個字符串,例如:

   a = "version 1.2.3";
   b = a - "version"; #b等於"1.2.3"
   a = "this is a test";
   b = "is a ";
   c = a - b; #c等於"this test"
   a = "test";
   c = " is a ";
   c = a - b; #a等於"testtest"

  除此之外,〉〈也可以用於字符串的處理。NASL有很多函數來構造或者修改字符串:

  4.1.處理正則表達式的ereg()函數

  在NASL中,模式匹配是由ereg()函數完成的。原型如下:

   result = ereg(pattern:〈pattern,string:〈string〉)

  正則表達式的語法是egrep風格的。細節請參考egrep的手冊頁。例如:

   if(ereg(pattern:".*",string:"test"))
    {
     display("Always execute\n");
    }

   mystring=recv(socket:soc,length:1024);
   if(ereg(pattern:"SSH-.*-1\..*",string:mysting))
    {
     display("SSH 1.x is running on this host");
    }

  4.2.egrep()函數

  egrep()函數返回一個多行文本中,匹配〈pattern〉的第一行。如果對單行文本使用這個函數,它就相當於ereg()。如果沒有匹配的行,它就返回FALSE。其原型如下:

   str=egrep(pattern:〈pattern〉,string:〈string〉)

  示例:

   soc=open_soc_tcp(80);
   str=string("HEAD / HTTP/1.0\r\n\r\n");
   sen(socket:soc,data:str);
   r=recv(socket:soc,length:1024);
   server=egrep(pattern:"^Server.*",string:r);
   if(server)display(server);

  4.3.crap()函數

  crap()函數非常便於測試緩衝區溢出,有兩種原型:

   crap(〈length〉)

  獲得一個以'X'填充的長度爲〈length〉的字符串。

   crap(length:〈length〉,data:〈data〉)

  高一個長度爲〈length〉的字符串,並使用〈data〉填充字符串。例如:

   a=crap(5); #a="XXXXX"
   b=crap(4096); #b="XXX...XXX"(4096個X)
   c=crap(length:12,data:"hello"); #c="hellohellohe"

  4.4.string()函數

  這個函數用來定製字符串。其原型爲:

   string(〈string1〉,[〈string2〉,...,〈stringN〉]);

  它能夠解釋字符串中\n、\t等特殊字符。例如:

   name="Renand";
   a=string("Hello,I am ",name,"\n"_; #a等於"Hello,I am Renaud"
   #末尾回行
   b=string(1," and "m",2," make ",1+2); #b等於"1 and 2 make 3"
   c=string("MKD ",crap(4096),"\r\n"); #c等於"MKD XXX...XXXXX"(4096個X)
   #後面是一個回車和一個回行

  4.5.strlen()函數

  strlen()函數返回一個字符串的長度,例如:

  a==strlen("abcd"); #a等於4

  4.6.raw_string()函數

  這個函數能夠把數字轉換爲對應的字符,例如:

   a=raw_string(80,81,82); #80、81、82分別對應ASCII字符的PQR

  4.7.strtoint()函數

  這個函數把一個NASL整數轉換爲一個二進制整數。原型爲:

   value=strtolen(number:〈nasl_integer〉,size:〈number_of_byte〉);

  這個函數比較適合於和raw_string()函數一塊使用。size參數是NASL整數的字節數,可以是:1、2、4。

  4.8.tolower()函數

  這個函數能夠把一個字符串中的所有大寫字符轉換爲小寫字符。原型爲:

   string2=tolower(〈string〉);

  例如:

   a="Hello,World"
   b=tolower(a); #b等於"hello,world"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章