###################################################################
# OpenVAS Vulnerability Test
#
# SMB Enumerate Services
#
# LSS-NVT-2010-001
#
# Developed by LSS Security Team <http://security.lss.hr>
#
# Copyright(C) 2010 LSS <http://www.lss.hr>
#
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 2 of
# the License, or(at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
###################################################################

if(description)
{
  script_id(102016);
  script_version("$Revision$-1.0");
  script_name("SMB Enumerate Services");
  desc = "
  This plugin implements the SvcOpenSCManager() and
  SvcEnumServices() calls to obtain, using the MS-DCE/RPC
  protocol over SMB, the list of active and inactive services and drivers
  of the remote host.

  An attacker may use this feature to gain better
  knowledge of the remote host.

  Solution : To prevent the listing of the services for being
  obtained, you should either have tight login restrictions,
  so that only trusted users can access your host, and/or you
  should filter incoming traffic to this port.

  Risk factor : Low
  ";
  script_description(desc);
  script_summary("Enumerates the list of remote services and drivers");
  script_category(ACT_GATHER_INFO);
  script_copyright("Copyright(C) 2010 LSS");
  script_family("Windows");
  script_dependencies('netbios_name_get.nasl', 'smb_login.nasl');
  script_require_keys('SMB/transport', 'SMB/name', 'SMB/login', 'SMB/password');
  script_require_ports(139, 445);
  exit(0);
}

include('smb_nt.inc');

#--------------------------------------------------------#
# Decodes the data sent back by svcenumservicesstatus()  #
#--------------------------------------------------------#

function svc_decode(data)
{
  # ret = '';
  sz = '';
  if(strlen(data) < 128)
    return(FALSE);

  for(i=4;i>0;i=i-1) 
    {
      sz = sz * 256;
      sz = sz + ord(data[123+i]);
    }

  # display('size : ', sz, '\n');

  len = strlen(data);
  num_svc = ord(data[len-15]);
  num_svc = num_svc * 256;
  num_svc = num_svc + ord(data[len-16]);

  if(!num_svc)
    {
      return(FALSE);
    }
  ret[0] = num_svc; # number of 'services'(services, drivers, processes)

  off = 0;
  lim = num_svc * 0x24;

  for(j = 0; j < lim; j = j + 0x24)
    {
      for(i = 4; i > 0; i = i - 1)
        {
          off = off * 256;
          off = off + ord(data[87+i+j]);
        }

      off2 = 0;
      for(i = 4; i > 0; i = i - 1)
        {
          off2 = off2 * 256;
          off2 = off2 + ord(data[91+i+j]);
        }

      if(off2 > strlen(data))return(0);
      if(off > strlen(data))return(0);

      name = '';
      svc = '';
      for(k=0;k<255;k = k+1)
        {
          if(!(ord(data[off2+k+88])))
            k = 255;
          else
            name = string(name, raw_string(ord(data[off2+k+88])));
        }

      for(k=0;k<255;k=k+1)
        {
          if(!(ord(data[off+k+88])))
            k = 255;
          else  
            svc = string(svc, raw_string(ord(data[off+k+88])));
        }

      ret[1] = ret[1] + string(name, ' [', svc, ']\n');
    }
  return(ret);
}


