mobiusft-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Mobiusft-list] User password report for Hive extension


From: Vladimir Santos
Subject: [Mobiusft-list] User password report for Hive extension
Date: Fri, 14 Jan 2011 06:49:47 +0300

Hello Eduardo,

I've been working on a user password hash report for use with the Hive extension and I'd like to send this new contribution to Mobius Forensic Toolkit project. It can be distributed under GPLv2 license or later.

During development I've found some bugs in the Hive extension. Firstly, there's no service for unregistering a report. A second bug is in the HiveFile.retrieve_nk method, where the classname property of a key is being miscalculated. The following code produces the right value:

key.classname = unicode(self.retrieve_value_data(value[9], value[11]), 'utf-16-le')

Another bug is the AttributeError produced when a report is selected before adding a hive file to the file list view in the Hive extension. There's yet one more bug in Hive Report extension, where the OSInformationReport class produces an struct.error if it is selected after removing the hive files from the file list view in the Hive extension.

I hope the user password report will be useful. In the following code the implementations of the RC4 and DES cryptographic algorithms in pure Python aren't very fast, but they prevent external dependencies.

Best regards,

Vladimir Santos

--- begin here ----------------------------------------------------------------

import struct
import hashlib
import binascii

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Cryptographic helper classes
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

# RC4 algorithm

class RC4(object):
  '''Alleged RC4 cipher

  Based on the posting 'RC4 Algorithm revealed' to Usenet
  newsgroups sci.crypt, alt.security, comp.security.misc and
  alt.privacy on September 14, 1994.

  http://en.wikipedia.org/wiki/RC4
  http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt
  '''
  def __init__(self, key):
    '''Creates a new RC4 object.
    '''
    if len(key) < 1 or len(key) > 256:
      raise ValueError('Key size must be between 1 and 256 bytes')

    self.__key = [ord(c) for c in key]
    self._i, self._j, self._S = self.__keyschedule(self.__key)

  def __keyschedule(self, key):
    '''Key-scheduling algorithm (KSA).
    '''
    j, S = 0, range(256)
    for i in range(256):
      j = (j + S[i] + key[i % len(key)]) % 256
      S[i], S[j] = S[j], S[i]
    i, j = 0, 0

    return i, j, S

  def __nextbyte(self, nbytes = 1):
    '''Pseudo-random generation algorithm (PRGA).
    '''
    i, j, S = self._i, self._j, self._S

    result = []
    for n in range(nbytes):
      i = (i + 1) % 256
      j = (j + S[i]) % 256
      S[i], S[j] = S[j], S[i]
      result.append(S[(S[i] + S[j]) % 256])

    self._i, self._j, self._S = i, j, S

    return result

  def __crypt(self, message):
    '''Encrypts or decrypts a message.
    '''
    return ''.join([chr(b ^ ord(c)) for b, c in
                    zip(self.__nextbyte(len(message)), message)])

  def copy(self):
    '''Makes a separate copy of this cipher object.
    '''
    other = self.__class__(self.key)
    other._i, other._j, other._S = self._i, self._j, self._S[:]
    return other

  def encrypt(self, message):
    '''Encrypts a message.
    '''
    return self.__crypt(message)
 
  def decrypt(self, message):
    '''Decrypts a message.
    '''
    return self.__crypt(message)

  @property
  def name(self):
    '''Name of the cipher algorithm.
    '''
    return 'rc4'

  @property
  def key(self):
    '''Current key of the cipher.
    '''
    return ''.join([chr(b) for b in self.__key])

  @property
  def block_size(self):
    '''Current block size of the cipher in bytes.
    '''
    return 1

  @property
  def key_size(self):
    '''Current key size of the cipher in bytes.
    '''
    return len(self.__key)

# DES algorithm

