/pypykatz/plugins/pypykatz_rekall.py

https://github.com/skelsec/pypykatz · Python · 99 lines · 71 code · 22 blank · 6 comment · 18 complexity · 96f404ab6f1e134f609cff3d6eff8acb MD5 · raw file

  1. #from builtins import str
  2. __author__ = ("Tamas Jos <info@skelsec.com>")
  3. from pypykatz.pypykatz import pypykatz
  4. from pypykatz.commons.readers.rekall.rekallreader import RekallReader
  5. from pypykatz.commons.common import *
  6. import json
  7. import ntpath
  8. import os
  9. from rekall.plugins.windows import common
  10. class Pypykatz(common.WindowsCommandPlugin):
  11. """Extract and decrypt passwords from the LSA Security Service."""
  12. """
  13. IMPORTANT: Using the default viewer on rekall will NOT show you all the info!!!
  14. Recommendation: Use the out_file and kerberos_dir flags to get all the juicy stuff
  15. """
  16. __name = "pypykatz"
  17. __args = [
  18. dict(name="override_timestamp", type="int", required=False,
  19. help="The msv dll file timestamp detection fails in some cases."),
  20. dict(name="out_file", required=False,
  21. help="The file name to write."),
  22. dict(name="kerberos_dir", required=False,
  23. help="The file name to write."),
  24. dict(name="json", required=False, type="bool",
  25. help="Write credentials to file in JSON format"),
  26. ]
  27. table_header = [
  28. dict(name='LUID', width=6),
  29. dict(name='Type', width=8),
  30. dict(name='Sess', width=2),
  31. dict(name='SID', width=20),
  32. dict(name='Module', width=7),
  33. dict(name='Info', width=7),
  34. dict(name='Domain', width=16),
  35. dict(name='User', width=16),
  36. dict(name='SType', width=9),
  37. dict(name='Secret', width=80)
  38. ]
  39. def __init__(self, *args, **kwargs):
  40. super(Pypykatz, self).__init__(*args, **kwargs)
  41. def collect(self):
  42. cc = self.session.plugins.cc()
  43. mimi = pypykatz.go_rekall(self.session, self.plugin_args.override_timestamp)
  44. if self.plugin_args.out_file and self.plugin_args.json:
  45. self.session.logging.info('Dumping results to file in JSON format')
  46. with open(self.plugin_args.out_file, 'w') as f:
  47. json.dump(mimi, f, cls = UniversalEncoder, indent=4, sort_keys=True)
  48. elif self.plugin_args.out_file:
  49. self.session.logging.info('Dumping results to file')
  50. with open(self.plugin_args.out_file, 'w') as f:
  51. f.write('FILE: ======== MEMORY =======\n')
  52. for luid in mimi.logon_sessions:
  53. f.write('\n'+str(mimi.logon_sessions[luid]))
  54. if len(mimi.orphaned_creds) > 0:
  55. f.write('\n== Orphaned credentials ==\n')
  56. for cred in mimi.orphaned_creds:
  57. f.write(str(cred))
  58. else:
  59. self.session.logging.info('Dumping results')
  60. for luid in mimi.logon_sessions:
  61. for row in mimi.logon_sessions[luid].to_row():
  62. yield row
  63. if self.plugin_args.kerberos_dir:
  64. directory = os.path.abspath(self.plugin_args.kerberos_dir)
  65. self.session.logging.info('Writing kerberos tickets to %s' % directory)
  66. base_filename = ntpath.basename('rekall_memory')
  67. ccache_filename = '%s_%s.ccache' % (base_filename, os.urandom(4).hex()) #to avoid collisions
  68. mimi.kerberos_ccache.to_file(os.path.join(directory, ccache_filename))
  69. for luid in mimi.logon_sessions:
  70. for kcred in mimi.logon_sessions[luid].kerberos_creds:
  71. for ticket in kcred.tickets:
  72. ticket.to_kirbi(directory)
  73. for cred in mimi.orphaned_creds:
  74. if cred.credtype == 'kerberos':
  75. for ticket in cred.tickets:
  76. ticket.to_kirbi(directory)
  77. return