#------------------------------------------------------#
# Obtains a handle we use in svcenumservicesstatus()   #
#------------------------------------------------------#
function svcopenscmanager(soc, name, uid, tid, pipe)
{
  tid_low = tid % 256;
  tid_high = tid / 256;
  uid_low = uid % 256;
  uid_high = uid / 256;
  pipe_low = pipe % 256;
  pipe_high = pipe / 256;

  req = raw_string(0x00, 0x00,
        0x00, 0x9c, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
        0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x59, 0x81,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
        g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00,
        0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
        0x00, 0x48, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
        0x00, pipe_low, pipe_high, 0x59, 0x00, 0x00, 0x5C, 0x00,
        0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
        0x5C, 0x00, 0x00, 0x00, 0x00, 0x14, 0x05, 0x00,
        0x0B, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x16,
        0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x81, 0xBB,
        0x7A, 0x36, 0x44, 0x98, 0xF1, 0x35, 0xAD, 0x32,
        0x98, 0xF0, 0x38, 0x00, 0x10, 0x03, 0x02, 0x00,
        0x00, 0x00, 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C,
        0xC9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10,
        0x48, 0x60, 0x02, 0x00, 0x00, 0x00);

  send(socket:soc, data:req);
  r = smb_recv(socket:soc, length:4096);
  if(!r)return(FALSE);

  len = strlen(name);
  add = 4 -((len+1) % 4);

  tot_len = 133 + len + add;
  tot_len_lo = tot_len % 256;
  tot_len_hi = tot_len / 256;

  if(odd)len = len + 1; 
  bcc = 66 + len + add;
  bcc_lo = bcc % 256;
  bcc_hi = bcc / 256;
  tot = 49 + len + add ;
  tot_hi = tot/256;
  tot_lo = tot%256;
 
  len2 = 25 + len + add;
  len2_lo = len2 % 256;
  len2_hi = len2 / 256;

  len    = len + 1;
  len_lo = len % 256;
  len_hi = len / 256;

  req = raw_string(0x00, 0x00,
        tot_len_hi, tot_len_lo, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
        0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x63, 0x81,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
        g_mlo, g_mhi, 0x10, 0x00, 0x00, tot_lo, tot_hi, 0x00,
        0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
        0x00, tot_lo, tot_hi, 0x54, 0x00, 0x02, 0x00, 0x26,
        0x00, pipe_low, pipe_high, bcc_lo, bcc_hi, 0x00, 0x5C, 0x00,
        0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
        0x5C, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x05, 0x00,
        0x00, 0x03, 0x10, 0x00, 0x00, 0x00, tot_lo, tot_hi,
        0x00, 0x00, 0x01, 0x00, 0x00, 0x00, len2_lo, len2_hi,
        0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x60, 0x02,
        0x7D, 0x00, len_lo, len_hi, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, len_lo, len_hi, 0x00, 0x00) +
        tolower(name) + raw_string(0);
      
  # req = req + raw_string(0x00);
  # else req = req + raw_string(0x00, 0x00);
  if( add )
    {
      req = req + crap(data:raw_string(0), length:add);
    }

  req = req + raw_string(0x00, 0x00,
        0x00, 0x00, 0x04, 0x00, 0x00, 0x00);
  
  send(socket:soc, data:req);
  r = smb_recv(socket:soc, length:4096);
  if(!r) return(FALSE);
  # if(strlen(r) < 100)return(FALSE);
  if(strlen(r) < 104) exit(0);
  # display('hu\n');
  
  #
  # extract the handle
  #
  hdl = '';
  i = 0;
  for(i = 0; i < 21; i= i + 1)
    {
      # display(hex(ord(r[83+i])), ' ');
      hdl =  string(hdl, raw_string(ord(r[83+i])));
    }
  # display('\n');
  return(hdl);
}


#------------------------------------------------#
# creates a valid smbreadx() request             #
#------------------------------------------------#
function smbreadx()
{
 return(raw_string(0x00, 0x00,
        0x00, 0x3C, 0xFF, 0x53, 0x4D, 0x42, 0x2E, 0x00,
        0x00, 0x00, 0x00, 0x18, 0x00, 0x80, 0x00, 0x00, 
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
        g_mlo, g_mhi, 0x0C, 0xFF, 0x00, 0x00, 0x00, pipe_low,
        pipe_high, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x02));
}


#----------------------------------------------#
# returns TRUE if svcenumservicesstatus needs  #
# to call smbreadx() to get the rest of the    #
# services list                                #
#----------------------------------------------#


