Guest User

Untitled

a guest
Jan 2nd, 2023
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.48 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2015 David Lundgren
  3. #
  4. # Python WMI Client
  5. # https://github.com/dlundgren/py-wmi-client
  6. #
  7. # Can be used in place of wmic when using check_wmi_plus.pl with Nagios.
  8. #
  9. # @author David Lundgren (@drlundgren)
  10. #
  11. # The MIT License (MIT)
  12. #
  13. # Copyright (c) 2015 David Lundgren
  14. #
  15. # Permission is hereby granted, free of charge, to any person obtaining a copy
  16. # of this software and associated documentation files (the "Software"), to deal
  17. # in the Software without restriction, including without limitation the rights
  18. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  19. # copies of the Software, and to permit persons to whom the Software is
  20. # furnished to do so, subject to the following conditions:
  21. #
  22. # The above copyright notice and this permission notice shall be included in all
  23. # copies or substantial portions of the Software.
  24. #
  25. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  26. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  27. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  28. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  29. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  30. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31. # SOFTWARE.
  32. #
  33. # From NEMS Linux's perspective, big thanks to Andrew Bartlett from the Samba
  34. # team for directing me to this script, removing our dependency on the old,
  35. # unsupported Samba version.
  36. #
  37. # 1.6.6 - Upgraded to Python 3 -Robbie Ferguson // NEMS Linux
  38. #
  39.  
  40. import argparse
  41. import re
  42. import sys
  43. import configparser
  44. import io
  45.  
  46. from natsort import natsorted, ns
  47. from impacket.dcerpc.v5.dtypes import NULL
  48. from impacket.dcerpc.v5.dcom import wmi
  49. from impacket.dcerpc.v5.dcomrt import DCOMConnection
  50.  
  51. APP_VERSION = '1.6.6'
  52.  
  53.  
  54. class WmiClient(object):
  55. """WMI Client"""
  56.  
  57. def __init__(self, auth, host):
  58. """
  59.  
  60. :param auth:
  61. :param host:
  62. """
  63. self.auth = auth
  64. self.host = host
  65.  
  66. def get_language(self, lang):
  67. """
  68. Retrieve the language passed in from int to string
  69.  
  70. :param lang: string
  71. :return:
  72. """
  73. if lang == 552:
  74. return 'en-US'
  75. return '??-??'
  76.  
  77. def format_value(self, value, cimtype, type):
  78. """
  79. Formats the value based on the cimtype and type
  80.  
  81. :param value:
  82. :param cimtype: string
  83. :param type: int
  84. :return:
  85. """
  86. if cimtype == 'string':
  87. if value == 0:
  88. return '(null)'
  89. else:
  90. return str(value).strip()
  91. elif cimtype == 'boolean': # boolean
  92. if value == 'True':
  93. return 'True'
  94. else:
  95. return 'False'
  96. elif value is None:
  97. if cimtype == 'uint32' or cimtype == 'uint64':
  98. return '0'
  99. else:
  100. return ('%s' % value).strip()
  101.  
  102. def print_results(self, queryObject, delimiter):
  103. """
  104. Prints the results in the classObject as wmic.c would
  105.  
  106. :param queryObject: IEnumWbemClassObject
  107. :param delimiter: string
  108. :return:
  109. """
  110.  
  111. keysprinted = False
  112.  
  113. while True:
  114. try:
  115. classObject = queryObject.Next(0xffffffff, 1)[0]
  116. # don't need this
  117. #print('CLASS: %s' % classObject.getClassName())
  118. record = classObject.getProperties()
  119. keys = []
  120. for name in record:
  121. keys.append(name.strip())
  122. keys = natsorted(keys, alg=ns.IGNORECASE)
  123.  
  124. # csv output should only have 1 header
  125. if keysprinted == False:
  126. print(delimiter.join(keys))
  127. keysprinted = True
  128.  
  129. tmp = []
  130. for key in keys:
  131. if key == 'MUILanguages':
  132. vals = []
  133. for v in record[key]['value']:
  134. vals.append(self.get_language(v))
  135. record[key]['value'] = vals
  136.  
  137. if isinstance(record[key]['value'], list):
  138. values = []
  139. for v in record[key]['value']:
  140. values.append(
  141. self.format_value(v, record[key]['qualifiers']['CIMTYPE'], record[key]['type']))
  142. tmp.append('(%s)' % ','.join(values))
  143. else:
  144. tmp.append('%s' % self.format_value(record[key]['value'], record[key]['qualifiers']['CIMTYPE'],
  145. record[key]['type']))
  146. print(delimiter.join(tmp))
  147. except Exception as e:
  148. if e.get_error_code() != wmi.WBEMSTATUS.WBEM_S_FALSE:
  149. raise
  150. else:
  151. break
  152.  
  153. def query_and_print(self, wql, **kwargs):
  154. """
  155. Querys and prints the results
  156.  
  157. :param wql:
  158. :param kwargs:
  159. :return:
  160. """
  161. namespace = '//./root/cimv2'
  162. delimiter = '|'
  163. conn = None
  164. classObject = None
  165. wmiService = None
  166. wmiLogin = None
  167.  
  168. if 'namespace' in kwargs:
  169. namespace = kwargs['namespace']
  170. if 'delimiter' in kwargs:
  171. delimiter = kwargs['delimiter']
  172.  
  173. try:
  174. conn = DCOMConnection(self.host, self.auth['username'], self.auth['password'], self.auth['domain'], '', '',
  175. None, oxidResolver=True, doKerberos=False)
  176. wmiInterface = conn.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
  177. wmiLogin = wmi.IWbemLevel1Login(wmiInterface)
  178. wmiService = wmiLogin.NTLMLogin(namespace, NULL, NULL)
  179. wmiLogin.RemRelease()
  180.  
  181. queryObject = wmiService.ExecQuery(wql.strip('\n'),
  182. wmi.WBEM_FLAG_RETURN_IMMEDIATELY | wmi.WBEM_FLAG_ENSURE_LOCATABLE)
  183. self.print_results(queryObject, delimiter)
  184. queryObject.RemRelease()
  185.  
  186. wmiService.RemRelease()
  187. conn.disconnect()
  188. except Exception as e:
  189. if classObject is not None:
  190. classObject.RemRelease()
  191. if wmiLogin is not None:
  192. wmiLogin.RemRelease()
  193. if wmiService is not None:
  194. wmiService.RemRelease()
  195. if conn is not None:
  196. conn.disconnect()
  197. raise Exception("Could not connect to %s: %s" % (self.host, e.message))
  198.  
  199.  
  200. if __name__ == '__main__':
  201. parser = argparse.ArgumentParser(description="WMI Client")
  202. parser.add_argument('-U', '--user', dest='user', help="[DOMAIN\]USERNAME[%%PASSWORD]")
  203. parser.add_argument('-A', '--authentication-file', dest='authfile', help="Authentication file")
  204. parser.add_argument('--delimiter', default='|', help="delimiter, default: |")
  205. parser.add_argument('--namespace', default='//./root/cimv2', help='namespace name (default //./root/cimv2)')
  206. parser.add_argument('host', metavar="//host")
  207. parser.add_argument('wql', metavar="query")
  208. parser.add_argument('--version', '-v', action="version", version="wmic-1.6.1-nemslinux")
  209.  
  210. options = parser.parse_args()
  211.  
  212. auth = {
  213. 'username': '',
  214. 'password': '',
  215. 'domain': ''
  216. }
  217. if options.authfile is not None:
  218. authfile = '[root]\n' + open(options.authfile, 'r').read()
  219. config = configparser.SafeConfigParser()
  220. config.readfp(io.StringIO(authfile))
  221. auth['domain'] = config.get('root', 'domain')
  222. auth['username'] = config.get('root', 'username')
  223. auth['password'] = config.get('root', 'password')
  224. elif options.user is not None:
  225. auth['domain'], auth['username'], auth['password'] = re.compile(
  226. '(?:(?:([^/\\\\%]*)[/\\\\])?([^%]*))(?:%(.*))?').match(options.user).groups('')
  227. else:
  228. print("Missing user information")
  229. sys.exit(1)
  230.  
  231. if auth['domain'] == '':
  232. auth['domain'] = 'WORKGROUP'
  233.  
  234. WmiClient(auth, options.host[2:]).query_and_print(options.wql, namespace=options.namespace,
  235. delimiter=options.delimiter)
Advertisement
Add Comment
Please, Sign In to add comment