class DES(object):
  '''DES cipher

  Based on the Data Encryption Standard defined by the National
  Institute of Standards and Technology (NIST) of the U.S. Department
  of Commerce in the Federal Information Processing Standards
  Publication 46-3 (FIPS PUB 46-3).
  '''
  # Initial permutation (IP)
  __IP = (
    57, 49, 41, 33, 25, 17,  9,  1,
    59, 51, 43, 35, 27, 19, 11,  3,
    61, 53, 45, 37, 29, 21, 13,  5,
    63, 55, 47, 39, 31, 23, 15,  7,
    56, 48, 40, 32, 24, 16,  8,  0,
    58, 50, 42, 34, 26, 18, 10,  2,
    60, 52, 44, 36, 28, 20, 12,  4,
    62, 54, 46, 38, 30, 22, 14,  6
  )
  # Inverse of the initial permutation (IP^-1)
  __IP_1 = (
    39,  7, 47, 15, 55, 23, 63, 31,
    38,  6, 46, 14, 54, 22, 62, 30,
    37,  5, 45, 13, 53, 21, 61, 29,
    36,  4, 44, 12, 52, 20, 60, 28,
    35,  3, 43, 11, 51, 19, 59, 27,
    34,  2, 42, 10, 50, 18, 58, 26,
    33,  1, 41,  9, 49, 17, 57, 25,
    32,  0, 40,  8, 48, 16, 56, 24
  )
  # E bit-selection table
  __E = (
    31,  0,  1,  2,  3,  4,
     3,  4,  5,  6,  7,  8,
     7,  8,  9, 10, 11, 12,
    11, 12, 13, 14, 15, 16,
    15, 16, 17, 18, 19, 20,
    19, 20, 21, 22, 23, 24,
    23, 24, 25, 26, 27, 28,
    27, 28, 29, 30, 31,  0
  )
  # Selection functions (S1 to S8)
  __S = (
    (
       14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
        0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
        4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
       15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
    ),
    (
       15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
        3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
        0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
       13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9
    ),
    (
       10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
       13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
       13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
        1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12
    ),
    (
        7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
       13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
       10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
        3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14
    ),
    (
        2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
       14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
        4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
       11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3
    ),
    (
       12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
       10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
        9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
        4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13
    ),
    (
        4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
       13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
        1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
        6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12
    ),
    (
       13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
        1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
        7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
        2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
    )
  )
  # Permutation function
  __P = (
    15,  6, 19, 20,
    28, 11, 27, 16,
     0, 14, 22, 25,
     4, 17, 30,  9,
     1,  7, 23, 13,
    31, 26,  2,  8,
    18, 12, 29,  5,
    21, 10,  3, 24
  )
  # Permuted choice 1
  __PC1 = (
    56, 48, 40, 32, 24, 16,  8,
     0, 57, 49, 41, 33, 25, 17,
     9,  1, 58, 50, 42, 34, 26,
    18, 10,  2, 59, 51, 43, 35,
    62, 54, 46, 38, 30, 22, 14,
     6, 61, 53, 45, 37, 29, 21,
    13,  5, 60, 52, 44, 36, 28,
    20, 12,  4, 27, 19, 11,  3
  )
  # Schedule of left shifts (rotations)
  __LSHIFT = (
    1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
  )
  # Permuted choice 2
  __PC2 = (
    13, 16, 10, 23,  0,  4,
     2, 27, 14,  5, 20,  9,
    22, 18, 11,  3, 25,  7,
    15,  6, 26, 19, 12,  1,
    40, 51, 30, 36, 46, 54,
    29, 39, 50, 44, 32, 47,
    43, 48, 38, 55, 33, 52,
    45, 41, 49, 35, 28, 31
  )

  def __init__(self, key):
    '''Creates a new DES object.
    '''
    self.__key = self.__fixparity(key)
    self.__kn = self.__keyschedule(self.__key)

  def __fixparity(self, key):
    '''Sets the last bit in every byte in key to reflect the odd
    parity. If a seven byte key is used, it will be expanded into
    eight bytes.
    '''
    if len(key) not in (7, 8):
      raise ValueError('Key size must be 7 or 8 bytes')

    key = [ord(c) for c in key]

    # expand seven byte key into eight bytes
    if len(key) == 7:
      key = [key[0] & 0xfe,
             ((key[0] & 0x01) << 7) | ((key[1] & 0xfc) >> 1),
             ((key[1] & 0x03) << 6) | ((key[2] & 0xf8) >> 2),
             ((key[2] & 0x07) << 5) | ((key[3] & 0xf0) >> 3),
             ((key[3] & 0x0f) << 4) | ((key[4] & 0xe0) >> 4),
             ((key[4] & 0x1f) << 3) | ((key[5] & 0xc0) >> 5),
             ((key[5] & 0x3f) << 2) | ((key[6] & 0x80) >> 6),
             (key[6] & 0x7f) << 1]

    # set odd parity for each byte of the key
    for i in range(self.key_size):
      parity = [1 for m in [1, 2, 4, 8, 16, 32, 64, 128] if (key[i] & m) > 0]
      if (len(parity) & 0x01) == 0:
        key[i] = (key[i] & 0xfe) | ((key[i] & 0x01) ^ 0x01)

    return key

  def __keyschedule(self, key):
    '''Key scheduling.
    '''
    kn = [0] * 16
    pc = self.__permutate(DES.__PC1, key)
    for n in range(16):
      # rotate left each half
      for i in range(DES.__LSHIFT[n]):
        msb = [(b & 0x80) >> 7 for b in pc[1:]]
        msb.append((pc[3] & 0x08) >> 3)
        msb.append((pc[0] & 0x80) >> 3)
        pc = [((pc[i] << 1) & 0xff) | msb[i] for i in range(7)]
        pc[3] = (pc[3] & 0xef) | msb[7]
      kn[n] = self.__permutate(DES.__PC2, pc)

    return kn

  def __permutate(self, table, data):
    '''Permutates data bits accordingly to the specified table.
    '''
    bytenum = len(table) >> 3
    x = [0] * bytenum
    for i in range(bytenum):
      tt = table[i << 3:(i << 3) + 8]
      x[i] = (((data[tt[0] >> 3] << (tt[0] & 7)) & 0x80) |
              (((data[tt[1] >> 3] << (tt[1] & 7)) & 0x80) >> 1) |
              (((data[tt[2] >> 3] << (tt[2] & 7)) & 0x80) >> 2) |
              (((data[tt[3] >> 3] << (tt[3] & 7)) & 0x80) >> 3) |
              (((data[tt[4] >> 3] << (tt[4] & 7)) & 0x80) >> 4) |
              (((data[tt[5] >> 3] << (tt[5] & 7)) & 0x80) >> 5) |
              (((data[tt[6] >> 3] << (tt[6] & 7)) & 0x80) >> 6) |
              (((data[tt[7] >> 3] << (tt[7] & 7)) & 0x80) >> 7))

    return x

  def __crypt(self, message, rounds):
    '''Encrypts or decrypts a message.
    '''
    if len(message) % self.block_size != 0:
      raise ValueError('Cipher block length must be multiple of 8 bytes')

    result = ''
    # process data in 8-byte chunks
    for blk in range(len(message) // self.block_size):
      i = blk * self.block_size
      block = [ord(c) for c in message[i:i + self.block_size]]
      # initial permutation
      block = self.__permutate(DES.__IP, block)
      l, r = block[:4], block[4:]
      for n in rounds:
        # expand input from 32 bits to 48 bits
        b = [x ^ y for x, y in zip(self.__kn[n], self.__permutate(DES.__E, r))]
        # define 6-bit blocks
        b = [(((b[0] & 0x80) >> 2) | ((b[0] & 0x04) << 2) |
              ((b[0] & 0x78) >> 3)),
             (((b[0] & 0x02) << 4) | (b[1] & 0x10) | ((b[0] & 0x01) << 3) |
              ((b[1] & 0xe0) >> 5)),
             (((b[1] & 0x08) << 2) | ((b[2] & 0x40) >> 2) |
              ((b[1] & 0x07) << 1) | ((b[2] & 0x80) >> 7)),
             ((b[2] & 0x20) | ((b[2] & 0x01) << 4) | ((b[2] & 0x1e) >> 1)),
             (((b[3] & 0x80) >> 2) | ((b[3] & 0x04) << 2) |
              ((b[3] & 0x78) >> 3)),
             (((b[3] & 0x02) << 4) | (b[4] & 0x10) | ((b[3] & 0x01) << 3) |
              ((b[4] & 0xe0) >> 5)),
             (((b[4] & 0x08) << 2) | ((b[5] & 0x40) >> 2) |
              ((b[4] & 0x07) << 1) | ((b[5] & 0x80) >> 7)),
             ((b[5] & 0x20) | ((b[5] & 0x01) << 4) | ((b[5] & 0x1e) >> 1))]
        # consolidate a single 32-bit block from 4-bit blocks
        s = [(DES.__S[0][b[0]] << 4) | DES.__S[1][b[1]],
             (DES.__S[2][b[2]] << 4) | DES.__S[3][b[3]],
             (DES.__S[4][b[4]] << 4) | DES.__S[5][b[5]],
             (DES.__S[6][b[6]] << 4) | DES.__S[7][b[7]]]
        # permutate the result of the iteration
        l, r = r, [x ^ y for x, y in zip(l, self.__permutate(DES.__P, s))]
      # final permutation (the inverse of the initial one)
      block = self.__permutate(DES.__IP_1, r + l)
      result = ''.join((result, ''.join(chr(c) for c in block)))
    return result

  def copy(self):
    '''Makes a separate copy of this cipher object.
    '''
    other = self.__class__(self.key)
    return other

  def encrypt(self, message):
    '''Encrypts a message.
    '''
    return self.__crypt(message, range(0, 16, 1))

  def decrypt(self, message):
    '''Decrypts a message.
    '''
    return self.__crypt(message, range(15, -1, -1))

  @property
  def name(self):
    '''Name of the cipher algorithm.
    '''
    return 'des'

  @property
  def key(self):
    '''Current key of the cipher.
    '''
    return ''.join([chr(b) for b in self.__key])

  @property
  def block_size(self):
    '''Current block size of the cipher in bytes.
    '''
    return 8

  @property
  def key_size(self):
    '''Current key size of the cipher in bytes.
    '''
    return 8

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Report: User Passowrd
#
# User password hash cryptography implementation is based upon Brendan Dolan-
# Gavitt's code at framework/win32/hashdump.py in the creddump distribution
# (http://code.google.com/p/creddump/).
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class UserPasswordReport(object):

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief initialize object
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __init__(self):
    self.name = 'user passwords'
    self.viewer = None

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief System hashed bootkey
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def _get_bootkey(self, registry):
    p = 'HKLM/SYSTEM/CurrentControlSet/Control/Lsa/'
    bootkey = binascii.a2b_hex(''.join(registry.get_key(p + i).classname for i
                                       in ('JD', 'Skew1', 'GBG', 'Data')))

    # permutation matrix for boot key
    bootkey = ''.join(bootkey[i] for i in ( 8,  5,  4,  2, 11,  9, 13,  3,
                                            0,  6,  1, 12, 14, 10, 15,  7))

    f = registry.get_data('HKLM/SAM/SAM/Domains/Account/F')
    md5 = hashlib.md5(f[112:128] +
                      'address@hidden&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0' +
                      bootkey +
                      '0123456789012345678901234567890123456789\0')
    rc4 = RC4(md5.digest())

    return rc4.encrypt(f[128:160])

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Decrypt the user hash
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def _decrypt_hash(self, bootkey, rid, enc_lmnthash, lmntstr):
    md5 = hashlib.md5(bootkey[:16] + struct.pack('<I', rid) + lmntstr)
    rc4 = RC4(md5.digest())
    obfkey = rc4.encrypt(enc_lmnthash)

    # convert rid to key
    des_key = ''.join([chr(rid & 0xff), chr((rid >> 8) & 0xff),
                       chr((rid >> 16) & 0xff), chr((rid >> 24) & 0xff)])
    des1 = DES(des_key + des_key[:3])
    des2 = DES(des_key[3] + des_key + des_key[:2])

    return des1.decrypt(obfkey[:8]) + des2.decrypt(obfkey[8:])

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief generate report
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def generate(self, registry):
    if ((registry.get_key('HKLM/SYSTEM') is None) or
        (registry.get_key('HKLM/SAM') is None)):
      return

    # set report name
    name = registry.get_data('HKLM/SYSTEM/CurrentControlSet/Control/'
                             'ComputerName/ComputerName/ComputerName') or ''
    self.viewer.set_report_name('User passwords of computer <{0}>'.format(name))

    # fill data
    empty_nthash = binascii.a2b_hex('31d6cfe0d16ae931b73c59d7e0c089c0')
    empty_lmhash = binascii.a2b_hex('aad3b435b51404ee')
    bootkey = self._get_bootkey(registry)

    users = registry.get_key('HKLM/SAM/SAM/Domains/Account/Users') or []
    for key in users:
      if key.name.startswith('0'):
        rid = int(key.name, 16)

        v = key.get_data('V')

        offset, size = struct.unpack('II', v[12:20])
        username = v[0xcc + offset:0xcc + offset + size].decode('utf-16')

        offset, size = struct.unpack('II', v[156:164])
        lmhash = self._decrypt_hash(bootkey, rid, v[0xcc + offset:0xcc +
                                    offset + size][4:], 'LMPASSWORD\0')

        offset, size = struct.unpack('II', v[168:176])
        nthash = self._decrypt_hash(bootkey, rid, v[0xcc + offset:0xcc +
                                    offset + size][4:], 'NTPASSWORD\0')

        password = ''

        status = ''
        if nthash == empty_nthash or lmhash.startswith(empty_lmhash):
          status = 'empty'
        elif lmhash.endswith(empty_lmhash):
          status = 'less than 8 bytes'
        elif lmhash != '' and not lmhash.endswith(empty_lmhash):
          status = 'greater than 7 bytes'
        elif nthash == '' and lmhash == '':
          status = 'no hashes'

        self.viewer.add_row((rid, username, binascii.b2a_hex(lmhash),
                             binascii.b2a_hex(nthash), password, status))

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief build viewer
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def build_viewer(self):
    self.viewer = gdata.mediator.call('ui.new-listview', None)
    self.viewer.add_column('rid', 'RID', column_type='int', is_sortable=True)
    self.viewer.add_column('username', 'username', is_sortable=True)
    self.viewer.add_column('lmhash', 'LM hash', is_sortable=True)
    self.viewer.add_column('nthash', 'NT hash', is_sortable=True)
    self.viewer.add_column('password', 'password', is_sortable=True)
    self.viewer.add_column('status', 'password status', is_sortable=True)
    self.viewer.set_report_id('os.user-passwords')
    self.viewer.set_report_app('%s v%s' % (EXTENSION_NAME, EXTENSION_VERSION))
    self.viewer.show()

usrpwdrpt = UserPasswordReport()
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief start function
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def pvt_start():
  gdata.mediator.call('registry.add-report', usrpwdrpt)

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief stop function
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def pvt_stop():
  gdata.mediator.call('registry.remove-report', usrpwdrpt)

--- end here ------------------------------------------------------------------

reply via email to

[Prev in Thread] Current Thread [Next in Thread]