function moredata(data)
{
  len_data = strlen(data);
  start = len_data - 4;
  for(_i = start; _i < len_data; _i = _i + 1)
    {
      # display(hex(data[_i]), ' ');
      if(ord(data[_i])) return(TRUE);
    }
  return(FALSE);
}

# svcenumservicesstatus global constants
SERVICE_STATE_ACTIVE              = raw_string(0x01, 0x00, 0x00, 0x00);
SERVICE_STATE_INACTIVE            = raw_string(0x02, 0x00, 0x00, 0x00);
SERVICE_STATE_ALL                 = raw_string(0x03, 0x00, 0x00, 0x00);#( SERVICE_STATE_ACTIVE | SERVICE_STATE_INACTIVE )
SERVICE_TYPE_KERNEL_DRIVER        = raw_string(0x01, 0x00, 0x00, 0x00);
SERVICE_TYPE_FS_DRIVER            = raw_string(0x02, 0x00, 0x00, 0x00);
SERVICE_TYPE_ADAPTER              = raw_string(0x04, 0x00, 0x00, 0x00);#couldn't get to work
SERVICE_TYPE_RECOGNIZER_DRIVER    = raw_string(0x08, 0x00, 0x00, 0x00);#couldn't get to work
SERVICE_TYPE_DRIVER               = raw_string(0x0F, 0x00, 0x00, 0x00);#(SERVICE_TYPE_KERNEL_DRIVER|SERVICE_TYPE_FS_DRIVER|SERVICE_TYPE_RECOGNIZER_DRIVER
SERVICE_TYPE_WIN32_OWN_PROCESS    = raw_string(0x10, 0x00, 0x00, 0x00);
SERVICE_TYPE_WIN32_SHARE_PROCESS  = raw_string(0x20, 0x00, 0x00, 0x00);
SERVICE_TYPE_WIN32                = raw_string(0x30, 0x00, 0x00, 0x00);#SERVICE_TYPE_WIN32_OWN_PROCESS|SERVICE_TYPE_WIN32_SHARE_PROCESS
SERVICE_TYPE_INTERACTIVE_PROCESS  = raw_string(0x00, 0x01, 0x00, 0x00);#0x100;

