
 How to write ".nes" Plugins for Nessus

 
0. Required includes and libraries
1. The arglists, the standard includes
2. The architecture of a plugin
3. How a plugin must register itself
4. System functions to improve the performances
   of a plugin
   
   
0. Required includes and libraries

 The plugins source should ONLY include the file 'includes.h'

1. The arglists

 An arglist is like the environement of the shell : it contains informations
 that the plugin may want to use, as well as informations about the plugin
 itself.
 An arglist should never be manipulated by other things that the specific
 system functions that I'll define in this document.
 	
2. The architecture of a plugin

 A plugin is a shared library which is dynamically loaded by nessusd,
 using dlopen().
 A plugin tests __one__ host, and not a whole network.
 
 It must have at least the two following functions :
 
  	int plugin_init(struct arglist *env);
 	int plugin_run(struct arglist *env);
 	
 plugin_init() is the initialization routine of the plugin, while plugin_run()
 is the main entry point of the plugin.
 
 A plugin may contain an infinite number of other functions...
 
3. How a plugin must register itself


 When nessusd is launched, it loads all the plugins that are in the 
 appropriate directory, and then calls the plugin_init() function
 of each plugin.
 During this function, the plugin must give some informations about
 itself to nessusd, such as its name, its category, and so on...
 Thus, the plugin_init() function should contain the following system
 calls :
 
  plug_set_name(struct arglist * env, char * name);
  	The name of the plugin. 'env' is the parameter given in
  	plugin_init().
  	
  	
  plug_set_description(struct arglist * env, char * description);
  	Decription of what the plugin does.
  	
  	
  plug_set_summary(struct arglist * env, char * summary);
  	Summary of the description (must be very short, because
  	it appears as a tooltips in the client)
  	
  plug_set_copyright(strct arglist * env, char * copyright);
  	Name of the author.
  	
  plug_set_category(struct arglist * env, int type); 
  
	Plugin type. Must be one of the following (declared in
	nessuslib.h) :
	
	  ACT_GATHER_INFO : what the plugin does is 100% legal.
                 This means that the plugin will access to public
                 informations on a given host (eg : it will do
                 a showmount on it, or check the presence of a
                 cgi without trying to exploit it)

          ACT_ATTACK : the plugin is aggressive against a given
                 host. It may try to get some files, such as /etc/passwd

          ACT_DENIAL : the plugin will try to crash a remote host 
          
        When the plugin are launched, they are launched using this order :
        informations, then attacks, then denial of service
        
    plug_set_family(struct arglist * env, char * family);
    
     	 Plugin family. It can be whatever you want... The 'great 
     	 families' are : CGI abuses, Denial of Service, Remote file
     	 access, etc...
     	 
        
        
        
4. "System" functions to use
       
  41. Memory-related functions

     A plugin should not use malloc() nor free(), but emalloc() and efree(),
     which are cleaner (they check that the memory could be allocated, and
     emalloc bzeroes a new pointer).
     efree() doesn't work EXACTLY the same way as 'free()', since you must
     give a pointer to your pointer as argument.
     ex:
     char * name = emalloc(300);
     /* do some stuff */
     efree(&name);
     
  42. Network-related functions

         421. Sockets

          int open_sock_tcp(struct arglist * desc, unsigned int port);
          int open_sock_udp(struct arglist * desc, unsigned int port);

                desc : the argument given in plugin_run()
                port : the port to connect to.
                
                Return :
                	the file desc. of a socket connected to this
                	port, or -1 if a problem occured.
                        
                        
	 422. Port state

	  It's possible to determine whether the remote host has
  	  a TCP port opened using the function :
	 
	  short host_get_port_state(struct arglist * env, int portnum)

	 This function reads in memory the result of the portscan, so
	 it's faster than trying to actually connect to the remote port.

	 It will return 1 if the port is open (or was not scanned), 0 if it's not.
         

         423. Misc

          short is_cgi_installed(struct arglist * desc, char * cginame);

           This function will return a non-zero value if the cgi 'cginame' is
           installed on the remote server.
           cginame must be the name of the cgi, not including its location
           (if cginame is 'phf', then this function will seek for '/cgi-bin/phf')
           
         424. Reading data from the sockets
         
          void recv_line(int soc, char * buf, int buf_len);
          
            Reads *ONE* line (until the '\n' char).
          
         425. FTP functions
         
          int ftp_log_in(int soc, char * user, char * password);
           
            This function reads the FTP banner, and logs in as user/password.
            Returns : 0 if no error occured
                      1 if some error occured
                      
          int ftp_get_pasv_address(int soc, struct sockaddr_in * addr)
          
             Sends the 'PASV' command to the remote ftp server we are connected
             to through the socket 'soc', and returns a ready-to-use
             sockaddr_in structure, containing the port to connect to, the
             server IP and all the required stuff
   
           
    43. Reporting a problem
        void post_hole(struct arglist * desc, int port, char * info);
        void post_info(struct arglist * desc, int port, char * info);

        post_hole() will be used only when a very serious problem has
        been found on port <port>.

        post_info() will be used when a little problem (ie a warning) has 
        been found on port <port>.
        
        If the problem found is not port-specific , then set <port> to
        -1.


     44. Prefs

        it's possible to access to the content of the nessusd configuration
        file.
        A nessud conf. file is like this :

        pref1 = value1
        pref2 = value2
        and so on...

        access to the preference file can be done with this
        function :

        char* get_preference(struct arglist * args, char * valuename);

                args : as usual, the argument given in plugin_run();
                valuename : the value we want.

        eg : get_preference(args, "email");
        returns the email adress of the owner of nessusd
        
        The two preferences that will be of some interest to you
        are 'email', which returns the email adress of the owner
        of nessusd and 'test_file' which is the name of the file
        that your plugin must attempt to get (in the case when 
        your plugin tries to read a file remotely).
        This value is, by default, '/etc/passwd'.
        
        Note that the two values must be checked (ie, get_preference()
        may return NULL).
        


     45. Misc

        char * plug_get_hostname(struct arglist * env);
        Get the full name of the host to test.
        
        struct inaddr * plug_get_hostip(struct arglist * env); 
        Returns a pointer to the IP of the host to test.
