###################################################################
# 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 the list of active and inactive 
  services and drivers of the remote host, using the MS-DCE/RPC
  protocol over SMB.

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

  Solution : To prevent access to the services and drivers 
  list, 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  #################
###################################