#----------------------------------------------#
# svcenumservicesstatus() :                    #
# This function makes the appropriate calls    #
# to get the list of the remote active services#
# and decodes the result. It returns FALSE if  #
# no service is running at all.                #
#----------------------------------------------#
function svcenumservicesstatus(soc, name, uid, tid, pipe, handle, svc_type, svc_state)
{
  tid_low = tid % 256;
  tid_high = tid / 256;
  uid_low = uid % 256;
  uid_high = uid / 256;
  pipe_low = pipe % 256;
  pipe_high = pipe / 256;

  #
  # We make a first call to svcenumservicesstatus(), and we declare
  # our buffer size as being 0 bytes. We receive an error with the
  # amount of bytes we'd need, then we make a second request
  # with that value.
  #
 
  #
  # First request
  #
  req = raw_string(0x00, 0x00,
        0x00, 0x94, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
        0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x6B, 0x80,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
        g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00,
        0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
        0x00, 0x40, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
        0x00, pipe_low, pipe_high, 0x51, 0x00, 0x00, 0x5C, 0x00,
        0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
        0x5C, 0x00, 0x00, 0x00, 0x00, 0x88, 0x05, 0x00,
        0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00,
        0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x1A) + handle + svc_type + svc_state +
        raw_string(0x24, 0x00, 0x00, 0x00, 0x74, 0xFF,
        0x12, 0x00, 0x00, 0x00, 0x00, 0x00);

  # display('strlen(req) : ', strlen(req), '\n');
  send(socket:soc, data:req);
  r = smb_recv(socket:soc, length:1024);
  if(strlen(r) < 128) return(NULL);
  len = '';
  for(i = 124; i < 128; i = i + 1) len = string(len, raw_string(ord(r[i])));

  #
  # Second request, with the appropriate length
  # 
  req = raw_string(0x00, 0x00,
        0x00, 0x94, 0xFF, 0x53, 0x4D, 0x42, 0x25, 0x00,
        0x00, 0x00, 0x00, 0x18, 0x03, 0x80, 0x6B, 0x80,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, tid_low, tid_high, 0x00, 0x28, uid_low, uid_high,
        g_mlo, g_mhi, 0x10, 0x00, 0x00, 0x40, 0x00, 0x00,
        0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
        0x00, 0x40, 0x00, 0x54, 0x00, 0x02, 0x00, 0x26,
        0x00, pipe_low, pipe_high, 0x51, 0x00, 0x00, 0x5C, 0x00,
        0x50, 0x00, 0x49, 0x00, 0x50, 0x00, 0x45, 0x00,
        0x5C, 0x00, 0x00, 0x00, 0x00, 0x88, 0x05, 0x00,
        0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00,
        0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x28, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x1A) + 
        handle + svc_type + svc_state + len + 
        raw_string(0x74, 0xFF,
        0x12, 0x00, 0x00, 0x00, 0x00, 0x00);

  send(socket:soc, data:req);
  r = smb_recv(socket:soc, length:65535);

  #
  # get what's left - smbreadX request
  #
  if(ord(r[9]))
    {
      req = smbreadx();
      send(socket:soc, data:req);
      r2 = smb_recv(socket:soc, length:67000);
 
      #
      # Merge the relevant portion of r2 into r
      #
      len_r2 = strlen(r2);
      for(k = 64; k < len_r2; k = k + 1)
        {
          r = r + raw_string(ord(r2[k]));
        }

      while(moredata(data:r2))
        {
          req = smbreadx();
          send(socket:soc, data:req);
          r2 = smb_recv(socket:soc, length:67000);
          len_r2 = strlen(r2);
          for(k = 88; k < len_r2; k = k + 1)
            {
              # display('->', r2[k], '\n');
              r = r + raw_string(ord(r2[k]));
            }
        }
    }

  # display(r);
  ret = svc_decode(data:r);
  if(svc_state == SERVICE_STATE_ACTIVE)
    {
      if(svc_type == SERVICE_TYPE_KERNEL_DRIVER)
        {
          set_kb_item(name:'SMB/number_of_active_kernel_drivers', value:ret[0]);
          set_kb_item(name:'SMB/active_kernel_drivers', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_FS_DRIVER)
        {
          set_kb_item(name:'SMB/number_of_active_fs_drivers', value:ret[0]);
          set_kb_item(name:'SMB/active_fs_drivers', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_ADAPTER)
        {
          set_kb_item(name:'SMB/number_of_active_adapters', value:ret[0]);
          set_kb_item(name:'SMB/active_adapters', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_RECOGNIZER_DRIVER)
        {
          set_kb_item(name:'SMB/number_of_active_recognizer_drivers', value:ret[0]);
          set_kb_item(name:'SMB/active_recognizer_drivers', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_DRIVER)
        {
          set_kb_item(name:'SMB/number_of_active_drivers', value:ret[0]);
          set_kb_item(name:'SMB/active_drivers', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_WIN32_OWN_PROCESS)
        {
          set_kb_item(name:'SMB/number_of_active_win32_own_processes', value:ret[0]);
          set_kb_item(name:'SMB/active_win32_own_procesess', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_WIN32_SHARE_PROCESS)
        {
          set_kb_item(name:'SMB/number_of_active_win32_share_processes', value:ret[0]);
          set_kb_item(name:'SMB/active_win32_share_procesess', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_WIN32)
        {
          set_kb_item(name:'SMB/number_of_active_win32_procesess', value:ret[0]);
          #set_kb_item(name:'SMB/active_win32_procesess', value:ret[1]);
          set_kb_item(name:'SMB/svcs', value:ret[1]); #changed naming convention to "svcs" to accomodate dependencies
        }
      if(svc_type == SERVICE_TYPE_INTERACTIVE_PROCESS)
        {
          set_kb_item(name:'SMB/number_of_active_interactive_processes', value:ret[0]);
          set_kb_item(name:'SMB/active_interactive_procesess', value:ret[1]);
        }
    }
  else if(svc_state == SERVICE_STATE_INACTIVE)
    {
      if(svc_type == SERVICE_TYPE_KERNEL_DRIVER)
        {
          set_kb_item(name:'SMB/number_of_inactive_kernel_drivers', value:ret[0]);
          set_kb_item(name:'SMB/inactive_kernel_drivers', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_FS_DRIVER)
        {
          set_kb_item(name:'SMB/number_of_inactive_fs_drivers', value:ret[0]);
          set_kb_item(name:'SMB/inactive_fs_drivers', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_ADAPTER)
        {
          set_kb_item(name:'SMB/number_of_inactive_adapters', value:ret[0]);
          set_kb_item(name:'SMB/inactive_adapters', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_RECOGNIZER_DRIVER)
        {
          set_kb_item(name:'SMB/number_of_inactive_recognizer_drivers', value:ret[0]);
          set_kb_item(name:'SMB/inactive_recognizer_drivers', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_DRIVER)
        {
          set_kb_item(name:'SMB/number_of_inactive_drivers', value:ret[0]);
          set_kb_item(name:'SMB/inactive_drivers', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_WIN32_OWN_PROCESS)
        {
          set_kb_item(name:'SMB/number_of_inactive_win32_own_processes', value:ret[0]);
          set_kb_item(name:'SMB/inactive_win32_own_procesess', value:ret[1]);
        }
        if(svc_type == SERVICE_TYPE_WIN32_SHARE_PROCESS)
        {
          set_kb_item(name:'SMB/number_of_inactive_win32_share_processes', value:ret[0]);
          set_kb_item(name:'SMB/inactive_win32_share_procesess', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_WIN32)
        {
          set_kb_item(name:'SMB/number_of_inactive_win32_procesess', value:ret[0]);
          set_kb_item(name:'SMB/inactive_win32_procesess', value:ret[1]);
        }
      if(svc_type == SERVICE_TYPE_INTERACTIVE_PROCESS)
        {
          set_kb_item(name:'SMB/number_of_inactive_interactive_processes', value:ret[0]);
          set_kb_item(name:'SMB/inactive_interactive_procesess', value:ret[1]);
        }
    }

  return(ret);      
}

####################################
###########  MAIN  #################
####################################

port = kb_smb_transport();
if(!port)port = 139;
login = kb_smb_login();
domain = kb_smb_domain();
pass = kb_smb_password();
name = chomp(kb_smb_name()); #TODO: check for a bug! kb_smb_name returned a name with trailing whitespace!

soc = open_sock_tcp(port);
if(!soc)
  {
    log_message(data:'MAIN: Can not open socket on tcp port ' + port);
    exit(-1);
  }

r = smb_session_request(soc:soc, remote:name);
if(!r)
  {
    log_message(data:'MAIN: SMB session request failed');
    close(soc);
    exit(-1);
  }

prot = smb_neg_prot(soc:soc);
if(!prot)
  {
    log_message(data:'MAIN: SMB negotiate protocol failed');
    close(soc);
    exit(-1);
  }

r = smb_session_setup(soc:soc, login:login, password:pass, domain:domain, prot:prot);
if(!r)
  {
    log_message(data:'MAIN: SMB session setup failed');
    close(soc);
    exit(-1);
  }

uid = session_extract_uid(reply:r);
if(!uid)
  {
    log_message(data:'MAIN: SMB session setup extract UID failed');
    close(soc);
    exit(-1);        
  }

r = smb_tconx(soc:soc, name:name, uid:uid, share:'IPC$');
if(!r)
  {
    log_message(data:'MAIN: SMB tree connect failed');
    close(soc);
    exit(-1);
  }

tid = tconx_extract_tid(reply:r);
if(!tid)
  {
    log_message(data:'MAIN: SMB tree extract TID failed');
    close(soc);
    exit(-1);
  }

# Create a pipe to \svcctl
r = smbntcreatex(soc:soc, uid:uid, tid:tid, name:'\\svcctl');
if(!r)
  {
    log_message(data:'MAIN: SMB open \\svcctl pipe failed');
    close(soc);
    exit(-1);
  }

# and extract its ID
pipe = smbntcreatex_extract_pipe(reply:r);
if(!pipe)
  {
    log_message(data:'MAIN: SMB extract FID failed');
    close(soc);
    exit(-1);
  }

# For the moment bind() is implemented in svcopenscmanager(). Due for implementation in msrpc.inc.
# dcerpc_bind(soc:soc, user_id:uid, tree_id:tid, fid:pipe); 

handle = svcopenscmanager(soc:soc, name:name, uid:uid, tid:tid, pipe:pipe);
if(handle == FALSE)
  {
    log_message(data:'MAIN: RPC OpenServiceManager failed');
    close(soc);
    exit(-1);  
  }

report_data = '';
report_data_separator = '\n\n##############################################\n\n';

services = svcenumservicesstatus(soc:soc, name:name, uid:uid, tid:tid, pipe:pipe,handle:handle, svc_type: SERVICE_TYPE_WIN32, svc_state: SERVICE_STATE_ACTIVE);
if(services == null)
  {
    log_message(data:'MAIN: RPC Enum Services(WIN32 active services) failed');
  }
report_data += 'WIN32 active services: \n' + services[1];
report_data += report_data_separator;

services = svcenumservicesstatus(soc:soc, name:name, uid:uid, tid:tid, pipe:pipe,handle:handle, svc_type: SERVICE_TYPE_WIN32, svc_state: SERVICE_STATE_INACTIVE);
if(services == null)
  {
    log_message(data:'MAIN: RPC Enum Services(WIN32 inactive services) failed');
  }
report_data += 'WIN32 inactive services: \n' + services[1];
report_data += report_data_separator;

services = svcenumservicesstatus(soc:soc, name:name, uid:uid, tid:tid, pipe:pipe,handle:handle, svc_type: SERVICE_TYPE_DRIVER, svc_state: SERVICE_STATE_ACTIVE);
if(services == null)
  {
    log_message(data:'MAIN: RPC Enum Services(WIN32 active drivers) failed');
  }
report_data += 'WIN32 active drivers: \n' + services[1];
report_data += report_data_separator;

services = svcenumservicesstatus(soc:soc, name:name, uid:uid, tid:tid, pipe:pipe,handle:handle, svc_type: SERVICE_TYPE_DRIVER, svc_state: SERVICE_STATE_INACTIVE);
if(services == null)
  {
    log_message(data:'MAIN: RPC Enum Services(WIN32 inactive drivers) failed');
  }
report_data += 'WIN32 inactive drivers: \n' + services[1];
report_data += report_data_separator;

services = svcenumservicesstatus(soc:soc, name:name, uid:uid, tid:tid, pipe:pipe,handle:handle, svc_type: SERVICE_TYPE_INTERACTIVE_PROCESS, svc_state: SERVICE_STATE_ACTIVE);
if(services == null)
  {
    log_message(data:'MAIN: RPC Enum Services(WIN32 active interactive services) failed');
  }
report_data += 'WIN32 active interactive services: \n' + services[1];
report_data += report_data_separator;

services = svcenumservicesstatus(soc:soc, name:name, uid:uid, tid:tid, pipe:pipe,handle:handle, svc_type: SERVICE_TYPE_INTERACTIVE_PROCESS, svc_state: SERVICE_STATE_INACTIVE);
if(services == null)
  {
    log_message(data:'MAIN: RPC Enum Services(WIN32 inactive interactive services) failed');
  }
report_data += 'WIN32 inactive interactive services: \n' + services[1];

security_note(data:report_data, port: port);

# display(services[1]);

close(soc);

###################################
###########  END  #################
###################################
