diff --git a/README.md b/README.md
index f6300c9..d354899 100644
--- a/README.md
+++ b/README.md
@@ -19,4 +19,19 @@ _pypykatz_ for MemProcFS exposes mimikatz functionality in the folder `/py/secre
3) Copy the _pypykatz_ for _MemProcFS_ plugin by copying all files from [`/files/plugins/pym_pypykatz`](https://github.com/ufrisk/MemProcFS-plugins/tree/master/files/plugins/pym_pypykatz) to corresponding folder in MemProcFS - overwriting any existing files there.
4) Start MemProcFS.
-#### Last updated: 2019-03-17
+## pypykatz regsecrets
+
+#### Author:
+Tamas Jos ([@skelsec](https://twitter.com/SkelSec)) , info@skelsec.com , https://github.com/skelsec/
+
+#### Overview:
+_regsecrets_ for MemProcFS exposes mimikatz functionality in the folder `/py/regsecrets/` in the file system root provided that the target is a supported Windows system. Functionality includes retrieval NTLM hashes for local accounts amongst other things.
+

+
+#### Installation instructions:
+1) Ensure MemProcFS supported version of 64-bit Python for Windows is on the system path (or specify in `-pythonpath` option when starting MemProcFS). NB! embedded Python will not work with _pypykatz_ and _aiowinreg_ since it requires access to Python pip installed packages.
+2) Install _pypykatz_ and _aiowinreg_ pip package, in correct python environment, by running `pip install pypykatz aiowinreg`.
+3) Copy the _pyregsecrets_ for _MemProcFS_ plugin by copying all files from [`/files/plugins/pym_regsecrets`](https://github.com/ufrisk/MemProcFS-plugins/tree/master/files/plugins/pym_regsecrets) to corresponding folder in MemProcFS - overwriting any existing files there.
+4) Start MemProcFS.
+
+#### Last updated: 2019-12-19
diff --git a/files/plugins/pym_regsecrets/__init__.py b/files/plugins/pym_regsecrets/__init__.py
new file mode 100644
index 0000000..e5eabee
--- /dev/null
+++ b/files/plugins/pym_regsecrets/__init__.py
@@ -0,0 +1,9 @@
+from plugins.pym_regsecrets.pym_regsecrets import (
+ Initialize,
+ Notify,
+)
+
+__all__ = [
+ "Initialize",
+ "Notify",
+]
\ No newline at end of file
diff --git a/files/plugins/pym_regsecrets/pym_regsecrets.py b/files/plugins/pym_regsecrets/pym_regsecrets.py
new file mode 100644
index 0000000..562613d
--- /dev/null
+++ b/files/plugins/pym_regsecrets/pym_regsecrets.py
@@ -0,0 +1,286 @@
+# pym_regsecrets.py
+#
+# Pypykatz RegSecrets plugin for MemProcFs
+#
+# https://github.com/skelsec/
+# https://gist.githubusercontent.com/skelsec/617abdc40a29a60edd337177f5dce85a/raw/b11e456acc23a454bd52e649cc42081c8ddd1b32/gistfile1.txt
+#
+# (c) Tamas Jos, 2019
+# Author: Tamas Jos (@skelsec), info@skelsec.com
+#
+# adaptation to MemProcFS plugin by:
+# (c) Ulf Frisk, 2019
+# Author: Ulf Frisk (@UlfFrisk), pcileech@frizk.net
+#
+
+from vmmpy import *
+from vmmpyplugin import *
+import traceback
+
+# globals needed for FS
+
+is_initialized = False
+import_failed = None
+parsing_failed = None
+result_all = ''
+result_sam = ''
+result_security = ''
+result_software = ''
+
+import_error_text_template = """
+The imports for pypykatz plugin have failed at some point.
+Common causes:
+ 1. You dont have pypykatz installed.
+ 2. You dont have the latest versions of pypykatz and/or aiowinreg.
+ 2. Python runtime environment used by MemProcFs is not the same as you have installed pypykatz in.
+ 3. You are not using the correct python version.
+
+Error traceback:
+%s
+"""
+
+parsing_error_template = """
+pypykatz plugin tried to parse the registry hives in the memory dump but failed.
+This could be caused by multiple things:
+ 1. The pypykatz's parser code is potato.
+ 2. MemProcFs could not fully parse the memory, usually this happens with incorrect memory dump files.
+
+Error traceback:
+%s
+"""
+
+import_error_text = None
+parsing_error_text = None
+
+try:
+ from pypykatz.registry.sam.sam import *
+ from pypykatz.registry.security.security import *
+ from pypykatz.registry.system.system import *
+ from pypykatz.registry.software.software import *
+ from aiowinreg.hive import AIOWinRegHive
+ from aiowinreg.filestruct.hbin import NTRegistryHbin
+ #this needs to be the last line!
+ import_failed = False
+
+except Exception as e:
+ import_failed = True
+ if VmmPyPlugin_fPrintV:
+ traceback.print_exc()
+ import_error_text = import_error_text_template % traceback.format_exc()
+ pass
+
+
+
+class MemProcFS_RegReader:
+ """
+ This class provides buffer-like reader interface which can be delegated to AIOWinreg's HIVE classes.
+ Emulates reading and seeking capablities of a buffer but actually calling the underlying MemProcFS API.
+ """
+ def __init__(self, va_hive):
+ self.va_hive = va_hive
+ self.position = 0
+ self.firstread = True
+
+ def read(self, count = -1):
+ if count < 0:
+ raise Exception('Cant read negative count')
+ elif count == 0:
+ return None
+
+ data = VmmPy_WinReg_HiveRead(self.va_hive, self.position, count, flags = 0)
+ self.position += count
+ return data
+
+ def seek(self, count, whence = 0):
+ if whence == 0:
+ if count < 0:
+ raise Exception('whence 0 requires positive values or 0')
+ self.position = count
+ elif whence == 1:
+ self.position += count
+ elif whence == 2:
+ raise Exception('Cant seek from the end!')
+
+def list_hives():
+ for x in VmmPy_WinReg_HiveList():
+ yield x
+
+
+
+def get_hive_va(hive_name, hive_name_short):
+ for hiveinfo in list_hives():
+ if 'name' in hiveinfo and hiveinfo['name'].endswith(hive_name):
+ return hiveinfo['va_hive']
+ for hiveinfo in list_hives():
+ if 'name' in hiveinfo and hive_name_short in hiveinfo['name']:
+ return hiveinfo['va_hive']
+ return None
+
+
+
+def create_hive(hive_name, hive_name_short):
+ hive_va = get_hive_va(hive_name, hive_name_short)
+ reader = MemProcFS_RegReader(hive_va)
+ hroot = NTRegistryHbin.read(reader)
+ reader = MemProcFS_RegReader(hive_va)
+ return AIOWinRegHive(reader, hroot, is_file = False)
+
+
+
+def parse_reg():
+ global result_all, result_sam, result_security, result_software
+
+ sam_hive = create_hive('SAM-MACHINE_SAM', 'SAM')
+ security_hive = create_hive('SECURITY-MACHINE_SECURITY', 'SECURITY')
+ system_hive = create_hive('SYSTEM-MACHINE_SYSTEM', 'SYSTEM')
+ software_hive = create_hive('SOFTWARE-MACHINE_SOFTWARE', 'SOFTWARE')
+
+ if system_hive is None:
+ raise Exception('System hive not found! this is mandatory for extracting secrets!')
+ system = SYSTEM(system_hive)
+ bootkey = system.get_bootkey()
+ #input('BootKey: %s' % bootkey.hex())
+
+ if sam_hive is not None:
+ sam = SAM(sam_hive, bootkey)
+ sam.get_secrets()
+ else:
+ print('SAM hive not found!')
+
+ if security_hive is not None:
+ security = SECURITY(security_hive, bootkey)
+ security.get_secrets()
+ else:
+ print('SECURITY hive not found!')
+
+ if software_hive is not None:
+ software = SOFTWARE(software_hive, bootkey)
+ software.get_default_logon()
+ else:
+ print('SOFTWARE hive not found!')
+
+ result_sam = str(sam)
+ result_security = str(security)
+ result_software = str(software)
+ result_all = result_sam + result_security + result_software
+
+
+
+def parse_reg_catch():
+ global parsing_failed, parsing_error_text
+
+ try:
+ parse_reg()
+ parsing_failed = False
+
+ except Exception as e:
+ parsing_failed = True
+ if VmmPyPlugin_fPrintV:
+ traceback.print_exc()
+ parsing_error_text = parsing_error_template % (traceback.format_exc())
+ pass
+
+
+
+def ReadResultFile(pid, file_name, file_attr, bytes_length, bytes_offset):
+ """
+ reads the all_results data as file on the virtual FS
+ """
+ global result_all, result_sam, result_security, result_software
+
+ if file_name == 'all.txt':
+ return result_all[bytes_offset:bytes_offset+bytes_length].encode()
+
+ if file_name == 'sam.txt':
+ return result_sam[bytes_offset:bytes_offset+bytes_length].encode()
+
+ if file_name == 'security.txt':
+ return result_security[bytes_offset:bytes_offset+bytes_length].encode()
+
+ if file_name == 'software.txt':
+ return result_software[bytes_offset:bytes_offset+bytes_length].encode()
+
+ return None
+
+
+
+def ReadErrors(pid, file_name, file_attr, bytes_length, bytes_offset):
+ try:
+
+ if file_name == 'import_error.txt':
+ return import_error_text.encode()[bytes_offset:bytes_offset+bytes_length]
+ if file_name == 'parsing_error.txt':
+ return parsing_error_text.encode()[bytes_offset:bytes_offset+bytes_length]
+
+ except Exception as e:
+ if VmmPyPlugin_fPrintV:
+ traceback.print_exc()
+ return None
+
+
+
+def List(pid, path):
+ #
+ # List function - this module employs a dynamic list function - which makes
+ # it responsible for providing directory listings of its contents in a
+ # highly optimized way. It is very important that the List function is as
+ # speedy as possible - to avoid locking up the file system.
+ #
+ # First check the directory to be listed. Only the module root directory is
+ # allowed. If it's not the module root directory return None.
+ global is_initialized, import_failed, parsing_failed, import_error_text, parsing_error_text
+ global result_all, result_sam, result_security, result_software
+
+ try:
+
+ if path != 'regsecrets':
+ return None
+
+ if is_initialized == False:
+ parse_reg_catch()
+ is_initialized = True
+
+ if import_failed == True:
+ print(import_failed)
+ result = {
+ 'import_error.txt': {'size': len(import_error_text), 'read': ReadErrors, 'write': None},
+ }
+ return result
+
+ if parsing_failed == True:
+ result = {
+ 'parsing_error.txt': {'size': len(parsing_error_text), 'read': ReadErrors, 'write': None},
+ }
+ return result
+
+ if path == 'regsecrets':
+ result = {
+ 'all.txt': {'size': len(result_all), 'read': ReadResultFile, 'write': None},
+ 'sam.txt': {'size': len(result_sam), 'read': ReadResultFile, 'write': None},
+ 'security.txt': {'size': len(result_security), 'read': ReadResultFile, 'write': None},
+ 'software.txt': {'size': len(result_software), 'read': ReadResultFile, 'write': None},
+ }
+ return result
+
+ return None
+
+ except Exception as e:
+ if VmmPyPlugin_fPrintV:
+ traceback.print_exc()
+ return None
+
+
+
+def Notify(fEvent, bytesData):
+ if fEvent == VMMPY_PLUGIN_EVENT_TOTALREFRESH and not import_failed and not parsing_failed:
+ global is_initialized
+ is_initialized = False
+
+
+
+def Initialize(target_system, target_memorymodel):
+ # Check that the operating system is 32-bit or 64-bit Windows. If it's not
+ # then raise an exception to terminate loading of this module.
+ if target_system != VMMPY_SYSTEM_WINDOWS_X64 and target_system != VMMPY_SYSTEM_WINDOWS_X86:
+ raise RuntimeError("Only Windows is supported by the pym_regsecrets module.")
+ VmmPyPlugin_FileRegisterDirectory(None, 'regsecrets', List)
diff --git a/files/plugins/pym_regsecrets/version.txt b/files/plugins/pym_regsecrets/version.txt
new file mode 100644
index 0000000..3eefcb9
--- /dev/null
+++ b/files/plugins/pym_regsecrets/version.txt
@@ -0,0 +1 @@
+1.0.0
diff --git a/versions.txt b/versions.txt
index 53b8d14..51b7019 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,2 +1,2 @@
-pluginupdater 1.0.0
pypykatz 1.1.0
+regsecrets 1.0.0