Repository: libyal/winreg-kb Branch: main Commit: 86dfd461ed7f Files: 200 Total size: 63.0 MB Directory structure: gitextract_od6kibol/ ├── .github/ │ └── workflows/ │ ├── test_docker.yml │ ├── test_docs.yml │ ├── test_macos.yml │ └── test_tox.yml ├── .gitignore ├── .pylintrc ├── .readthedocs.yaml ├── .yamllint.yaml ├── ACKNOWLEDGEMENTS ├── AUTHORS ├── LICENSE ├── MANIFEST.in ├── MANIFEST.test_data.in ├── README.md ├── appveyor.yml ├── config/ │ ├── appveyor/ │ │ └── install.ps1 │ ├── dpkg/ │ │ ├── changelog │ │ ├── clean │ │ ├── compat │ │ ├── control │ │ ├── copyright │ │ ├── python3-winregrc.install │ │ ├── rules │ │ └── source/ │ │ └── format │ └── pylint/ │ └── spelling-private-dict ├── dependencies.ini ├── docs/ │ ├── conf.py │ ├── index.rst │ ├── requirements.txt │ └── sources/ │ ├── EventLog-keys.md │ ├── api/ │ │ ├── modules.rst │ │ ├── winregrc.rst │ │ └── winregrc.scripts.rst │ ├── application-keys/ │ │ ├── 7-Zip.md │ │ ├── CCleaner.md │ │ ├── MSDN-web-browser.md │ │ ├── Microsoft-Office.md │ │ ├── Terminal-server-client.md │ │ ├── WinRAR.md │ │ └── index.rst │ ├── explorer-keys/ │ │ ├── Bit-bucket.md │ │ ├── Control-panel-item-identifiers.md │ │ ├── Delegate-folders.md │ │ ├── Known-folder-identifiers.md │ │ ├── MUI-cache.md │ │ ├── Most-recently-used.md │ │ ├── Mount-points.md │ │ ├── Program-cache.md │ │ ├── Shell-folders.md │ │ ├── Typed-paths.md │ │ ├── User-assist.md │ │ └── index.rst │ ├── internet-explorer-keys/ │ │ ├── Browser-helper-objects.md │ │ ├── Policies.md │ │ ├── Types-URLs.md │ │ └── index.rst │ ├── security-accounts-manager-keys/ │ │ ├── Domains.md │ │ ├── Security-accounts-manager.md │ │ └── index.rst │ ├── system-keys/ │ │ ├── Application-compatibility-cache.md │ │ ├── Background-activity-moderator.md │ │ ├── Boot-verification.md │ │ ├── COM-class-identifiers.md │ │ ├── Cached-credentials.md │ │ ├── Certificates.md │ │ ├── Codepage.md │ │ ├── Current-control-set.md │ │ ├── Environment-variables.md │ │ ├── File-system.md │ │ ├── Language.md │ │ ├── Local-security-authority.md │ │ ├── Mounted-devices.md │ │ ├── Prefetch.md │ │ ├── Run-and-RunOnce.md │ │ ├── Services-and-drivers.md │ │ ├── Session-manager.md │ │ ├── Shell-folder-identifiers.md │ │ ├── System-restore.md │ │ ├── Task-scheduler.md │ │ ├── Time-zones.md │ │ ├── USB-storage.md │ │ ├── Volume-shadow-copies.md │ │ ├── Windows-error-reporting.md │ │ ├── Windows-product-information.md │ │ ├── Windows-system-locations.md │ │ └── index.rst │ └── windows-registry/ │ ├── Files.md │ ├── Hives.md │ ├── MUI-form.md │ └── index.rst ├── pyproject.toml ├── run_tests.py ├── test_data/ │ ├── NTUSER.DAT.LOG │ ├── SAM │ ├── SECURITY │ ├── SOFTWARE │ └── SYSTEM ├── test_dependencies.ini ├── tests/ │ ├── __init__.py │ ├── appcompatcache.py │ ├── application_identifiers.py │ ├── cached_credentials.py │ ├── data_format.py │ ├── environment_variables.py │ ├── eventlog_providers.py │ ├── filters.py │ ├── hexdump.py │ ├── interface.py │ ├── knownfolders.py │ ├── mounted_devices.py │ ├── mru.py │ ├── msie_zone_info.py │ ├── output_writer.py │ ├── profiles.py │ ├── programscache.py │ ├── sam.py │ ├── services.py │ ├── shellfolders.py │ ├── sysinfo.py │ ├── task_cache.py │ ├── test_lib.py │ ├── type_libraries.py │ └── userassist.py ├── tox.ini ├── utils/ │ ├── __init__.py │ ├── check_dependencies.py │ ├── dependencies.py │ └── update_release.sh ├── winreg-kb.ini └── winregrc/ ├── __init__.py ├── appcompatcache.py ├── appcompatcache.yaml ├── application_identifiers.py ├── cached_credentials.py ├── catalog.py ├── controlpanel_items.py ├── data/ │ └── observed_shellfolders.yaml ├── data_format.py ├── delegatefolders.py ├── environment_variables.py ├── errors.py ├── eventlog_providers.py ├── filters.py ├── hexdump.py ├── interface.py ├── knownfolders.py ├── mounted_devices.py ├── mounted_devices.yaml ├── mru.py ├── mru.yaml ├── msie_zone_info.py ├── output_writers.py ├── profiles.py ├── programscache.py ├── programscache.yaml ├── sam.py ├── sam.yaml ├── scripts/ │ ├── __init__.py │ ├── appcompatcache.py │ ├── application_identifiers.py │ ├── cached_credentials.py │ ├── catalog.py │ ├── controlpanel_items.py │ ├── delegatefolders.py │ ├── environment_variables.py │ ├── eventlog_providers.py │ ├── knownfolders.py │ ├── mounted_devices.py │ ├── mru.py │ ├── msie_zone_info.py │ ├── profiles.py │ ├── programscache.py │ ├── sam.py │ ├── services.py │ ├── shellfolders.py │ ├── srum_extensions.py │ ├── sysinfo.py │ ├── syskey.py │ ├── task_cache.py │ ├── time_zones.py │ ├── type_libraries.py │ ├── usbstor.py │ └── userassist.py ├── services.py ├── shell_property_keys.py ├── shellfolders.py ├── srum_extensions.py ├── sysinfo.py ├── syskey.py ├── task_cache.py ├── task_cache.yaml ├── time_zone_information.yaml ├── time_zones.py ├── type_libraries.py ├── usbstor.py ├── usbstor.yaml ├── userassist.py ├── userassist.yaml ├── versions.py └── volume_scanner.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/test_docker.yml ================================================ # Run tests on Fedora and Ubuntu Docker images using GIFT COPR and GIFT PPA on commit name: test_docker on: [push] permissions: read-all jobs: test_fedora: runs-on: ubuntu-latest strategy: matrix: version: ['43'] container: image: registry.fedoraproject.org/fedora:${{ matrix.version }} steps: - uses: actions/checkout@v6 - name: Set up container run: | dnf install -y dnf-plugins-core langpacks-en - name: Install dependencies run: | dnf copr -y enable @gift/dev dnf install -y @development-tools libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3 python3-acstore python3-artifacts python3-build python3-devel python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pytsk3 python3-pyyaml python3-setuptools python3-wheel python3-xattr - name: Run tests env: LANG: C.utf8 run: | python3 ./run_tests.py - name: Run end-to-end tests run: | if test -f tests/end-to-end.py; then PYTHONPATH=. python3 ./tests/end-to-end.py --debug -c config/end-to-end.ini; fi - name: Build source distribution (sdist) run: | python3 -m build --no-isolation --sdist - name: Build binary distribution (wheel) run: | python3 -m build --no-isolation --wheel test_ubuntu: runs-on: ubuntu-latest strategy: matrix: version: ['26.04'] container: image: ubuntu:${{ matrix.version }} steps: - uses: actions/checkout@v6 - name: Set up container env: DEBIAN_FRONTEND: noninteractive run: | apt-get update -q apt-get install -y libterm-readline-gnu-perl locales software-properties-common locale-gen en_US.UTF-8 ln -f -s /usr/share/zoneinfo/UTC /etc/localtime - name: Install dependencies run: | add-apt-repository -y ppa:gift/dev apt-get update -q apt-get install -y build-essential libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3 python3-acstore python3-artifacts python3-build python3-dev python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-venv python3-wheel python3-xattr python3-yaml - name: Run tests env: LANG: en_US.UTF-8 run: | python3 ./run_tests.py - name: Run end-to-end tests env: LANG: en_US.UTF-8 run: | if test -f tests/end-to-end.py; then PYTHONPATH=. python3 ./tests/end-to-end.py --debug -c config/end-to-end.ini; fi - name: Build source distribution (sdist) run: | python3 -m build --no-isolation --sdist - name: Build binary distribution (wheel) run: | python3 -m build --no-isolation --wheel ================================================ FILE: .github/workflows/test_docs.yml ================================================ # Run docs tox tests on Ubuntu Docker images using the deadsnakes and GIFT PPAs name: test_docs on: pull_request: branches: - main push: branches: - main permissions: read-all jobs: build: runs-on: ubuntu-latest strategy: matrix: python-version: ['3.12'] container: image: ubuntu:24.04 steps: - uses: actions/checkout@v6 - name: Set up container env: DEBIAN_FRONTEND: noninteractive run: | apt-get update -q apt-get install -y libterm-readline-gnu-perl locales software-properties-common locale-gen en_US.UTF-8 ln -f -s /usr/share/zoneinfo/UTC /etc/localtime - name: Install dependencies env: DEBIAN_FRONTEND: noninteractive run: | add-apt-repository -y universe add-apt-repository -y ppa:deadsnakes/ppa add-apt-repository -y ppa:gift/dev apt-get update -q apt-get install -y build-essential git libffi-dev pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-acstore python3-artifacts python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml tox - name: Run tests env: LANG: en_US.UTF-8 run: | tox -e docs ================================================ FILE: .github/workflows/test_macos.yml ================================================ # Run tests on Mac OS. name: test_macos on: [push, pull_request] permissions: read-all jobs: test_macos: runs-on: ${{ matrix.os }} strategy: matrix: include: - os: macos-26 python-version: '3.14' toxenv: 'py314' steps: - uses: actions/checkout@v6 - name: Install dependencies run: | brew update -q brew install -q gettext gnu-sed python@${{ matrix.python-version }} tox || true brew link --force gettext - name: Run tests run: | tox -e ${{ matrix.toxenv }} ================================================ FILE: .github/workflows/test_tox.yml ================================================ # Run tox tests on Ubuntu Docker images using the deadsnakes and GIFT PPAs name: test_tox on: pull_request: branches: - main push: branches: - main permissions: read-all jobs: build: runs-on: ubuntu-latest strategy: matrix: include: - python-version: '3.10' toxenv: 'py310' - python-version: '3.11' toxenv: 'py311' - python-version: '3.12' toxenv: 'py312' - python-version: '3.13' toxenv: 'py313' - python-version: '3.14' toxenv: 'py314' container: image: ubuntu:24.04 steps: - uses: actions/checkout@v6 - name: Set up container env: DEBIAN_FRONTEND: noninteractive run: | apt-get update -q apt-get install -y libterm-readline-gnu-perl locales software-properties-common locale-gen en_US.UTF-8 ln -f -s /usr/share/zoneinfo/UTC /etc/localtime - name: Install dependencies env: DEBIAN_FRONTEND: noninteractive run: | add-apt-repository -y universe add-apt-repository -y ppa:deadsnakes/ppa add-apt-repository -y ppa:gift/dev apt-get update -q apt-get install -y build-essential git libffi-dev pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-acstore python3-artifacts python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml tox - name: Run tests env: LANG: en_US.UTF-8 run: | tox -e ${{ matrix.toxenv }},wheel coverage: runs-on: ubuntu-latest strategy: matrix: python-version: ['3.12'] container: image: ubuntu:24.04 steps: - uses: actions/checkout@v6 - name: Set up container env: DEBIAN_FRONTEND: noninteractive run: | apt-get update -q apt-get install -y libterm-readline-gnu-perl locales software-properties-common locale-gen en_US.UTF-8 ln -f -s /usr/share/zoneinfo/UTC /etc/localtime - name: Install dependencies env: DEBIAN_FRONTEND: noninteractive run: | add-apt-repository -y universe add-apt-repository -y ppa:deadsnakes/ppa add-apt-repository -y ppa:gift/dev apt-get update -q apt-get install -y build-essential curl git libffi-dev pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-acstore python3-artifacts python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml tox - name: Run tests with coverage env: LANG: en_US.UTF-8 run: | tox -e coverage - name: Upload coverage report to Codecov uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} lint: runs-on: ubuntu-latest strategy: matrix: python-version: ['3.12'] container: image: ubuntu:24.04 steps: - uses: actions/checkout@v6 - name: Set up container env: DEBIAN_FRONTEND: noninteractive run: | apt-get update -q apt-get install -y libterm-readline-gnu-perl locales software-properties-common locale-gen en_US.UTF-8 ln -f -s /usr/share/zoneinfo/UTC /etc/localtime - name: Install dependencies env: DEBIAN_FRONTEND: noninteractive run: | add-apt-repository -y universe add-apt-repository -y ppa:deadsnakes/ppa add-apt-repository -y ppa:gift/dev apt-get update -q apt-get install -y build-essential git libffi-dev pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv libbde-python3 libcaes-python3 libcreg-python3 libewf-python3 libfcrypto-python3 libfsapfs-python3 libfsext-python3 libfsfat-python3 libfshfs-python3 libfsntfs-python3 libfsxfs-python3 libfvde-python3 libfwnt-python3 libfwps-python3 libfwsi-python3 libhmac-python3 libluksde-python3 libmodi-python3 libphdi-python3 libqcow-python3 libregf-python3 libsigscan-python3 libsmdev-python3 libsmraw-python3 libvhdi-python3 libvmdk-python3 libvsapm-python3 libvsgpt-python3 libvshadow-python3 libvslvm-python3 python3-acstore python3-artifacts python3-dfdatetime python3-dfimagetools python3-dfvfs python3-dfwinreg python3-dtfabric python3-pip python3-pytsk3 python3-setuptools python3-xattr python3-yaml tox - name: Run linter env: LANG: en_US.UTF-8 run: | tox -e lint ================================================ FILE: .gitignore ================================================ # Files to ignore by git # Back-up files *~ *.swp # Generic auto-generated build files *.pyc *.pyo # Specific auto-generated build files /.tox /__pycache__ /build /dist /MANIFEST.test_data /winregrc.egg-info ================================================ FILE: .pylintrc ================================================ # Pylint 3.2.x configuration file # # This file is generated by l2tdevtools update-dependencies.py, any dependency # related changes should be made in dependencies.ini. [MAIN] # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks=no # Clear in-memory caches upon conclusion of linting. Useful if running pylint # in a server-like mode. clear-cache-post-run=no # Load and enable all available extensions. Use --list-extensions to see a list # all available extensions. #enable-all-extensions= # In error mode, messages with a category besides ERROR or FATAL are # suppressed, and no reports are done by default. Error mode is compatible with # disabling specific errors. #errors-only= # Always return a 0 (non-error) status code, even if lint errors are found. # This is primarily useful in continuous integration scripts. #exit-zero= # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. # extension-pkg-allow-list= extension-pkg-allow-list=pybde,pycaes,pycreg,pyewf,pyfcrypto,pyfsapfs,pyfsext,pyfsfat,pyfshfs,pyfsntfs,pyfsxfs,pyfvde,pyfwnt,pyfwps,pyfwsi,pyhmac,pyluksde,pymodi,pyphdi,pyqcow,pyregf,pysigscan,pysmdev,pysmraw,pytsk3,pyvhdi,pyvmdk,pyvsapm,pyvsgpt,pyvshadow,pyvslvm,xattr # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. (This is an alternative name to extension-pkg-allow-list # for backward compatibility.) extension-pkg-whitelist= # Return non-zero exit code if any of these messages/categories are detected, # even if score is above --fail-under value. Syntax same as enable. Messages # specified are enabled, while categories only check already-enabled messages. fail-on= # Specify a score threshold under which the program will exit with error. fail-under=10 # Interpret the stdin as a python script, whose filename needs to be passed as # the module_or_package argument. #from-stdin= # Files or directories to be skipped. They should be base names, not paths. ignore=CVS # Add files or directories matching the regular expressions patterns to the # ignore-list. The regex matches against paths and can be in Posix or Windows # format. Because '\\' represents the directory delimiter on Windows systems, # it can't be used as an escape character. ignore-paths= # Files or directories matching the regular expression patterns are skipped. # The regex matches against base names, not paths. The default value ignores # Emacs file locks ignore-patterns=^\.# # List of module names for which member attributes should not be checked and # will not be imported (useful for modules/projects where namespaces are # manipulated during runtime and thus existing member attributes cannot be # deduced by static analysis). It supports qualified module names, as well as # Unix pattern matching. ignored-modules= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the # number of processors available to use, and will cap the count on Windows to # avoid hangs. jobs=1 # Control the amount of potential inferred values when inferring a single # object. This can help the performance when dealing with large functions or # complex, nested conditions. limit-inference-results=100 # List of plugins (as comma separated values of python module names) to load, # usually to register additional checkers. # load-plugins= load-plugins=pylint.extensions.docparams # Pickle collected data for later comparisons. persistent=yes # Resolve imports to .pyi stubs if available. May reduce no-member messages and # increase not-an-iterable messages. prefer-stubs=no # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. py-version=3.12 # Discover python modules and packages in the file system subtree. # recursive=no recursive=yes # Add paths to the list of the source roots. Supports globbing patterns. The # source root is an absolute path or a path relative to the current working # directory used to determine a package namespace for modules located under the # source root. source-roots= # When enabled, pylint would attempt to guess common misconfiguration and emit # user-friendly hints instead of false-positive error messages. suggestion-mode=yes # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no # In verbose mode, extra non-checker-related info will be displayed. #verbose= [BASIC] # Naming style matching correct argument names. argument-naming-style=snake_case # Regular expression matching correct argument names. Overrides argument- # naming-style. If left empty, argument names will be checked with the set # naming style. #argument-rgx= argument-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ # Naming style matching correct attribute names. attr-naming-style=snake_case # Regular expression matching correct attribute names. Overrides attr-naming- # style. If left empty, attribute names will be checked with the set naming # style. #attr-rgx= attr-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ # Bad variable names which should always be refused, separated by a comma. bad-names=foo, bar, baz, toto, tutu, tata # Bad variable names regexes, separated by a comma. If names match any regex, # they will always be refused bad-names-rgxs= # Naming style matching correct class attribute names. class-attribute-naming-style=any # Regular expression matching correct class attribute names. Overrides class- # attribute-naming-style. If left empty, class attribute names will be checked # with the set naming style. #class-attribute-rgx= class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]*|(__.*__))$ # Naming style matching correct class constant names. class-const-naming-style=UPPER_CASE # Regular expression matching correct class constant names. Overrides class- # const-naming-style. If left empty, class constant names will be checked with # the set naming style. #class-const-rgx= # Naming style matching correct class names. class-naming-style=PascalCase # Regular expression matching correct class names. Overrides class-naming- # style. If left empty, class names will be checked with the set naming style. #class-rgx= class-rgx=[A-Z_][a-zA-Z0-9]+$ # Naming style matching correct constant names. const-naming-style=UPPER_CASE # Regular expression matching correct constant names. Overrides const-naming- # style. If left empty, constant names will be checked with the set naming # style. #const-rgx= const-rgx=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$ # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. docstring-min-length=-1 # Naming style matching correct function names. function-naming-style=snake_case # Regular expression matching correct function names. Overrides function- # naming-style. If left empty, function names will be checked with the set # naming style. #function-rgx= function-rgx=[A-Z_][a-zA-Z0-9_]*$ # Good variable names which should always be accepted, separated by a comma. good-names=i, j, k, ex, Run, _ # Good variable names regexes, separated by a comma. If names match any regex, # they will always be accepted good-names-rgxs= # Include a hint for the correct naming format with invalid-name. include-naming-hint=no # Naming style matching correct inline iteration names. inlinevar-naming-style=any # Regular expression matching correct inline iteration names. Overrides # inlinevar-naming-style. If left empty, inline iteration names will be checked # with the set naming style. #inlinevar-rgx= inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ # Naming style matching correct method names. method-naming-style=snake_case # Regular expression matching correct method names. Overrides method-naming- # style. If left empty, method names will be checked with the set naming style. #method-rgx= method-rgx=(test|[A-Z_])[a-zA-Z0-9_]*$ # Naming style matching correct module names. module-naming-style=snake_case # Regular expression matching correct module names. Overrides module-naming- # style. If left empty, module names will be checked with the set naming style. #module-rgx= module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= # Regular expression which should only match function or class names that do # not require a docstring. no-docstring-rgx=^_ # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. # These decorators are taken in consideration only for invalid-name. property-classes=abc.abstractproperty # Regular expression matching correct type alias names. If left empty, type # alias names will be checked with the set naming style. #typealias-rgx= # Regular expression matching correct type variable names. If left empty, type # variable names will be checked with the set naming style. #typevar-rgx= # Naming style matching correct variable names. variable-naming-style=snake_case # Regular expression matching correct variable names. Overrides variable- # naming-style. If left empty, variable names will be checked with the set # naming style. #variable-rgx= variable-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ [CLASSES] # Warn about protected attribute access inside special methods check-protected-access-in-special-methods=no # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__, __new__, setUp, asyncSetUp, __post_init__ # List of member names, which should be excluded from the protected access # warning. exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. # valid-metaclass-classmethod-first-arg=mcs valid-metaclass-classmethod-first-arg=cls [DESIGN] # List of regular expressions of class ancestor names to ignore when counting # public methods (see R0903) exclude-too-few-public-methods= # List of qualified class names to ignore when counting class parents (see # R0901) ignored-parents= # Maximum number of arguments for function / method. # max-args=5 max-args=10 # Maximum number of attributes for a class (see R0902). max-attributes=7 # Maximum number of boolean expressions in an if statement (see R0916). max-bool-expr=5 # Maximum number of branch for function / method body. max-branches=12 # Maximum number of locals for function / method body. max-locals=15 # Maximum number of parents for a class (see R0901). max-parents=7 # Maximum number of public methods for a class (see R0904). max-public-methods=20 # Maximum number of return / yield for function / method body. max-returns=6 # Maximum number of statements in function / method body. max-statements=50 # Minimum number of public methods for a class (see R0903). min-public-methods=2 [EXCEPTIONS] # Exceptions that will emit a warning when caught. overgeneral-exceptions=builtins.BaseException,builtins.Exception [FORMAT] # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. expected-line-ending-format= # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). # indent-string=' ' indent-string=' ' # Maximum number of characters on a single line. # max-line-length=100 max-line-length=80 # Maximum number of lines in a module. max-module-lines=1000 # Allow the body of a class to be on the same line as the declaration if body # contains single statement. single-line-class-stmt=no # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=no [IMPORTS] # List of modules that can be imported at any level, not just the top level # one. allow-any-import-level= # Allow explicit reexports by alias from a package __init__. allow-reexport-from-package=no # Allow wildcard imports from modules that define __all__. allow-wildcard-with-all=no # Deprecated modules which should not be used, separated by a comma. deprecated-modules= # Output a graph (.gv or any supported image format) of external dependencies # to the given file (report RP0402 must not be disabled). ext-import-graph= # Output a graph (.gv or any supported image format) of all (i.e. internal and # external) dependencies to the given file (report RP0402 must not be # disabled). import-graph= # Output a graph (.gv or any supported image format) of internal dependencies # to the given file (report RP0402 must not be disabled). int-import-graph= # Force import order to recognize a module as part of the standard # compatibility libraries. known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant # Couples of modules and preferred modules, separated by a comma. preferred-modules= [LOGGING] # The type of string formatting that logging methods do. `old` means using % # formatting, `new` is for `{}` formatting. logging-format-style=old # Logging modules to check that the string format arguments are in logging # function parameter format. logging-modules=logging [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, # UNDEFINED. confidence=HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, UNDEFINED # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once). You can also use "--disable=all" to # disable everything first and then re-enable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use "--disable=all --enable=classes # --disable=W". disable=assignment-from-none, bad-inline-option, deprecated-pragma, duplicate-code, file-ignored, fixme, locally-disabled, logging-format-interpolation, logging-fstring-interpolation, missing-param-doc, raise-missing-from, raw-checker-failed, suppressed-message, too-few-public-methods, too-many-ancestors, too-many-boolean-expressions, too-many-branches, too-many-instance-attributes, too-many-lines, too-many-locals, too-many-nested-blocks, too-many-positional-arguments, too-many-public-methods, too-many-return-statements, too-many-statements, unsubscriptable-object, use-implicit-booleaness-not-comparison-to-string, use-implicit-booleaness-not-comparison-to-zero, useless-suppression, use-symbolic-message-instead # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. # enable= enable=c-extension-no-member [METHOD_ARGS] # List of qualified names (i.e., library.method) which require a timeout # parameter e.g. 'requests.api.get,requests.api.post' timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. notes=FIXME, XXX, TODO # Regular expression of note tags to take in consideration. notes-rgx= [REFACTORING] # Maximum number of nested blocks for function / method body max-nested-blocks=5 # Complete name of functions that never returns. When checking for # inconsistent-return-statements if a never returning function is called then # it will be considered as an explicit return statement and no message will be # printed. never-returning-functions=sys.exit,argparse.parse_error # Let 'consider-using-join' be raised when the separator to join on would be # non-empty (resulting in expected fixes of the type: ``"- " + " - # ".join(items)``) suggest-join-with-non-empty-separator=yes [REPORTS] # Python expression which should return a score less than or equal to 10. You # have access to the variables 'fatal', 'error', 'warning', 'refactor', # 'convention', and 'info' which contain the number of messages in each # category, as well as 'statement' which is the total number of statements # analyzed. This score is used by the global evaluation report (RP0004). evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)) # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details. msg-template= # Set the output format. Available formats are: text, parseable, colorized, # json2 (improved json format), json (old json format) and msvs (visual # studio). You can also give a reporter class, e.g. # mypackage.mymodule.MyReporterClass. #output-format= # Tells whether to display a full report or only the messages. reports=no # Activate the evaluation score. # score=yes score=no [SIMILARITIES] # Comments are removed from the similarity computation ignore-comments=yes # Docstrings are removed from the similarity computation ignore-docstrings=yes # Imports are removed from the similarity computation ignore-imports=yes # Signatures are removed from the similarity computation ignore-signatures=yes # Minimum lines number of a similarity. min-similarity-lines=4 [SPELLING] # Limits count of emitted suggestions for spelling mistakes. max-spelling-suggestions=4 # Spelling dictionary name. Available dictionaries: en_AG (hunspell), en_AU # (hunspell), en_BS (hunspell), en_BW (hunspell), en_BZ (hunspell), en_CA # (hunspell), en_DK (hunspell), en_GB (hunspell), en_GH (hunspell), en_HK # (hunspell), en_IE (hunspell), en_IN (hunspell), en_JM (hunspell), en_MW # (hunspell), en_NA (hunspell), en_NG (hunspell), en_NZ (hunspell), en_PH # (hunspell), en_SG (hunspell), en_TT (hunspell), en_US (hunspell), en_ZA # (hunspell), en_ZM (hunspell), en_ZW (hunspell). spelling-dict= # List of comma separated words that should be considered directives if they # appear at the beginning of a comment and should not be checked. spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy: # List of comma separated words that should not be checked. spelling-ignore-words= # A path to a file that contains the private dictionary; one word per line. spelling-private-dict-file= # Tells whether to store unknown words to the private dictionary (see the # --spelling-private-dict-file option) instead of raising a message. spelling-store-unknown-words=no [STRING] # This flag controls whether inconsistent-quotes generates a warning when the # character used as a quote delimiter is used inconsistently within a module. check-quote-consistency=no # This flag controls whether the implicit-str-concat should generate a warning # on implicit string concatenation in sequences defined over several lines. check-str-concat-over-line-jumps=no [TYPECHECK] # List of decorators that produce context managers, such as # contextlib.contextmanager. Add to this list to register other decorators that # produce valid context managers. contextmanager-decorators=contextlib.contextmanager # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. generated-members= # Tells whether to warn about missing members when the owner of the attribute # is inferred to be None. ignore-none=yes # This flag controls whether pylint should warn about no-member and similar # checks whenever an opaque object is returned when inferring. The inference # can return multiple potential results while evaluating a Python object, but # some branches might not be evaluated, which results in partial inference. In # that case, it might be useful to still emit no-member and other checks for # the rest of the inferred objects. ignore-on-opaque-inference=yes # List of symbolic message names to ignore for Mixin members. ignored-checks-for-mixins=no-member, not-async-context-manager, not-context-manager, attribute-defined-outside-init # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace # Show a hint with possible names when a member name was not found. The aspect # of finding the hint is based on edit distance. missing-member-hint=yes # The minimum edit distance a name should have in order to be considered a # similar match for a missing member name. missing-member-hint-distance=1 # The total number of similar names that should be taken in consideration when # showing a hint for a missing member. missing-member-max-choices=1 # Regex pattern to define which classes are considered mixins. mixin-class-rgx=.*[Mm]ixin # List of decorators that change the signature of a decorated function. signature-mutators= [VARIABLES] # List of additional names supposed to be defined in builtins. Remember that # you should avoid defining new builtins when possible. additional-builtins= # Tells whether unused global variables should be treated as a violation. allow-global-unused-variables=yes # List of names allowed to shadow builtins allowed-redefined-builtins= # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. callbacks=cb_, _cb # A regular expression matching the name of dummy variables (i.e. expected to # not be used). dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ # Argument names that match this expression will be ignored. ignored-argument-names=_.*|^ignored_|^unused_ # Tells whether we should check for unused import in __init__ files. init-import=no # List of qualified module names which can have objects that can redefine # builtins. redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io ================================================ FILE: .readthedocs.yaml ================================================ # Read the Docs configuration file for Sphinx projects # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details version: 2 build: os: ubuntu-24.04 tools: python: "3.12" sphinx: configuration: docs/conf.py fail_on_warning: false python: install: - requirements: docs/requirements.txt ================================================ FILE: .yamllint.yaml ================================================ extends: default rules: line-length: disable indentation: spaces: consistent indent-sequences: false check-multi-line-strings: true ================================================ FILE: ACKNOWLEDGEMENTS ================================================ Acknowledgements: winreg-kb Copyright (c) 2013-2022, Joachim Metz Copied with permission from [the Greendale data set](https://github.com/dfirlabs/greendale-specimens). * regf/studentpc8/NTUSER.DAT * regf/studentpc8/NTUSER.DAT.LOG * regf/studentpc8/SAM * regf/studentpc8/SECURITY * regf/studentpc8/SOFTWARE * regf/studentpc8/SYSTEM * regf/studentpc8/UsrClass.dat ================================================ FILE: AUTHORS ================================================ # Names should be added to this file with this pattern: # # For individuals: # Name (email address) # # For organizations: # Organization (fnmatch pattern) # # See python fnmatch module documentation for more information. Joachim Metz (joachim.metz@gmail.com) ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: MANIFEST.in ================================================ include ACKNOWLEDGEMENTS AUTHORS LICENSE README.md include dependencies.ini run_tests.py utils/dependencies.py include utils/check_dependencies.py exclude .gitignore exclude *.pyc recursive-exclude winregrc *.pyc # Do not include the test data otherwise the sdist will be too large for PyPI. recursive-exclude test_data * # The test scripts are not required in a binary distribution package they # are considered source distribution files and excluded by find_package(). recursive-include tests *.py ================================================ FILE: MANIFEST.test_data.in ================================================ include ACKNOWLEDGEMENTS AUTHORS LICENSE README.md include dependencies.ini run_tests.py utils/dependencies.py include utils/check_dependencies.py exclude .gitignore exclude *.pyc recursive-exclude winregrc *.pyc recursive-include test_data * # The test scripts are not required in a binary distribution package they # are considered source distribution files and excluded by find_package(). recursive-include tests *.py ================================================ FILE: README.md ================================================ winreg-kb is a project to build a Windows Registry Knowledge Base. winregrc is a Python module part of winreg-kb to allow reuse of Windows Registry Resources. For more information see: * Project documentation: https://winreg-kb.readthedocs.io/en/latest ================================================ FILE: appveyor.yml ================================================ environment: matrix: - DESCRIPTION: "Run tests on Windows with 32-bit Python 3.14" MACHINE_TYPE: "x86" APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 PYTHON: "C:\\Python314" PYTHON_VERSION: "3.14" L2TBINARIES_TRACK: "dev" TARGET: tests - DESCRIPTION: "Run tests on Windows with 64-bit Python 3.14" MACHINE_TYPE: "amd64" APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 PYTHON: "C:\\Python314-x64" PYTHON_VERSION: "3.14" L2TBINARIES_TRACK: "dev" TARGET: tests - DESCRIPTION: "Build wheel on Windows with 32-bit Python 3.14" MACHINE_TYPE: "amd64" APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 PYTHON: "C:\\Python314-x64" PYTHON_VERSION: "3.14" L2TBINARIES_TRACK: "dev" TARGET: wheel - DESCRIPTION: "Build wheel on Windows with 64-bit Python 3.14" MACHINE_TYPE: "amd64" APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 PYTHON: "C:\\Python314-x64" PYTHON_VERSION: "3.14" L2TBINARIES_TRACK: "dev" TARGET: wheel install: - cmd: "%PYTHON%\\python.exe -m pip install -U build pip setuptools twine wheel" - ps: .\config\appveyor\install.ps1 build_script: - cmd: IF [%TARGET%]==[wheel] ( "%PYTHON%\\python.exe" -m build --wheel ) test_script: - cmd: IF [%TARGET%]==[tests] ( "%PYTHON%\\python.exe" run_tests.py && IF EXIST "tests\\end-to-end.py" ( set PYTHONPATH=. && "%PYTHON%\\python.exe" "tests\\end-to-end.py" --debug -c "config\\end-to-end.ini" ) ) artifacts: - path: dist\*.whl ================================================ FILE: config/appveyor/install.ps1 ================================================ # Script to set up tests on AppVeyor Windows. $Dependencies = "PyYAML acstore artifacts dfdatetime dfimagetools dfvfs dfwinreg dtfabric libbde libcaes libcreg libewf libfcrypto libfsapfs libfsext libfsfat libfshfs libfsntfs libfsxfs libfvde libfwnt libfwps libfwsi libhmac libluksde libmodi libphdi libqcow libregf libsigscan libsmdev libsmraw libvhdi libvmdk libvsapm libvsgpt libvshadow libvslvm pytsk3 xattr" If ($Dependencies.Length -gt 0) { $Dependencies = ${Dependencies} -split " " $Output = Invoke-Expression -Command "git clone https://github.com/log2timeline/l2tdevtools.git ..\l2tdevtools 2>&1" | %{ "$_" } Write-Host (${Output} | Out-String) If ($env:APPVEYOR_REPO_BRANCH -eq "main") { $Track = "stable" } Else { $Track = $env:APPVEYOR_REPO_BRANCH } New-Item -ItemType "directory" -Name "dependencies" $env:PYTHONPATH = "..\l2tdevtools" $Output = Invoke-Expression -Command "& '${env:PYTHON}\python.exe' ..\l2tdevtools\tools\update.py --download-directory dependencies --machine-type ${env:MACHINE_TYPE} --track ${env:L2TBINARIES_TRACK} ${Dependencies} 2>&1" | %{ "$_" } Write-Host (${Output} | Out-String) } ================================================ FILE: config/dpkg/changelog ================================================ winreg-kb (20260413-1) unstable; urgency=low * Auto-generated -- Joachim Metz Mon, 13 Apr 2026 06:58:45 +0200 ================================================ FILE: config/dpkg/clean ================================================ winregrc/*.pyc *.pyc ================================================ FILE: config/dpkg/compat ================================================ 9 ================================================ FILE: config/dpkg/control ================================================ Source: winreg-kb Section: python Priority: extra Maintainer: Joachim Metz Build-Depends: debhelper (>= 9), dh-python, python3-all (>= 3.10~), python3-setuptools, pybuild-plugin-pyproject Standards-Version: 4.1.4 X-Python3-Version: >= 3.10 Homepage: https://github.com/libyal/winreg-kb Package: python3-winregrc Architecture: all Depends: libbde-python3 (>= 20220121), libcaes-python3 (>= 20240114), libcreg-python3 (>= 20200725), libewf-python3 (>= 20131210), libfcrypto-python3 (>= 20240114), libfsapfs-python3 (>= 20220709), libfsext-python3 (>= 20220829), libfsfat-python3 (>= 20220925), libfshfs-python3 (>= 20220831), libfsntfs-python3 (>= 20211229), libfsxfs-python3 (>= 20220829), libfvde-python3 (>= 20220121), libfwnt-python3 (>= 20210717), libfwps-python3 (>= 20240225), libfwsi-python3 (>= 20240315), libhmac-python3 (>= 20230205), libluksde-python3 (>= 20220121), libmodi-python3 (>= 20210405), libphdi-python3 (>= 20220228), libqcow-python3 (>= 20201213), libregf-python3 (>= 20201002), libsigscan-python3 (>= 20230109), libsmdev-python3 (>= 20140529), libsmraw-python3 (>= 20140612), libvhdi-python3 (>= 20201014), libvmdk-python3 (>= 20140421), libvsapm-python3 (>= 20230506), libvsgpt-python3 (>= 20211115), libvshadow-python3 (>= 20160109), libvslvm-python3 (>= 20160109), python3-acstore (>= 20230101), python3-artifacts (>= 20220219), python3-dfdatetime (>= 20221112), python3-dfimagetools (>= 20240301), python3-dfvfs (>= 20240115), python3-dfwinreg (>= 20240229), python3-dtfabric (>= 20230518), python3-pytsk3 (>= 20210419), python3-xattr (>= 0.7.2), python3-yaml (>= 3.10), ${misc:Depends} Description: Python 3 module of Windows Registry resources (winregrc) winregrc is a Python module part of winreg-kb to allow reuse of Windows Registry resources. Package: winreg-kb-tools Architecture: all Depends: python3-winregrc (>= ${binary:Version}), ${misc:Depends} Description: Tools for Windows Registry knowledge base (winreg-kb) Winreg-kb is a project to build a Windows Registry knowledge base. ================================================ FILE: config/dpkg/copyright ================================================ Format: http://dep.debian.net/deps/dep5 Upstream-Name: dtfabric Source: https://github.com/libyal/dtfabric Files: * Copyright: 2016-2017, Joachim Metz License: Apache-2.0 License: Apache-2.0 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at . http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. . On Debian systems, the complete text of the Apache version 2.0 license can be found in "/usr/share/common-licenses/Apache-2.0". ================================================ FILE: config/dpkg/python3-winregrc.install ================================================ usr/lib/python3*/dist-packages/winregrc/*.py usr/lib/python3*/dist-packages/winregrc/*.yaml usr/lib/python3*/dist-packages/winregrc*.dist-info/* ================================================ FILE: config/dpkg/rules ================================================ #!/usr/bin/make -f %: dh $@ --buildsystem=pybuild --with=python3 .PHONY: override_dh_auto_test override_dh_auto_test: ================================================ FILE: config/dpkg/source/format ================================================ 3.0 (quilt) ================================================ FILE: config/pylint/spelling-private-dict ================================================ appcompatcachecachedentry argparse args backports bool cachedtask codecs codepage config csd currentversion datatypefabric datatypemap datatypemapcontext datetimevalues des dev dfdatetime dfvfs dfwinreg dll dpkg dtfabric endian fileio filename filenames filesystem filetime gid guid knownfolder kwargs lockdown lsa lzma macos mappingerror mostrecentlyusedentry mru msi nl ons os outputwriter parseheader pathspec posixtime pre py pyfwsi pyregf rb rc readfp regf sdist shellfolder stdin stdout str subkeys sys syskey timestamp timestamps tuple typelibrary useraccount userassistentry username vfsstat volumescannermediator windowsservice windowsvolumescanner winregistry winregistrykey winregistryvalue winregrc xp ================================================ FILE: dependencies.ini ================================================ [acstore] dpkg_name: python3-acstore minimum_version: 20230101 rpm_name: python3-acstore version_property: __version__ [artifacts] dpkg_name: python3-artifacts minimum_version: 20220219 rpm_name: python3-artifacts version_property: __version__ [dfdatetime] dpkg_name: python3-dfdatetime minimum_version: 20221112 rpm_name: python3-dfdatetime version_property: __version__ [dfimagetools] dpkg_name: python3-dfimagetools minimum_version: 20240301 rpm_name: python3-dfimagetools version_property: __version__ [dfvfs] dpkg_name: python3-dfvfs minimum_version: 20240115 rpm_name: python3-dfvfs version_property: __version__ [dfwinreg] dpkg_name: python3-dfwinreg minimum_version: 20240229 rpm_name: python3-dfwinreg version_property: __version__ [dtfabric] dpkg_name: python3-dtfabric minimum_version: 20230518 rpm_name: python3-dtfabric version_property: __version__ [pybde] dpkg_name: libbde-python3 l2tbinaries_name: libbde minimum_version: 20220121 pypi_name: libbde-python rpm_name: libbde-python3 version_property: get_version() [pycaes] dpkg_name: libcaes-python3 l2tbinaries_name: libcaes minimum_version: 20240114 pypi_name: libcaes-python rpm_name: libcaes-python3 version_property: get_version() [pycreg] dpkg_name: libcreg-python3 l2tbinaries_name: libcreg minimum_version: 20200725 pypi_name: libcreg-python rpm_name: libcreg-python3 version_property: get_version() [pyewf] dpkg_name: libewf-python3 l2tbinaries_name: libewf minimum_version: 20131210 pypi_name: libewf-python rpm_name: libewf-python3 version_property: get_version() [pyfcrypto] dpkg_name: libfcrypto-python3 l2tbinaries_name: libfcrypto minimum_version: 20240114 pypi_name: libfcrypto-python rpm_name: libfcrypto-python3 version_property: get_version() [pyfsapfs] dpkg_name: libfsapfs-python3 l2tbinaries_name: libfsapfs minimum_version: 20220709 pypi_name: libfsapfs-python rpm_name: libfsapfs-python3 version_property: get_version() [pyfsext] dpkg_name: libfsext-python3 l2tbinaries_name: libfsext minimum_version: 20220829 pypi_name: libfsext-python rpm_name: libfsext-python3 version_property: get_version() [pyfsfat] dpkg_name: libfsfat-python3 l2tbinaries_name: libfsfat minimum_version: 20220925 pypi_name: libfsfat-python rpm_name: libfsfat-python3 version_property: get_version() [pyfshfs] dpkg_name: libfshfs-python3 l2tbinaries_name: libfshfs minimum_version: 20220831 pypi_name: libfshfs-python rpm_name: libfshfs-python3 version_property: get_version() [pyfsntfs] dpkg_name: libfsntfs-python3 l2tbinaries_name: libfsntfs minimum_version: 20211229 pypi_name: libfsntfs-python rpm_name: libfsntfs-python3 version_property: get_version() [pyfsxfs] dpkg_name: libfsxfs-python3 l2tbinaries_name: libfsxfs minimum_version: 20220829 pypi_name: libfsxfs-python rpm_name: libfsxfs-python3 version_property: get_version() [pyfvde] dpkg_name: libfvde-python3 l2tbinaries_name: libfvde minimum_version: 20220121 pypi_name: libfvde-python rpm_name: libfvde-python3 version_property: get_version() [pyfwnt] dpkg_name: libfwnt-python3 l2tbinaries_name: libfwnt minimum_version: 20210717 pypi_name: libfwnt-python rpm_name: libfwnt-python3 version_property: get_version() [pyfwps] dpkg_name: libfwps-python3 l2tbinaries_name: libfwps minimum_version: 20240225 pypi_name: libfwps-python rpm_name: libfwps-python3 version_property: get_version() [pyfwsi] dpkg_name: libfwsi-python3 l2tbinaries_name: libfwsi minimum_version: 20240315 pypi_name: libfwsi-python rpm_name: libfwsi-python3 version_property: get_version() [pyhmac] dpkg_name: libhmac-python3 l2tbinaries_name: libhmac minimum_version: 20230205 pypi_name: libhmac-python rpm_name: libhmac-python3 version_property: get_version() [pyluksde] dpkg_name: libluksde-python3 l2tbinaries_name: libluksde minimum_version: 20220121 pypi_name: libluksde-python rpm_name: libluksde-python3 version_property: get_version() [pymodi] dpkg_name: libmodi-python3 l2tbinaries_name: libmodi minimum_version: 20210405 pypi_name: libmodi-python rpm_name: libmodi-python3 version_property: get_version() [pyphdi] dpkg_name: libphdi-python3 l2tbinaries_name: libphdi minimum_version: 20220228 pypi_name: libphdi-python rpm_name: libphdi-python3 version_property: get_version() [pyqcow] dpkg_name: libqcow-python3 l2tbinaries_name: libqcow minimum_version: 20201213 pypi_name: libqcow-python rpm_name: libqcow-python3 version_property: get_version() [pyregf] dpkg_name: libregf-python3 l2tbinaries_name: libregf minimum_version: 20201002 pypi_name: libregf-python rpm_name: libregf-python3 version_property: get_version() [pysigscan] dpkg_name: libsigscan-python3 l2tbinaries_name: libsigscan minimum_version: 20230109 pypi_name: libsigscan-python rpm_name: libsigscan-python3 version_property: get_version() [pysmdev] dpkg_name: libsmdev-python3 l2tbinaries_name: libsmdev minimum_version: 20140529 pypi_name: libsmdev-python rpm_name: libsmdev-python3 version_property: get_version() [pysmraw] dpkg_name: libsmraw-python3 l2tbinaries_name: libsmraw minimum_version: 20140612 pypi_name: libsmraw-python rpm_name: libsmraw-python3 version_property: get_version() [pytsk3] dpkg_name: python3-pytsk3 minimum_version: 20210419 rpm_name: python3-pytsk3 version_property: get_version() [pyvhdi] dpkg_name: libvhdi-python3 l2tbinaries_name: libvhdi minimum_version: 20201014 pypi_name: libvhdi-python rpm_name: libvhdi-python3 version_property: get_version() [pyvmdk] dpkg_name: libvmdk-python3 l2tbinaries_name: libvmdk minimum_version: 20140421 pypi_name: libvmdk-python rpm_name: libvmdk-python3 version_property: get_version() [pyvsapm] dpkg_name: libvsapm-python3 l2tbinaries_name: libvsapm minimum_version: 20230506 pypi_name: libvsapm-python rpm_name: libvsapm-python3 version_property: get_version() [pyvsgpt] dpkg_name: libvsgpt-python3 l2tbinaries_name: libvsgpt minimum_version: 20211115 pypi_name: libvsgpt-python rpm_name: libvsgpt-python3 version_property: get_version() [pyvshadow] dpkg_name: libvshadow-python3 l2tbinaries_name: libvshadow minimum_version: 20160109 pypi_name: libvshadow-python rpm_name: libvshadow-python3 version_property: get_version() [pyvslvm] dpkg_name: libvslvm-python3 l2tbinaries_name: libvslvm minimum_version: 20160109 pypi_name: libvslvm-python rpm_name: libvslvm-python3 version_property: get_version() [xattr] dpkg_name: python3-xattr is_optional: true minimum_version: 0.7.2 pypi_name: xattr rpm_name: python3-xattr version_property: __version__ [yaml] dpkg_name: python3-yaml l2tbinaries_name: PyYAML minimum_version: 3.10 pypi_name: PyYAML rpm_name: python3-pyyaml version_property: __version__ ================================================ FILE: docs/conf.py ================================================ """Sphinx build configuration file.""" import os import sys from sphinx.ext import apidoc from docutils import nodes from docutils import transforms # Change PYTHONPATH to include winregrc module and dependencies. sys.path.insert(0, os.path.abspath('..')) import winregrc # pylint: disable=wrong-import-position import utils.dependencies # pylint: disable=wrong-import-position # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. needs_sphinx = '2.0.1' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'recommonmark', 'sphinx.ext.autodoc', 'sphinx.ext.coverage', 'sphinx.ext.doctest', 'sphinx.ext.napoleon', 'sphinx.ext.viewcode', 'sphinx_markdown_tables', 'sphinx_rtd_theme', ] # We cannot install architecture dependent Python modules on readthedocs, # therefore we mock most imports. pip_installed_modules = set() dependency_helper = utils.dependencies.DependencyHelper( dependencies_file=os.path.join('..', 'dependencies.ini'), test_dependencies_file=os.path.join('..', 'test_dependencies.ini')) modules_to_mock = set(dependency_helper.dependencies.keys()) modules_to_mock = modules_to_mock.difference(pip_installed_modules) autodoc_mock_imports = sorted(modules_to_mock) # Options for the Sphinx Napoleon extension, which reads Google-style # docstrings. napoleon_google_docstring = True napoleon_numpy_docstring = False napoleon_include_init_with_doc = True napoleon_include_private_with_doc = False napoleon_include_special_with_doc = True # General information about the project. # pylint: disable=redefined-builtin project = 'Windows Registry knowledge base (winreg-kb)' copyright = 'The Windows Registry knowledge base (winreg-kb) authors' version = winregrc.__version__ release = winregrc.__version__ # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The master toctree document. master_doc = 'index' # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'sphinx_rtd_theme' # Output file base name for HTML help builder. htmlhelp_basename = 'winregkbdoc' # -- Options linkcheck ---------------------------------------------------- linkcheck_ignore = [ ] # -- Code to rewrite links for readthedocs -------------------------------- # This function is a Sphinx core event callback, the format of which is detailed # here: https://www.sphinx-doc.org/en/master/extdev/appapi.html#events # pylint: disable=unused-argument def RunSphinxAPIDoc(app): """Runs sphinx-apidoc to auto-generate documentation. Args: app (sphinx.application.Sphinx): Sphinx application. Required by the the Sphinx event callback API. """ current_directory = os.path.abspath(os.path.dirname(__file__)) module_path = os.path.join(current_directory, '..', 'winregrc') api_directory = os.path.join(current_directory, 'sources', 'api') apidoc.main(['-o', api_directory, module_path, '--force']) class MarkdownLinkFixer(transforms.Transform): """Transform definition to parse .md references to internal pages.""" default_priority = 1000 _URI_PREFIXES = [] def _FixLinks(self, node): """Corrects links to .md files not part of the documentation. Args: node (docutils.nodes.Node): docutils node. Returns: docutils.nodes.Node: docutils node, with correct URIs outside of Markdown pages outside the documentation. """ if isinstance(node, nodes.reference) and 'refuri' in node: reference_uri = node['refuri'] for uri_prefix in self._URI_PREFIXES: if (reference_uri.startswith(uri_prefix) and not ( reference_uri.endswith('.asciidoc') or reference_uri.endswith('.md'))): node['refuri'] = reference_uri + '.md' break return node def _Traverse(self, node): """Traverses the document tree rooted at node. Args: node (docutils.nodes.Node): docutils node. """ self._FixLinks(node) for child_node in node.children: self._Traverse(child_node) # pylint: disable=arguments-differ def apply(self): """Applies this transform on document tree.""" self._Traverse(self.document) # pylint: invalid-name def setup(app): """Called at Sphinx initialization. Args: app (sphinx.application.Sphinx): Sphinx application. """ # Triggers sphinx-apidoc to generate API documentation. app.connect('builder-inited', RunSphinxAPIDoc) app.add_config_value( 'recommonmark_config', {'enable_auto_toc_tree': True}, True) app.add_transform(MarkdownLinkFixer) ================================================ FILE: docs/index.rst ================================================ Welcome to the winreg-kb documentation ======================================== winreg-kb is a project to build a Windows Registry Knowledge Base. winregrc is a Python module part of winreg-kb to allow reuse of Windows Registry Resources. The source code is available from the `project page `__. .. toctree:: :maxdepth: 2 sources/windows-registry/index .. toctree:: :maxdepth: 2 sources/system-keys/index .. toctree:: :maxdepth: 2 sources/security-accounts-manager-keys/index .. toctree:: :maxdepth: 2 sources/explorer-keys/index .. toctree:: :maxdepth: 2 Windows EventLog keys .. toctree:: :maxdepth: 2 sources/internet-explorer-keys/index .. toctree:: :maxdepth: 2 sources/application-keys/index .. toctree:: :maxdepth: 2 API documentation Indices and tables ================== * :ref:`genindex` * :ref:`modindex` ================================================ FILE: docs/requirements.txt ================================================ certifi >= 2023.11.17 docutils Markdown recommonmark sphinx >= 4.1.0 sphinx-markdown-tables sphinx-rtd-theme >= 0.5.1 ================================================ FILE: docs/sources/EventLog-keys.md ================================================ # EventLog keys ## EventLog providers Information about EventLog providers is stored across multiple keys: * the Services\EventLog key, which has been around since at least Windows NT 3.5 * the WINEVT\Publishers key, which was introduced in Windows Vista Note that the combined information of both keys can be needed, for example the Services\EventLog key: ``` Log type : System Log source : Microsoft-Windows-Time-Service Identifier : {06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb} Event message files : %SystemRoot%\system32\w32time.dll ``` ``` Log type : System Log source : W32Time Identifier : {06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb} Event message files : %SystemRoot%\system32\w32time.dll ``` In combination with the corresponding WINEVT\Publishers key: ``` Name : Microsoft-Windows-Time-Service Identifier : {06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb} Event message files : %SystemRoot%\system32\w32time.dll ``` Is the following EvenLog provider: ``` Name : Microsoft-Windows-Time-Service Identifier : {06edcfeb-0fd0-4e53-acca-a6f8bbf81bcb} Log type : System Log source(s) : Microsoft-Windows-Time-Service : W32Time Event message files : %SystemRoot%\system32\w32time.dll ``` Note that an EventLog provider can have multiple log types and log sources. It is not known if a log source that matches the EventLog provider name can be deduplicated. Or as specified as Event XML: ``` ``` ## Services\EventLog key The event sources are stored in the Services\EventLog key: ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\ ``` On Windows NT it can be found in the SYSTEM Registry file. The Services\EventLog key contains a per EventLog type sub key, for example for the "System" EventLog type: ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\System\ ``` Common EventLog types are: * Application * Security * System The EventLog type sub key contains a per EventLog source-per-type sub key, for example for the "Workstation" EventLog source: ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\System\Workstation\ ``` Note that the log source is case insensitive; so "Workstation" and "workstation" are considered equivalent. ### Services\EventLog type sub key Values: Name | Data type | Description --- | --- | --- Sources | | Array of strings with end-of-string character containing the names of the event sources #### Services\EventLog source-per-type sub key The Services\EventLog source-per-type sub key contains information about a single event source. Values: Name | Data type | Description --- | --- | --- CategoryCount | REG_DWORD | Number of event categories supported CategoryMessageFile | REG_EXPAND_SZ | Path to the category message file. A category message file contains language-dependent strings that describe the categories. EventMessageFile | REG_EXPAND_SZ | Path to event message files. An event message file contains language-dependent strings that describe the events. Note that this value can contain multiple filenames, for example "C:\WINDOWS\system32\COMRES.DLL;C:\WINDOWS\system32\xpsp2res.dll". Multiple files are delimited using a semicolon. ParameterMessageFile | REG_EXPAND_SZ | Path to the parameter message file. A parameter message file contains language-independent strings that are to be inserted into the event description strings. ProviderGuid | REG_SZ | Identifier, in the form "{%GUID%}", of the event provider. TypesSupported | REG_DWORD | Bitmask of supported types ##### TypesSupported value data Value | Identifier | Description --- | --- | --- 0x0001 | EVENTLOG_ERROR_TYPE | 0x0002 | EVENTLOG_WARNING_TYPE | 0x0004 | EVENTLOG_INFORMATION_TYPE | 0x0008 | EVENTLOG_AUDIT_SUCCESS | 0x0010 | EVENTLOG_AUDIT_FAILURE | ## WINEVT\Publishers key The event publishers (or providers) are stored in the WINEVT\Publishers key: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\WINEVT\Publishers ``` On Windows Vista or later it can be found in the SOFTWARE Registry file. The WINEVT\Publishers key contains a GUID type sub key, for example "{de513a55-c345-438b-9a74-e18cac5c5cc5}": ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\WINEVT\Publishers\%GUID% ``` ### WINEVT\Publishers GUID sub key A WINEVT\Publishers GUID sub key contains information about a single event publisher. Values: Name | Data type | Description --- | --- | --- (default) | REG_SZ | Case insensitive log source. MessageFileName | REG_EXPAND_SZ | Path to an event message file. An event message file contains language-dependent strings that describe the events. ResourceFileName | REG_EXPAND_SZ | Path to an event resource file. ParameterFileName | REG_EXPAND_SZ | Path to an event parameter file. ## Message file paths A message file path can be defined in numerous different ways for example: As an absolute path ``` C:\Windows\System32\mscoree.dll ``` As a relative path: ``` mscoree.dll ``` As a path using environment variables: ``` %SystemDrive%\Windows\System32\mscoree.dll %SystemRoot%\System32\mscoree.dll %WinDir%\System32\mscoree.dll ``` As a path using universal OEM runtime macros: ``` $(runtime.system32)\mscoree.dll ``` ``` \SystemRoot\system32\mscoree.dll ``` ## EventLog provider with multiple provider GUIDs Seen on Windows 8.0, 8.1, 10, 11 and 2012: ``` Key path: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\Application\Microsoft-Windows-KdsSvc Name: Microsoft-Windows-KdsSvc Last written time: Oct 30, 2015 07:25:12.126588100 UTC Value: 0 providerGuid Type: string (REG_SZ) Data size: 78 Data: {d4be7726-dc7a-11df-a6e6-0902dfd72085} ``` ``` Key path: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\WINEVT\Publishers\{89203471-d554-47d4-bde4-7552ec219999} Name: {89203471-d554-47d4-bde4-7552ec219999} Last written time: Oct 30, 2015 07:25:53.860831900 UTC Value: 0 (default) Type: string (REG_SZ) Data size: 50 Data: Microsoft-Windows-KdsSvc Value: 1 ResourceFileName Type: expandable string (REG_EXPAND_SZ) Data size: 66 Data: %SystemRoot%\system32\KdsCli.dll Value: 2 MessageFileName Type: expandable string (REG_EXPAND_SZ) Data size: 66 Data: %SystemRoot%\system32\KdsCli.dll ``` ## EventLog provider with multiple log types Seen on Windows 10: ``` Key path: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\Application\Microsoft-Windows-EventCollector Name: Microsoft-Windows-EventCollector Last written time: Sep 13, 2014 07:27:56.080450600 UTC Value: 0 ProviderGuid Type: string (REG_SZ) Data size: 78 Data: {b977cf02-76f6-df84-cc1a-6a4b232322b6} Value: 1 EventMessageFile Type: expandable string (REG_EXPAND_SZ) Data size: 66 Data: %SystemRoot%\system32\wecsvc.dll ``` ``` Key path: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\System\Microsoft-Windows-EventCollector Name: Microsoft-Windows-EventCollector Last written time: Sep 13, 2014 07:27:56.080450600 UTC Value: 0 ProviderGuid Type: string (REG_SZ) Data size: 78 Data: {b977cf02-76f6-df84-cc1a-6a4b232322b6} Value: 1 EventMessageFile Type: expandable string (REG_EXPAND_SZ) Data size: 66 Data: %SystemRoot%\system32\wecsvc.dll ``` ``` Key path: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\WINEVT\Publishers\{b977cf02-76f6-df84-cc1a-6a4b232322b6} Name: {b977cf02-76f6-df84-cc1a-6a4b232322b6} Last written time: Sep 13, 2014 07:27:56.080450600 UTC Value: 0 (default) Type: string (REG_SZ) Data size: 66 Data: Microsoft-Windows-EventCollector Value: 1 ResourceFileName Type: expandable string (REG_EXPAND_SZ) Data size: 66 Data: %SystemRoot%\system32\wecsvc.dll Value: 2 MessageFileName Type: expandable string (REG_EXPAND_SZ) Data size: 66 Data: %SystemRoot%\system32\wecsvc.dll ``` ## External Links * [Eventlog Key](https://learn.microsoft.com/en-us/windows/win32/eventlog/eventlog-key) * [Event Sources](https://learn.microsoft.com/en-us/windows/win32/eventlog/event-sources) * [winevt.h header](https://learn.microsoft.com/en-us/windows/win32/api/winevt/) * [Windows Event Log](https://learn.microsoft.com/en-us/windows/win32/api/_wes/) ================================================ FILE: docs/sources/api/modules.rst ================================================ winregrc ======== .. toctree:: :maxdepth: 4 winregrc ================================================ FILE: docs/sources/api/winregrc.rst ================================================ winregrc package ================ Subpackages ----------- .. toctree:: :maxdepth: 4 winregrc.scripts Submodules ---------- winregrc.appcompatcache module ------------------------------ .. automodule:: winregrc.appcompatcache :members: :show-inheritance: :undoc-members: winregrc.application\_identifiers module ---------------------------------------- .. automodule:: winregrc.application_identifiers :members: :show-inheritance: :undoc-members: winregrc.cached\_credentials module ----------------------------------- .. automodule:: winregrc.cached_credentials :members: :show-inheritance: :undoc-members: winregrc.catalog module ----------------------- .. automodule:: winregrc.catalog :members: :show-inheritance: :undoc-members: winregrc.controlpanel\_items module ----------------------------------- .. automodule:: winregrc.controlpanel_items :members: :show-inheritance: :undoc-members: winregrc.data\_format module ---------------------------- .. automodule:: winregrc.data_format :members: :show-inheritance: :undoc-members: winregrc.delegatefolders module ------------------------------- .. automodule:: winregrc.delegatefolders :members: :show-inheritance: :undoc-members: winregrc.environment\_variables module -------------------------------------- .. automodule:: winregrc.environment_variables :members: :show-inheritance: :undoc-members: winregrc.errors module ---------------------- .. automodule:: winregrc.errors :members: :show-inheritance: :undoc-members: winregrc.eventlog\_providers module ----------------------------------- .. automodule:: winregrc.eventlog_providers :members: :show-inheritance: :undoc-members: winregrc.filters module ----------------------- .. automodule:: winregrc.filters :members: :show-inheritance: :undoc-members: winregrc.hexdump module ----------------------- .. automodule:: winregrc.hexdump :members: :show-inheritance: :undoc-members: winregrc.interface module ------------------------- .. automodule:: winregrc.interface :members: :show-inheritance: :undoc-members: winregrc.knownfolders module ---------------------------- .. automodule:: winregrc.knownfolders :members: :show-inheritance: :undoc-members: winregrc.mounted\_devices module -------------------------------- .. automodule:: winregrc.mounted_devices :members: :show-inheritance: :undoc-members: winregrc.mru module ------------------- .. automodule:: winregrc.mru :members: :show-inheritance: :undoc-members: winregrc.msie\_zone\_info module -------------------------------- .. automodule:: winregrc.msie_zone_info :members: :show-inheritance: :undoc-members: winregrc.output\_writers module ------------------------------- .. automodule:: winregrc.output_writers :members: :show-inheritance: :undoc-members: winregrc.profiles module ------------------------ .. automodule:: winregrc.profiles :members: :show-inheritance: :undoc-members: winregrc.programscache module ----------------------------- .. automodule:: winregrc.programscache :members: :show-inheritance: :undoc-members: winregrc.sam module ------------------- .. automodule:: winregrc.sam :members: :show-inheritance: :undoc-members: winregrc.services module ------------------------ .. automodule:: winregrc.services :members: :show-inheritance: :undoc-members: winregrc.shell\_property\_keys module ------------------------------------- .. automodule:: winregrc.shell_property_keys :members: :show-inheritance: :undoc-members: winregrc.shellfolders module ---------------------------- .. automodule:: winregrc.shellfolders :members: :show-inheritance: :undoc-members: winregrc.srum\_extensions module -------------------------------- .. automodule:: winregrc.srum_extensions :members: :show-inheritance: :undoc-members: winregrc.sysinfo module ----------------------- .. automodule:: winregrc.sysinfo :members: :show-inheritance: :undoc-members: winregrc.syskey module ---------------------- .. automodule:: winregrc.syskey :members: :show-inheritance: :undoc-members: winregrc.task\_cache module --------------------------- .. automodule:: winregrc.task_cache :members: :show-inheritance: :undoc-members: winregrc.time\_zones module --------------------------- .. automodule:: winregrc.time_zones :members: :show-inheritance: :undoc-members: winregrc.type\_libraries module ------------------------------- .. automodule:: winregrc.type_libraries :members: :show-inheritance: :undoc-members: winregrc.usbstor module ----------------------- .. automodule:: winregrc.usbstor :members: :show-inheritance: :undoc-members: winregrc.userassist module -------------------------- .. automodule:: winregrc.userassist :members: :show-inheritance: :undoc-members: winregrc.versions module ------------------------ .. automodule:: winregrc.versions :members: :show-inheritance: :undoc-members: winregrc.volume\_scanner module ------------------------------- .. automodule:: winregrc.volume_scanner :members: :show-inheritance: :undoc-members: Module contents --------------- .. automodule:: winregrc :members: :show-inheritance: :undoc-members: ================================================ FILE: docs/sources/api/winregrc.scripts.rst ================================================ winregrc.scripts package ======================== Submodules ---------- winregrc.scripts.appcompatcache module -------------------------------------- .. automodule:: winregrc.scripts.appcompatcache :members: :show-inheritance: :undoc-members: winregrc.scripts.application\_identifiers module ------------------------------------------------ .. automodule:: winregrc.scripts.application_identifiers :members: :show-inheritance: :undoc-members: winregrc.scripts.cached\_credentials module ------------------------------------------- .. automodule:: winregrc.scripts.cached_credentials :members: :show-inheritance: :undoc-members: winregrc.scripts.catalog module ------------------------------- .. automodule:: winregrc.scripts.catalog :members: :show-inheritance: :undoc-members: winregrc.scripts.controlpanel\_items module ------------------------------------------- .. automodule:: winregrc.scripts.controlpanel_items :members: :show-inheritance: :undoc-members: winregrc.scripts.delegatefolders module --------------------------------------- .. automodule:: winregrc.scripts.delegatefolders :members: :show-inheritance: :undoc-members: winregrc.scripts.environment\_variables module ---------------------------------------------- .. automodule:: winregrc.scripts.environment_variables :members: :show-inheritance: :undoc-members: winregrc.scripts.eventlog\_providers module ------------------------------------------- .. automodule:: winregrc.scripts.eventlog_providers :members: :show-inheritance: :undoc-members: winregrc.scripts.knownfolders module ------------------------------------ .. automodule:: winregrc.scripts.knownfolders :members: :show-inheritance: :undoc-members: winregrc.scripts.mounted\_devices module ---------------------------------------- .. automodule:: winregrc.scripts.mounted_devices :members: :show-inheritance: :undoc-members: winregrc.scripts.mru module --------------------------- .. automodule:: winregrc.scripts.mru :members: :show-inheritance: :undoc-members: winregrc.scripts.msie\_zone\_info module ---------------------------------------- .. automodule:: winregrc.scripts.msie_zone_info :members: :show-inheritance: :undoc-members: winregrc.scripts.profiles module -------------------------------- .. automodule:: winregrc.scripts.profiles :members: :show-inheritance: :undoc-members: winregrc.scripts.programscache module ------------------------------------- .. automodule:: winregrc.scripts.programscache :members: :show-inheritance: :undoc-members: winregrc.scripts.sam module --------------------------- .. automodule:: winregrc.scripts.sam :members: :show-inheritance: :undoc-members: winregrc.scripts.services module -------------------------------- .. automodule:: winregrc.scripts.services :members: :show-inheritance: :undoc-members: winregrc.scripts.shellfolders module ------------------------------------ .. automodule:: winregrc.scripts.shellfolders :members: :show-inheritance: :undoc-members: winregrc.scripts.srum\_extensions module ---------------------------------------- .. automodule:: winregrc.scripts.srum_extensions :members: :show-inheritance: :undoc-members: winregrc.scripts.sysinfo module ------------------------------- .. automodule:: winregrc.scripts.sysinfo :members: :show-inheritance: :undoc-members: winregrc.scripts.syskey module ------------------------------ .. automodule:: winregrc.scripts.syskey :members: :show-inheritance: :undoc-members: winregrc.scripts.task\_cache module ----------------------------------- .. automodule:: winregrc.scripts.task_cache :members: :show-inheritance: :undoc-members: winregrc.scripts.time\_zones module ----------------------------------- .. automodule:: winregrc.scripts.time_zones :members: :show-inheritance: :undoc-members: winregrc.scripts.type\_libraries module --------------------------------------- .. automodule:: winregrc.scripts.type_libraries :members: :show-inheritance: :undoc-members: winregrc.scripts.usbstor module ------------------------------- .. automodule:: winregrc.scripts.usbstor :members: :show-inheritance: :undoc-members: winregrc.scripts.userassist module ---------------------------------- .. automodule:: winregrc.scripts.userassist :members: :show-inheritance: :undoc-members: Module contents --------------- .. automodule:: winregrc.scripts :members: :show-inheritance: :undoc-members: ================================================ FILE: docs/sources/application-keys/7-Zip.md ================================================ # 7-Zip **TODO this page currently contains rough notes, fine tune these** The 7-Zip application uses the following Windows Registry key to store various user specific information. ``` HKEY_CURRENT_USER\Software\7-Zip ``` Sub keys: Name | Description --- | --- FM | Values: Name | Data type | Description --- | --- | --- Lang | | Language tag, for example "en-US" or "-" if empty. ## 7-Zip FM sub key Sub keys: Name | Description --- | --- Columns | Values: Name | Data type | Description --- | --- | --- FlatViewArc# | | Where # is a numeric value e.g. 0 or 1 FolderShortcuts | | FolderHistory | | Contains a list of UTF-16 little-endian encoded strings with an end-of-string character ListMode | | Panels | | PanelPath# | | Where # is a numeric value e.g. 0 or 1
Contains an UTF-16 little-endian encoded string Position | | ### 7-Zip FM Columns sub key Values: Name | Data type | Description --- | --- | --- 7-Zip.Rar | REG_BINARY | 7-Zip.7z | REG_BINARY | ================================================ FILE: docs/sources/application-keys/CCleaner.md ================================================ # CCleaner **TODO this page currently contains rough notes, fine tune these** The CCleaner application uses the following Windows Registry key to store its configuration. ``` HKEY_CURRENT_USER\Software\Piriform\CCleaner ``` Values: Name | Data type | Description --- | --- | --- (App)Program Name | REG_SZ | AutoClose | | Automatically close program after cleaning, where 0 = Disabled and 1 = Enabled BackupDir | | Default path for the Issues Registry back up BackupPrompt | | Prompts user to back up the contents of the Issues Registry before removing them, where 0 = Disabled and 1 = Enabled BrowserMonitoring | | Whether automatic browser cleaning is active (CCleaner Professional), where 0 = Disabled and 1 = Enabled CookiesToSave | REG_SZ | Lists of cookies to preserve DefaultDetailedView | | Show detailed view screen (for the whole analysis or cleaning) after the operation finishes, where 0 = Disabled and 1 = Enabled DelayTemp | | Delete temporary (Windows) files older than 48 hours, where 0 = Disabled and 1 = Enabled FFDetailed | | Display a detailed log of Firefox/Mozilla temporary files, where 0 = Disabled and 1 = Enabled HideWarnings | | Hide warnings when advanced items is selected in the cleaning options tree, where 0 = Disabled and 1 = Enabled HomeScreen | | Starts on Health Check or Custom Clean, where 0 = Custom Clean and 1 = Health Check IEDetailed | | Display a detailed log of Internet Explorer temporary files, where 0 = Disabled and 1 = Enabled Language | | Language, contains a locale identifier (LCID). MinimizeSystemTray | | Minimize program to system tray on close, where 0 = Disabled and 1 = Enabled Monitoring | | Have Smart Cleaning, where 0 = Disabled and 1 = Enabled MSG_CONFIRMCLEAN | | Ask for confirmation before starting the Cleaning operation, where the value can be "True" or "False" MSG_WARNCHROMECACHE | | Warn when cleaning the Internet Cache in Google Chrome, where the value can be "True" or "False" MSG_WARNMOZCACHE | | Warn when cleaning the Internet Cache in Mozilla Firefox, where the value can be "True" or "False" RunICS | | No longer used, will automatically be set to 0 SecureDeleteMethod | | Secure deletion method, where 0 = Simple Overwrite (1 pass), 1 = DOD 5220.22-M (3 passes), 2 = NSA (7 passes) or 3 = Gutmann (35 passes) SecureDeleteType | | Use a secure deletion method, where 0 = Disabled and 1 = Enabled SystemMonitoring | | Activate System Smart Cleaning (or Active Monitoring for CCleaner Professional), where 0 = Disabled and 1 = Enabled SystemMonitoringSavingsAction | | System Smart Cleaning (or Active Monitoring for CCleaner Professional) mode, where 3 = "prompt to clean", 4 = "auto clean with notification" and 5 = "auto clean without notification" UpdateBackgroundCheck | | Check for software updates every 10 minutes (after program start), where 0 = Disabled and 1 = Enabled UpdateKey | REG_SZ | The last update check date and time formatted as: "MM/DD/YYYY hh:mm:ss [A|P]M", for example "07/13/2013 10:03:14 AM". WINDOW_HEIGHT | REG_SZ | Window height dimension in number of pixels. WINDOW_LEFT | REG_SZ | Window left position in number of pixels. WINDOW_MAX | REG_SZ | Windows is maximized, where 0 = not maximized WINDOW_TOP | REG_SZ | Window top position in number of pixels. WINDOW_WIDTH | REG_SZ | Window width dimension in number of pixels. WipeMFTFreeSpace | | Wipe free space in the NTFS Master File Table (MFT), where 0 = Disabled and 1 = Enabled ## (App)Program Name These entries indicate programs that are not part of the default set of enabled Cleaning Rules, and whether they should be cleaned. Note: Making an entry of "App(Your Program)]=true" will not allow CCleaner to clean it, as you would instead need to use the methods listed here. True = Checkbox selected when you start CCleaner. False = Checkbox cleared when you start CCleaner. Known Cleaning Rules: * (App)Cookies, contains "True" if the cookies should be cleaned; * (App)Delete Index.dat files * (App)History * (App)Last Download Location * (App)Other Explorer MRUs * (App)Recent Documents * (App)Recently Typed URLs * (App)Run (in Start Menu) * (App)Temporary Internet Files * (App)Thumbnail Cache ## IncludeX (e.g. Include1, Include2) Custom files or folders that should be included in cleaning [PATH|FILE]|Path|Filename ## ExcludeX (e.g. Exclude1, Exclude2) Custom files or folders that should be excluded from cleaning. [REG|PATH|FILE]|Path|Filename ## FinderIncludeX (e.g. FinderInclude1, FinderInclude2) Drives or folders CCleaner to use when searching for duplicate files. PATH|PATH\|Filetype|[RECURSE] ## FinderIncludeStates Whether the checkboxes have been checked or unchecked for folders referenced by FinderIncludeX. 0 = Cleared 1 = Selected For example, if there are three FinderIncludeX statements, you can specify the checked/cleared status using the pipe symbol: FinderIncludeStates=1|0|1 would check the first and last items, and the middle one would be unchecked. ## External Links * [Writing a CCleaner RegRipper Plugin Part 1](https://cheeky4n6monkey.blogspot.com/2012/02/writing-ccleaner-regripper-plugin-part.html) * [Writing a CCleaner RegRipper Plugin Part 2](http://cheeky4n6monkey.blogspot.com/2012/02/writing-ccleaner-regripper-plugin-part_05.html) ================================================ FILE: docs/sources/application-keys/MSDN-web-browser.md ================================================ # MSDN web browser **TODO this page currently contains rough notes, fine tune these** ``` HKEY_CURRENT_USER\Software\Microsoft\MSDN\9.0\WebBrowser\MRU ``` Values: Name | Data type | Description --- | --- | --- %NUMERIC% | REG_SZ | Where %NUMERIC% is a string in the form: "[0-9]+" ================================================ FILE: docs/sources/application-keys/Microsoft-Office.md ================================================ # Microsoft Office **TODO this page currently contains rough notes, fine tune these** ## Microsoft Outlook keys ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\ ``` Where %VERSION% corresponds to: Value | Description --- | --- 8.0 | Outlook 97 8.5 | Outlook 98 9.0 | Outlook 2000 10.0 | Outlook 2002/XP 11.0 | Outlook 2003 12.0 | Outlook 2007 14.0 | Outlook 2010 15.0 | Outlook 2013 Values: Name | Data type | Description --- | --- | --- ForcePSTPath | REG_EXPAND_SZ | ``` HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Outlook\Catalog ``` ``` HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Outlook\Search HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Outlook\Search\Catalog ``` ``` HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search ``` Values: Name | Data type | Description --- | --- | --- %FILENAME% | REG_DWORD | Where %FILENAME% is the full filename of Outlook file. ``` HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search\Catalog ``` Values: Name | Data type | Description --- | --- | --- %FILENAME% | REG_BINARY | Where %FILENAME% is the full filename of Outlook file. For "file/options/search" allow to search through "deleted items" ``` Key: HKCU\Software\Microsoft\Office\14.0\Outlook\Search Value: IncludeDeletedItems ``` Where the value data is: ``` 1 = Yes ``` Outlook generates log files in %temp%\Outlook logging: ``` Key: HKEY_CURRENT_USER\Software\Microsoft\Office\version number\Outlook\Search Value: EnableLogging = 0xffff0000 ``` Protected View mode ``` Key: HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Outlook\Security Key: HKEY_CURRENT_USER\Software\Policies\Microsoft\Office\14.0\Outlook\Security Value: MarkInternalAsUnsafe ``` Where the value data is: ``` 1 = Yes ``` ### Offline Address Book (OAB) ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\Cached Mode ``` Values: Name | Data type | Description --- | --- | --- DownloadOAB | REG_DWORD | Setting the value to zero prevents Offline Address Book (OAB) download and forces Outlook to use the global address list. If the "Cached Mode" key does not exist, create it. ### Secure Temp Folder ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\Security ``` Values: Name | Data type | Description --- | --- | --- OutlookSecureTempFolder | REG_SZ | ## Most Recently Used (MRU) keys ### File Name MRU keys Values: Name | Data type | Description --- | --- | --- Maximum Entries | | Numeric value Value | | Numeric value ``` HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\Common\Open Find\Microsoft Office Excel\Settings\Open\File Name MRU HKEY_CURRENT_USER\Software\Microsoft\Office\11.0\Common\Open Find\Microsoft Office Excel\Settings\Save As\File Name MRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\Open Find\Microsoft Office Excel\Settings\Open\File Name MRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\Open Find\Microsoft Office Excel\Settings\Save As\File Name MRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Common\Open Find\Microsoft Office Word\Settings\Save As\File Name MRU ``` ### Item MRU keys Values: Name | Data type | Description --- | --- | --- %ITEM% | | Where %ITEM% is a string in the form: "Item [0-9]+" ``` HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Excel\File MRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Excel\Options\MRUFuncs HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\PowerPoint\File MRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\PowerPoint\RecentAnimationList\EntranceMRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\PowerPoint\RecentAnimationList\EmphasisMRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\PowerPoint\RecentAnimationList\ExitMRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\PowerPoint\RecentAnimationList\MotionPathMRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\PowerPoint\Slide Libraries\Taskpane MRU HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Word\File MRU ``` Every %ITEM% value contains: in Office 12 ``` [F00000000][T%FILETIME%]*\\%FILENAME% ``` in Office 14 ``` [F00000000][T%FILETIME%][O00000000]*%FILENAME% ``` Where T%FILETIME% contains a FILETIME timestamp as a hexadecimal string (base-16), in upper case, e.g. T01CD10EC460129A0 ### Other MRU keys Find Contact toolbar button (Outlook 97 – 2003) ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\Contact\QuickFindMRU\QuickfindMRU ``` Find Pane’s Look in list ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\Contact\StripSearchMRU\StripSearchMRU ``` Appointment Locations ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\Preferences\LocationMRU ``` Advanced Find’s Search for Word(s) ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\Office Finder\MRU 1 ``` Advanced Find’s More Choices, Categories ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\Office Finder\MRU 3 ``` Choose Form dialog (New Item-> More Items-> Choose Form) (Outlook 2010 – 2013) ``` HKEY_CURRENT_USER\Software\Microsoft\Office\%VERSION%\Outlook\Office ``` ## External links * [Administering the offline address book in Outlook](https://support.microsoft.com/en-us/topic/administering-the-offline-address-book-in-outlook-51958cc8-684a-83f9-aea5-97d4dddc0af4) ================================================ FILE: docs/sources/application-keys/Terminal-server-client.md ================================================ # Terminal server client The most recent used (MRU) connnections of the Terminal server client can be found in the key: ``` HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default ``` Values: Name | Data type | Description --- | --- | --- MRU# | REG_SZ | The most recently used connection.
Where # is a string in the form: "[0-9]+" The contents of MRU# is either an IP address, e.g. 192.168.16.60, or a hostname, e.g. computer.domain.com. ## External Links * [How to Remove Entries from the Remote Desktop Connection Computer Box](https://learn.microsoft.com/en-us/troubleshoot/windows-server/remote/remove-entries-from-remote-desktop-connection-computer) ================================================ FILE: docs/sources/application-keys/WinRAR.md ================================================ # WinRAR **TODO this page currently contains rough notes, fine tune these** The WinRAR application uses the following Windows Registry key to store various user specific information. ``` HKEY_CURRENT_USER\Software\WinRAR\ArcHistory HKEY_CURRENT_USER\Software\WinRAR\DialogEditHistory\ArcName HKEY_CURRENT_USER\Software\WinRAR\DialogEditHistory\ExtrPath ``` Values: Name | Data type | Description --- | --- | --- %ITEM% | REG_SZ | Where %ITEM% is a string in the form: "[0-9]+" ================================================ FILE: docs/sources/application-keys/index.rst ================================================ ################ Application keys ################ .. toctree:: :maxdepth: 1 7-Zip <7-Zip> CCleaner Microsoft Office Terminal server client WinRAR ================================================ FILE: docs/sources/explorer-keys/Bit-bucket.md ================================================ # Bit bucket The Windows Explorer bit bucket key contains Recycler configuration properties and information about the Recycler of connected volumes. ``` HKEY_CURRENT_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket ``` Seen on Windows 2000, XP and 2003. Sub keys: Name | Description --- | --- %NAME% | Where %NAME% contains a drive letter, for example "c" Values: Name | Data type | Description --- | --- | --- NoRecycleFiles | REG_DWORD | NukeOnDelete | REG_DWORD | Percent | REG_DWORD | UseGlobalSettings | REG_DWORD | ## BitBucket\\%NAME% sub key Values: Name | Data type | Description --- | --- | --- IsUnicode | REG_DWORD | VolumeSerialNumber | REG_DWORD | ================================================ FILE: docs/sources/explorer-keys/Control-panel-item-identifiers.md ================================================ # Control panel item identifiers A control panel item identifier is a GUID that identifies a specific control panel item. ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace\{%GUID%} ``` Values: Name | Data type | Description --- | --- | --- Category | REG_DWORD | (default) | REG_SZ | Module name of the control panel item PreferredPlan | REG_SZ | ================================================ FILE: docs/sources/explorer-keys/Delegate-folders.md ================================================ # Delegate folders keys Windows explorer uses delegate folders to provide alternative graphical representations. ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\*\NameSpace\DelegateFolders\{%GUID%} ``` Values: Name | Data type | Description --- | --- | --- (default) | REG_SZ | Name (or description) of the delegate folder. ## External links * [DELEGATEITEMID structure (shobjidl_core.h)](https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ns-shobjidl_core-delegateitemid) ================================================ FILE: docs/sources/explorer-keys/Known-folder-identifiers.md ================================================ # Known folder identifier keys A known folder identifier is a GUID that identifies a system folder. It was introduced in Windows Vista to replace the constant special item identifier list (CSIDL). ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions ``` Values: Name | Data type | Description --- | --- | --- Attributes | REG_DWORD | Category | REG_DWORD | Name | REG_SZ | Name of the known folder LocalizedName | REG_EXPAND_SZ | Localized name of the known folder ParentFolder | REG_SZ | Path of the parent directory known folder, can contain a known folder identifier PreCreate | REG_DWORD | RelativePath | REG_SZ | Relative path of the known folder ### LocalizedName value data The LocalizedName value contains a localized version of the folder name, e.g. on Windows XP the folder identifier key: ``` HKEY_CLASSES_ROOT\CLSID\{450d8fba-ad25-11d0-98a8-0800361b1103} ``` Has a LocalizedString value with the following data: ``` @%SystemRoot%\system32\SHELL32.dll,-9227 ``` Which is the [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html) for "My Documents". ## External links * [libfwsi: Known Folder Identifiers](https://github.com/libyal/libfwsi/wiki/Known-Folder-Identifiers) ================================================ FILE: docs/sources/explorer-keys/MUI-cache.md ================================================ # Multilingual User Interface (MUI) cache Seen on Windows XP and 2003 ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\ShellNoRoam\MUICache ``` Seen on Windows Vista and later ``` HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache ``` ================================================ FILE: docs/sources/explorer-keys/Most-recently-used.md ================================================ # Most recently used (MRU) The Windows Registry contains various keys with information about Most Recently files Used (MRU). Windows Explorer (or Windows shell), extensively uses such keys. Several different variants of MRU keys are known to be used, such as: * Keys with a MRUList value * Keys with a MRUListEx value * BagMRU key ## Keys with a MRUList value Values: Name | Data type | Description --- | --- | --- MRUList | | Contains a list of the most recently used (MRU) items.
Consists of an array of UTF-16 little-endian formatted character value.
The first value represents the most recently used item, the second the second recently used item and so forth. The last value indicates the end of the list and should be 0 (0x0000). %ALPHA% | | Where %ALPHA% is a string in the form: "[a-z]"
The value name corresponds to a string value in the MRUList value. E.g. a MRUList value of "a" (0x0061) corresponds to the value "a". ### String MRUList values The following keys with a MRUList value contain %ALPHA% values that consists of an UTF-16 little-endian formatted string with an end-of-string character. Sub keys of: `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\` Registry key | Windows version | Description --- | --- | --- ComDlg32\LastVisitedMRU | 2000, XP | ComDlg32\OpenSaveMRU\%EXTENSION% | 2000, XP |
Where %EXTENSION% is a file extension like "exe" or "\*" Doc Find Spec MRU | | Most recently used "Find Files" commands FileExts\%EXTENSION%\OpenWithList | 2000, XP, Vista | Most recently used "Open With" commands
Where %EXTENSION% is a file extension like ".exe" FindComputerMRU | | Most recently used "Find Computer" commands Map Network Drive MRU | XP | Most recently used mapped network drives PrnPortsMRU | | Most recently used printer ports RecentDocs | 2000, XP | RecentDocs\%EXTENSION% | 2000, XP |
Where %EXTENSION% is a file extension like ".exe" or "Folder" RunMRU | NT4, 2000, XP, Vista | Most recently used "Run" commands WordWheelQuery | | ### Shell Item List MRUList values The following keys with a MRUList value contain %ALPHA% values that consists of a Shell Item List. Sub keys of: `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\` Registry key | Windows version | Description --- | --- | --- DesktopStreamMRU | NT4 | How icons are arranged on the desktop.
Although the key is present on later versions of Windows it does not seem to be used anymore. ## Keys with a MRUListEx value Values: Name | Data type | Description --- | --- | --- MRUListEx | | Contains a list of the most recently used (MRU) items.
Consists of an array of 4-byte little-endian values.
The first value represents the most recently used item, the second the second recently used item and so forth. The last value indicates the end of the list and should be -1 (0xffffffff). %NUMERIC% | | Where %NUMERIC% is a string in the form: "[0-9]+"
The value name corresponds to a 4-byte numeric value in the MRUListEx value. E.g. a MRUListEx value of 0x00000001 corresponds to the value named "1". The value data of the numeric value depends on the sub key. ### String MRUListEx values The following keys with a MRUListEx value contain %NUMERIC% values that consists of an UTF-16 little-endian formatted string with an end-of-string character. ### Shell Item List MRUListEx values The following keys with a MRUListEx value contain %NUMERIC% values that consists of a Shell Item List. Sub keys of: `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\` Registry key | Windows version | Description --- | --- | --- ComDlg32\OpenSavePidlMRU\%EXTENSION% | Vista |
Where %EXTENSION% is a file extension like "exe" or "\*" StreamMRU | 2000, XP | ### String and Shell Item MRUListEx values The following keys with a MRUListEx value contain %NUMERIC% values that consists of a String and Shell Item. The String and Shell Item is variable of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | ... | | The filename stored as an UTF-16 little-endian formatted string with end-of-string character ... | ... | | The filename stored as a Shell Item.
The Shell Item is empty if not set. Sub keys of: `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\` Registry key | Windows version | Description --- | --- | --- RecentDocs | Vista | RecentDocs\%EXTENSION% | Vista | Where %EXTENSION% is a file extension like .exe or Folder ### String and Shell Item List MRUListEx values The following keys with a MRUListEx value contain %NUMERIC% values that consists of a String and Shell Item List. The String and Shell Item List is variable of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | ... | | The filename stored as an UTF-16 little-endian formatted string with end-of-string character ... | ... | | The path stored as a Shell Item List.
The first Shell Item is empty if not set. Sub keys of: `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\` Registry key | Windows version | Description --- | --- | --- ComDlg32\LastVisitedPidlMRU | Vista, 7 | ## BagMRU key The values in the BagMRU and sub keys are also referred to as "shellbags". BagMRU keys as of XP (stored in NTUSER.DAT) ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\BagMRU HKEY_CURRENT_USER\Software\Microsoft\Windows\ShellNoRoam\BagMRU ``` Additional BagMRU keys as of Vista (stored in USRCLASS.DAT) ``` HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\BagMRU HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\ShellNoRoam\BagMRU HKEY_CURRENT_USER\Software\Classes\Wow6432Node\Local Settings\Software\Microsoft\Windows\Shell\BagMRU HKEY_CURRENT_USER\Software\Classes\Wow6432Node\Local Settings\Software\Microsoft\Windows\ShellNoRoam\BagMRU ``` Seen in Windows 7: ``` HKEY_CURRENT_USER\Local Settings\Software\Microsoft\Windows\Shell\BagMRU ``` The BagMRU sub keys form a hierarchy similar to a folder structure. Values: Name | Data type | Description --- | --- | --- NodeSlot | REG_DWORD | Contains the node slot index number (also referred to as bag number)
This number corresponds to the sub key name the corresponding Bags sub key.
E.g. bag number 1 in HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\BagMRU relates to the Bags sub key HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Bags\1 NodeSlots | | Only present in the root BagMRU key. MRUListEx | REG_BINARY | Contains a list of the most recently used (MRU) items.
Consists of an array of 4-byte little-endian values.
The first value represents the most recently used item, the second the second recently used item and so forth. The last value indicates the end of the list and should be -1 (0xffffffff). %NUMERIC% | REG_BINARY | Where %NUMERIC% is a string in the form: "[0-9]+"
The value name corresponds to a 4-byte numeric value in the MRUListEx value. E.g. a MRUListEx value of 0x00000001 corresponds to the value named "1".
Contains a shell item ### Bag number shell sub key The numbered sub keys of the Bags key have a Shell sub key e.g. ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Bags\1\Shell ``` This key contains various values: Name | Data type | Description --- | --- | --- Address | | Buttons | | Col | | ColInfo | | FolderType | | FFlags | | HotKey | | Links | | MinPos%GEOMETRY%(1).bottom | | Where %GEOMETRY% is the screen geometry in the form 1100x705 MinPos%GEOMETRY%(1).left | | Where %GEOMETRY% is the screen geometry in the form 1100x705 MinPos%GEOMETRY%(1).right | | Where %GEOMETRY% is the screen geometry in the form 1100x705 MinPos%GEOMETRY%(1).top | | Where %GEOMETRY% is the screen geometry in the form 1100x705 MinPos%GEOMETRY%(1).x | | Where %GEOMETRY% is the screen geometry in the form 1100x705 MinPos%GEOMETRY%(1).y | | Where %GEOMETRY% is the screen geometry in the form 1100x705 Mode | | Rev | | ScrollPos%GEOMETRY%(1).x | | Where %GEOMETRY% is the screen geometry in the form 1100x705 ScrollPos%GEOMETRY%(1).y | | Where %GEOMETRY% is the screen geometry in the form 1100x705 ShowCmd | | Sort | | SortDir | | Vid | | WFlags | | ## Notes This section contains some notes on explorer MRU keys that need to be completed. ### Wallpaper MRU key MRUListEx value Sub keys of: `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\` Registry key | Windows version | Description --- | --- | --- Wallpaper\MRU | XP, 2003 | Most recently used wallpapers ``` 00000000 43 00 3a 00 5c 00 57 00 49 00 4e 00 44 00 4f 00 |C.:.\.W.I.N.D.O.| 00000010 57 00 53 00 5c 00 42 00 6c 00 75 00 65 00 20 00 |W.S.\.B.l.u.e. .| 00000020 4c 00 61 00 63 00 65 00 20 00 31 00 36 00 2e 00 |L.a.c.e. .1.6...| 00000030 62 00 6d 00 70 00 00 00 70 00 00 00 00 00 00 00 |b.m.p...p.......| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000050 00 00 00 00 78 01 08 00 00 00 00 00 00 00 00 00 |....x...........| 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000a0 00 00 00 00 28 f6 0b 00 00 00 00 00 70 4b 0c 00 |....(.......pK..| 000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000c0 00 00 00 00 00 00 00 00 28 f6 0b 00 00 00 00 00 |........(.......| 000000d0 78 5b 0c 00 00 00 00 00 20 f6 0b 00 00 00 00 00 |x[...... .......| 000000e0 78 01 08 00 00 00 00 00 00 00 00 00 00 00 00 00 |x...............| 000000f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000110 00 00 00 00 00 00 00 00 78 01 08 00 92 02 00 00 |........x.......| 00000120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000170 00 00 00 00 00 00 00 00 28 f6 0b 00 00 00 00 00 |........(.......| 00000180 01 02 00 00 00 00 00 00 68 4b 0c 00 08 10 00 00 |........hK......| 00000190 68 4b 0c 00 00 00 00 00 70 4b 0c 00 78 01 08 00 |hK......pK..x...| 000001a0 08 10 00 00 2f 2d f4 77 51 8e e4 77 f8 00 00 00 |..../-.wQ..w....| 000001b0 00 00 00 00 00 00 00 00 00 00 00 00 50 f4 a2 00 |............P...| 000001c0 70 4b 0c 00 00 10 00 00 03 00 00 00 28 8d e4 77 |pK..........(..w| 000001d0 f4 dc 0b 00 36 8e e4 77 04 01 00 00 ab 3d 29 77 |....6..w.....=)w| 000001e0 40 fd a2 00 00 00 00 00 d6 0f 00 00 a8 4e 0c 00 |@............N..| 000001f0 00 d0 fd 7f 00 00 00 00 be 20 08 00 01 00 00 00 |......... ......| 00000200 e0 dc 0b 00 08 00 00 00 30 00 00 00 30 00 00 00 |........0...0...| 00000210 00 60 a9 0f c6 f2 c2 01 |.`......| ``` ### Explorer MRUList ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MRU ``` ### CIDSizeMRU MRUListEx Seen on Windows Vista ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\CIDSizeMRU ``` ``` 00000000 66 00 69 00 72 00 65 00 66 00 6f 00 78 00 2e 00 |f.i.r.e.f.o.x...| 00000010 65 00 78 00 65 00 00 00 00 00 00 00 00 00 00 00 |e.x.e...........| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| ... 00000200 00 00 00 00 00 00 00 00 12 00 00 00 0b 00 00 00 |................| 00000210 22 04 00 00 15 03 00 00 00 00 00 00 00 00 00 00 |"...............| 00000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000230 00 00 00 00 00 00 00 00 1a 00 00 00 27 00 00 00 |............'...| 00000240 7c 02 00 00 d6 00 00 00 00 00 00 00 00 00 00 00 |...............| ``` MRUListEx ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\FirstFolder ``` Contains an UTF-16 little-endian formatted string. ## External Links * [Windows Shell Item format specification](https://github.com/libyal/libfwsi/blob/main/documentation/Windows%20Shell%20Item%20format.asciidoc) ================================================ FILE: docs/sources/explorer-keys/Mount-points.md ================================================ # Moint points ## MountPoints ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints ``` Seen on: * Windows 2000 Sub keys: Name | Description --- | --- %NAME% | Where %NAME% contains the name of the mount point (or drive mapping). Where the following forms of %NAME% have been observed: * Drive letter, for example "C" ### MountPoints name sub key Sub keys: Name | Description --- | --- `_Autorun` | `_DIL` | `_LabelFromReg` | Values: Name | Data type | Description --- | --- | --- `_UB` | REG_BINARY | BaseClass | REG_SZ | Version | REG_DWORD | ## MountPoints2 ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2 ``` Seen on: * Windows XP * Windows 2003 * Windows Vista * Windows 2008 * Windows 7 * Windows 8.0 * Windows 8.1 * Windows 10 Sub keys: Name | Description --- | --- CPC | (Introduced in Windows Vista?) CPC\LocalMOF | (Introduced in Windows 7?) CPC\Volume | (Introduced in Windows Vista?) %NAME% | Where %NAME% contains the name of the mount point (or drive mapping). Where the following variants of %NAME% have been observed: * Drive letter, for example "C" * Volume identifier (GUID), for example "{01234567-89ab-cdef-0123-456789abcdef}" * UNC path, for example "##1.2.3.4#username" ### MountPoints2 name sub key Sub keys: Name | Description --- | --- `_Autorun` | `_Autorun\Action` | `_Autorun\DefaultIcon` | `_Autorun\DefaultLabel` | Shell | Shell\Autoplay | Shell\Autoplay\DropTarget | Shell\AutoRun | Shell\AutoRun\Command | Values: Name | Data type | Description --- | --- | --- BaseClass | REG_SZ | ================================================ FILE: docs/sources/explorer-keys/Program-cache.md ================================================ # Program cache The Windows explorer ProgramsCache Registry values can be stored in the following Windows Registry keys. * Explorer\\StartPage key * Explorer\\StartPage2 key ## Explorer\\StartPage key ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\StartPage ``` Seen in Windows XP, 2003 and Vista. Values: Name | Data type | Description --- | --- | --- ProgramsCache | REG_BINARY | All the started the programs.
**Contains a Jump list?** ## Explorer\\StartPage2 key ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\StartPage2 ``` Seen in Windows 7. Values: Name | Data type | Description --- | --- | --- ProgramsCache | REG_BINARY | All the started the programs.
**Contains a Jump list?** ProgramsCacheSMP | REG_BINARY | The applications pinned to the Start Menu.
Contains a Jump list. ProgramsCacheTBP | REG_BINARY | The applications pinned to the Taskband.
Contains a Jump list. Note that the format of the ProgramsCache value data slightly differs from that of the ProgramsCacheSMP and ProgramsCacheTBP value data. ## ProgramsCache value data format ProgramsCacheSMP - Empty list ``` 00000000 01 00 00 00 |.........| 00000000 00 00 00 00 |.........| 00000000 02 |.........| ``` ProgramsCacheTBP ``` 0x00000000 01 00 00 00 0b 00 00 00 01 aa 02 00 00 ................ 0x00000000 01 00 00 00 07 00 00 00 01 0e 03 00 00 ................ 00000000 01 00 00 00 |................| number of entries? 00000000 0e 00 00 00 |................| start of entry marker? 00000000 01 |................| relative offset to next entry? 00000000 f2 02 00 00 |................| 00000000 14 00 1f |................| shell item list 00000010 80 c8 27 34 1f 10 5c 10 42 aa 03 2e e4 52 87 d6 |..'4..\.B....R..| ... 000002f0 00 78 00 65 00 00 00 00 00 00 00 1c 00 |.x.e............| end of list? 000002f0 00 00 |.x.e............| start of entry marker? 000002f0 01 |.x.e............| 00000300 3c 02 00 00 |<........'4..\.B| shell item list 00000300 14 00 1f 80 c8 27 34 1f 10 5c 10 42 |<........'4..\.B| ... 00000bb0 4f 00 4b 00 2e 00 45 00 58 00 45 00 00 00 00 00 |O.K...E.X.E.....| 00000bc0 00 00 1c 00 |.......| end of list? 00000bc0 00 00 |.......| 00000bc0 02 |.......| ``` StartPage2\ProgramsCache ``` Window 7 00000000 13 00 00 00 c3 53 5b 62 48 ab c1 4e ba 1f a1 ef |.....S[bH..N....| 00000010 41 46 fc 19 00 80 00 00 00 |AF.......~.1....| shell item list? 00000010 7e 00 31 00 00 00 00 |AF.......~.1....| 00000020 00 6a 3d 6c 3e 11 00 50 72 6f 67 72 61 6d 73 00 |.j=l>..Programs.| 00000030 00 66 00 08 00 04 00 ef be 6a 3d 53 3e 6a 3d 6c |.f.......j=S>j=l| 00000040 3e 2a 00 00 00 c1 e2 00 00 00 00 01 00 00 00 00 |>*..............| 00000050 00 00 00 00 00 3c 00 00 00 00 00 50 00 72 00 6f |.....<.....P.r.o| 00000060 00 67 00 72 00 61 00 6d 00 73 00 00 00 40 00 73 |.g.r.a.m.s...@.s| 00000070 00 68 00 65 00 6c 00 6c 00 33 00 32 00 2e 00 64 |.h.e.l.l.3.2...d| 00000080 00 6c 00 6c 00 2c 00 2d 00 32 00 31 00 37 00 38 |.l.l.,.-.2.1.7.8| 00000090 00 32 00 00 00 18 00 00 00 |.2........<...:.| 00000090 01 3c 02 00 00 |.2........<...:.| shell item list? 00000090 3a 02 |.2........<...:.| 000000a0 32 00 85 05 00 00 30 3f 97 a9 20 00 49 4e 54 45 |2.....0?.. .INTE| 000000b0 52 4e 7e 31 2e 4c 4e 4b 00 00 b8 00 08 00 04 00 |RN~1.LNK........| 000000c0 ef be 6a 3d 6c 3e 6a 3d 6c 3e 2a 00 00 00 b8 e3 |..j=l>j=l>*.....| ... 00012e80 00 00 00 00 00 00 1c 00 00 00 02 |...........| 0x00019890 6d 00 2e 00 65 00 78 00 65 00 00 00 00 00 00 00 m...e.x.e....... 0x000198a0 20 00 00 00 ......9....O.'H TODO: edge case or remnant data? 0x000198a0 02 ab 95 39 9e 9c 1f 13 4f b8 27 48 ......9....O.'H 0x000198b0 b2 4b 6c 71 74 00 .Klqt.T...R.1... 0x000198b0 54 00 00 00 52 00 31 00 00 00 .Klqt.T...R.1... 0x000198c0 00 00 0c 3d a4 33 11 00 54 61 73 6b 42 61 72 00 ...=.3..TaskBar. 0x000198d0 3c 00 08 00 04 00 ef be 0c 3d a4 33 0c 3d a4 33 <........=.3.=.3 0x000198e0 2a 00 00 00 69 ee 00 00 00 00 04 00 00 00 00 00 *...i........... ``` StartPage\ProgramsCache ``` Windows XP and 2003 00000000 09 00 00 00 0b 00 |......V...T.1...| data size 00000000 56 00 00 00 |......V...T.1...| shell item list 00000000 54 00 31 00 00 00 |......V...T.1...| 00000010 00 00 04 3b a3 79 11 00 50 72 6f 67 72 61 6d 73 |...;.y..Programs| 00000020 00 00 3c 00 03 00 04 00 ef be 04 3b 8c 79 04 3b |..<........;.y.;| 00000030 a3 79 14 00 26 00 50 00 72 00 6f 00 67 00 72 00 |.y..&.P.r.o.g.r.| 00000040 61 00 6d 00 73 00 00 00 40 73 68 65 6c 6c 33 32 |a.m.s...@shell32| 00000050 2e 64 6c 6c 2c 2d 32 31 37 38 32 00 18 00 00 00 |.dll,-21782.....| 00000060 01 d4 00 00 00 |.......2.#....;.| 00000060 d2 00 32 00 23 03 00 00 04 3b a3 |.......2.#....;.| 00000070 79 20 00 49 4e 54 45 52 4e 7e 31 2e 4c 4e 4b 00 |y .INTERN~1.LNK.| 00000080 00 42 00 03 00 04 00 ef be 04 3b a3 79 04 3b a3 |.B........;.y.;.| ... 0x000003e0 1c 00 00 00 .........T.1.... sentinel of 0x00 seen before shell item list with more than one shell item? 0x000003e0 00 b0 00 00 00 .........T.1.... shell item list 0x000003e0 54 00 31 00 00 00 00 .........T.1.... 0x000003f0 00 04 3b a3 79 11 00 50 72 6f 67 72 61 6d 73 00 ..;.y..Programs. ... 0x00001020 00 00 00 00 00 1c 00 00 00 ................ unknown data 9 bytes (0x02 end marker?) 0x00001020 02 16 00 02 00 00 00 ................ 0x00001030 00 00 .........2.....: data size 0x00001030 01 ea 00 00 00 .........2.....: shell item list 0x00001030 e8 00 32 00 1b 06 00 00 3a .........2.....: ... 0x00004a40 00 65 00 78 00 65 00 00 00 00 00 1c 00 00 00 .e.x.e.......... unknown data 11 bytes 0x00004a40 02 .e.x.e.......... 0x00004a50 10 02 19 00 02 00 00 00 00 00 ................ 0x00004a50 01 ca 00 00 00 ................ 0x00004a50 c8 ................ 0x00004a60 00 32 00 42 06 00 00 04 3b 12 7a 20 00 4d 4f 5a .2.B....;.z .MOZ ... 00004b10 00 65 00 66 00 6f 00 78 00 2e 00 65 00 78 00 65 |.e.f.o.x...e.x.e| 00004b20 00 00 00 00 00 1c 00 00 00 |..........| 00004b20 02 |..........| ``` ``` Windows Vista (c3535b62-48ab-c14e-ba1f-a1ef4146fc19 FOLDERID_StartMenu) 0x00000000 0c 00 00 00 c3 53 5b 62 48 ab c1 4e ba 1f a1 ef .....S[bH..N.... 0x00000010 41 46 fc 19 AF...|...z.1.... 0x00000010 00 7c 00 00 00 AF...|...z.1.... ... 0x00009fe0 72 00 33 00 32 00 2e 00 65 00 78 00 65 00 00 00 r.3.2...e.x.e... 0x00009ff0 00 00 00 00 1c 00 00 00 .........a.O..M. TODO: edge case or remnant data? 0x00009ff0 02 61 ae 4f 05 d8 4d 87 .........a.O..M. 0x0000a000 47 80 b6 09 02 20 c4 b7 00 02 G.... .... ``` Value data header Windows XP and 2003. Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0x00000009 | Format version 4 | 2 | 0x000b | **Unknown** Value data header Windows Vista. Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0x0000000c | Format version 4 | 16 | | Known folder identifier
Contains a GUID
c3535b62-48ab-c14e-ba1f-a1ef4146fc19 (FOLDERID_StartMenu) 20 | 1 | | **Unknown (sentinel?)** ProgramsCache value data header Windows 7 and 2008. Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0x00000013 | Format version 4 | 16 | | Known folder identifier
Contains a GUID
c3535b62-48ab-c14e-ba1f-a1ef4146fc19 (FOLDERID_StartMenu) 20 | 1 | | **Unknown (sentinel?)** ProgramsCacheSMP and ProgramsCacheTBP value data header Windows 7 and 2008. Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0x00000001 | Format version 4 | 4 | | **Unknown** 5 | 1 | | **Unknown (sentinel?)** Value data entry. Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | | Entry data size 4 | ... | | Entry data
Contains a shell item list ... | 1 | | **Unknown (sentinel?)**
**Seen 0x00, 0x01, 0x02 (end marker?)** **if sentinel is 0x02 and there is more data then look for 0x00 which should be followed by 02 00 00 00 00 00 01** ================================================ FILE: docs/sources/explorer-keys/Shell-folders.md ================================================ # Shell folders Shell Folder identifiers are class identifiers with Shell Folder sub key. In the Windows Registry Some Class identifiers (CLSID) have a ShellFolder sub key for example: ``` HKEY_LOCAL_MACHINE\Software\CLSID\{%GUID%}\ShellFolder ``` Where {%GUID%} is a GUID in the form: {00000000-0000-0000-0000-000000000000}. A shell folder can be system or user specific. System shell folders: ``` HKEY_CURRENT_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders HKEY_CURRENT_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders HKEY_CURRENT_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Backup ``` WoW64 (Windows 32-bit on Windows 64-bit) system shell folders: ``` HKEY_CURRENT_MACHINE\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders HKEY_CURRENT_MACHINE\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders HKEY_CURRENT_MACHINE\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Backup ``` Per-user shell folders: ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders ``` Values: Name | Data type | Description --- | --- | --- %NAME% | REG_SZ or REG_EXPAND_SZ | Path to the corresponding directory ================================================ FILE: docs/sources/explorer-keys/Typed-paths.md ================================================ # Typed paths ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths ``` Value| Data type| Description --- | --- | --- %ITEM% | REG_SZ | Where %ITEM% is a string in the form: "url[0-9]+" ================================================ FILE: docs/sources/explorer-keys/User-assist.md ================================================ # User Assist key The User Assist key contains settings and data of programs that were launched via Windows Explorer (explorer.exe). ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\Currentversion\Explorer\UserAssist ``` Sub keys: Name | Description --- | --- {%GUID%} | The User Assist logged data Settings | Settings to control User Assist logging Note that the Settings sub key does not exist by default. ## Known GUIDs GUID | Windows Versions | Description --- | --- | --- {0D6D4F41-2994-4BA0-8FEF-620E43CD2812} | XP, Vista | *TODO assumed as: IE7* {5E6AB780-7743-11CF-A12B-00AA004AE837} | 2000, XP, 2003, Vista | Microsoft Internet Toolbar {75048700-EF1F-11D0-9888-006097DEACF9} | 2000, XP, 2003, Vista | ActiveDesktop {9E04CAB2-CC14-11DF-BB8C-A2F1DED72085} | 8, 10 | {A3D53349-6E61-4557-8FC7-0028EDCEEBF6} | 8, 10 | {B267E3AD-A825-4A09-82B9-EEC22AA3B847} | 8 | {BCB48336-4DDD-48FF-BB0B-D3190DACB3E2} | 8.1 | {CAA59E3C-4792-41A5-9909-6A6A8D32490E} | 8 | {CEBFF5CD-ACE2-4F4F-9178-9926F41749EA} | 2008 (R2?), 7, 8, 10 | *TODO assumed as: Application or Executable File Execution* {F2A1CB5A-E3CC-4A2E-AF9D-505A7009D442} | 8, 10 | {F4E57C4B-2036-45F0-A9AB-443BCFE33D9F} | 2008 (R2?), 7, 8, 10 | *TODO assumed as: Shortcut File Execution* {FA99DFC7-6AC2-453A-A5E2-5E2AFF4507BD} | 8, 10 | Note that the User Assist key does not seem to be present on NT4, therefore this functionality was likely introduced in Windows 2000. Sometimes more information about the GUID can be found in the key: ``` HKEY_LOCAL_MACHINE\Software\Classes\CLSID\{%GUID%}\ ``` ## GUID sub key Sub keys: Name | Description --- | --- Count | Contains the User Assist log entries Values: Name | Data type | Description --- | --- | --- Version | REG_DWORD | Indicates the User Assist log format version ### Version value data Value | Windows Versions --- | --- 3 | 2000, XP, 2003, Vista 5 | 2008 (R2?), 7, 8 ### Count sub key Values: Name | Data type | Description --- | --- | --- %NAME% | REG_SZ | Where %NAME% is obfuscated using a technique described below. Windows Versions | Obfuscation technique --- | --- 2000, XP, 2003, Vista, 2008 (R2?), 7, 8 | ROT-13 of character values in the ASCII `[A-Za-z]` range. + Values outside of this range e.g. `[0-9]` and values outside the basic ASCII range (>= 0x80) are not obfuscated. 7 beta | Vigenère cipher with key: BWHQNKTEZYFSLMRGXADUJOPIVC #### Named value Value | Description --- | --- UEME_CTLSESSION | Session identifier UEME_CTLCUACount:ctor | UEME_RUNCPL | Executed control applets (.cpl) UEME_RUNPATH | Executed programs UEME_RUNPIDL | Programs started via a PIDL (shell item list) e.g. using a Shortcut UEME_RUNWMCMD | Programs started via a Run Command UEME_UIHOTKEY | Programs started via a Hotkey UEME_UIQCUT | Programs started via a Quick Launch menu shortcut UEME_UISCUT | Programs started via a Desktop shortcut UEME_UITOOLBAR | Programs started via Windows Explorer Toolbar buttons Note does UEME stand for User Experience Monitoring Element/Extension? Note does CTL stand for client? Note does CUA stand for current user (file) associations? With the exception of the UEME_CTLSESSION value, these values appear to use a similar data types. The structure of a data type depends on the Version value of the GUID sub key. The following versions have been observed: * version 3, that is used by Windows 2000, XP, 2003 and Vista. * version 5, that is used by Windows 2008 (R2?), 7, 8. #### UEME_CTLSESSION value data ##### UEME_CTLSESSION value data - version 3 The UEME_CTLSESSION value data - version 3 is 8 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | | Unknown 4 | 4 | | Current session identifier ##### UEME_CTLSESSION value data - version 5 The UEME_CTLSESSION value data - version 5 is 1612 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 1 | Unknown (version?) 4 | 4 | | Unknown 8 | 4 | | Unknown 12 | 4 | | Unknown 16 | ... | | Unknown (array of 3x records at offset 0x10, 0x224, 0x438) The UEME_CTLSESSION value data - version 5 record is 532 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | | Unknown 8 | 4 | | Unknown 12 | 4 | | Unknown 16 | ... | | Unknown (UTF-16 little-endian string with end-of-string character) ... | ... | | Unknown #### Other value data ##### Other value data - version 3 The other value data - version 3 is 16 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | | Session identifier 4 | 4 | | Number of executions 8 | 8 | | Last execution time, which contains a FILETIME ##### Other value data - version 5 The other value data - version 5 is 72 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | | Unknown (Seen: 0, -1 (0xffffffff) or 1) 4 | 4 | | Number or executions 8 | 4 | | Unknown (sometimes referred to as number of application focuses) 12 | 4 | | Unknown (sometimes referred to as application focus time, does its meaning differ per GUID?) 16 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 20 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 24 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 28 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 32 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 36 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 40 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 44 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 48 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 52 | 4 | | Unknown (Contains a 32-bit floating point, 0.0 or -1.0 if not set ?) 56 | 4 | | Unknown, sometimes -1 (0xffffffff) 60 | 8 | | Last execution time, contains a FILETIME or 0 if not set 68 | 4 | 0 | Unknown (empty value ?) ## Settings sub key Values: Name | Data type | Description --- | --- | --- NoLog | REG_DWORD | Turn of logging. Set to 1 to disable logging of the User Assist information NoEncrypt | REG_DWORD | Turn of obfuscation of %NAME% values. Set to 1 to disable name obfuscation ## External links * [UserAssist](https://blog.didierstevens.com/programs/userassist), by Didier Stevens * [Windows 7 Beta: ROT13 Replaced With Vigenère? Great Joke!](https://blog.didierstevens.com/2009/01/18/quickpost-windows-7-beta-rot13-replaced-with-vigenere-great-joke/) * [Windows-userassist-keys](https://www.aldeid.com/wiki/Windows-userassist-keys) * [libfwsi: Known Folder Identifiers](https://github.com/libyal/libfwsi/wiki/Known-Folder-Identifiers) ================================================ FILE: docs/sources/explorer-keys/index.rst ================================================ ##################### Windows explorer keys ##################### .. toctree:: :maxdepth: 1 Bit bucket Control panel item identifiers Delegate folders Known folder identifiers Mount points Most recently used (MRU) Multilingual User Interface (MUI) cache Program cache Shell folders Typed paths User assist ================================================ FILE: docs/sources/internet-explorer-keys/Browser-helper-objects.md ================================================ # Browser helper objects (BHO) ``` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects ``` ================================================ FILE: docs/sources/internet-explorer-keys/Policies.md ================================================ # Policies The Internet Explorer polices are stored in multiple keys. Order of application: 1. HKEY_LOCAL_MACHINE policy key (Administrative override) 1. HKEY_CURRENT_USER policy key 1. HKEY_CURRENT_USER preference key 1. HKEY_LOCAL_MACHINE preference key (System default settings) Note that the location of the HKEY_LOCAL_MACHINE policy and preference key is dependent on the usage of WoW64 (Windows 32-bit on Windows 64-bit). Normal: 1. HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Internet Explorer\\Main\\FeatureControl 1. HKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Internet Explorer\\Main\\FeatureControl 1. HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl 1. HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl WoW64: 1. HKEY_LOCAL_MACHINE\\Wow6432Node\\Software\\Policies\\Microsoft\\Internet Explorer\\Main\\FeatureControl 1. HKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Internet Explorer\\Main\\FeatureControl 1. HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl 1. HKEY_LOCAL_MACHINE\\Wow6432Node\\Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl ## Policies ``` HKEY_CURRENT_USER\Software\Policies\Microsoft\Internet Explorer ``` Values: Value | Data type | Description --- | --- | --- Download Directory | REG_SZ | The user specific download directory ### Download policies ``` HKEY_CURRENT_USER\Software\Policies\Microsoft\Internet Explorer\Download ``` Values: Value | Data type | Description --- | --- | --- CheckExeSignatures | REG_SZ | RunInvalidSignatures | REG_DOWRD | ## Feature controls ### Security Zones Value | Description --- | --- 0 | My Computer 1 | Local Intranet Zone 2 | Trusted sites Zone 3 | Internet Zone 4 | Restricted Sites Zone Also stored in "Description" Registry value in zone-specific Registry key. ### Local Machine Zone Lockdown Applies the Lockdown Zones instead of the Zones. ``` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_LOCALMACHINE_LOCKDOWN\ HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_LOCALMACHINE_LOCKDOWN\ HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_LOCALMACHINE_LOCKDOWN\ ``` Add a REG_DWORD value to this key named for your application (for example, MyApplication.exe) and set it to 1. Any other setting for this value will disable Local Machine Zone Lockdown for the application. ### Network Protocol Lockdown ``` HKEY_LOCAL_MACHINE\Software\(Policies)\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_PROTOCOL_LOCKDOWN HKEY_CURRENT_USER\Software\(Policies)\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_PROTOCOL_LOCKDOWN HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_PROTOCOL_LOCKDOWN ``` ### HTML from CD ``` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_LOCALMACHINE_LOCKDOWN\Settings\LOCALMACHINE_CD_UNLOCK ``` ## Notes ``` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy ``` ## External Links * [About URL Security Zones](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms537183(v=vs.85)) * [Internet Explorer Local Machine Zone Lockdown](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc782928(v=ws.10)) * [Internet Explorer Network Protocol Lockdown](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc737488(v=ws.10)) * [Internet Explorer Protected Mode Elevation Policy and Administrative Templates](https://learn.microsoft.com/en-us/archive/blogs/juanand/internet-explorer-protected-mode-elevation-policy-and-administrative-templates) * [Internet Explorer security zones registry entries for advanced users](https://learn.microsoft.com/en-us/previous-versions/troubleshoot/browsers/security-privacy/ie-security-zones-registry-entries) * [Internet Feature Controls](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/general-info/ee330720(v=vs.85)) * [Introduction to Feature Controls](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms537184(v=vs.85)) * [Understanding user-agent strings](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/ms537503(v=vs.85)) ================================================ FILE: docs/sources/internet-explorer-keys/Types-URLs.md ================================================ # Typed URLs .... HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\TypedURLs .... Values: Name | Data type | Description --- | --- | --- %ITEM% | REG_SZ | Where %ITEM% is a string in the form: "url[0-9]+" ================================================ FILE: docs/sources/internet-explorer-keys/index.rst ================================================ ###################### Internet explorer keys ###################### .. toctree:: :maxdepth: 1 Browser helper objects Policies Typed URLs ================================================ FILE: docs/sources/security-accounts-manager-keys/Domains.md ================================================ # Domains The Security Accounts Manager (SAM) domains are stored in the key: ``` HKEY_LOCAL_MACHINE\SAM\SAM\Domains ``` Sub keys: Name | Description --- | --- Account | user, group, and local group accounts. Builtin | built-in local groups, such as the Administrators and Users groups, that are established when the operating system is installed. Values: Name | Data type | Description --- | --- | --- (default) | | ## Account or Builtin sub key Sub keys: Name | Description --- | --- Aliases | Groups | Users | Values: Name | Data type | Description --- | --- | --- F | REG_BINARY | V | REG_BINARY | ### F value data Offset | Size | Value | Description --- | --- | --- | --- 0 | ... | | **Unknown** ### V value data The V value data consists of: * 17 x user information descriptors * security descriptor * username * full name * comment * user comment * **Unknown** * home directory * home directory connect * script path * profile path * workstations * hours allowed * **Unknown** * LM hash (LANMAN) * NTLM hash * **Unknown** * **Unknown** * user information data #### User information descriptor A user information descriptor is 12 byte of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | | Data offset
The offset is relative to the end of the last user information descriptor 4 | 4 | | Data size 8 | 4 | | **Unknown** ## Aliases sub key Sub keys: Name | Description --- | --- Members | Names | %RID% | Where %RID% is the relative identifier (RID) which corresponds to the last sub authority of the SID. ### Aliases RID sub key Values: Name | Data type | Description --- | --- | --- C | REG_BINARY | #### C value data Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | | The relative identifier (RID) 4 | 4 | | **Unknown (empty values)** 8 | 4 | | Size of unknown data at offset 52 12 | 2 | 2 | **Unknown: major format version ?** 14 | 2 | 1 | **Unknown: minor format version ?** 16 | 4 | | Name string offset
Relative from offset 52 20 | 4 | | Name string size
Contains number of bytes 24 | 4 | | **Unknown (empty values)** 28 | 4 | | Description string offset
Relative from offset 52 32 | 4 | | Description string size
Contains number of bytes 36 | 4 | | **Unknown (empty values)** 40 | 4 | | SID array offset
Relative from offset 52 44 | 4 | | SID array size 48 | 4 | | SID array number of values 52 | ... | | Contains an https://code.google.com/p/libfwnt/wiki/SecurityDescriptor[NT security descriptor] ... | ... | | Name string
Contains an UTF-16 little-endian formatted string without end-of-string character
The data is stored using 4-byte alignment ... | ... | | Description string
Contains an UTF-16 little-endian formatted string without end-of-string character
The data is stored using 4-byte alignment ... | ... | | SID array
Contains Windows NT Security Identifiers (SIDs) ### Aliases Members sub key Sub keys: Name | Description --- | --- %SID% | Where %SID% is the security identifier (SID) in the form of a string e.g. S-1-5. #### Aliases Members SID sub key Sub keys: Name | Description --- | --- %RID% | Where %RID% is the relative identifier (RID) which corresponds to the last sub authority of the SID. ## Groups sub key Sub keys: Name | Description --- | --- Names | %RID% | ### C value data Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | 2 | **Unknown: major format version ?** 2 | 2 | 1 | **Unknown: minor format version ?** 4 | 4 | | The relative identifier (RID) 8 | 20 | | **Unknown (empty values)** 28 | 2 | 2 | **Unknown: major format version ?** 30 | 2 | 1 | **Unknown: minor format version ?** 32 | 4 | | Name string offset
Relative from offset 68 36 | 4 | | Name string size
Contains number of bytes 40 | 4 | | **Unknown (empty values)** 44 | 4 | | Description string offset
Relative from offset 68 48 | 4 | | Description string size
Contains number of bytes 52 | 4 | | **Unknown (empty values)** 56 | 4 | | Group member array offset
Relative from offset 68 60 | 4 | | Group member array size
Contains number of bytes 64 | 4 | | Group member array number of values 68 | ... | | Contains a [security descriptor](https://github.com/libyal/libfwnt/blob/main/documentation/Security%20Descriptor.asciidoc) ... | ... | | Name string
Contains an UTF-16 little-endian formatted string without end-of-string character
The data is stored using 4-byte alignment ... | ... | | Description string
Contains an UTF-16 little-endian formatted string without end-of-string character
The data is stored using 4-byte alignment ... | ... | | Group member array
Contains 4-byte RID values ## Users sub key Sub keys: Name | Description --- | --- Names | %RID% | Where %RID% is the relative identifier (RID) which corresponds to the last sub authority of the SID. ### Users RID sub key Values: Name | Data type | Description --- | --- | --- F | REG_BINARY | V | REG_BINARY | #### F value data Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | 2 | **Unknown: major version ?** 2 | 2 | 2 | **Unknown: minor version ?** 4 | 2 | | **Unknown: Extended data flags ?** 6 | 2 | | **Unknown: Extended data size ?** 8 | 8 | | Last logon date and time (lastLogon)
Contains a FILETIME 16 | 8 | | **Unknown (lastLogoff?)** 24 | 8 | | Password last set date and time (pwdLastSet)
Contains a FILETIME 32 | 8 | | Account expires date and time (accountExpires)
Contains a FILETIME, where 0x7fffffffffffffff represents Never 40 | 8 | | Last password failure date and time (badPasswordTime)
Contains a FILETIME 48 | 4 | | Relative identifier (UserId)
The relative identifier (RID) corresponds to the the last authority of the SID 52 | 4 | | Primary group identifier (PrimaryGroupId) 56 | 4 | | User account control flags (UserAccountControl)
See section: [User account control flags](#user-account-control-flags) 60 | 2 | | Country code (countryCode)
See section: [Country code](#country-code) 62 | 2 | | Codepage (codePage) 64 | 2 | | Number of password failures (badPwdCount) 66 | 2 | | Number of logons (logonCount) 68 | 4 | | **Unknown** 72 | 4 | | **Unknown** 76 | 4 | | **Unknown (checksum?)** Extended data: Offset | Size | Value | Description --- | --- | --- | --- 80 | | | Note that the relative identifier (RID) is sometimes referred to as user number or user identifier. ##### User account control flags The user account control flags (or USER_ACCOUNT Codes) are defined in subauth.h Value | Identifier | Description --- | --- | --- 0x00000001 | USER_ACCOUNT_DISABLED | Account disabled (inactive) 0x00000002 | USER_HOME_DIRECTORY_REQUIRED | Home directory required 0x00000004 | USER_PASSWORD_NOT_REQUIRED | User password not required 0x00000008 | USER_TEMP_DUPLICATE_ACCOUNT | Temporary duplicate account 0x00000010 | USER_NORMAL_ACCOUNT | Normal user account 0x00000020 | USER_MNS_LOGON_ACCOUNT | Majority Node Set (MNS) logon user account 0x00000040 | USER_INTERDOMAIN_TRUST_ACCOUNT | Interdomain trust account 0x00000080 | USER_WORKSTATION_TRUST_ACCOUNT | Workstation trust account 0x00000100 | USER_SERVER_TRUST_ACCOUNT | Server trust account
Object is a domain controller (DC) 0x00000200 | USER_DONT_EXPIRE_PASSWORD | User password does not expire 0x00000400 | USER_ACCOUNT_AUTO_LOCKED | Account auto locked 0x00000800 | USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED | Encryped text password is allowed 0x00001000 | USER_SMARTCARD_REQUIRED | Smart Card required 0x00002000 | USER_TRUSTED_FOR_DELEGATION | Trusted for Delegation 0x00004000 | USER_NOT_DELEGATED | Not delegated 0x00008000 | USER_USE_DES_KEY_ONLY | Use DES key only 0x00010000 | USER_DONT_REQUIRE_PREAUTH | Preauth not required 0x00020000 | USER_PASSWORD_EXPIRED | Password Expired 0x00040000 | USER_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION | Used by Kerberos see MS-KILE 0x00080000 | USER_NO_AUTH_DATA_REQUIRED | Used by Kerberos see RFC4120 0x00100000 | USER_PARTIAL_SECRETS_ACCOUNT | Partial secrets account
Object is a read-only domain controller (RODC) 0x00200000 | USER_USE_AES_KEYS | Use AES keys Note that these flags differ from ADS_USER_FLAG_ENUM. Mappings between the two are defined in "MS-SAMR: userAccountControl Mapping Table". Note that the samba project defines these as flags with the WBC_ACB prefix, where WBC is short for winbind client. ##### Country code **Unknown. Is this suppose to be the country phone prefix?** Value | Description --- | --- 000 | System Default 001 | United States 002 | Canada (French) 003 | Latin America 031 | Netherlands 032 | Belgium 033 | France 034 | Spain 039 | Italy 041 | Switzerland 044 | United Kingdom 045 | Denmark 046 | Sweden 047 | Norway 049 | Germany 061 | Australia 081 | Japan 082 | Korea 086 | China (PRC) 088 | Taiwan 099 | Asia 351 | Portugal 358 | Finland 785 | Arabic 972 | Hebrew #### V value data ### Account types Value | Identifier | Description --- | --- | --- 0x00000000 | SAM_DOMAIN_OBJECT | Represents a domain object 0x10000000 | SAM_GROUP_OBJECT | Represents a group object 0x10000001 | SAM_NON_SECURITY_GROUP_OBJECT | Represents a group object that is not used for authorization context generation 0x20000000 | SAM_ALIAS_OBJECT | Represents an alias object 0x20000001 | SAM_NON_SECURITY_ALIAS_OBJECT | Represents an alias object that is not used for authorization context generation 0x30000000 | SAM_USER_OBJECT | Represents a user object 0x30000001 | SAM_MACHINE_ACCOUNT | Represents a computer object 0x30000002 | SAM_TRUST_ACCOUNT | Represents a user object that is used for domain trusts 0x40000000 | SAM_APP_BASIC_GROUP | Represents an application-defined group 0x40000001 | SAM_APP_QUERY_GROUP | Represents an application-defined group whose members are determined by the results of a query ### Predefined RIDs Value | Identifier | Description --- | --- | --- 0x000001f4 | DOMAIN_USER_RID_ADMIN | User: Administrator 0x000001f5 | DOMAIN_USER_RID_GUEST | User: Guest 0x000001f6 | DOMAIN_USER_RID_KRBTGT | User: krbtgt (Key Distribution Center Service) 0x00000201 | DOMAIN_GROUP_RID_USERS | Group: Domain Users 0x00000203 | DOMAIN_GROUP_RID_COMPUTERS | Group: Domain Computers 0x00000204 | DOMAIN_GROUP_RID_CONTROLLERS | Group: Domain Controllers 0x00000220 | DOMAIN_ALIAS_RID_ADMINS | Group: Administrators 0x00000209 | DOMAIN_GROUP_RID_READONLY_CONTROLLERS | Group: Read-only Domain Controllers ## External Links * [ACCOUNT_TYPE Values](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/e742be45-665d-4576-b872-0bc99d1e1fbe) * [Built-in and Account Domains](https://learn.microsoft.com/en-us/windows/win32/secmgmt/built-in-and-account-domains) * [Predefined RIDs](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/565a6584-3061-4ede-a531-f5c53826504b) * [SAMPR_USER_ALL_INFORMATION](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/dc966b81-da27-4dae-a28c-ec16534f1cb9) * [Security Account Manager (SAM)](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc756748(v=ws.10)) * [SysKey and the SAM](https://moyix.blogspot.com/2008/02/syskey-and-sam.html), by Brendan Dolan-Gavitt, February 21, 2008 * [USER_ACCOUNT Codes](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/b10cfda1-f24f-441b-8f43-80cb93e786ec) * [userAccountControl Mapping Table](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/8a193181-a7a2-49df-a8b1-f689aaa6987c) * [USER_ALL_INFORMATION structure](https://learn.microsoft.com/en-us/windows/win32/api/subauth/ns-subauth-user_all_information) * [Well-known SIDs](https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids) ================================================ FILE: docs/sources/security-accounts-manager-keys/Security-accounts-manager.md ================================================ # Security Accounts Manager (SAM) The Security Accounts Manager (SAM) is stored in the key: ``` HKEY_LOCAL_MACHINE\SAM\SAM ``` Sub keys: Name | Description --- | --- Domains | Built-in and account domains RXACT | Values: Name | Data type | Description --- | --- | --- C | REG_BINARY | ### C value data The C value data is variable of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | | **Unknown (Format version?)** 2 | 2 | | **Unknown** 4 | 4 | | **Unknown (empty?)** 8 | 4 | | Security descriptor data size 12 | 2 | | **Unknown** 14 | 2 | | **Unknown** 16 | ... | | Security descriptor data #### Format version Value | Description --- | --- 1 | Used in Windows NT 3.1 2 | Used in Windows NT 3.5 3 | Used in Windows NT 4 6 | Used in Windows 2000 7 | Used in Windows XP and later 9 | Used in Windows Windows 11 ================================================ FILE: docs/sources/security-accounts-manager-keys/index.rst ================================================ ############################## Security accounts manager keys ############################## .. toctree:: :maxdepth: 1 Security accounts manager Domains ================================================ FILE: docs/sources/system-keys/Application-compatibility-cache.md ================================================ # Application compatibility cache The Application compatibility cache can be found in the following Windows Registry keys. In Windows 2000 and XP: ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatibility ``` In Windows 2003 and later: ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache ``` Note that several sources claim that the Application Compatibility Cache is part of the [Application Compatibility Database](https://learn.microsoft.com/en-us/windows/win32/devnotes/application-compatibility-database). However unfortunately these claims are not backed by sources or facts. Since the previous article does not mention the relationship between the cache and the database, this document the Application Compatibility Cache to part of the Windows Application Compatibility subsystem instead. Note that the actual difference between the Application Compatibility Cache and Shim (Database) Cache is currently unknown. Be aware that in other sources the terms can be used interchangeable. Since MSDN explicitly defines BaseFlushAppcompatCache and ShimFlushCache, there is likely a subtle difference to what data is cached. Also see: [Understanding Shims](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-7/dd837644(v=ws.10)). ## Windows 2000 Windows 2000 stores Application Compatibility related data in subkeys in: ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatibility ``` At this time it is unclear if these subkeys serve the same purpose as the AppCompatCache value in later versions of Windows. The subkeys are named as the executable files e.g. `Uninstall.exe` and have been seen to contain the following values: Name | Data type | Description --- | --- | --- %NAME% | | **Unknown (seen: x, 462)** DllPatch-%NAME% | | **Unknown** Also seen values named like `00008 WindowsNT4.0`. ### Windows 2000 unknown value The Windows 2000 unknown value is variable of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0x0000000c | **Unknown 1 (header size?)** 4 | 4 | | **Unknown 2 (empty values)** 8 | 4 | | **Unknown 3** 12 | 4 | | **Unknown 4** Contains additional data if "Unknown 4 > 0" ``` Empty? 00000000 0c 00 00 00 00 00 00 00 06 00 00 00 00 00 00 00 |................| With data: 00000000 0c 00 00 00 00 00 00 00 06 00 00 00 04 00 00 00 |................| 00000010 10 00 00 00 00 00 00 00 00 00 15 00 ff ff ff ff |................| 00000020 ff ff ff ff 0f 00 00 00 |........(...A.u.| Sting byte size followed by string: 00000020 28 00 00 00 41 00 75 00 |........(...A.u.| 00000030 74 00 6f 00 43 00 41 00 44 00 20 00 41 00 70 00 |t.o.C.A.D. .A.p.| 00000040 70 00 6c 00 69 00 63 00 61 00 74 00 69 00 6f 00 |p.l.i.c.a.t.i.o.| 00000050 6e 00 00 00 |n.......| 00000050 00 00 00 00 |n.......| ``` ### Windows 2000 DllPatch value The Windows 2000 DllPatch value is variable of size and contains an UTF-16 little-endian formatted string with end-of-string character e.g. 'shcmn.dll 7'. **It is currently unclear what the trailing number represents.** ## Windows XP Windows XP stores the application compatibility cache in the value: AppCompatCache. The value data consists of: * header * array of LRU cache entry index values * array of cache entries (suggested that the maximum is 92) Note that 64-bit versions of Windows XP will use the Windows 2003 64-bit format. ### Windows XP application compat cache header The Windows XP application compat cache header is 400 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0xef, 0xbe, 0xad, 0xde | Signature 4 | 4 | | Number of cached entries 8 | 4 | | Number of LRU array entries 12 | 4 | | **Unknown (empty values)** 16 | ... | | LRU array
Contains 32-bit value of the index within the array of cache entries
**Currently it is unclear if the top or the bottom of the array is the LRU** ... | ... | | **Unknown (padding?)**
Contains 0-byte values ### Windows XP 32-bit application compat cache entry The Windows XP 32-bit application compat cache entry is 552 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 x ( MAX_PATH + 4 ) = 528 | | Path
UTF-16 little-endian string with end-of-character
Note that the unused bytes can contain remnant data 528 | 8 | | Last modification time
Contains a FILETIME 536 | 8 | | File size 544 | 8 | | Last update time
Contains a FILETIME Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ## Windows 2003 Windows 2003 stores the application compatibility cache in the value: AppCompatCache The value data consists of: * header * array of cache entries (suggested that the maximum is 512) * string data ### Windows 2003 application compat cache header The Windows 2003 application compat cache header is 8 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0xfe, 0x0f, 0xdc, 0xba | Signature 4 | 4 | | Number of cached entries ### Windows 2003 32-bit application compat cache entry The Windows 2003 32-bit application compat cache entry is 24 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | | Path size 2 | 2 | | Maximum path size 4 | 4 | | Path offset
The offset value is relative to the start of the header 8 | 8 | | Last modification time
Contains a FILETIME 16 | 8 | | File size Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ### Windows 2003 64-bit application compat cache entry The Windows 2003 64-bit application compat cache entry is 32 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | | Path size 2 | 2 | | Maximum path size 4 | 4 | | **Unknown (padding)** 8 | 8 | | Path offset
The offset value is relative to the start of the header 16 | 8 | | Last modification time
Contains a FILETIME 24 | 8 | | File size Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ## Windows Vista and 2008 Windows Vista and 2008 store the application compatibility cache in the value: AppCompatCache The value data consists of: * header * array of cache entries (suggested that the maximum is 1024) * string data [NOTE] If the cache is empty it will only consists of a header. ### Windows Vista application compat cache header The Windows Vista application compat cache header is 8 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0xfe, 0x0f, 0xdc, 0xba | Signature 4 | 4 | | Number of cached entries ### Windows Vista 32-bit application compat cache entry The Windows Vista 32-bit application compat cache entry is 24 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | | Path size 2 | 2 | | Maximum path size 4 | 4 | | Path offset
The offset value is relative to the start of the header 8 | 8 | | Last modification time
Contains a FILETIME 16 | 4 | | Insertion flags 20 | 4 | | Shim flags Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ### Windows Vista 64-bit application compat cache entry The Windows Vista 64-bit application compat cache entry is 32 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | | Path size 2 | 2 | | Maximum path size 4 | 4 | | **Unknown (padding)** 8 | 8 | | Path offset
The offset value is relative to the start of the header 16 | 8 | | Last modification time
Contains a FILETIME 24 | 4 | | Insertion flags 28 | 4 | | Shim flags Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ## Windows 7 and 2008 R2 Windows 7 and 2008 R2 store the application compatibility cache in the value: AppCompatCache The value data consists of: * header * array of cache entries (suggested that the maximum is 1024) * data * string data ### Windows 7 application compat cache header The Windows 7 application compat cache header is 128 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 0xee, 0x0f, 0xdc, 0xba | Signature 4 | 4 | | Number of cached entries 8 | 4 | 120 | **Unknown (size?)** 12 | 116 | | **Unknown (cache statistics?)** ### Windows 7 32-bit application compat cache entry The Windows 7 32-bit application compat cache entry is 32 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | | Path size
The byte of the path without the end-of-string character 2 | 2 | | Maximum path size
The byte of the path with the end-of-string character 4 | 4 | | Path offset
The offset value is relative to the start of the header 8 | 8 | | Last modification time
Contains a FILETIME 16 | 4 | | Insertion flags 20 | 4 | | Shim flags 24 | 4 | | Data size 28 | 4 | | Data offset
The offset value is relative to the start of the header Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ### Windows 7 64-bit application compat cache entry The Windows 7 64-bit application compat cache entry is 48 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | | Path size
The byte of the path without the end-of-string character 2 | 2 | | Maximum path size
The byte of the path with the end-of-string character 4 | 4 | | **Unknown (padding)** 8 | 8 | | Path offset
The offset value is relative to the start of the header 16 | 8 | | Last modification time
Contains a FILETIME 24 | 4 | | Insertion flags 28 | 4 | | Shim flags 32 | 8 | | Data size 40 | 8 | | Data offset
The offset value is relative to the start of the header Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ## Windows 8 Windows 8 store the application compatibility cache in the value: AppCompatCache The value data consists of: * header * array of cache entries ### Windows 8 application compat cache header The Windows 8 application compat cache header is 128 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 128 | Header size (or cache entry array offset) 4 | 4 | | **Unknown** 8 | 120 | | **Unknown** ### Windows 8.0 application compat cache entry The Windows 8.0 application compat cache entry is variable bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | "00ts" | Signature 4 | 4 | | **Unknown** 8 | 4 | | Cache entry data size
The size of the cache entry without the first 12 bytes 12 | 2 | | Path size 14 | ... | | Path
UTF-16 little-endian string without end-of-character ... | 4 | | **Unknown (Insertion flags?)** ... | 4 | | **Unknown (Shim flags?)** ... | 8 | | Last modification time
Contains a FILETIME ... | 4 | | Data size ... | ... | | Data Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ### Windows 8.1 application compat cache entry The Windows 8.1 application compat cache entry is variable bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | "10ts" | Signature 4 | 4 | | **Unknown** 8 | 4 | | Cache entry data size
The size of the cache entry without the first 12 bytes 12 | 2 | | Path size 14 | ... | | Path
UTF-16 little-endian string without end-of-character ... | 4 | | **Unknown (Insertion flags?)** ... | 4 | | **Unknown (Shim flags?)** ... | 2 | | **Unknown** ... | 8 | | Last modification time
Contains a FILETIME ... | 4 | | Data size ... | ... | | Data Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ## Windows 10 Windows 10 store the application compatibility cache in the value: AppCompatCache The value data consists of: * header * array of cache entries ### Windows 10 application compat cache header The Windows 10 application compat cache header is 48 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 48 | Header size (or cache entry array offset) 4 | 4 | | **Unknown** 8 | 4 | | **Unknown (empty values)** 12 | 4 | | **Unknown** 16 | 4 | | **Unknown** 20 | 16 | | **Unknown (empty values)** 36 | 4 | | Number of cached entries 40 | 8 | | **Unknown (empty values)** The Windows 10 Creator update application compat cache header is 52 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 52 | Header size (or cache entry array offset) 4 | 4 | | **Unknown** 8 | 4 | | **Unknown (empty values)** 12 | 4 | | **Unknown** 16 | 4 | | **Unknown** 20 | 8 | | **Unknown (empty values)** 28 | 4 | | **Unknown** 32 | 8 | | **Unknown (empty values)** 40 | 4 | | Number of cached entries 44 | 8 | | **Unknown (empty values)** ### Windows 10 application compat cache entry The Windows 10 application compat cache entry is variable bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | "10ts" | Signature 4 | 4 | | **Unknown** 8 | 4 | | Cache entry data size
The size of the cache entry without the first 12 bytes 12 | 2 | | Path size 14 | ... | | Path
UTF-16 little-endian string without end-of-character ... | 8 | | Last modification time
Contains a FILETIME ... | 4 | | Data size ... | ... | | Data Note that the last modification time applies to that of the file e.g. for NTFS this is the last modified time of the file as stored in the $STANDARD_INFORMATION attribute. ## Insertion flags **TODO describe** Value | Identifier | Description --- | --- | --- 0x00000001 | | 0x00000002 | | **Indicated as executed by CSRSS.EXE flag**
**Client/Server Runtime Subsystem (CSRSS)** 0x00000004 | | 0x00000008 | | 0x00000010 | | **Unknown (Seen in Windows 8.0, 8.1)** 0x00000020 | | **Unknown (Seen in Windows 8.0, 8.1)** 0x00000040 | | **Unknown (Seen in Windows 8.0, 8.1)** 0x00000080 | | **Unknown (Seen in Windows 8.0, 8.1)** | | 0x00010000 | | **Unknown (Seen in Windows 8.1)** 0x00020000 | | **Unknown (Seen in Windows 8.1)** 0x00030000 | | **Unknown (Seen in Windows 8.1)** 0x00040000 | | **Unknown (Seen in Windows 8.1)** 0x00100000 | | **Unknown (Seen in Windows 8.1)** 0x00200000 | | **Unknown (Seen in Windows 8.1)** 0x00400000 | | **Unknown (Seen in Windows 8.1)** 0x00800000 | | **Unknown (Seen in Windows 8.1)** ## Shim flags **TODO describe** Value | Identifier | Description --- | --- | --- 0x00000001 | | **Unknown (Has data?)** | | 0x00000020 | | | | 0x00000100 | | **Unknown (Seen in Windows 7)** | | 0x00001000 | | **Unknown (Seen in Windows 7, 8.0)** | | 0x00010000 | | **Unknown (Seen in Windows 8.0, 8.1)** 0x00020000 | | **Unknown (Seen in Windows 8.0)** | | 0x00100000 | | **Unknown (Seen in Windows 8.1)** 0x00200000 | | **Unknown (Seen in Windows 8.1)** | | 0x01000000 | | **Unknown (Seen in Windows 8.0, 8.1)** 0x02000000 | | **Unknown (Seen in Windows 8.0)** | | 0x10000000 | | **Unknown (Seen in Windows 8.1)** ## Data **TODO describe** ## Notes ``` https://technet.microsoft.com/en-us/library/cc787360(v=ws.10).aspx Are these related? 0x00000001 MS-DOS-based program 0x00000002 OS/2-based program 0x00000004 Windows-based 16-bit program 0x00000008 Windows-based 32-bit program 0x0000000C Windows-based 16-bit and 32-bit program 0x0000000F Any version of a program 0x00000010 Return user name instead of computer name for GetComputerName. 0x00000020 Return Terminal Server build number instead of Windows 2000 build number for GetVersion. 0x00000040 Synchronize user .ini file to system version.* 0x00000080 Do not substitute user \Windows directory.** 0x00000100 Disable registry mapping for program or registry key. 0x00000200 Per-object user/system global mapping 0x00000400 Return system \Windows directory instead of user \Windows directory for GetWindowsDir. 0x00000800 Limit the reported physical memory for GlobalMemoryStatus. 0x00001000 Log object creation to file. 0x20000000 Do not put program to sleep on unsuccessful keyboard polling (Windows-based 16-bit programs only). ``` Related DLLs: * apphelp.dll; related to "AppHelp" functionality and Application Compatibility database * kernel32.dll; base cache management functionality Is the Application compatibility cache in Windows also referred to as AppHelpCache? AppHelp: https://msdn.microsoft.com/en-us/library/bb432181(v=vs.85).aspx Different shim types? MSIE and RPC shim types? Related Registry keys: ``` HKLM\Sofware\Microsoft\Windows NT\CurrentVersion\AppCompatFlags ``` Flushing the cache Windows Vista and later: ``` Rundll32.exe apphelp.dll,ShimFlushCache ``` Flushing the cache Windows XP and Windows Server 2003 ``` Rundll32.exe kernel32.dll,BaseFlushAppcompatCache ``` ================================================ FILE: docs/sources/system-keys/Background-activity-moderator.md ================================================ # Background activity moderator (BAM) The Background Activity Moderator (BAM) key seems to have been introduced in Windows 10 after version 1709. The BAM keys can be found in the following Registry paths: ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\bam\UserSettings\ HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings\ ``` Within the UserSettings key, there is a key for each user SID containing a value for each tracked executable. ## Example Entry Registry Key: ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings\S-1-5-21-321011808-3761883066-353627080-1000 ``` Value Name: ``` \Device\HarddiskVolume1\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ``` Value Data: ``` 00000000 15 3e ae 36 57 de d4 01 00 00 00 00 00 00 00 00 |.>®6WÞÔ.........| 00000010 00 00 00 00 02 00 00 00 |........| ``` ## Value Data Format Offset | Size | Value | Description --- | --- | --- | --- 0 | 8 | | Execution time
Contains a FILETIME 8 | 8 | | **Unknown (empty values)** 16 | 4 | | Flag indicating whether the entry is a "Windows app" 20 | 4 | 0x02, 0x00, 0x00, 0x00 | **Unknown (always 2)** ================================================ FILE: docs/sources/system-keys/Boot-verification.md ================================================ # Boot Verification key ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BootVerification ``` The BootVerification key stores configuration for Bootvrfy.exe, a program included in Windows Server 2003 that notifies the system that startup was successful. Bootvrfy.exe can be run on a local or remote computer. Known values of the BootVerification key: Name | Data type | Description --- | --- | --- ErrorControl | REG_DWORD | Known value: 1 %SERVICE%\ImagePath | REG_EXPAND_SZ | Known value: "Bootvrfy.exe" ObjectName | REG_SZ | Known value: "LocalSystem" Start Entry | REG_DWORD | Known value: 3 Type Entry | REG_DWORD | Known value: 2 To run a custom startup verification program the standard startup verification functions in Winlogon need to be disabled. This can be done by setting the Winlogon ReportBootOk value to 0. ``` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon ``` ## Boot Verification Program key ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\BootVerificationProgram ``` The BootVerificationProgram key stores configuration for a custom startup verification program. Known values of the BootVerificationProgram key: Name | Data type | Description --- | --- | --- ImagePath | REG_SZ, REG_EXPAND_SZ | path of a custom startup verification program According Windows server 2003 documentation Bootvrfy.exe and a custom startup verification program cannot be used in parallel. ## External links * [BootVerification](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc778559(v=ws.10)) * [BootVerificationProgram](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc782537(v=ws.10)) * [BootVerificationProgram\ImagePath](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc786702(v=ws.10)) * [ReportBootOk](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc739989(v=ws.10)) ================================================ FILE: docs/sources/system-keys/COM-class-identifiers.md ================================================ # Component object model (COM) class identifiers (CLSIDs) The component object model (COM) class Identifier (CLSID) key can be found in: ``` HKEY_CLASSES_ROOT\CLSID\{%GUID%} HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{%GUID%} ``` Sub keys: Name | Description --- | --- AuxUserType | Application's short display name and names CLSID | Class identifiers Control | ActiveX Control settings Conversion | Convert dialog box format conversion settings DataFormats | Data formats supported by an application DefaultIcon | Default icon settings Implemented Categories | InprocServer | 16-bit in-process server settings InProcServer32 | 32-bit (and 64-bit) in-process server settings Insertable | Insert Object dialog box list box settings Interface | Supported interface IDs (IIDs) LocalServer32 | 32-bit local server application settings MiscStatus | Settings how to create and display the object PersistentHandler | Verb | Application verbs MSDN defines DefaultIcon as a REG_SZ value but in Windows XP it seems to be a key where the icon resource identifier is stored in the default value of the key. Values: Name | Data type | Description --- | --- | --- AppID | REG_SZ | Associated application identifier
Contains a string in the form: "{GUID}" AutoConvertTo | REG_SZ | Automatic conversion class identifier AutoTreatAs | REG_SZ | Automatically treat as (emulation) class identifier InprocHandler | REG_SZ | 16-bit custom in-process handler InprocHandler32 | REG_SZ | 32-bit custom in-process handler LocalServer | REG_SZ| 16-bit local server application ProgID | REG_SZ | Associated program identifier
Contains a string in the form: "Program.Component" ToolBoxBitmap32 | REG_SZ | Toolbar or toolbox button bitmap
Contains a resource identifier TreatAs | REG_SZ | Identifier of class that can emulate the current class Version | REG_SZ | version number VersionIndependentProgID | REG_SZ | Version independent associated program identifier ## Type libraries key The type libraries (typelib or tlb) key can be found in: ``` HKEY_CLASSES_ROOT\TypeLib\{%GUID%} HKEY_CLASSES_ROOT\Wow6432Node\TypeLib\{%GUID%} ``` Sub keys: Name | Description --- | --- %GUID% | Type library identifier ## Type library identifier subkey Sub keys: Name | Description --- | --- %VERSION% | Type library version in the format: "major.minor" Values: Name | Data type | Description --- | --- | --- (Default) | REG_SZ | Type library description ### Type library version subkey Sub keys: Name | Description --- | --- %LCID% | Locale identifier such as: "409", where "0" is the system default language (LANG_SYSTEM_DEFAULT). FLAGS | HELPDIR | TODO: Determine what MSDN means with the LCID may have a neutral sublanguage ID. Is 0 the neutral sublanguage ID? #### Type library locale subkey Sub keys: Name | Description --- | --- %PLATFORM% | Platform identifier such as: "win32" ##### Type library platform subkey Values: Name | Data type | Description --- | --- | --- (Default) | REG_SZ | Path to the type library file.
This can be a stand-alone .tlb file or the "typelib" resource inside a PE/COFF file. #### Type library help directory subkey Values: Name | Data type | Description --- | --- | --- (Default) | REG_SZ | Path of the directory where the Help file for type library is located ## External Links * [CLSID Key](https://learn.microsoft.com/en-us/windows/win32/com/clsid-key-hklm) * [ProxyStubClsid](https://learn.microsoft.com/en-us/windows/win32/com/proxystubclsid) * [Registering a Type Library](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/automat/registering-a-type-library) ================================================ FILE: docs/sources/system-keys/Cached-credentials.md ================================================ # Cached credentials ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon ``` Values: Name | Data type | Description --- | --- | --- CachedLogonsCount | REG_SZ | Number of cached log-ons.
According to MSDN the value must be in the range "0" - "50" ## Credentials cache ``` HKEY_LOCAL_MACHINE\Security\Cache ``` Values: Name | Description --- | --- NL$Control | NL$%NUMBER% | Cached credential Where %NUMBER% contains the number of the cached credential. ### NL$Control value ``` 00000000 04 00 01 00 0a 00 00 00 |........| ``` ### NL$%NUMBER% value Offset | Size | Value | Description --- | --- | --- | --- _Metadata_ ||| 0 | 2 | | Username string size 2 | 2 | | Hostname string size 4 | 2 | | **Unknown (username string size)** 6 | 2 | | **Unknown (Full name string size)** 8 | 4 | | **Unknown** 12 | 2 | | **Unknown (Profile path string size)** 14 | 2 | | **Unknown (Profile mount drive letter string size)** 16 | 4 | | **Unknown** 20 | 4 | | **Unknown** 24 | 4 | | **Unknown** 28 | 2 | | **Unknown** 30 | 2 | | **Unknown** 32 | 8 | | **Unknown (date and time)**
Contains a FILETIME timestamp 40 | 2 | | **Unknown** 42 | 2 | | **Unknown** 44 | 4 | | **Unknown** 48 | 4 | | **Unknown** 52 | 4 | | **Unknown** 56 | 4 | | **Unknown** 60 | 2 | | Hostname with domain string size 62 | 2 | | **Unknown** _Data_ ||| 64 | 16 | | **Unknown (CH)** 80 | 16 | | **Unknown (T)** 96 | ... | | Encrypted data ``` metadata * username size * domain size * Length of the full domain name 0x00000000 0e 00 14 00 0e 00 1c 00 00 00 00 00 38 00 04 00 ............8... 0x00000010 53 04 00 00 01 02 00 00 02 00 00 00 14 00 18 00 S............... 0x00000020 72 0f 92 b3 b1 f8 cc 01 r............... FILETIME 0x00000020 04 00 01 00 01 00 00 00 r............... 0x00000030 01 00 00 00 20 00 00 00 10 00 00 00 20 00 00 00 .... ....... ... CH: random 16 byte key that is used to generate the decryption key for the encrypted data 0x00000040 e6 ad 1f 22 b9 d1 d3 48 22 f6 d6 61 33 d7 32 74 ..."...H"..a3.2t T 0x00000050 29 4c 83 1b af bc ca c9 fc 27 9c be 1e 44 2b 69 )L.......'...D+i Encrypted data 0x00000060 52 46 67 5f f6 85 b0 0f 7a a3 69 03 cc 72 4b 8b RFg_....z.i..rK. 0x00000070 8b 51 e9 9c 4a 65 92 2d 19 7d 6f 94 d2 81 93 0d .Q..Je.-.}o..... 0x00000080 f2 9e 7d 2e 11 17 46 a0 31 ac 2c 65 49 89 c2 c0 ..}...F.1.,eI... 0x00000090 92 7a 63 6c ca b2 74 ba 5f 73 c0 d3 6c 0c 58 51 .zcl..t._s..l.XQ 0x000000a0 46 e9 45 48 9b ce 86 a1 68 ae f7 12 f8 d2 c7 7e F.EH....h......~ 0x000000b0 4d 39 a9 bd d4 ad fc e8 b0 b1 94 36 c5 4d 1f 3b M9.........6.M.; 0x000000c0 3c ce b8 dc a9 50 41 54 f4 5a 31 61 57 66 66 7a <....PAT.Z1aWffz 0x000000d0 0d 54 9a c0 7e d4 1a a8 e6 af 83 fb cd 61 a1 fe .T..~........a.. 0x000000e0 85 31 ce c9 24 fa f3 a5 7e 71 c9 a4 81 11 e3 b7 .1..$...~q...... 0x000000f0 7c ce fb 38 b0 81 b9 75 cc 78 7e 66 9c 7b 4d a7 |..8...u.x~f.{M. 0x00000100 7d 6e 55 d6 8d 22 2d e9 8d 48 0c 22 f1 bc 6b 58 }nU.."-..H."..kX 0x00000110 17 84 db 5b ba 91 8a 39 70 a1 d8 b5 16 df 99 cf ...[...9p....... 0x00000120 ea f1 af dc 75 27 ea 83 22 ff 8a 5e 63 b2 a9 f9 ....u'.."..^c... 0x00000130 b4 05 47 26 b8 e7 e4 b7 06 bc d9 4b 0f 20 92 25 ..G&.......K. .% 0x00000140 07 7a a5 6b 4e 54 4a 19 19 51 bf 5f c2 09 8b 5e .z.kNTJ..Q._...^ 0x00000150 f1 a3 be aa 1f c3 66 c3 cd 09 7b 85 45 02 0d 28 ......f...{.E..( 0x00000160 02 a5 f8 8a f2 b1 52 a3 a3 dc a4 c7 ed f5 ca 6c ......R........l 0x00000170 13 3c e5 18 3d fe b3 fc 28 3f be 9b 62 d0 1a 5a .<..=...(?..b..Z 0x00000180 90 ce e2 a6 c2 aa 2d 40 78 d8 cc db a4 a7 44 e8 ......-@x.....D. 0x00000190 0d ff c8 08 49 19 5b 21 67 f2 62 be 7b f2 be d3 ....I.[!g.b.{... 0x000001a0 37 18 53 33 61 3e 21 7a e6 08 e3 f2 d5 1c 81 ce 7.S3a>!z........ 0x000001b0 9a 45 71 85 bf a6 e9 fd ea 7e b7 2f 01 0d 7d c7 .Eq......~./..}. 0x000001c0 46 9f e5 73 F..s ``` Offset | Size | Value | Description --- | --- | --- | --- 0 | 16 | | **Unknown (password hash)** 16 | 16 | | **Unknown** 32 | 8 | | **Unknown** 40 | 4 | | **Unknown** 44 | 4 | | **Unknown** 48 | 8 | | **Unknown** 56 | 16 | | **Unknown** 72 | ... | | Username string ... | ... | | 32-bit alignment padding ... | ... | | Hostname string ... | ... | | 32-bit alignment padding ... | ... | | Hostname and domain string ... | ... | | 32-bit alignment padding ... | ... | | Profile path string ... | ... | | 32-bit alignment padding ... | ... | | Profile mount drive letter string ... | ... | | 32-bit alignment padding ``` Decrypted data: 0x00000000 6e 37 5e e6 a7 99 6c 5c 55 85 74 67 09 af a0 65 n7^...l\U.tg...e 0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x00000020 01 00 00 00 00 00 00 00 c4 01 00 00 02 00 00 00 ................ 0x00000030 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x00000040 00 00 00 00 00 00 00 00 ........t.d.u.n. Sizes from metadata 0e 00 14 00 0e 00 1c 00 0x00000040 74 00 64 00 75 00 6e 00 ........t.d.u.n. 0x00000050 67 00 61 00 6e 00 g.a.n...S.H.I.E. 0x00000050 00 00 g.a.n...S.H.I.E. 0x00000050 53 00 48 00 49 00 45 00 g.a.n...S.H.I.E. 0x00000060 4c 00 44 00 42 00 41 00 53 00 45 00 L.D.B.A.S.E.S.H. 0x00000060 53 00 48 00 L.D.B.A.S.E.S.H. 0x00000070 49 00 45 00 4c 00 44 00 42 00 41 00 53 00 45 00 I.E.L.D.B.A.S.E. 0x00000080 2e 00 4c 00 4f 00 43 00 41 00 4c 00 ..L.O.C.A.L.t.d. 0x00000080 74 00 64 00 ..L.O.C.A.L.t.d. 0x00000090 75 00 6e 00 67 00 61 00 6e 00 00 00 u.n.g.a.n...T.i. 0x00000090 54 00 69 00 u.n.g.a.n...T.i. 0x000000a0 6d 00 6f 00 74 00 68 00 79 00 20 00 44 00 75 00 m.o.t.h.y. .D.u. 0x000000b0 6e 00 67 00 61 00 6e 00 n.g.a.n.\.\.c.o. 0x000000b0 5c 00 5c 00 63 00 6f 00 n.g.a.n.\.\.c.o. 0x000000c0 6e 00 74 00 72 00 6f 00 6c 00 6c 00 65 00 72 00 n.t.r.o.l.l.e.r. 0x000000d0 5c 00 68 00 6f 00 6d 00 65 00 5c 00 25 00 75 00 \.h.o.m.e.\.%.u. 0x000000e0 73 00 65 00 72 00 6e 00 61 00 6d 00 65 00 25 00 s.e.r.n.a.m.e.%. 0x000000f0 48 00 3a 00 01 02 00 00 07 00 00 00 07 02 00 00 H.:............. 0x00000100 07 00 00 00 53 00 48 00 49 00 45 00 4c 00 44 00 ....S.H.I.E.L.D. 0x00000110 42 00 41 00 53 00 45 00 07 00 00 20 01 05 00 00 B.A.S.E.... .... 0x00000120 00 00 00 05 15 00 00 00 97 2a 67 79 a0 54 4a b6 .........*gy.TJ. 0x00000130 19 87 28 7e 3c 02 00 00 01 04 00 00 00 00 00 05 ..(~<........... 0x00000140 15 00 00 00 97 2a 67 79 a0 54 4a b6 19 87 28 7e .....*gy.TJ...(~ 0x00000150 43 00 4f 00 4e 00 54 00 52 00 4f 00 4c 00 4c 00 C.O.N.T.R.O.L.L. 0x00000160 45 00 52 00 E.R. ``` NL$7 ``` 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 04 00 01 00 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000a0 00 00 00 00 00 00 00 00 |........| ``` ## External Links * [Cached domain logon information](https://learn.microsoft.com/en-us/troubleshoot/windows-server/user-profiles-and-logon/cached-domain-logon-information) ================================================ FILE: docs/sources/system-keys/Certificates.md ================================================ # Certificates ``` HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\Certificates ``` ## External Links * [Certificates Tools and Settings](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc787544(v=ws.10)) ================================================ FILE: docs/sources/system-keys/Codepage.md ================================================ # Codepage The codepage settings are stored in the key: ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage ``` Values: Name | Data type | Description --- | --- | --- `#` | REG_SZ | The name of the code page National Language Support file (.nls)
Where # is the code page number, e.g. 1252
Contains a string with the name of the corresponding file e.g. c_1252.nls ACP | REG_SZ | The default ANSI (extended ASCII) code page
Contains a string with the number of the corresponding code page e.g. 1252 MACCP | REG_SZ | The default Macintosh code page
Contains a string with the number of the corresponding code page e.g. 1252 OEMCP | REG_SZ | The default OEM code page
Contains a string with the number of the corresponding code page e.g. 1252 OEMHAL | REG_SZ | **Unknown**
Contains a string with the name of the corresponding file e.g. vgaoem.fon ================================================ FILE: docs/sources/system-keys/Current-control-set.md ================================================ # Current control set The Windows Registry contains the Current control set key: ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet ``` ## Current Control Set - Windows 9x/Me In Windows 9x/Me the Current Control Set key is stored in the SYSTEM.DAT Registry file. ## Current Control Set - Windows NT On Windows NT the Current Control Set key is only present at run-time. The contents of the key is stored in the SYSTEM Registry file and can be determined by reading the Current value from the key: ``` \Select ``` The Current value contains number of the current control set. Normally 1 or 2 but other values like 3 or 47 are known to be used. For example a value of 1 maps to the Control Set key: ``` \ControlSet001 ``` Normally there are multiple Control Set keys the role each of the Control Set keys can be different: > ControlSet001 may be the last control set you booted with, while > ControlSet002 could be what is known as the last known good control set, or > the control set that last successfully booted Windows. These roles are defined by the other values in the Select key: Name | Data type | Description --- | --- | --- Current | REG_DWORD | Current Control Set Default | REG_DWORD | Default Control Set Failed | REG_DWORD | Control Set that failed to boot LastKnownGood | REG_DWORD | Last known good Control Set ### Notes * Determine if a value of 0 indicates not set * Confirm if speculations that 9 is the largest value ControlSet00# ================================================ FILE: docs/sources/system-keys/Environment-variables.md ================================================ # Environment variables The environment variables are stored in multiple keys. ## Session Manager\\Environment key ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment ``` Values: Name | Data type | Description --- | --- | --- %NAME% | REG_SZ | Value of an environment variable, where %NAME% contains the name of the environment variable. For example the "windir" value that contains "%SystemRoot%". ## Windows\\CurrentVersion key Values of environment variables such as %%ProgramFiles% can be derived from values in the Windows\\CurrentVersion key: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion ``` Values: Name | Data type | Description --- | --- | --- CommonFilesDir | REG_SZ | Value of %CommonProgramFiles% environment variable CommonFilesDir (x86) | REG_SZ | Value of %CommonProgramFiles(x86)% environment variable CommonW6432Dir | REG_SZ | Value of %CommonProgramW6432% environment variable ProgramFilesDir | REG_SZ | Value of %ProgramFiles% environment variable ProgramFilesDir (x86) | REG_SZ | Value of %ProgramFiles(x86)% environment variable ProgramW6432Dir | REG_SZ | Value of %ProgramW6432% environment variable For example the "ProgramFilesDir (x86)" value that contains "C:\Program Files (x86)". ## Windows NT\\CurrentVersion key The %SystemRoot% environment variable can be derived from values in the Windows NT\\CurrentVersion key: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion ``` Values: Name | Data type | Description --- | --- | --- SystemRoot | REG_SZ | Value of %SystemRoot% environment variable For example the "SystemRoot" value that contains "C:\\Windows" ## CurrentVersion\\ProfileList key Values of environment variables such as %ProgramData% can be derived from values in the CurrentVersion\\ProfileList key: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList ``` Values: Name | Data type | Description --- | --- | --- AllUsersProfile | REG_SZ | Value of the %AllUsersProfile% environment variable (Seen on Windows XP) Default | REG_SZ | (Seen on Windows Vista) DefaultUserProfile | REG_SZ | (Seen on Windows XP) ProfilesDirectory | REG_EXPAND_SZ | Profiles directory, for example "C:\Documents and Settings" on Windows XP or "C:\Users" on Windows Vista. ProgramData | REG_SZ | Value of the %ProgramData% environment variable (Seen on Windows Vista) Public | REG_SZ | Value of the %Public% environment variable If the AllUsersProfile value does not start with an environment variable or an absolute path, but a relative path, it is currently assumed that the value should be prefixed with the value in ProfilesDirectory. ## User specific environment variables ``` HKEY_CURRENT_USER\Environment ``` Values: Name | Data type | Description --- | --- | --- %NAME% | REG_SZ | Value of an user specific environment variable, where %NAME% contains the name of the environment variable. ================================================ FILE: docs/sources/system-keys/File-system.md ================================================ # File system Windows file system settings are stored in the File system key. ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem ``` # File System key Values: Name | Data type | Description --- | --- | --- NtfsAllowExtendedCharacterIn8dot3Name | REG_DWORD | NtfsDisable8dot3NameCreation | REG_DWORD | NtfsDisableLastAccessUpdate | REG_DWORD | NtfsEncryptionService | REG_SZ | Win31FileSystem | REG_DWORD | Win95TruncatedExtensions | REG_DWORD | ## NTFS Disable Short (8.3) Filename Creation value Value | Description --- | --- 0 | For NTFS short (8.3) filenames are created 1 | For NTFS short (8.3) filenames are *not* created ## NTFS Disable Last Access Time value Value | Description --- | --- 0 | For NTFS the last-accessed timestamp of a file is updated whenever the file is opened. 1 | For NTFS the last-accessed timestamp of a file is *not* updated whenever the file is opened. **TODO the explanation of the values differs between versions of Windows** The meaning of the value 0 for Windows 2000 according to [NtfsDisableLastAccessUpdate](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc959914(v=technet.10)): ``` When listing directories, NTFS updates the last-access timestamp on each directory it detects, and it records each time change in the NTFS log. ``` In contrast to the meaning of the value 0 for Windows 2003 according to [NtfsDisableLastAccessUpdate](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc758569(v=ws.10)): ``` NTFS updates the last-accessed timestamp of a file whenever that file is opened. ``` **TODO value does not exist by default until Windows XP SP3/Vista** ## External Links ### Windows 2000 * [NtfsDisable8dot3NameCreation](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc959352(v=technet.10)) * [NtfsDisableLastAccessUpdate](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc959914(v=technet.10)) * [Win31FileSystem](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976058(v=technet.10)) * [NtfsEncryptionService](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976057(v=technet.10)) * [NtfsAllowExtendedCharacterIn8dot3Name](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc963196(v=technet.10)) ### Windows 2003 * [NtfsAllowExtendedCharacterIn8dot3Name](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc781607(v=ws.10)) * [NtfsDisable8dot3NameCreation](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc778996(v=ws.10)) * [NtfsDisableLastAccessUpdate](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc758569(v=ws.10)) * [NtfsEncryptionService](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc739602(v=ws.10)) * [Win95TruncatedExtensions](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc756733(v=ws.10)) ================================================ FILE: docs/sources/system-keys/Language.md ================================================ # Language The language settings are stored in the key: ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Language ``` Values: Name | Data type | Description --- | --- | --- `#` | REG_SZ | The name of the code page National Language Support file (.nls)
Where # is a hexadecimal formatted LCID, e.g. 0409
Contains "l_intl.nls", which is a reference to "\Windows\System32\l_intl.nls" Default | REG_SZ | The default system language, contains a hexadecimal formatted LCID InstallLanguage | REG_SZ | contains a hexadecimal formatted LCID ## Language groups ``` HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Language Groups ``` ================================================ FILE: docs/sources/system-keys/Local-security-authority.md ================================================ # Local Security Authority (LSA) Windows 2000 and later. ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa ``` ## Boot key The boot key can be determined as following. Determine a 32-character string by combining the classnames of the following subkeys: * JD * Skew1 * GBG * Data The string contains a base16 encoded 16-byte binary data that contains the scrambled key data. To unscramble the key data: ``` scrambled_key = codecs.decode(class_name_string, 'hex') key = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] for index, scrambled_index in enumerate([ 8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]): key[index] = scrambled_key[scrambled_index] key = codecs.encode(b''.join(key), 'hex') ``` ## LSA key The Local Security Authority (LSA) (or Syskey) is a 128-bit RC4 encryption key used to protect credentials stored in the Windows Registry. ``` Key: HKEY_LOCAL_MACHINE\Security\Policy\PolSecretEncryptionKey Default value ``` ``` Windows XP 00000000 01 00 00 00 01 00 00 00 00 00 00 00 |..............?.| RC4 encrypted data 00000000 fd d4 3f b3 |..............?.| 00000010 ee 4f cd 45 2d 02 e8 1e f2 ac bd 4f fc 15 12 09 |.O.E-......O....| 00000020 0a b5 48 17 33 8f 42 79 8b 89 11 d8 ec 6e 1c ec |..H.3.By.....n..| 00000030 38 5f 27 df 72 ca 57 96 8d 16 d9 37 |8_'.r.W....7..d.| RC4 key material 00000030 c4 14 64 d1 |8_'.r.W....7..d.| 00000040 a8 47 7a d4 4b a3 62 d8 e7 2b ef 76 |.Gz.K.b..+.v| ``` ``` md5 = MD5.new() md5.update(boot_key) iteration = 0 while iteration < 1000: md5.update(value_data[60:76]) iteration += 1 rc4_key = md5.digest() rc4 = ARC4.new(rc4_key) decrypted_data = rc4.decrypt(value_data[12:60]) lsa_key = decrypted_data[16:32] ``` ``` 0x00000000 80 3a ce f0 5f 15 d3 11 b7 e6 00 80 5f 48 ca eb .:.._......._H.. 0x00000010 01 d6 5d f4 43 aa 0a 86 d9 42 d1 17 34 ce 66 7c ..].C....B..4.f| 0x00000020 24 9a 83 44 c6 a7 57 30 44 dc 27 06 26 94 77 8a $..D..W0D.'.&.w. ``` ## NL$KM ``` Key: HKEY_LOCAL_MACHINE\Security\Policy\Secrets\NL$KM\CurrVal Default value ``` ``` Windows XP 00000000 48 00 00 00 48 00 00 20 9c c3 0c 00 |H...H.. ........| DES encrypted data 00000000 c2 0d 08 10 |H...H.. ........| 00000010 9a 04 04 bf 14 8b c7 d0 0b e2 9c 40 52 a7 8e aa |...........@R...| 00000020 01 49 25 70 71 dc a0 69 8e 6c 03 1c b7 db 19 5c |.I%pq..i.l.....\| 00000030 8f f4 11 d1 8d 73 07 b0 6f 1a db 0b ee cb 69 7f |.....s..o.....i.| 00000040 73 50 24 82 f8 e1 a6 27 97 a9 cc 04 8e e4 ca bb |sP$....'........| 00000050 33 68 00 7c |3h.|| ``` ``` decrypted data (_LSA_BLOB) 0x00000000 40 00 00 00 01 00 00 00 09 fe 44 48 1b 35 73 b7 @.........DH.5s. 0x00000010 3b 1d fc f7 48 9f c9 60 3b 60 7d cf 62 35 50 fd ;...H..`;`}.b5P. 0x00000020 b5 d8 8f 21 75 ec 01 e9 85 25 96 6c 68 52 c9 30 ...!u....%.lhR.0 0x00000030 fb 1d b6 9d cd 8c 14 90 91 de f1 dd 5d d7 64 2a ............].d* 0x00000040 ce 40 97 5a f1 59 71 20 .@.Z.Yq ``` ``` Windows 7 00000000 00 00 00 01 |....a.!v.......N| 00000000 61 d8 21 76 d9 02 af de bd aa ba 4e |....a.!v.......N| 00000010 f3 3f de 78 03 00 00 00 00 00 00 00 1a 7a 20 be |.?.x.........z .| 00000020 73 10 0b 57 34 88 16 81 00 42 50 a1 8f 5e 78 46 |s..W4....BP..^xF| 00000030 bb f3 5e 61 9b 59 fa de ff 14 7c c1 70 97 66 8e |..^a.Y....|.p.f.| 00000040 c8 98 54 5c 8e 0e 13 7d e7 ba 9a 98 8b cf a4 6f |..T\...}.......o| 00000050 6d 84 5f 84 9c 9f d9 08 c3 5d 5c bd e9 1a 78 c6 |m._......]\...x.| 00000060 63 de 80 2d ec 3c 75 1f 1b e0 10 f5 24 1c 5d 41 |c..-. Contains a SHA-256 or CRC32, before KB2305420. A byte-order-mark at beginning of the file is not included in the calculation of the hash. Path | | Path of the corresponding Registry key in the TaskCache Tree sub key Triggers | | ##### TaskCache\\Tree\\%GUID%\\DynamicInfo sub key Seen in Windows Vista, Windows 2008 and Windows 7: The dynamic information entry is 28 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 3 | **Unknown** 4 | 8 | | **Unknown timestamp (last registered or update time?)**
Contains a FILETIME or 0 if not set 12 | 8 | | **Unknown timestamp (launch time?)**
Contains a FILETIME or 0 if not set 20 | 4 | | **Unknown (flags?)** 24 | 4 | | **Unknown (empty values)** ``` 0x00000000 03 00 00 00 1c ec 45 16 3f 04 ca 01 00 00 00 00 ......E.?....... 0x00000010 00 00 00 00 00 00 00 00 00 00 00 00 ............ 0x00000000 03 00 00 00 16 6f 4a 0f 7f fe c6 01 66 b7 6c 0d .....oJ.....f.l. 0x00000010 6b 4c c9 01 2b 04 07 80 00 00 00 00 kL..+....... ``` Seen in Windows 8 and Windows 10: **TODO: check Windows 2012** The dynamic information entry is 36 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | 3 | **Unknown** 4 | 8 | | **Unknown timestamp (last registered or update time?)**
Contains a FILETIME or 0 if not set 12 | 8 | | **Unknown timestamp (launch time?)**
Contains a FILETIME or 0 if not set 20 | 4 | | **Unknown (flags?)** 24 | 4 | | **Unknown (empty values)** 28 | 8 | | **Unknown timestamp**
Contains a FILETIME or 0 if not set ``` 0x00000000 03 00 00 00 4b 5a 0b 60 ff 6a cd 01 5c 32 e7 45 ....KZ.`.j..\2.E 0x00000010 1b b6 ce 01 20 04 07 80 00 00 00 00 a2 b1 86 4f .... ..........O 0x00000020 1b b6 ce 01 .... ``` ##### Path value The path value is relative from: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree ``` For example the path: ``` \Microsoft\Windows\Media Center\ehDRMInit ``` Corresponds to: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Windows\Media Center\ehDRMInit ``` ##### Triggers value Note that the FILETIME value appear to be stored in local time. ================================================ FILE: docs/sources/system-keys/Time-zones.md ================================================ # Time zones ## Time zone information key The time zone information is stored in the following key: ``` HKEY_LOCAL_MACHINE\CurrentControlSet\Control\TimeZoneInformation ``` Values: Name | Data type | Description --- | --- | --- ActiveTimeBias | REG_DWORD | The active time bias, in minutes, as configured for the time zone accounting for daylight saving. This is the bias that was used to configure the CMOS clock. Bias | REG_DWORD | The current bias, in minutes, for local time translation on this computer. DaylightBias | REG_DWORD | The bias value, in minutes, to be used during local time translations that occur during daylight saving time. DaylightName | REG_SZ | A description for daylight saving time. DaylightStart | REG_BINARY | The date and local time when the transition from standard time to daylight saving time occurs on this operating system.
Contains a SYSTEMTIME structure. DynamicDaylightTimeDisabled | REG_DWORD | Indicates whether dynamic daylight saving time is disabled.
0 indicates automatic adjustment
1 indicates automatic adjustment is disabled RealTimeIsUniversal | REG_DWORD | Indicates if the CMOS clock is configured by using the local date/time (default) or UTC.
0 indicates that the CMOS clock is configured for local date/time
1 indicates that the CMOS clock is configured by using UTC StandardBias | REG_DWORD | The bias value, in minutes, to be used during local time translations that occur during standard time. StandardName | REG_SZ | A description for standard time. StandardStart | REG_BINARY | The date and local time when the transition from daylight saving time to standard time occurs on this operating system.
Contains a SYSTEMTIME structure. TimeZoneKeyName | REG_SZ | The name of the Time Zones name sub key. Notes: * the relation between the local time and bias is as following: ``` UTC = local time + bias ``` * the names are stored outside the Windows Registry and are references using [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html) for example: ``` @tzres.dll,-931 ``` * the TimeZoneKeyName is not always present * The RealTimeIsUniversal value is not installed in the system by default and is not officially supported by Windows The values in this key corresponds with the [TIME_ZONE_INFORMATION](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-time_zone_information) and [DYNAMIC_TIME_ZONE_INFORMATION](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information) structures. ## Time Zones key The time zones definitions are stored in the following key: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zones ``` Sub keys: Name | Description --- | --- %TIMEZONENAME% | %TIMEZONENAME% represents the name of the Windows name of the time zone. The Unicode organization maintains windowsZones.xml to map the Windows names to corresponding IANA names. Values: Name | Data type | Description --- | --- | --- TzVersion | REG_DWORD | ### Time Zones %TIMEZONENAME% sub key Sub keys: Name | Description --- | --- Dynamic DST | Contains the dynamic daylight saving time values Note that not every Time Zones name sub key contains a Dynamic Daylight Saving Time sub key (Dynamic DST). Values: Name | Data type | Description --- | --- | --- Display | REG_SZ | The display name Dlt | REG_SZ | The description for daylight time Index | | MapID | | MUI_Display | REG_SZ | The display name in [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html) MUI_Dlt | REG_SZ | The description for daylight time in [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html) MUI_Std | REG_SZ | The description for standard time in [MUI Form](https://winreg-kb.readthedocs.io/en/latest/sources/windows-registry/MUI-form.html) Std | REG_SZ | The description for standard time TZI | REG_BINARY | Time zone information
Contains a Registry Time Zone information structure #### Dynamic Daylight Saving Time sub key The Dynamic Daylight Saving Time sub key contains time zone information for time zones that apply different daylight saving per year. Values: Name | Data type | Description --- | --- | --- FirstEntry | REG_DWORD | The first year in the key LastEntry | REG_DWORD | The last year in the key %YEAR% | REG_BINARY | Time zone information
Contains a Registry Time Zone information structure Where %YEAR% represents the year the dynamic daylight saving time zone information applies to, e.g. 2006. ### Data Structures #### SYSTEMTIME structure The SYSTEMTIME structure is 16 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 2 | | Year 2 | 2 | | Month
Where 1 represents January 4 | 2 | | Day of week
Where 0 represents Sunday 6 | 2 | | Day of month
Where 1 represents the first day 8 | 2 | | Hour
Where hour ranges from 0 to 23 10 | 2 | | Minutes
Where minutes ranges from 0 to 59 12 | 2 | | Seconds
Where seconds ranges from 0 to 59 14 | 2 | | Milli seconds
Where milli seconds ranges from 0 to 999 #### Registry Time Zone information structure The Registry Time Zone information (`TIME_ZONE_INFORMATION` or `_REG_TZI_FORMAT`) structure is 44 bytes of size and consists of: Offset | Size | Value | Description --- | --- | --- | --- 0 | 4 | | Bias
Contains the difference between UTC and local time, in minutes 4 | 4 | | StandardBias
Contains the difference between UTC and local time, in minutes, or 0 if not set 8 | 4 | | DaylightBias
Contains the difference between standard and daylight savings time, in minutes
The total difference is: Bias + DaylightBias 12 | 16 | | StandardDate
Date and time when the daylight savings time switches to standard time, in local time
Contains a SYSTEMTIME structure with year set to 0 28 | 16 | | DaylightDate
Date and time when the standard time switches to daylight savings time, in local time
Contains a SYSTEMTIME structure with year set to 0 The wDayOfWeek member of a SYSTEMTIME structure represents the appropriate weekday, and the wDay member represents the occurrence of the day of the week within the month, where 5 indicates the final occurrence during the month if that day of the week only occurs 4 times in the month. If the wYear member is 0, the date is relative, meaning the daylight savings occurs yearly. Otherwise the date is abosule, meaning daylight savings only changes once. Note that DaylightBias can be set when DaylightDate is not set. ## External Links * [Computer Time Management and Embedded Systems (Standard 7 SP1)](https://learn.microsoft.com/en-us/previous-versions/windows/embedded/ff794720(v=winembedded.60)) * [TIME_ZONE_INFORMATION structure (timezoneapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-time_zone_information) * [DYNAMIC_TIME_ZONE_INFORMATION structure (timezoneapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information) * [SYSTEMTIME structure (minwinbase.h)](https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime) * [windowsZones.xml](https://github.com/unicode-org/cldr/blob/main/common/supplemental/windowsZones.xml) ================================================ FILE: docs/sources/system-keys/USB-storage.md ================================================ # USB storage The USBSTOR driver tracks various information about attached USB storage devices in the key. ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USBSTOR ``` The USBSTOR key contains one or more device keys. ## Device key The name of the device key is formatted as: ``` &Ven_&Prod_&Rev_ ``` Note that the number of values in the name is variable. For example: `Disk&Ven_&Prod_&Rev_0.00` or `Disk&Ven_&Prod_` The device key contains one or more device instance keys. ## Device instance key The name of the device instance key is formatted as: For example: `1002131402536a&0` Sub keys: Name | Description --- | --- Device Parameters | LogConf | Properties | Values: Name | Data type | Description --- | --- | --- Capabilities | REG_DWORD_LITTLE_ENDIAN | Class | REG_SZ | ClassGUID | REG_SZ | CompatibleIDs | REG_MULTI_SZ | ConfigFlags | REG_DWORD_LITTLE_ENDIAN | ContainerID | REG_SZ | DeviceDesc | REG_SZ | Driver | REG_SZ | FriendlyName | REG_SZ | Human readable description of the USB storage device HardwareID | REG_MULTI_SZ | Mfg | REG_SZ | Manufacturer information Service | REG_SZ | ## Device Parameters key Sub keys: Name | Description --- | --- MediaChangeNotification | Partmgr | ### Device Parameters\Partmgr key Values: Name | Data type | Description --- | --- | --- Attributes | REG_DWORD_LITTLE_ENDIAN | DiskId | REG_SZ | Contains a GUID ## LogConf key ## Properties key Sub keys: Name | Description --- | --- %GUID% | Property set identifier ### Property set key (Properties\\%GUID%) Sub keys: Name | Description --- | --- %NUMERIC% | Property identifier #### Property key (Properties\\%GUID%\\%NUMERIC%) Sub keys: Name | Description --- | --- %NUMERIC% | #### Property value key (Properties\\%GUID%\\%NUMERIC%\\%NUMERIC%) Values: Name | Data type | Description --- | --- | --- Data | REG_BINARY | Value data Type | REG_BINARY | Value type Value type: * 0x0007 value data contains a 32-bit little-endian integer * 0x0010 value data contains a FILETIME * 0x0012 value data contains an UTF-16 litte-endian encoded string ### Example ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USBSTOR\Disk&Ven_HP&Prod_v100w&Rev_1024\AA951D0000007252&0\Properties\{540b947e-8b40-45bc-a8a2-6a0b894cbda2}\00000004\00000000 Property set: 540b947e-8b40-45bc-a8a2-6a0b894cbda2 (System.Devices) Property identifier: 4 (PKEY_Device_BusReportedDeviceDesc) Type: 0x00000012 (UTF-16 litte-endian encoded string) Data: "HP v100w USB Device" ``` ## External links * [USB device registry entries](https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-device-specific-registry-settings) * [Identifiers Generated by USBSTOR.SYS](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-generated-by-usbstor-sys) * [DEVPKEY_Device_InstallDate](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/devpkey-device-installdate) * [DEVPKEY_Device_FirstInstallDate](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/devpkey-device-firstinstalldate) ================================================ FILE: docs/sources/system-keys/Volume-shadow-copies.md ================================================ # Volume shadow copies ## FilesNotToSnapshot key ``` HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\BackupRestore\FilesNotToSnapshot ``` Value| Data type| Description --- | --- | --- | %NAME% | REG_MULTI_SZ | Where %NAME% contains an array of strings that contain the path of files that are excluded from being added to a volume shadow snapshot.
The files paths can contain the * wildcard. ## External Links * [Excluding Files from Shadow Copies](https://learn.microsoft.com/en-us/windows/win32/vss/excluding-files-from-shadow-copies) ================================================ FILE: docs/sources/system-keys/Windows-error-reporting.md ================================================ # Windows Error Reporting (WER) keys ## Windows Error Reporting (WER) system key ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting ``` Sub keys: Name | Description --- | --- Assert Filtering Policy | BrokerUp | Consent | Debug | Hangs | HeapControlledList | LocalDumps | RuntimeExceptionHelperModules | WMR | Values: Name | Data type | Description --- | --- | --- BypassDataThrottling | REG_DWORD | Bypass WER client data throttling ConfigureArchive | REG_DWORD | Archive only the parameters or all data EnableZip | REG_DWORD | ErrorPort | REG_SZ | MachineID | | MaxQueueSizePercentage | | PurgeThreshholdValueInKB | | ServiceTimeout | REG_DWORD | ### BypassDataThrottling value 0 - Disable data bypass throttling 1 - Enable data bypass throttling ### ConfigureArchive value 1 - Parameters only (default on Windows 7) 2 - All data (default on Windows Vista) ### Consent sub key Values: Name | Data type | Description --- | --- | --- DefaultConsent | REG_DWORD | The default consent choice DefaultOverrideBehavior | REG_DWORD | The default consent overrides the vertical consent NewUserDefaultConsent | REG_DWORD | #### DefaultConsent value 1 - Always ask (default) 2 - Parameters only 3 - Parameters and safe data 4 - All data #### DefaultOverrideBehavior value 0 - Vertical consent will override the default consent (default) 1 - Default consent will override the application-specific consent| ### Debug sub key Sub keys: Name | Description --- | --- UIHandles | Values: Name | Data type | Description --- | --- | --- StoreLocation | REG_SZ | Location of last report? #### UIHandles sub key Values: Name | Data type | Description --- | --- | --- CheckingForSolutionDialog | | CloseDialog | | FirstLevelConsentDialog | | RecoveryDialog | | RestartDialog | | ### Hangs sub key Values: Name | Data type | Description --- | --- | --- NHRTimes | | ### LocalDumps sub key Per-application setting can be define by an application-specific key under: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps ``` For example an application-key for MyApplication.exe ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApplication.exe ``` Values: Name | Data type | Description --- | --- | --- DumpCount | REG_DWORD | The maximum number of dump files in the folder. Older dump files are overwritten if the maximum has been reached.
By default: 10 DumpFolder | REG_EXPAND_SZ | The path where the dump files are to be stored.
By default: %LOCALAPPDATA%\CrashDumps DumpType | REG_DWORD | The dump type
By default: 1 (Mini dump) CustomDumpFlags | REG_DWORD | Custom dump flag when dump type is 0 (Custom dump). #### DumpType value Value | Description --- | --- 0 | Custom dump 1 | Mini dump (default) 2 | Full dump #### CustomDumpFlags value The CustomDumpFlags value contains a bitwise combination of the MINIDUMP_TYPE enumeration values. ## Windows Error Reporting (WER) user key ``` HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting ``` Sub keys: Name | Description --- | --- Consent | Hangs | Values: Name | Data type | Description --- | --- | --- AutoApproveOSDumps | REG_DWORD | Disabled | REG_DWORD | DisableArchive | REG_DWORD | DisableQueue | REG_DWORD | DontSendAdditionalData | REG_DWORD | DontShowUI | REG_DWORD | ForceQueue | REG_DWORD | LastCrashSelfReportTime | | LastQueuePesterTime | REG_QWORD_LITTLE_ENDIAN | LastResponsePesterTime | | LoggingDisabled | REG_DWORD | MaxArchiveCount | REG_DWORD | MaxQueueCount | REG_DWORD | MaxQueueSize | REG_DWORD | ## Notes ### Kernel faults sub key Sub keys: Name | Description --- | --- Queue | #### Queue sub key Values: Name | Data type | Description --- | --- | --- %FILENAME% | | Creation time of the minidump?
Contains a FILETIME ``` C:\\Windows\\Minidump\\MMDDYY-#-01.dmp ``` ### Other C:\Users\%USERNAME%\AppData\Local\Microsoft\Windows\WER Sub directories: Name | Description --- | --- ERC | ReportArchive | ReportQueue | ## External Links * [Collecting User-Mode Dumps](https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps) * [MINIDUMP_TYPE enumeration](https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ne-minidumpapiset-minidump_type) * [WER Settings](https://learn.microsoft.com/en-us/windows/win32/wer/wer-settings) ================================================ FILE: docs/sources/system-keys/Windows-product-information.md ================================================ # Windows product information Windows product information can be found in the key: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion ``` Values: Name | Data type | Description --- | --- | --- BuildLab | REG_SZ | CSDVersion | REG_SZ | Service pack CurrentBuild | REG_SZ | Current build (obsolete) e.g. 1.511.1 CurrentBuildNumber | REG_SZ | Current build number e.g. 2600 CurrentType | REG_SZ | CurrentVersion | REG_SZ | Current major and minor version e.g. 5.1 DigitalProductId | REG_BINARY | InstallDate | REG_LONG | LicenseInfo | REG_BINARY | PathName | REG_SZ | Windows path name e.g. C:\Windows ProductId | REG_SZ | Product identifier ProductName | REG_SZ | Product name e.g Microsoft Windows XP RegDone | | RegisteredOrganization | REG_SZ | Registered organization RegisteredOwner | REG_SZ | Registered owner SoftwareType | REG_SZ | Software type e.g. SYSTEM SourcePath | REG_SZ | SubVersionNumber | | SystemRoot | REG_SZ | The system root also the value of %SystemRoot% ================================================ FILE: docs/sources/system-keys/Windows-system-locations.md ================================================ # Windows system locations Windows system locations can be found in the key: ``` HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion ``` Values: Name | Data type | Description --- | --- | --- CommonFilesDir | REG_SZ | path of the common program files directory, also set in the %CommomProgramFiles% environment variable CommonFilesDir (x86) | REG_SZ | path of the 32-bit common program directory folder on a 64-bit Windows installation, also set in the %CommomProgramFiles(x86)% environment variable DevicePath | REG_SZ | MediaPath | REG_SZ | MediaPathUnexpanded | REG_SZ | PF_AccessoriesName | | ProductId | | ProgramFilesDir | REG_SZ | path of the "Program Files" directory, also set in the %ProgramFiles% environment variable ProgramFilesDir (x86) | REG_SZ | path of the 32-bit "Program Files" directory on a 64-bit Windows installation, also set in the %ProgramFiles(x86)% environment variable SM_AccessoriesName | | SM_ConfigureProgramsExisted | | SM_ConfigureProgramsName | | SM_GamesName | | WallPaperDir | REG_SZ | ================================================ FILE: docs/sources/system-keys/index.rst ================================================ ################### Windows system keys ################### .. toctree:: :maxdepth: 1 Application compatibility cache Background activity moderator Boot verification Cached credentials Certificates Codepage COM class identifiers Current control set Environment variables File system Language Local security authority Mounted devices Prefetch Run and RunOnce Services and drivers Session manager Shell folder identifiers System restore Task scheduler Time zones USB storage Volume shadow copies Windows error reporting Windows product information Windows system locations ================================================ FILE: docs/sources/windows-registry/Files.md ================================================ # Windows Registry files ## Windows Registry files - Windows 3.1 On Windows 3.1 the SHCC file format is used to store Windows Registry data. Paths of known Windows Registry files: Filename | Path | Description --- | --- | --- REG.DAT | %SystemRoot% | Entire registry ## Windows Registry files - Windows 9x/Me On Windows 9x/Me the [CREG](https://github.com/libyal/libcreg/blob/main/documentation/Windows%209x%20Registry%20File%20(CREG)%20format.asciidoc) file format is used to store Windows Registry data. Paths of known Windows Registry files: Filename | Path | Description | Corresponding Registry Key --- | --- | --- | --- SYSTEM.DAT | %SystemRoot% | System specific part of the Registry | `HKEY_LOCAL_MACHINE` USER.DAT | %SystemRoot% | User specific part of the Registry | `HKEY_USERS` ### Root keys The root key of both SYSTEM.DAT and USER.DAT contains an empty name string. ## Windows Registry files - Windows NT On Windows NT and later the [REGF](https://github.com/libyal/libregf/blob/main/documentation/Windows%20NT%20Registry%20File%20(REGF)%20format.asciidoc) file format is used to store Windows Registry data. Paths of known Windows Registry files: Filename | Path | Description | Corresponding Registry Key | Windows version --- | --- | --- | --- | --- Amcache.hve | %SystemRoot%\AppCompat\Programs | *TODO* | | 8, 10 BBI | %SystemRoot%\System32\config | *TODO* | | 10 BCD | \Boot or \EFI\Microsoft\Boot (on boot volume) | Boot Configuration Data (BCD) | `HKEY_LOCAL_MACHINE\BCD00000000` | Windows Vista and later default | %SystemRoot%\System32\config | *TODO* | | NT 4 and later DRIVERS | %SystemRoot%\System32\config | *TODO* | | 10 ELAM | %SystemRoot%\System32\config | *TODO* | | 10 NTUSER.DAT | %UserProfile% | User specific part of the Registry | `HKEY_CURRENT_USER` | NT 4 and later NTUSER.MAN | %UserProfile% | Mandatory user specific part of the Registry | | NT 4 and later SAM | %SystemRoot%\System32\config | Security Account Manager (SAM) part of the Registry | `HKEY_LOCAL_MACHINE\SAM` | NT 4 and later SECURITY | %SystemRoot%\System32\config | *TODO* | `HKEY_LOCAL_MACHINE\Security` | NT 4 and later SOFTWARE | %SystemRoot%\System32\config | Software specific part of the Registry | `HKEY_LOCAL_MACHINE\Software` | NT 4 and later Syscache.hve | System Volume Information | *TODO* | | 7, 2008 SYSTEM | %SystemRoot%\System32\config | System specific part of the Registry | `HKEY_LOCAL_MACHINE\System` | NT 4 and later userdiff | %SystemRoot%\System32\config | *TODO* | | NT 4 and later UsrClass.dat | %UserProfile%\Local Settings\Application Data\Microsoft\Windows | `HKEY_CURRENT_USER\Software\Classes` | | 2000, XP, 2003 UsrClass.dat | %UserProfile%\AppData\Local\Microsoft\Windows | File associations and COM Registry entries | `HKEY_CURRENT_USER\Software\Classes` | Vista and later *TODO Windows NT 3.1 user specific file under %SystemRoot%\System32\config* *TODO BCD check Windows 8 and 10* *TODO userdiff no longer present in Windows 10 ?* *TODO what about \Windows\profiles\user profile\user.dat ?* *TODO what about \Windows\System32\SMI\Store\Machine\SCHEMA.DAT (Windows 7)* ### Root keys The root key names of the different Windows Registry files differ per version of Windows. #### Root key - default *TODO* #### Root key - NTUSER.DAT Windows version | Root key name --- | --- NT 4 | .Default 2000, XP, 2003 | $$$PROTO.HIV Vista | CMI-CreateHive{B01E557D-7818-4BA7-9885-E6592398B44E} 2008 | *TODO* 2016 | *TODO* 2019 | *TODO* 7 | CMI-CreateHive{D43B12B8-09B5-40DB-B4F6-F6DFEB78DAEC} 8 | CsiTool-CreateHive-{00000000-0000-0000-0000-000000000000} 10 | ROOT #### Root key - SAM Windows version | Root key name --- | --- NT4, 2000, XP, 2003 | SAM Vista | CMI-CreateHive{87E016C8-C811-4B12-9C3A-CDA552F3458D} 2008 | *TODO* 2016 | *TODO* 2019 | *TODO* 7 | CMI-CreateHive{C4E7BA2B-68E8-499C-B1A1-371AC8D717C7} 8 | *TODO* 10 | *TODO* #### Root key - SECURITY Windows version | Root key name --- | --- NT4, 2000, XP, 2003 | SECURITY Vista | *TODO* 2008 | *TODO* 2016 | *TODO* 2019 | *TODO* 7 | *TODO* 8 | *TODO* 10 | *TODO* #### Root key - SOFTWARE Windows version | Root key name --- | --- NT4 | Software 2000, XP | $$$PROTO.HIV 2003 | *TODO* Vista | CMI-CreateHive{29EE1162-53C9-4474-A2B6-D90A7F6B0A7C} 2008 | *TODO* 2016 | *TODO* 2019 | *TODO* 7 | CMI-CreateHive{199DAFC2-6F16-4946-BF90-5A3FC3A60902} 8 | CsiTool-CreateHive-{00000000-0000-0000-0000-000000000000} 10 | *TODO* #### Root key - Syscache.hve Windows version | Root key name --- | --- 7, 2008 | {%GUID%} 2016 | *TODO* 2019 | *TODO* 8 | *TODO* 10 | *TODO* Where {%GUID%} is a placeholder for a random GUID in the form: {00000000-0000-0000-0000-000000000000} *Note how consistent are the GUIDs icw CreateHive ?* #### Root key - SYSTEM Windows version | Root key name --- | --- NT4 | System 2000, XP, 2003 | $$$PROTO.HIV Vista | CMI-CreateHive{C619BFE8-791A-4B77-922B-F114AB570920} 2008 | *TODO* 7 | CMI-CreateHive{2A7FB991-7BBE-4F9D-B91E-7CB51D4737F5} 8 | CsiTool-CreateHive-{00000000-0000-0000-0000-000000000000} #### Root key - userdiff *TODO* #### Root key - UsrClass.dat Windows version | Root key name --- | --- 2000 | *TODO* XP | %SID%_Classes, where %SID%_Classes is a string of the SID of the user 2003 | *TODO* Vista, 7 | %SID%_Classes, where %SID%_Classes is a string of the SID of the user 2008 | *TODO* 2016 | *TODO* 2019 | *TODO* 8 | *TODO* 10 | %SID%_Classes, where %SID%_Classes is a string of the SID of the user ### Virtual keys Windows version | Key path | Description --- | --- | --- 2000 and later | `HKEY_LOCAL_MACHINE\System\CurrentControlSet` | See [Current control set](../system-keys/Current-control-set.html) 2000 and later | `HKEY_CURRENT_USER\Software\Classes` | Maps to UsrClass.dat 2000 and later | `HKEY_CLASSES_ROOT` | Combination of system (`HKEY_LOCAL_MACHINE\Software\Classes`) and user-specific (`HKEY_CURRENT_USER\Software\Classes`) settings Vista and later | `HKEY_CURRENT_USER\Software\Classes\VirtualStore\Machine\Software` | User-specific changes to `HKEY_LOCAL_MACHINE\Software` ## External Links * [HKEY_CLASSES_ROOT Key](https://learn.microsoft.com/en-us/windows/win32/sysinfo/hkey-classes-root-key) * [Registry Virtualization](https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-virtualization) ================================================ FILE: docs/sources/windows-registry/Hives.md ================================================ # Windows Registry hives Name | Short name | Description --- | --- | --- HKEY_CLASSES_ROOT | HKCR | Used by Windows 3.1, 9x/Me and NT 4 and later
Refers to values in both HKEY_CURRENT_USER\\Software\\Classes and HKEY_LOCAL_MACHINE\\Software\\Classes HKEY_CURRENT_CONFIG | HKCC | Used by Windows 9x/Me and NT 4 and later
Refers to the current control set in HKLM HKEY_CURRENT_USER | HKCU | Information regarding the current active user
Used by Windows 9x/Me and NT 4 and later
Refers to the active user key in HKEY_USERS HKEY_DYN_DATA | | Dynamic data
Used by Windows 9x/Me HKEY_LOCAL_MACHINE | HKLM | Local settings
Used by Windows 9x/Me and NT 4 and later HKEY_PERFORMANCE_DATA | | Performance data
Used by Windows NT 4 and later HKEY_USERS | HKU | Information about all active users
Used by Windows 9x/Me and NT 4 and later ================================================ FILE: docs/sources/windows-registry/MUI-form.md ================================================ # Multilingual User Interface (MUI) form The Multilingual User Interface (MUI) form is used to store strings in multiple languages. This is also known as Registry string redirection. The actual strings are stored in the resource sections of PE/COFF files (also referred to as resource file) e.g .exe, .dll. In the Registry the MUI strings are referenced using the following form: ``` @path,-stringID[;comment] ``` Where: * path; is the full path or filename of the resource file that contains the string * stringID; the identifier of the string within the string resource of the resource file * comment; a comment For example the MUI form string: ``` @%SystemRoot%\system32\SHELL32.dll,-9227 ``` This MUI form string refers to the string with identifier 9227, stored in the string resource of SHELL32.dll. Which, for an English version of SHELL32.dll, corresponds to: "My Documents". An example of a MUI form with comment: ``` @wfplwfs.inf,%WfpLwfs_Name%;WFP LightWeight Filters ``` ## Notes What about the form (seen in the Shell Folder value LocalizedString): ``` @%SystemRoot%\System32\fvecpl.dll,-1#immutable1 ``` What does # represent here? ``` @wd.inf,%WdServiceDisplayName%;Microsoft Watchdog Timer Driver ``` Yet another variation seen in Windows 2000. ``` @C:\WINNT\system32\shell32.dll,-9227@1033,My Documents ``` ## External Links * [Multilingual User Interface](https://learn.microsoft.com/en-us/windows/win32/intl/multilingual-user-interface) * [Using Registry String Redirection](https://learn.microsoft.com/en-us/windows/win32/intl/using-registry-string-redirection) ================================================ FILE: docs/sources/windows-registry/index.rst ================================================ ################ Windows Registry ################ .. toctree:: :maxdepth: 1 Hives Files Multilingual User Interface (MUI) form ================================================ FILE: pyproject.toml ================================================ [build-system] requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" [project] name = "winregrc" version = "20260506" description = "Windows Registry resources (winregrc)" maintainers = [ { name = "Joachim Metz", email = "joachim.metz@gmail.com" }, ] license = "Apache-2.0" license-files = ["ACKNOWLEDGEMENTS", "AUTHORS", "LICENSE"] readme = "README.md" classifiers = [ "Development Status :: 2 - Pre-Alpha", "Programming Language :: Python", ] requires-python = ">=3.10" dependencies = [ "PyYAML >= 3.10", "acstore >= 20230101", "artifacts >= 20220219", "dfdatetime >= 20221112", "dfimagetools >= 20240301", "dfvfs >= 20240115", "dfwinreg >= 20240229", "dtfabric >= 20230518", "libbde-python >= 20220121", "libcaes-python >= 20240114", "libcreg-python >= 20200725", "libewf-python >= 20131210", "libfcrypto-python >= 20240114", "libfsapfs-python >= 20220709", "libfsext-python >= 20220829", "libfsfat-python >= 20220925", "libfshfs-python >= 20220831", "libfsntfs-python >= 20211229", "libfsxfs-python >= 20220829", "libfvde-python >= 20220121", "libfwnt-python >= 20210717", "libfwps-python >= 20240225", "libfwsi-python >= 20240315", "libhmac-python >= 20230205", "libluksde-python >= 20220121", "libmodi-python >= 20210405", "libphdi-python >= 20220228", "libqcow-python >= 20201213", "libregf-python >= 20201002", "libsigscan-python >= 20230109", "libsmdev-python >= 20140529", "libsmraw-python >= 20140612", "libvhdi-python >= 20201014", "libvmdk-python >= 20140421", "libvsapm-python >= 20230506", "libvsgpt-python >= 20211115", "libvshadow-python >= 20160109", "libvslvm-python >= 20160109", "pytsk3 >= 20210419", "xattr >= 0.7.2 ; platform_system != \"Windows\"", ] [project.scripts] appcompatcache = "winregrc.scripts.appcompatcache:Main" application_identifiers = "winregrc.scripts.application_identifiers:Main" cached_credentials = "winregrc.scripts.cached_credentials:Main" catalog = "winregrc.scripts.catalog:Main" controlpanel_items = "winregrc.scripts.controlpanel_items:Main" delegatefolders = "winregrc.scripts.delegatefolders:Main" environment_variables = "winregrc.scripts.environment_variables:Main" eventlog_providers = "winregrc.scripts.eventlog_providers:Main" knownfolders = "winregrc.scripts.knownfolders:Main" mounted_devices = "winregrc.scripts.mounted_devices:Main" mru = "winregrc.scripts.mru:Main" msie_zone_info = "winregrc.scripts.msie_zone_info:Main" profiles = "winregrc.scripts.profiles:Main" programscache = "winregrc.scripts.programscache:Main" sam = "winregrc.scripts.sam:Main" services = "winregrc.scripts.services:Main" shellfolders = "winregrc.scripts.shellfolders:Main" srum_extensions = "winregrc.scripts.srum_extensions:Main" sysinfo = "winregrc.scripts.sysinfo:Main" syskey = "winregrc.scripts.syskey:Main" task_cache = "winregrc.scripts.task_cache:Main" time_zones = "winregrc.scripts.time_zones:Main" type_libraries = "winregrc.scripts.type_libraries:Main" usbstor = "winregrc.scripts.usbstor:Main" userassist = "winregrc.scripts.userassist:Main" [project.urls] Documentation = "https://winregrc.readthedocs.io/en/latest" Homepage = "https://github.com/libyal/winreg-kb" Repository = "https://github.com/libyal/winreg-kb" [tool.setuptools] package-dir = {"winregrc" = "winregrc"} [tool.setuptools.package-data] winregrc = [ "*.yaml", "data/*.yaml", ] ================================================ FILE: run_tests.py ================================================ #!/usr/bin/env python3 """Script to run the tests.""" import sys import unittest # Change PYTHONPATH to include winregrc. sys.path.insert(0, '.') import utils.dependencies # pylint: disable=wrong-import-position if __name__ == '__main__': fail_unless_has_test_file = '--fail-unless-has-test-file' in sys.argv setattr(unittest, 'fail_unless_has_test_file', fail_unless_has_test_file) if fail_unless_has_test_file: # Remove --fail-unless-has-test-file otherwise it will conflict with # the argparse tests. sys.argv.remove('--fail-unless-has-test-file') dependency_helper = utils.dependencies.DependencyHelper() if not dependency_helper.CheckTestDependencies(): sys.exit(1) test_suite = unittest.TestLoader().discover('tests', pattern='*.py') test_results = unittest.TextTestRunner(verbosity=2).run(test_suite) if not test_results.wasSuccessful(): sys.exit(1) ================================================ FILE: test_data/SOFTWARE ================================================ [File too large to display: 62.2 MB] ================================================ FILE: test_dependencies.ini ================================================ ================================================ FILE: tests/__init__.py ================================================ ================================================ FILE: tests/appcompatcache.py ================================================ #!/usr/bin/env python3 """Tests for the Application Compatibility Cache collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import appcompatcache from winregrc import output_writers from tests import test_lib _CACHE_DATA_WINDOWS_XP = bytes(bytearray([ 0xef, 0xbe, 0xad, 0xde, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x57, 0x00, 0x53, 0x00, 0x5c, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x68, 0x00, 0x74, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x2e, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x5c, 0x00, 0x62, 0x00, 0x37, 0x00, 0x66, 0x00, 0x30, 0x00, 0x62, 0x00, 0x32, 0x00, 0x38, 0x00, 0x39, 0x00, 0x32, 0x00, 0x62, 0x00, 0x32, 0x00, 0x31, 0x00, 0x32, 0x00, 0x31, 0x00, 0x31, 0x00, 0x61, 0x00, 0x35, 0x00, 0x36, 0x00, 0x33, 0x00, 0x30, 0x00, 0x35, 0x00, 0x31, 0x00, 0x38, 0x00, 0x64, 0x00, 0x30, 0x00, 0x35, 0x00, 0x38, 0x00, 0x66, 0x00, 0x34, 0x00, 0x38, 0x00, 0x64, 0x00, 0x39, 0x00, 0x5c, 0x00, 0x75, 0x00, 0x70, 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x75, 0x00, 0x70, 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xe9, 0x54, 0x2b, 0x7a, 0xc4, 0x01, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xd3, 0x0e, 0xc7, 0xe9, 0x39, 0xca, 0x01 ])) _CACHE_DATA_WINDOWS_2003 = bytes(bytearray([ 0xfe, 0x0f, 0xdc, 0xba, 0x01, 0x00, 0x00, 0x00, 0x72, 0x00, 0x74, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x35, 0x86, 0x76, 0x44, 0xf2, 0xc2, 0x01, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x44, 0x00, 0x4f, 0x00, 0x57, 0x00, 0x53, 0x00, 0x5c, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x4e, 0x00, 0x45, 0x00, 0x54, 0x00, 0x5c, 0x00, 0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x5c, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x34, 0x00, 0x33, 0x00, 0x32, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x00, 0x00 ])) _CACHE_DATA_WINDOWS_VISTA = bytes(bytearray([ 0xfe, 0x0f, 0xdc, 0xba, 0x01, 0x00, 0x00, 0x00, 0x46, 0x00, 0x48, 0x00, 0x20, 0x00, 0x00, 0x00, 0xc2, 0xfe, 0x87, 0x5e, 0x7b, 0xfe, 0xc6, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x5c, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x59, 0x00, 0x53, 0x00, 0x54, 0x00, 0x45, 0x00, 0x4d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x49, 0x00, 0x53, 0x00, 0x50, 0x00, 0x54, 0x00, 0x49, 0x00, 0x53, 0x00, 0x2e, 0x00, 0x45, 0x00, 0x58, 0x00, 0x45, 0x00, 0x00, 0x00 ])) _CACHE_DATA_WINDOWS_8_0 = bytes(bytearray([ 0x80, 0x00, 0x00, 0x00, 0x2e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x74, 0x73, 0x9e, 0x6b, 0x3c, 0x8a, 0x68, 0x00, 0x00, 0x00, 0x52, 0x00, 0x53, 0x00, 0x59, 0x00, 0x53, 0x00, 0x56, 0x00, 0x4f, 0x00, 0x4c, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x77, 0x00, 0x62, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x50, 0x00, 0x72, 0x00, 0x76, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0xa4, 0xa4, 0xbc, 0xfc, 0xed, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00 ])) _CACHE_DATA_WINDOWS_8_1 = bytes(bytearray([ 0x80, 0x00, 0x00, 0x00, 0x09, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x15, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x30, 0x74, 0x73, 0xbc, 0x4c, 0xa0, 0x05, 0x5e, 0x00, 0x00, 0x00, 0x46, 0x00, 0x53, 0x00, 0x59, 0x00, 0x53, 0x00, 0x56, 0x00, 0x4f, 0x00, 0x4c, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0xb5, 0x1f, 0x73, 0x13, 0x34, 0x9f, 0xce, 0x01, 0x00, 0x00, 0x00, 0x00 ])) _CACHE_DATA_WINDOWS_10 = bytes(bytearray([ 0x30, 0x00, 0x00, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x30, 0x74, 0x73, 0x64, 0x7e, 0xcd, 0xc9, 0xcc, 0x00, 0x00, 0x00, 0x42, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x5c, 0x00, 0x4d, 0x00, 0x70, 0x00, 0x53, 0x00, 0x69, 0x00, 0x67, 0x00, 0x53, 0x00, 0x74, 0x00, 0x75, 0x00, 0x62, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x80, 0x99, 0xe3, 0x66, 0x30, 0xd6, 0xcf, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ])) _CACHE_DATA_WINDOWS_10_CREATOR = bytes(bytearray([ 0x34, 0x00, 0x00, 0x00, 0x1a, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x30, 0x74, 0x73, 0xd5, 0xf1, 0x23, 0x93, 0xd4, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x73, 0x00, 0x20, 0x00, 0x28, 0x00, 0x78, 0x00, 0x38, 0x00, 0x36, 0x00, 0x29, 0x00, 0x5c, 0x00, 0x4e, 0x00, 0x56, 0x00, 0x49, 0x00, 0x44, 0x00, 0x49, 0x00, 0x41, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x33, 0x00, 0x44, 0x00, 0x20, 0x00, 0x56, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x6e, 0x00, 0x76, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x65, 0x00, 0x67, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0xe9, 0x09, 0x99, 0x7b, 0xa8, 0x9e, 0xd2, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ])) class TestOutputWriter(output_writers.StdoutOutputWriter): """Output writer for testing. Attributes: cached_entries (list[AppCompatCacheCachedEntry]): Application Compatibility Cache cached entries. """ def __init__(self): """Initializes an output writer object.""" super().__init__() self.cached_entries = [] def WriteCachedEntry(self, cached_entry): """Writes the Application Compatibility Cache cached entry to stdout. Args: cached_entry (AppCompatCacheCachedEntry): Application Compatibility Cache cached entry. """ self.cached_entries.append(cached_entry) class AppCompatCacheDataParserTest(test_lib.BaseTestCase): """Tests for the Application Compatibility Cache data parser.""" # pylint: disable=protected-access def testCheckSignature(self): """Tests the CheckSignature function.""" parser = appcompatcache.AppCompatCacheDataParser() format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_XP) self.assertEqual(format_type, parser._FORMAT_TYPE_XP) format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_2003) self.assertEqual(format_type, parser._FORMAT_TYPE_2003) format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_VISTA) # TODO: add support to detect Vista format. self.assertEqual(format_type, parser._FORMAT_TYPE_2003) # TODO: add Windows 7 test. format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_8_0) self.assertEqual(format_type, parser._FORMAT_TYPE_8) format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_8_1) self.assertEqual(format_type, parser._FORMAT_TYPE_8) format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_10) self.assertEqual(format_type, parser._FORMAT_TYPE_10) format_type = parser.CheckSignature(_CACHE_DATA_WINDOWS_10_CREATOR) self.assertEqual(format_type, parser._FORMAT_TYPE_10) # TODO: add bogus data tests. def testParseHeader(self): """Tests the ParseHeader function.""" parser = appcompatcache.AppCompatCacheDataParser() header_object = parser.ParseHeader( parser._FORMAT_TYPE_XP, _CACHE_DATA_WINDOWS_XP) self.assertIsNotNone(header_object) header_object = parser.ParseHeader( parser._FORMAT_TYPE_2003, _CACHE_DATA_WINDOWS_2003) self.assertIsNotNone(header_object) # TODO: fix Vista support. # header_object = parser.ParseHeader( # parser._FORMAT_TYPE_VISTA, _CACHE_DATA_WINDOWS_VISTA) # self.assertIsNotNone(header_object) # TODO: add Windows 7 test. header_object = parser.ParseHeader( parser._FORMAT_TYPE_8, _CACHE_DATA_WINDOWS_8_0) self.assertIsNotNone(header_object) header_object = parser.ParseHeader( parser._FORMAT_TYPE_8, _CACHE_DATA_WINDOWS_8_1) self.assertIsNotNone(header_object) header_object = parser.ParseHeader( parser._FORMAT_TYPE_10, _CACHE_DATA_WINDOWS_10) self.assertIsNotNone(header_object) # TODO: add bogus data tests. class AppCompatCacheCollectorTest(test_lib.BaseTestCase): """Tests for the Application Compatibility Cache collector.""" def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\System' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('Select') registry_file.AddKeyByPath('\\', registry_key) value_data = b'\x01\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Current', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) registry_key.AddValue(registry_value) registry_key = dfwinreg_fake.FakeWinRegistryKey('AppCompatibility') registry_file.AddKeyByPath( '\\ControlSet001\\Control\\Session Manager', registry_key) registry_value = dfwinreg_fake.FakeWinRegistryValue( 'AppCompatCache', data=_CACHE_DATA_WINDOWS_XP, data_type=dfwinreg_definitions.REG_BINARY) registry_key.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() test_output_writer = TestOutputWriter() collector_object = appcompatcache.AppCompatCacheCollector( output_writer=test_output_writer) result = collector_object.Collect(registry, all_control_sets=True) self.assertTrue(result) test_output_writer.Close() self.assertEqual(len(collector_object.cached_entries), 1) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = TestOutputWriter() collector_object = appcompatcache.AppCompatCacheCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) test_output_writer.Close() self.assertEqual(len(collector_object.cached_entries), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/application_identifiers.py ================================================ #!/usr/bin/env python3 """Tests for the Windows application identifiers (AppID) collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import application_identifiers from tests import test_lib as shared_test_lib class ApplicationIdentifiersCollectorTest(shared_test_lib.BaseTestCase): """Tests for the Windows application identifiers (AppID) collector.""" def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\Software' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey( '{fd6c8b29-e936-4a61-8da6-b0c12ad3ba00}') registry_file.AddKeyByPath('\\Classes\\AppID', registry_key) value_data = 'Wordpad'.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( '', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() collector_object = application_identifiers.ApplicationIdentifiersCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 1) application_identifier = test_results[0] self.assertIsNotNone(application_identifier) self.assertEqual(application_identifier.description, 'Wordpad') self.assertEqual( application_identifier.guid, '{fd6c8b29-e936-4a61-8da6-b0c12ad3ba00}') def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = application_identifiers.ApplicationIdentifiersCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/cached_credentials.py ================================================ #!/usr/bin/env python3 """Tests for the domain cached credentials collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import cached_credentials from winregrc import output_writers from tests import test_lib class TestOutputWriter(output_writers.StdoutOutputWriter): """Output writer for testing. Attributes: cached_entries (list[AppCompatCacheCachedEntry]): Application Compatibility Cache cached entries. """ def __init__(self): """Initializes an output writer object.""" super().__init__() self.cached_entries = [] def WriteCachedEntry(self, cached_entry): """Writes the Application Compatibility Cache cached entry to stdout. Args: cached_entry (AppCompatCacheCachedEntry): Application Compatibility Cache cached entry. """ self.cached_entries.append(cached_entry) class CachedCredentialsKeyCollectorTest(test_lib.BaseTestCase): """Tests for the Application Compatibility Cache collector.""" # pylint: disable=protected-access _NL_KEY_MATERIAL_DATA = bytes(bytearray([ 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x20, 0x9c, 0xc3, 0x0c, 0x00, 0xc2, 0x0d, 0x08, 0x10, 0x9a, 0x04, 0x04, 0xbf, 0x14, 0x8b, 0xc7, 0xd0, 0x0b, 0xe2, 0x9c, 0x40, 0x52, 0xa7, 0x8e, 0xaa, 0x01, 0x49, 0x25, 0x70, 0x71, 0xdc, 0xa0, 0x69, 0x8e, 0x6c, 0x03, 0x1c, 0xb7, 0xdb, 0x19, 0x5c, 0x8f, 0xf4, 0x11, 0xd1, 0x8d, 0x73, 0x07, 0xb0, 0x6f, 0x1a, 0xdb, 0x0b, 0xee, 0xcb, 0x69, 0x7f, 0x73, 0x50, 0x24, 0x82, 0xf8, 0xe1, 0xa6, 0x27, 0x97, 0xa9, 0xcc, 0x04, 0x8e, 0xe4, 0xca, 0xbb, 0x33, 0x68, 0x00, 0x7c])) _POLICY_ENCRYPTION_DATA = bytes(bytearray([ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xd4, 0x3f, 0xb3, 0xee, 0x4f, 0xcd, 0x45, 0x2d, 0x02, 0xe8, 0x1e, 0xf2, 0xac, 0xbd, 0x4f, 0xfc, 0x15, 0x12, 0x09, 0x0a, 0xb5, 0x48, 0x17, 0x33, 0x8f, 0x42, 0x79, 0x8b, 0x89, 0x11, 0xd8, 0xec, 0x6e, 0x1c, 0xec, 0x38, 0x5f, 0x27, 0xdf, 0x72, 0xca, 0x57, 0x96, 0x8d, 0x16, 0xd9, 0x37, 0xc4, 0x14, 0x64, 0xd1, 0xa8, 0x47, 0x7a, 0xd4, 0x4b, 0xa3, 0x62, 0xd8, 0xe7, 0x2b, 0xef, 0x76])) def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ registry = dfwinreg_registry.WinRegistry() key_path_prefix = 'HKEY_LOCAL_MACHINE\\Security' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('Cache') registry_file.AddKeyByPath('\\', registry_key) registry_key = dfwinreg_fake.FakeWinRegistryKey('PolSecretEncryptionKey') registry_file.AddKeyByPath('\\Policy', registry_key) registry_value = dfwinreg_fake.FakeWinRegistryValue( '', data=self._POLICY_ENCRYPTION_DATA, data_type=dfwinreg_definitions.REG_BINARY) registry_key.AddValue(registry_value) registry_key = dfwinreg_fake.FakeWinRegistryKey('CurrVal') registry_file.AddKeyByPath('\\Policy\\Secrets\\NL$KM', registry_key) registry_value = dfwinreg_fake.FakeWinRegistryValue( '', data=self._NL_KEY_MATERIAL_DATA, data_type=dfwinreg_definitions.REG_BINARY) registry_key.AddValue(registry_value) registry_file.Open(None) registry.MapFile(key_path_prefix, registry_file) key_path_prefix = 'HKEY_LOCAL_MACHINE\\System' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey( 'Data', class_name='902a3f2c') registry_file.AddKeyByPath( '\\CurrentControlSet\\Control\\Lsa', registry_key) registry_key = dfwinreg_fake.FakeWinRegistryKey( 'GBG', class_name='c0d054a4') registry_file.AddKeyByPath( '\\CurrentControlSet\\Control\\Lsa', registry_key) registry_key = dfwinreg_fake.FakeWinRegistryKey('JD', class_name='1ae33251') registry_file.AddKeyByPath( '\\CurrentControlSet\\Control\\Lsa', registry_key) registry_key = dfwinreg_fake.FakeWinRegistryKey( 'Skew1', class_name='be6a589c') registry_file.AddKeyByPath( '\\CurrentControlSet\\Control\\Lsa', registry_key) registry_file.Open(None) registry.MapFile(key_path_prefix, registry_file) return registry def testGetBootKey(self): """Tests the _GetBootKey function.""" registry = self._CreateTestRegistry() collector_object = cached_credentials.CachedCredentialsKeyCollector() boot_key = collector_object._GetBootKey(registry) self.assertEqual(boot_key, b'\xc0j\xbe2\xa4\xd0*Q\x1aX\xe3\x90?T,\x9c') def testGetLSAKey(self): """Tests the _GetLSAKey function.""" registry = self._CreateTestRegistry() collector_object = cached_credentials.CachedCredentialsKeyCollector() lsa_key = collector_object._GetLSAKey( registry, b'\xc0j\xbe2\xa4\xd0*Q\x1aX\xe3\x90?T,\x9c') self.assertEqual(lsa_key, b'\x01\xd6]\xf4C\xaa\n\x86\xd9B\xd1\x174\xcef|') def testGetNLKey(self): """Tests the _GetNLKey function.""" registry = self._CreateTestRegistry() collector_object = cached_credentials.CachedCredentialsKeyCollector() expected_nl_key = ( b'\t\xfeDH\x1b5s\xb7;\x1d\xfc\xf7H\x9f\xc9`;`}\xcfb5P\xfd\xb5\xd8\x8f!u' b'\xec\x01\xe9\x85%\x96lhR\xc90\xfb\x1d\xb6\x9d\xcd\x8c\x14\x90\x91\xde' b'\xf1\xdd]\xd7d*\xce@\x97Z\xf1Yq ') nl_key = collector_object._GetNLKey( registry, b'\x01\xd6]\xf4C\xaa\n\x86\xd9B\xd1\x174\xcef|') self.assertEqual(nl_key, expected_nl_key) def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() test_output_writer = TestOutputWriter() collector_object = cached_credentials.CachedCredentialsKeyCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertTrue(result) test_output_writer.Close() # TODO: # self.assertEqual(len(collector_object.cached_entries), 1) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = TestOutputWriter() collector_object = cached_credentials.CachedCredentialsKeyCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) test_output_writer.Close() # TODO: # self.assertEqual(len(collector_object.cached_entries), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/data_format.py ================================================ """Tests for binary data format and file.""" import io import unittest from dtfabric import errors as dtfabric_errors from dtfabric.runtime import data_maps as dtfabric_data_maps from dtfabric.runtime import fabric as dtfabric_fabric from winregrc import data_format from winregrc import errors from tests import test_lib class ErrorBytesIO(io.BytesIO): """Bytes IO that errors.""" # The following methods are part of the file-like object interface. # pylint: disable=invalid-name def read(self, size=None): # pylint: disable=redundant-returns-doc,unused-argument """Reads bytes. Args: size (Optional[int]): number of bytes to read, where None represents all remaining bytes. Returns: bytes: bytes read. Raises: OSError: for testing. """ raise OSError('Unable to read for testing purposes.') class ErrorDataTypeMap(dtfabric_data_maps.DataTypeMap): """Data type map that errors.""" # pylint: disable=redundant-returns-doc def FoldByteStream(self, mapped_value, **unused_kwargs): """Folds the data type into a byte stream. Args: mapped_value (object): mapped value. Returns: bytes: byte stream. Raises: FoldingError: if the data type definition cannot be folded into the byte stream. """ raise dtfabric_errors.FoldingError( 'Unable to fold to byte stream for testing purposes.') def MapByteStream(self, byte_stream, **unused_kwargs): """Maps the data type on a byte stream. Args: byte_stream (bytes): byte stream. Returns: object: mapped value. Raises: dtfabric.MappingError: if the data type definition cannot be mapped on the byte stream. """ raise dtfabric_errors.MappingError( 'Unable to map byte stream for testing purposes.') class BinaryDataFormatTest(test_lib.BaseTestCase): """Binary data format tests.""" # pylint: disable=protected-access _DATA_TYPE_FABRIC_DEFINITION = b"""\ name: uint32 type: integer attributes: format: unsigned size: 4 units: bytes --- name: point3d type: structure attributes: byte_order: little-endian members: - name: x data_type: uint32 - name: y data_type: uint32 - name: z data_type: uint32 --- name: shape3d type: structure attributes: byte_order: little-endian members: - name: number_of_points data_type: uint32 - name: points type: sequence element_data_type: point3d number_of_elements: shape3d.number_of_points """ _DATA_TYPE_FABRIC = dtfabric_fabric.DataTypeFabric( yaml_definition=_DATA_TYPE_FABRIC_DEFINITION) def testDebugPrintData(self): """Tests the _DebugPrintData function.""" output_writer = test_lib.TestOutputWriter() test_format = data_format.BinaryDataFormat( output_writer=output_writer) data = b'\x00\x01\x02\x03\x04\x05\x06' test_format._DebugPrintData('Description', data) expected_output = [ 'Description:\n', ('0x00000000 00 01 02 03 04 05 06 ' '.......\n\n')] self.assertEqual(output_writer.output, expected_output) def testDebugPrintDecimalValue(self): """Tests the _DebugPrintDecimalValue function.""" output_writer = test_lib.TestOutputWriter() test_format = data_format.BinaryDataFormat( output_writer=output_writer) test_format._DebugPrintDecimalValue('Description', 1) expected_output = ['Description\t\t\t\t\t\t\t\t: 1\n'] self.assertEqual(output_writer.output, expected_output) # TODO add tests for _DebugPrintFiletimeValue def testDebugPrintValue(self): """Tests the _DebugPrintValue function.""" output_writer = test_lib.TestOutputWriter() test_format = data_format.BinaryDataFormat( output_writer=output_writer) test_format._DebugPrintValue('Description', 'Value') expected_output = ['Description\t\t\t\t\t\t\t\t: Value\n'] self.assertEqual(output_writer.output, expected_output) def testDebugPrintText(self): """Tests the _DebugPrintText function.""" output_writer = test_lib.TestOutputWriter() test_format = data_format.BinaryDataFormat( output_writer=output_writer) test_format._DebugPrintText('Text') expected_output = ['Text'] self.assertEqual(output_writer.output, expected_output) # TODO: add tests for _GetDataTypeMap # TODO: add tests for _ReadDefinitionFile def testReadStructureFromByteStream(self): """Tests the _ReadStructureFromByteStream function.""" output_writer = test_lib.TestOutputWriter() test_format = data_format.BinaryDataFormat( debug=True, output_writer=output_writer) data_type_map = self._DATA_TYPE_FABRIC.CreateDataTypeMap('point3d') test_format._ReadStructureFromByteStream( b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00', 0, data_type_map, 'point3d') # Test with missing byte stream. with self.assertRaises(ValueError): test_format._ReadStructureFromByteStream( None, 0, data_type_map, 'point3d') # Test with missing data map type. with self.assertRaises(ValueError): test_format._ReadStructureFromByteStream( b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00', 0, None, 'point3d') # Test with data type map that raises an dtfabric.MappingError. data_type_map = ErrorDataTypeMap(None) with self.assertRaises(errors.ParseError): test_format._ReadStructureFromByteStream( b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00', 0, data_type_map, 'point3d') if __name__ == '__main__': unittest.main() ================================================ FILE: tests/environment_variables.py ================================================ #!/usr/bin/env python3 """Tests for the environment variables collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import environment_variables from tests import test_lib as shared_test_lib class EnvironmentVariablesCollectorTest(shared_test_lib.BaseTestCase): """Tests for the environment variables collector.""" def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\System' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('Environment') registry_file.AddKeyByPath( '\\CurrentControlSet\\Control\\Session Manager', registry_key) value_data = '%SystemRoot%\\TEMP'.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'TEMP', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() collector_object = environment_variables.EnvironmentVariablesCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 1) environment_variable = test_results[0] self.assertIsNotNone(environment_variable) self.assertEqual(environment_variable.name, '%TEMP%') self.assertEqual(environment_variable.value, '%SystemRoot%\\TEMP') def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = environment_variables.EnvironmentVariablesCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/eventlog_providers.py ================================================ #!/usr/bin/env python3 """Tests for the Windows Event Log providers collector.""" import unittest from dfwinreg import regf as dfwinreg_regf from dfwinreg import registry as dfwinreg_registry from winregrc import eventlog_providers from tests import test_lib as shared_test_lib class EventLogProvidersCollectorTest(shared_test_lib.BaseTestCase): """Tests for the Windows Event Log providers collector.""" def testCollect(self): """Tests the Collect function.""" software_test_path = self._GetTestFilePath(['SOFTWARE']) self._SkipIfPathNotExists(software_test_path) system_test_path = self._GetTestFilePath(['SYSTEM']) self._SkipIfPathNotExists(system_test_path) registry = dfwinreg_registry.WinRegistry() with open(software_test_path, 'rb') as software_file_object: with open(system_test_path, 'rb') as system_file_object: registry_file = dfwinreg_regf.REGFWinRegistryFile( ascii_codepage='cp1252') registry_file.Open(software_file_object) key_path_prefix = registry.GetRegistryFileMapping(registry_file) registry_file.SetKeyPathPrefix(key_path_prefix) registry.MapFile(key_path_prefix, registry_file) registry_file = dfwinreg_regf.REGFWinRegistryFile( ascii_codepage='cp1252') registry_file.Open(system_file_object) key_path_prefix = registry.GetRegistryFileMapping(registry_file) registry_file.SetKeyPathPrefix(key_path_prefix) registry.MapFile(key_path_prefix, registry_file) collector_object = eventlog_providers.EventLogProvidersCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 974) eventlog_provider = test_results[0] self.assertIsNone(eventlog_provider.identifier) self.assertIsNone(eventlog_provider.name) self.assertEqual(eventlog_provider.log_sources, ['.NET Runtime']) self.assertEqual(eventlog_provider.log_types, ['Application']) self.assertEqual(eventlog_provider.category_message_files, set()) self.assertEqual( eventlog_provider.event_message_files, set(['C:\\Windows\\System32\\mscoree.dll'])) self.assertEqual(eventlog_provider.parameter_message_files, set()) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = eventlog_providers.EventLogProvidersCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/filters.py ================================================ #!/usr/bin/env python3 """Tests for the Windows Registry key and value filters.""" import unittest from winregrc import filters from tests import test_lib as shared_test_lib class WindowsRegistryKeyPathFilterTest(shared_test_lib.BaseTestCase): """Tests for the Windows Registry key path filter.""" def testInitialize(self): """Tests the initialize function.""" test_filter = filters.WindowsRegistryKeyPathFilter('test') self.assertIsNotNone(test_filter) # TODO: add test for key_paths. # TODO: add test for Match. class WindowsRegistryKeyPathPrefixFilterTest(shared_test_lib.BaseTestCase): """Tests for the Windows Registry key path prefix filter.""" def testInitialize(self): """Tests the initialize function.""" test_filter = filters.WindowsRegistryKeyPathPrefixFilter('test') self.assertIsNotNone(test_filter) # TODO: add test for Match. class WindowsRegistryKeyPathSuffixFilterTest(shared_test_lib.BaseTestCase): """Tests for the Windows Registry key path suffix filter.""" def testInitialize(self): """Tests the initialize function.""" test_filter = filters.WindowsRegistryKeyPathSuffixFilter('test') self.assertIsNotNone(test_filter) # TODO: add test for Match. class WindowsRegistryKeyWithValuesFilterTest(shared_test_lib.BaseTestCase): """Tests for the Windows Registry key with values filter.""" def testInitialize(self): """Tests the initialize function.""" test_filter = filters.WindowsRegistryKeyWithValuesFilter(['test']) self.assertIsNotNone(test_filter) # TODO: add test for Match. if __name__ == '__main__': unittest.main() ================================================ FILE: tests/hexdump.py ================================================ #!/usr/bin/env python3 """Tests for the hexadecimal representation functions.""" import unittest from winregrc import hexdump from tests import test_lib as shared_test_lib class HexdumpTest(shared_test_lib.BaseTestCase): """Tests for the hexadecimal representation functions.""" def testHexdump(self): """Tests the Collect function.""" hexdump.Hexdump(b'') hexdump.Hexdump(b'\x00\x01\x02\x03\x04\x05\x06') hexdump.Hexdump(b'\x00\x01\x02\x03\x04\x05\x06\x07\x08') hexdump.Hexdump( b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f') hexdump.Hexdump( b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f') if __name__ == '__main__': unittest.main() ================================================ FILE: tests/interface.py ================================================ #!/usr/bin/env python3 """Tests for the Windows Registry key and value collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from winregrc import interface from tests import test_lib as shared_test_lib class WindowsRegistryKeyCollectorTest(shared_test_lib.BaseTestCase): """Tests for the Windows Registry key and value collector.""" # pylint: disable=protected-access def testGetStringValueFromKey(self): """Tests the _GetStringValueFromKey function.""" collector = interface.WindowsRegistryKeyCollector() registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey') value_data = 'ValueData'.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'TestValue', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) value = collector._GetStringValueFromKey( registry_key, 'TestValue', default_value='DefaultValue') self.assertEqual(value, 'ValueData') value = collector._GetStringValueFromKey( None, 'TestValue', default_value='DefaultValue') self.assertEqual(value, 'DefaultValue') value = collector._GetStringValueFromKey( registry_key, 'Bogus', default_value='DefaultValue') self.assertEqual(value, 'DefaultValue') collector = interface.WindowsRegistryKeyCollector() registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey') value_data = b'\x03\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'TestValue', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) registry_key.AddValue(registry_value) value = collector._GetStringValueFromKey( registry_key, 'TestValue', default_value='DefaultValue') self.assertEqual(value, 'DefaultValue') def testGetValueDataFromKey(self): """Tests the _GetValueDataFromKey function.""" collector = interface.WindowsRegistryKeyCollector() registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey') value_data = 'ValueData'.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'TestValue', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) value = collector._GetValueDataFromKey(registry_key, 'TestValue') self.assertEqual(value, value_data) def testGetValueFromKey(self): """Tests the _GetValueFromKey function.""" collector = interface.WindowsRegistryKeyCollector() registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey') value_data = 'ValueData'.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'TestValue', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) value = collector._GetValueFromKey( registry_key, 'TestValue', default_value='DefaultValue') self.assertEqual(value, 'ValueData') value = collector._GetValueFromKey( None, 'TestValue', default_value='DefaultValue') self.assertEqual(value, 'DefaultValue') value = collector._GetValueFromKey( registry_key, 'Bogus', default_value='DefaultValue') self.assertEqual(value, 'DefaultValue') collector = interface.WindowsRegistryKeyCollector() registry_key = dfwinreg_fake.FakeWinRegistryKey('TestKey') value_data = b'\x03\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'TestValue', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) registry_key.AddValue(registry_value) value = collector._GetValueFromKey( registry_key, 'TestValue', default_value='DefaultValue') self.assertEqual(value, 3) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/knownfolders.py ================================================ #!/usr/bin/env python3 """Tests for the Windows known folders collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import knownfolders from tests import test_lib as shared_test_lib class KnownFoldersCollectorTest(shared_test_lib.BaseTestCase): """Tests for the Windows known folders collector.""" _DISPLAY_NAME = 'Downloads' _IDENTIFIER = '374de290-123f-4565-9164-39c4925e467b' _LOCALIZED_DISPLAY_NAME = '@%SystemRoot%\\system32\\shell32.dll,-21798' def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\Software' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('FolderDescriptions') registry_file.AddKeyByPath( '\\Microsoft\\Windows\\CurrentVersion\\Explorer', registry_key) subkey = dfwinreg_fake.FakeWinRegistryKey(self._IDENTIFIER) registry_key.AddSubkey(self._IDENTIFIER, subkey) value_data = self._DISPLAY_NAME.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Name', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) value_data = self._LOCALIZED_DISPLAY_NAME.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'LocalizedName', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() collector_object = knownfolders.KnownFoldersCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 1) known_folder = test_results[0] self.assertIsNotNone(known_folder) self.assertEqual(known_folder.display_name, self._DISPLAY_NAME) self.assertEqual(known_folder.identifier, self._IDENTIFIER) self.assertEqual( known_folder.localized_display_name, self._LOCALIZED_DISPLAY_NAME) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = knownfolders.KnownFoldersCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/mounted_devices.py ================================================ #!/usr/bin/env python3 """Tests for the Windows mounted devices collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import mounted_devices from tests import test_lib as shared_test_lib class MountedDevicesCollectorTest(shared_test_lib.BaseTestCase): """Tests for the Windows mounted devices collector.""" def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\System' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('MountedDevices') registry_file.AddKeyByPath('\\', registry_key) value_data = b'\x78\x56\x34\x12\x00\x10\x00\x00\x00\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( '\\DosDevices\\C:', data=value_data, data_type=dfwinreg_definitions.REG_BINARY) registry_key.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() collector_object = mounted_devices.MountedDevicesCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 1) mounted_device = test_results[0] self.assertIsNotNone(mounted_device) self.assertEqual(mounted_device.identifier, '\\DosDevices\\C:') self.assertEqual(mounted_device.disk_identity, 0x12345678) self.assertEqual(mounted_device.partition_offset, 0x1000) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = mounted_devices.MountedDevicesCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/mru.py ================================================ #!/usr/bin/env python3 """Tests for the Most Recently Used (MRU) collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import mru from tests import test_lib class MostRecentlyUsedCollectorTest(test_lib.BaseTestCase): """Tests for the Most Recently Used (MRU) collector.""" def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_CURRENT_USER' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('RecentDocs') registry_file.AddKeyByPath( '\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer', registry_key) value_data = b'a\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'MRUList', data=value_data, data_type=dfwinreg_definitions.REG_BINARY) registry_key.AddValue(registry_value) value_data = 'MyFile.txt\x00'.encode('utf_16_le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'a', data=value_data, data_type=dfwinreg_definitions.REG_BINARY) registry_key.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = mru.MostRecentlyUsedCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertTrue(result) test_output_writer.Close() self.assertEqual(len(collector_object.mru_entries), 1) mru_entry = collector_object.mru_entries[0] self.assertIsNotNone(mru_entry) self.assertEqual(mru_entry.string, 'MyFile.txt') def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = mru.MostRecentlyUsedCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) test_output_writer.Close() self.assertEqual(len(collector_object.mru_entries), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/msie_zone_info.py ================================================ #!/usr/bin/env python3 """Tests for the Microsoft Internet Explorer (MSIE) zone collector.""" import unittest from dfwinreg import regf as dfwinreg_regf from dfwinreg import registry as dfwinreg_registry from winregrc import msie_zone_info from tests import test_lib as shared_test_lib class MSIEZoneInformationCollectorTest(shared_test_lib.BaseTestCase): """Tests for the Microsoft Internet Explorer (MSIE) zone collector.""" def testCollect(self): """Tests the Collect function.""" test_path = self._GetTestFilePath(['SOFTWARE']) self._SkipIfPathNotExists(test_path) registry = dfwinreg_registry.WinRegistry() with open(test_path, 'rb') as file_object: registry_file = dfwinreg_regf.REGFWinRegistryFile(ascii_codepage='cp1252') registry_file.Open(file_object) key_path_prefix = registry.GetRegistryFileMapping(registry_file) registry_file.SetKeyPathPrefix(key_path_prefix) registry.MapFile(key_path_prefix, registry_file) collector_object = msie_zone_info.MSIEZoneInformationCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 1724) zone_information = test_results[0] self.assertEqual(zone_information.zone, '0') self.assertEqual(zone_information.zone_name, 'Computer') self.assertEqual(zone_information.control, '1809') self.assertEqual(zone_information.control_value, 3) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = msie_zone_info.MSIEZoneInformationCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/output_writer.py ================================================ #!/usr/bin/env python3 """Tests for the output writer.""" import unittest from winregrc import output_writers from tests import test_lib as shared_test_lib class StdoutOutputWriterTest(shared_test_lib.BaseTestCase): """Tests for the stdout output writer.""" # pylint: disable=protected-access def testFormatDataInHexadecimal(self): """Tests the _FormatDataInHexadecimal function.""" test_output_writer = output_writers.StdoutOutputWriter() data = b'\x00\x01\x02\x03\x04\x05\x06' expected_formatted_data = ( '0x00000000 00 01 02 03 04 05 06 ' '.......\n' '\n') formatted_data = test_output_writer._FormatDataInHexadecimal(data) self.assertEqual(formatted_data, expected_formatted_data) data = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09' expected_formatted_data = ( '0x00000000 00 01 02 03 04 05 06 07 08 09 ' '..........\n' '\n') formatted_data = test_output_writer._FormatDataInHexadecimal(data) self.assertEqual(formatted_data, expected_formatted_data) data = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' expected_formatted_data = ( '0x00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ' '................\n' '\n') formatted_data = test_output_writer._FormatDataInHexadecimal(data) self.assertEqual(formatted_data, expected_formatted_data) data = ( b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f') expected_formatted_data = ( '0x00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ' '................\n' '...\n' '0x00000020 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ' '................\n' '\n') formatted_data = test_output_writer._FormatDataInHexadecimal(data) self.assertEqual(formatted_data, expected_formatted_data) def testOpenClose(self): """Tests the Open and Close functions.""" test_output_writer = output_writers.StdoutOutputWriter() result = test_output_writer.Open() self.assertTrue(result) test_output_writer.Close() def testWriteDebugData(self): """Tests the WriteDebugData function.""" test_output_writer = output_writers.StdoutOutputWriter() test_output_writer.WriteDebugData('Description', b'DATA') def testWriteValue(self): """Tests the WriteValue function.""" test_output_writer = output_writers.StdoutOutputWriter() test_output_writer.WriteValue('Description', 'Value') def testWriteText(self): """Tests the WriteText function.""" test_output_writer = output_writers.StdoutOutputWriter() test_output_writer.WriteText('Test') if __name__ == '__main__': unittest.main() ================================================ FILE: tests/profiles.py ================================================ #!/usr/bin/env python3 """Tests for the user profiles collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import profiles from tests import test_lib as shared_test_lib class UserProfilesCollectorTest(shared_test_lib.BaseTestCase): """Tests for the Windows user profiles collector.""" _SID = 'S-1-5-18' _PROFILE_PATH = '%systemroot%\\system32\\config\\systemprofile' def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\Software' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('ProfileList') registry_file.AddKeyByPath( '\\Microsoft\\Windows NT\\CurrentVersion', registry_key) subkey = dfwinreg_fake.FakeWinRegistryKey(self._SID) registry_key.AddSubkey(self._SID, subkey) value_data = self._PROFILE_PATH.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'ProfileImagePath', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() collector_object = profiles.UserProfilesCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 1) user_profile = test_results[0] self.assertIsNotNone(user_profile) self.assertEqual(user_profile.security_identifier, self._SID) self.assertEqual(user_profile.profile_path, self._PROFILE_PATH) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = profiles.UserProfilesCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/programscache.py ================================================ #!/usr/bin/env python3 """Tests for the Programs Cache information collector.""" import unittest from dfwinreg import regf as dfwinreg_regf from dfwinreg import registry as dfwinreg_registry from winregrc import errors from winregrc import output_writers from winregrc import programscache from tests import test_lib class TestOutputWriter(output_writers.StdoutOutputWriter): """Output writer for testing. Attributes: text (list[str]): text. """ def __init__(self): """Initializes an output writer object.""" super().__init__() self.text = [] def WriteText(self, text): """Writes text to stdout. Args: text (str): text to write. """ self.text.append(text) class ProgramsCacheDataParserTest(test_lib.BaseTestCase): """Tests for the Programs Cache data parser.""" def testParse(self): """Tests the Parse function.""" data_parser = programscache.ProgramsCacheDataParser() with self.assertRaises(errors.ParseError): data_parser.Parse(b'') class ProgramsCacheCollectorTest(test_lib.BaseTestCase): """Tests for the Programs Cache information collector.""" def testCollect(self): """Tests the Collect function.""" test_path = self._GetTestFilePath(['NTUSER.DAT']) self._SkipIfPathNotExists(test_path) registry = dfwinreg_registry.WinRegistry() with open(test_path, 'rb') as file_object: registry_file = dfwinreg_regf.REGFWinRegistryFile(ascii_codepage='cp1252') registry_file.Open(file_object) key_path_prefix = registry.GetRegistryFileMapping(registry_file) registry_file.SetKeyPathPrefix(key_path_prefix) registry.MapFile(key_path_prefix, registry_file) test_output_writer = test_lib.TestOutputWriter() collector_object = programscache.ProgramsCacheCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertTrue(result) test_output_writer.Close() # TODO: test program cache values. def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = programscache.ProgramsCacheCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) test_output_writer.Close() if __name__ == '__main__': unittest.main() ================================================ FILE: tests/sam.py ================================================ #!/usr/bin/env python3 """Tests for the Security Account Manager (SAM) collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import errors from winregrc import sam from tests import test_lib _F_VALUE_DATA = bytes(bytearray([ 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xd2, 0x12, 0xa1, 0xfc, 0x88, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8f, 0x64, 0xcc, 0xfd, 0x88, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x52, 0x35, 0x00])) _V_VALUE_DATA = bytes(bytearray([ 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x14, 0x80, 0x9c, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x14, 0x00, 0x44, 0x00, 0x05, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x14, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x58, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x5b, 0x03, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xff, 0x07, 0x0f, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x44, 0x00, 0x02, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0x9b, 0x7d, 0xee, 0x68, 0xf4, 0xd1, 0xe6, 0x5e, 0xe5, 0xbd, 0xa3, 0x09, 0xf4, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x18, 0x00, 0x42, 0x00, 0x75, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x2d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x61, 0x00, 0x63, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x61, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2f, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0xd8, 0x31, 0x5b, 0x1f, 0x33, 0x69, 0x27, 0x07, 0x1f, 0xda, 0xf2, 0x03, 0xec, 0x2c, 0xf6, 0x84, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00])) class SecurityAccountManagerDataParserTest(test_lib.BaseTestCase): """Tests for the Security Account Manager (SAM) data parser.""" def testParseFValue(self): """Tests the ParseFValue function.""" user_account = sam.UserAccount() data_parser = sam.SecurityAccountManagerDataParser() data_parser.ParseFValue(_F_VALUE_DATA, user_account) self.assertEqual(user_account.last_login_time, 129347632925692440) self.assertEqual(user_account.last_password_set_time, 129347637947436870) self.assertEqual(user_account.account_expiration_time, 0) self.assertEqual(user_account.last_password_failure_time, 0) self.assertEqual(user_account.rid, 500) self.assertEqual(user_account.primary_gid, 513) self.assertEqual(user_account.user_account_control_flags, 0x211) self.assertEqual(user_account.codepage, 0) self.assertEqual(user_account.number_of_password_failures, 0) self.assertEqual(user_account.number_of_logons, 6) with self.assertRaises(errors.ParseError): data_parser.ParseFValue(b'', user_account) # TODO: add bogus data tests. def testParseVValue(self): """Tests the ParseVValue function.""" user_account = sam.UserAccount() data_parser = sam.SecurityAccountManagerDataParser() data_parser.ParseVValue(_V_VALUE_DATA, user_account) self.assertEqual(user_account.username, 'Administrator') # TODO: tests other values set by ParseVValue. with self.assertRaises(errors.ParseError): data_parser.ParseVValue(b'', user_account) # TODO: add bogus data tests. # TODO: add more tests. class SecurityAccountManagerCollectorTest(test_lib.BaseTestCase): """Tests for the Security Account Manager (SAM) collector.""" _RID = '000001F4' def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\SAM' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('Users') registry_file.AddKeyByPath('\\SAM\\Domains\\Account', registry_key) subkey = dfwinreg_fake.FakeWinRegistryKey(self._RID) registry_key.AddSubkey(self._RID, subkey) registry_value = dfwinreg_fake.FakeWinRegistryValue( 'F', data=_F_VALUE_DATA, data_type=dfwinreg_definitions.REG_BINARY) subkey.AddValue(registry_value) registry_value = dfwinreg_fake.FakeWinRegistryValue( 'V', data=_V_VALUE_DATA, data_type=dfwinreg_definitions.REG_BINARY) subkey.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = sam.SecurityAccountManagerCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertTrue(result) test_output_writer.Close() self.assertEqual(len(collector_object.user_accounts), 1) user_account = collector_object.user_accounts[0] self.assertIsNotNone(user_account) self.assertEqual(user_account.username, 'Administrator') def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = sam.SecurityAccountManagerCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) test_output_writer.Close() self.assertEqual(len(collector_object.user_accounts), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/services.py ================================================ #!/usr/bin/env python3 """Tests for the services collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import services from tests import test_lib as shared_test_lib class WindowsServicesCollectorTest(shared_test_lib.BaseTestCase): """Tests for the services collector.""" _DESCRIPTION = '@%SystemRoot%\\System32\\wwansvc.dll,-258' _DISPLAY_NAME = '@%SystemRoot%\\System32\\wwansvc.dll,-257' _IMAGE_PATH = '%SystemRoot%\\system32\\svchost.exe -k LocalServiceNoNetwork' _OBJECT_NAME = 'NT Authority\\LocalService' def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\System' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('Services') registry_file.AddKeyByPath('\\CurrentControlSet', registry_key) subkey = dfwinreg_fake.FakeWinRegistryKey('WwanSvc') registry_key.AddSubkey('WwanSvc', subkey) value_data = self._DESCRIPTION.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Description', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) value_data = self._DISPLAY_NAME.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'DisplayName', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) value_data = self._IMAGE_PATH.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'ImagePath', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) value_data = self._OBJECT_NAME.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'ObjectName', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) value_data = b'\x03\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Start', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) subkey.AddValue(registry_value) value_data = b'\x20\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Type', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) subkey.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() collector_object = services.WindowsServicesCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 1) windows_service = test_results[0] self.assertIsNotNone(windows_service) self.assertEqual(windows_service.description, self._DESCRIPTION) self.assertEqual(windows_service.display_name, self._DISPLAY_NAME) self.assertEqual(windows_service.image_path, self._IMAGE_PATH) self.assertEqual(windows_service.name, 'WwanSvc') self.assertEqual(windows_service.object_name, self._OBJECT_NAME) self.assertEqual(windows_service.service_type, 32) self.assertEqual(windows_service.start_value, 3) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = services.WindowsServicesCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) # TODO: add tests for Compare method if __name__ == '__main__': unittest.main() ================================================ FILE: tests/shellfolders.py ================================================ #!/usr/bin/env python3 """Tests for the Windows shell folders collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import shellfolders from tests import test_lib as shared_test_lib class ShellFoldersCollectorTest(shared_test_lib.BaseTestCase): """Tests for the Windows shell folders collector.""" _GUID1 = '{2227a280-3aea-1069-a2de-08002b30309d}' _GUID2 = '{e7de9b1a-7533-4556-9484-b26fb486475e}' _LOCALIZED_STRING1 = '@%SystemRoot%\\system32\\prnfldr.dll,-8036' _NAME1 = 'Printers' def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\Software' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('CLSID') registry_file.AddKeyByPath('\\Classes', registry_key) subkey = dfwinreg_fake.FakeWinRegistryKey(self._GUID1) registry_key.AddSubkey(self._GUID1, subkey) shell_folder_key = dfwinreg_fake.FakeWinRegistryKey('ShellFolder') subkey.AddSubkey('ShellFolder', shell_folder_key) value_data = self._NAME1.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( '', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) value_data = self._LOCALIZED_STRING1.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'LocalizedString', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) subkey = dfwinreg_fake.FakeWinRegistryKey(self._GUID2) registry_key.AddSubkey(self._GUID2, subkey) shell_folder_key = dfwinreg_fake.FakeWinRegistryKey('ShellFolder') subkey.AddSubkey('ShellFolder', shell_folder_key) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() collector_object = shellfolders.ShellFoldersCollector() test_results = sorted( collector_object.Collect(registry), key=lambda folder: folder.identifier) self.assertEqual(len(test_results), 2) shell_folder = test_results[0] self.assertIsNotNone(shell_folder) self.assertEqual(shell_folder.identifier, self._GUID1) self.assertEqual(shell_folder.name, self._NAME1) self.assertEqual(shell_folder.localized_string, self._LOCALIZED_STRING1) shell_folder = test_results[1] self.assertIsNotNone(shell_folder) self.assertEqual(shell_folder.identifier, self._GUID2) self.assertIsNone(shell_folder.name) self.assertIsNone(shell_folder.localized_string) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() collector_object = shellfolders.ShellFoldersCollector() test_results = list(collector_object.Collect(registry)) self.assertEqual(len(test_results), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/sysinfo.py ================================================ #!/usr/bin/env python3 """Tests for the system information collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import sysinfo from tests import test_lib class SystemInfoCollectorTest(test_lib.BaseTestCase): """Tests for the system information collector.""" # pylint: disable=protected-access _CSD_VERSION = 'Service Pack 1' _CURRENT_BUILD_NUMBER = '7601' _CURRENT_TYPE = 'Multiprocessor Free' _CURRENT_VERSION = '6.1' _INSTALLATION_DATE = 1289406535 _PATH_NAME = 'C:\\Windows' _PRODUCT_IDENTIFIER = '00426-067-1817155-86250' _PRODUCT_NAME = 'Windows 7 Ultimate' _REGISTERED_ORGANIZATION = '' _REGISTERED_OWNER = 'Windows User' _SYSTEM_ROOT = 'C:\\Windows' def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\Software' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('CurrentVersion') registry_file.AddKeyByPath('\\Microsoft\\Windows NT', registry_key) value_data = self._CSD_VERSION.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'CSDVersion', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) value_data = self._CURRENT_BUILD_NUMBER.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'CurrentBuildNumber', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) value_data = self._CURRENT_TYPE.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'CurrentType', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) value_data = self._CURRENT_VERSION.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'CurrentVersion', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) value_data = b'\x47\xc8\xda\x4c' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'InstallDate', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) registry_key.AddValue(registry_value) value_data = self._PRODUCT_IDENTIFIER.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'ProductId', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) value_data = self._PRODUCT_NAME.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'ProductName', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) # TODO: add more values. registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testParseInstallDate(self): """Tests the _ParseInstallDate function.""" collector_object = sysinfo.SystemInfoCollector() date_time = collector_object._ParseInstallDate(None) self.assertIsNone(date_time) value_data = b'\x47\xc8\xda\x4c' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'InstallDate', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) date_time = collector_object._ParseInstallDate(registry_value) self.assertIsNotNone(date_time) value_data = b'\x00\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'InstallDate', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) date_time = collector_object._ParseInstallDate(registry_value) self.assertIsNotNone(date_time) def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = sysinfo.SystemInfoCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertTrue(result) test_output_writer.Close() self.assertIsNotNone(collector_object.system_information) self.assertEqual( collector_object.system_information.csd_version, self._CSD_VERSION) self.assertEqual( collector_object.system_information.current_build_number, self._CURRENT_BUILD_NUMBER) self.assertEqual( collector_object.system_information.current_type, self._CURRENT_TYPE) self.assertEqual( collector_object.system_information.current_version, self._CURRENT_VERSION) self.assertIsNotNone(collector_object.system_information.installation_date) self.assertEqual( collector_object.system_information.product_identifier, self._PRODUCT_IDENTIFIER) self.assertEqual( collector_object.system_information.product_name, self._PRODUCT_NAME) # TODO: add more values. def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = sysinfo.SystemInfoCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) test_output_writer.Close() self.assertIsNone(collector_object.system_information) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/task_cache.py ================================================ #!/usr/bin/env python3 """Tests for the Task Cache information collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import task_cache from tests import test_lib _DYNAMIC_INFO_DATA = bytes(bytearray([ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x7d, 0x12, 0x3f, 0x04, 0xca, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])) _DYNAMIC_INFO2_DATA = bytes(bytearray([ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x7d, 0x12, 0x3f, 0x04, 0xca, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x7d, 0x12, 0x3f, 0x04, 0xca, 0x01])) class TaskCacheDataParserTest(test_lib.BaseTestCase): """Tests for the Task Cache data parser.""" def testParseDynamicInfo(self): """Tests the ParseDynamicInfo function.""" data_parser = task_cache.TaskCacheDataParser() cached_task = task_cache.CachedTask() data_parser.ParseDynamicInfo(_DYNAMIC_INFO_DATA, cached_task) # TODO: compare date time value. self.assertIsNotNone(cached_task.last_registered_time) # TODO: compare date time value. self.assertIsNotNone(cached_task.launch_time) cached_task = task_cache.CachedTask() data_parser.ParseDynamicInfo(_DYNAMIC_INFO2_DATA, cached_task) # TODO: compare date time value. self.assertIsNotNone(cached_task.last_registered_time) # TODO: compare date time value. self.assertIsNotNone(cached_task.launch_time) class TaskCacheCollectorTest(test_lib.BaseTestCase): """Tests for the Task Cache information collector.""" _GUID1 = '{8905ECD8-016F-4DC2-90E6-A5F1FA6A841A}' _GUID2 = '{F93C7104-998A-4A38-B935-775A3138B3C3}' _GUID3 = '{FE7B674F-2430-40A1-9162-AFC3727E3DC3}' _NAME1 = 'AD RMS Rights Policy Template Management (Automated)' _NAME2 = 'Notifications' _NAME3 = 'AutoWake' _PATH = ( '\\Microsoft\\Windows\\Active Directory Rights Management Services ' 'Client\\AD RMS Rights Policy Template Management (Automated)') def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\Software' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._GUID1) registry_file.AddKeyByPath( '\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tasks', registry_key) registry_value = dfwinreg_fake.FakeWinRegistryValue( 'DynamicInfo', data=_DYNAMIC_INFO_DATA, data_type=dfwinreg_definitions.REG_BINARY) registry_key.AddValue(registry_value) value_data = self._PATH.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Path', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._NAME1) registry_file.AddKeyByPath(( '\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tree\\' 'Microsoft\\Windows\\Active Directory Rights Management Services ' 'Client'), registry_key) value_data = '{8905ECD8-016F-4DC2-90E6-A5F1FA6A841A}\x00'.encode( 'utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Id', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._GUID2) registry_file.AddKeyByPath( '\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tasks', registry_key) registry_value = dfwinreg_fake.FakeWinRegistryValue( 'DynamicInfo', data=_DYNAMIC_INFO2_DATA, data_type=dfwinreg_definitions.REG_BINARY) registry_key.AddValue(registry_value) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._NAME2) registry_file.AddKeyByPath(( '\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tree\\' 'Microsoft\\Windows\\Location'), registry_key) value_data = '{F93C7104-998A-4A38-B935-775A3138B3C3}\x00'.encode( 'utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Id', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._GUID3) registry_file.AddKeyByPath( '\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tasks', registry_key) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._NAME3) registry_file.AddKeyByPath(( '\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\Tree\\' 'Microsoft\\Windows\\SideShow'), registry_key) value_data = '{FE7B674F-2430-40A1-9162-AFC3727E3DC3}\x00'.encode( 'utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Id', data=value_data, data_type=dfwinreg_definitions.REG_SZ) registry_key.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def _CreateTestRegistryEmpty(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\Software' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey('Tasks') registry_file.AddKeyByPath( '\\Microsoft\\Windows NT\\CurrentVersion\\Schedule\\TaskCache', registry_key) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = task_cache.TaskCacheCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertTrue(result) test_output_writer.Close() self.assertEqual(len(collector_object.cached_tasks), 2) cached_tasks = sorted( collector_object.cached_tasks, key=lambda task: task.identifier) cached_task = cached_tasks[0] self.assertIsNotNone(cached_task) self.assertEqual(cached_task.identifier, self._GUID1) # TODO: fix test # self.assertEqual(cached_task.name, self._NAME1) cached_task = cached_tasks[1] self.assertIsNotNone(cached_task) self.assertEqual(cached_task.identifier, self._GUID2) # TODO: fix test # self.assertEqual(cached_task.name, self._NAME2) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = task_cache.TaskCacheCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) test_output_writer.Close() self.assertEqual(len(collector_object.cached_tasks), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/test_lib.py ================================================ """Shared test case.""" import os import unittest from winregrc import output_writers class BaseTestCase(unittest.TestCase): """The base test case.""" _TEST_DATA_PATH = os.path.join(os.getcwd(), 'test_data') # Show full diff results, part of TestCase so does not follow our naming # conventions. maxDiff = None def _GetTestFilePath(self, path_segments): """Retrieves the path of a test file in the test data directory. Args: path_segments (list[str]): path segments inside the test data directory. Returns: str: path of the test file. """ # Note that we need to pass the individual path segments to os.path.join # and not a list. return os.path.join(self._TEST_DATA_PATH, *path_segments) def _SkipIfPathNotExists(self, path): """Skips the test if the path does not exist. Args: path (str): path of a test file. Raises: SkipTest: if the path does not exist and the test should be skipped. """ if not os.path.exists(path): filename = os.path.basename(path) raise unittest.SkipTest(f'missing test file: {filename:s}') class TestOutputWriter(output_writers.StdoutOutputWriter): """Test output writer. Attributes: output (list[str]): output written. """ def __init__(self): """Initializes a test output writer.""""" super().__init__() self.output = [] def Close(self): """Closes the output writer object.""" return def Open(self): """Opens the output writer object.""" return def WriteText(self, text): """Writes text to the output. Args: text (str): text to write. """ self.output.append(text) ================================================ FILE: tests/type_libraries.py ================================================ #!/usr/bin/env python3 """Tests for the type libraries collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import type_libraries from tests import test_lib class TypeLibraryTest(test_lib.BaseTestCase): """Tests for the type library.""" _DESCRIPTION = 'Microsoft Office List 14.0' _FILENAME = 'C:\\PROGRA~1\\MICROS~2\\Office14\\STSLIST.DLL' _IDENTIFIER = '{edcd5812-6a06-43c3-afac-46ef5d14e22c}' _VERSION = '3.0' def testInitialize(self): """Tests the initialize function.""" type_library = type_libraries.TypeLibrary( self._IDENTIFIER, self._VERSION, self._DESCRIPTION, self._FILENAME) self.assertIsNotNone(type_library) class TypeLibraryCollectorTest(test_lib.BaseTestCase): """Tests for the type libraries collector.""" _DESCRIPTION1 = 'Microsoft Office List 14.0' _FILENAME1 = 'C:\\PROGRA~1\\MICROS~2\\Office14\\STSLIST.DLL' _IDENTIFIER1 = '{edcd5812-6a06-43c3-afac-46ef5d14e22c}' _VERSION1 = '3.0' _DESCRIPTION2 = 'IAS SDO Helper 1.0 Type Library' _FILENAME2 = '%SystemRoot%\\system32\\sdohlp.dll\\1' _IDENTIFIER2 = '{e9970f91-b6aa-11d9-b032-000d56c25c27}' _VERSION2 = '1.0' def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_LOCAL_MACHINE\\Software' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._IDENTIFIER1) registry_file.AddKeyByPath('\\Classes\\TypeLib', registry_key) subkey = dfwinreg_fake.FakeWinRegistryKey(self._VERSION1) registry_key.AddSubkey(self._VERSION1, subkey) value_data = self._DESCRIPTION1.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( '', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) language_key = dfwinreg_fake.FakeWinRegistryKey('409') subkey.AddSubkey('409', language_key) platform_key = dfwinreg_fake.FakeWinRegistryKey('Win32') language_key.AddSubkey('Win32', platform_key) value_data = self._FILENAME1.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( '', data=value_data, data_type=dfwinreg_definitions.REG_SZ) platform_key.AddValue(registry_value) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._IDENTIFIER2) registry_file.AddKeyByPath('\\Classes\\TypeLib', registry_key) subkey = dfwinreg_fake.FakeWinRegistryKey(self._VERSION2) registry_key.AddSubkey(self._VERSION2, subkey) value_data = self._DESCRIPTION1.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( '', data=value_data, data_type=dfwinreg_definitions.REG_SZ) subkey.AddValue(registry_value) language_key = dfwinreg_fake.FakeWinRegistryKey('0') subkey.AddSubkey('0', language_key) platform_key = dfwinreg_fake.FakeWinRegistryKey('x64') language_key.AddSubkey('x64', platform_key) value_data = self._FILENAME1.encode('utf-16-le') registry_value = dfwinreg_fake.FakeWinRegistryValue( '', data=value_data, data_type=dfwinreg_definitions.REG_SZ) platform_key.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = type_libraries.TypeLibrariesCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertTrue(result) self.assertEqual(len(collector_object.type_libraries), 2) type_library = collector_object.type_libraries[0] self.assertIsNotNone(type_library) self.assertEqual(type_library.description, self._DESCRIPTION1) self.assertEqual(type_library.identifier, self._IDENTIFIER1) self.assertEqual(type_library.typelib_filename, self._FILENAME1) self.assertEqual(type_library.version, self._VERSION1) def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = type_libraries.TypeLibrariesCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) self.assertEqual(len(collector_object.type_libraries), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tests/userassist.py ================================================ #!/usr/bin/env python3 """Tests for the Windows User Assist collector.""" import unittest from dfwinreg import definitions as dfwinreg_definitions from dfwinreg import fake as dfwinreg_fake from dfwinreg import registry as dfwinreg_registry from winregrc import userassist from tests import test_lib _ENTRY_DATA_V3 = bytes(bytearray([ 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0xe3, 0x6e, 0x4b, 0x17, 0x15, 0xca, 0x01])) _ENTRY_DATA_V5 = bytes(bytearray([ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x30, 0x05, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0xff, 0xff, 0xff, 0xff, 0x04, 0xa8, 0x92, 0xd2, 0xab, 0x80, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00])) class UserAssistDataParserTest(test_lib.BaseTestCase): """Tests for the User Assist data parser.""" def testParseEntry(self): """Tests the ParseEntry function.""" data_parser = userassist.UserAssistDataParser() data_parser.ParseEntry(3, _ENTRY_DATA_V3) data_parser.ParseEntry(5, _ENTRY_DATA_V5) class UserAssistCollectorTest(test_lib.BaseTestCase): """Tests for the Windows User Assist collector.""" _GUID = '{5E6AB780-7743-11CF-A12B-00AA004AE837}' _UEME_CTLSESSION_VALUE_DATA = bytes(bytearray([ 0xb0, 0xa8, 0x50, 0x0e, 0x01, 0x00, 0x00, 0x00])) _ENTRY_VALUE_DATA = bytes(bytearray([ 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x54, 0x4b, 0xf6, 0xd3, 0x15, 0x15, 0xca, 0x01])) def _CreateTestRegistry(self): """Creates Registry keys and values for testing. Returns: dfwinreg.WinRegistry: Windows Registry for testing. """ key_path_prefix = 'HKEY_CURRENT_USER' registry_file = dfwinreg_fake.FakeWinRegistryFile( key_path_prefix=key_path_prefix) registry_key = dfwinreg_fake.FakeWinRegistryKey(self._GUID) registry_file.AddKeyByPath( '\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\UserAssist', registry_key) value_data = b'\x03\x00\x00\x00' registry_value = dfwinreg_fake.FakeWinRegistryValue( 'Version', data=value_data, data_type=dfwinreg_definitions.REG_DWORD) registry_key.AddValue(registry_value) subkey = dfwinreg_fake.FakeWinRegistryKey('Count') registry_key.AddSubkey('Count', subkey) registry_value = dfwinreg_fake.FakeWinRegistryValue( 'HRZR_PGYFRFFVBA', data=self._UEME_CTLSESSION_VALUE_DATA, data_type=dfwinreg_definitions.REG_BINARY) subkey.AddValue(registry_value) registry_value = dfwinreg_fake.FakeWinRegistryValue( 'HRZR_EHACVQY:%pfvqy2%\\Jvaqbjf Zrffratre.yax', data=self._ENTRY_VALUE_DATA, data_type=dfwinreg_definitions.REG_BINARY) subkey.AddValue(registry_value) registry_file.Open(None) registry = dfwinreg_registry.WinRegistry() registry.MapFile(key_path_prefix, registry_file) return registry def testCollect(self): """Tests the Collect function.""" registry = self._CreateTestRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = userassist.UserAssistCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertTrue(result) test_output_writer.Close() self.assertEqual(len(collector_object.user_assist_entries), 1) # TODO: test user assist entry values. def testCollectEmpty(self): """Tests the Collect function on an empty Registry.""" registry = dfwinreg_registry.WinRegistry() test_output_writer = test_lib.TestOutputWriter() collector_object = userassist.UserAssistCollector( output_writer=test_output_writer) result = collector_object.Collect(registry) self.assertFalse(result) test_output_writer.Close() self.assertEqual(len(collector_object.user_assist_entries), 0) if __name__ == '__main__': unittest.main() ================================================ FILE: tox.ini ================================================ [tox] envlist = py3{10,11,12,13,14},coverage,docs,lint,wheel [testenv] allowlist_externals = ./run_tests.py pip_pre = True passenv = CFLAGS CPPFLAGS LDFLAGS setenv = PYTHONPATH = {toxinidir} deps = coverage: coverage wheel: build setuptools >= 65 wheel commands = py3{10,11,12,13,14}: ./run_tests.py coverage: coverage erase coverage: coverage run --source=winregrc --omit="*_test*,*__init__*,*test_lib*" run_tests.py coverage: coverage xml wheel: python -m build --no-isolation --wheel [testenv:docs] usedevelop = True deps = -rdocs/requirements.txt commands = sphinx-build -b html -d build/doctrees docs dist/docs sphinx-build -b linkcheck docs dist/docs [testenv:lint] skipsdist = True pip_pre = True passenv = CFLAGS CPPFLAGS LDFLAGS setenv = PYTHONPATH = {toxinidir} deps = pylint >= 3.3.0, < 3.4.0 setuptools >= 65 yamllint >= 1.26.0 commands = pylint --version yamllint -v pylint --rcfile=.pylintrc tests winregrc yamllint -c .yamllint.yaml winregrc ================================================ FILE: utils/__init__.py ================================================ """Data formats.""" __version__ = '20170423' ================================================ FILE: utils/check_dependencies.py ================================================ #!/usr/bin/env python3 """Script to check for the availability and version of dependencies.""" import sys # Change PYTHONPATH to include dependencies. sys.path.insert(0, '.') import utils.dependencies # pylint: disable=wrong-import-position if __name__ == '__main__': dependency_helper = utils.dependencies.DependencyHelper() if not dependency_helper.CheckDependencies(): sys.exit(1) ================================================ FILE: utils/dependencies.py ================================================ """Helper to check for availability and version of dependencies.""" import configparser import os import re class DependencyDefinition: """Dependency definition. Attributes: dpkg_name (str): name of the dpkg package that provides the dependency. is_optional (bool): True if the dependency is optional. l2tbinaries_name (str): name of the l2tbinaries package that provides the dependency. maximum_version (str): maximum supported version, a greater or equal version is not supported. minimum_version (str): minimum supported version, a lesser version is not supported. name (str): name of (the Python module that provides) the dependency. pypi_name (str): name of the PyPI package that provides the dependency. python2_only (bool): True if the dependency is only supported by Python 2. python3_only (bool): True if the dependency is only supported by Python 3. rpm_name (str): name of the rpm package that provides the dependency. skip_check (bool): True if the dependency should be skipped by the CheckDependencies or CheckTestDependencies methods of DependencyHelper. skip_requires (bool): True if the dependency should be excluded from pyproject.toml dependencies. version_property (str): name of the version attribute or function. """ def __init__(self, name): """Initializes a dependency configuration. Args: name (str): name of the dependency. """ super().__init__() self.dpkg_name = None self.is_optional = False self.l2tbinaries_name = None self.maximum_version = None self.minimum_version = None self.name = name self.pypi_name = None self.python2_only = False self.python3_only = False self.rpm_name = None self.skip_check = None self.skip_requires = None self.version_property = None class DependencyDefinitionReader: """Dependency definition reader.""" _VALUE_NAMES = frozenset([ 'dpkg_name', 'is_optional', 'l2tbinaries_name', 'maximum_version', 'minimum_version', 'pypi_name', 'python2_only', 'python3_only', 'rpm_name', 'skip_check', 'skip_requires', 'version_property']) def _GetConfigValue(self, config_parser, section_name, value_name): """Retrieves a value from the config parser. Args: config_parser (ConfigParser): configuration parser. section_name (str): name of the section that contains the value. value_name (str): name of the value. Returns: object: configuration value or None if the value does not exists. """ try: return config_parser.get(section_name, value_name) except configparser.NoOptionError: return None def Read(self, file_object): """Reads dependency definitions. Args: file_object (file): file-like object to read from. Yields: DependencyDefinition: dependency definition. """ config_parser = configparser.ConfigParser(interpolation=None) config_parser.read_file(file_object) for section_name in config_parser.sections(): dependency_definition = DependencyDefinition(section_name) for value_name in self._VALUE_NAMES: value = self._GetConfigValue(config_parser, section_name, value_name) setattr(dependency_definition, value_name, value) yield dependency_definition class DependencyHelper: """Dependency helper. Attributes: dependencies (dict[str, DependencyDefinition]): dependencies. """ _VERSION_NUMBERS_REGEX = re.compile(r'[0-9.]+') _VERSION_SPLIT_REGEX = re.compile(r'\.|\-') def __init__( self, dependencies_file='dependencies.ini', test_dependencies_file='test_dependencies.ini'): """Initializes a dependency helper. Args: dependencies_file (Optional[str]): path to the dependencies configuration file. test_dependencies_file (Optional[str]): path to the test dependencies configuration file. """ super().__init__() self._test_dependencies = {} self.dependencies = {} dependency_reader = DependencyDefinitionReader() with open(dependencies_file, 'r', encoding='utf-8') as file_object: for dependency in dependency_reader.Read(file_object): self.dependencies[dependency.name] = dependency if os.path.exists(test_dependencies_file): with open(test_dependencies_file, 'r', encoding='utf-8') as file_object: for dependency in dependency_reader.Read(file_object): self._test_dependencies[dependency.name] = dependency def _CheckPythonModule(self, dependency): """Checks the availability of a Python module. Args: dependency (DependencyDefinition): dependency definition. Returns: tuple: containing: bool: True if the Python module is available and conforms to the minimum required version, False otherwise. str: status message. """ module_object = self._ImportPythonModule(dependency.name) if not module_object: return False, f'missing: {dependency.name:s}' if not dependency.version_property: return True, dependency.name return self._CheckPythonModuleVersion( dependency.name, module_object, dependency.version_property, dependency.minimum_version, dependency.maximum_version) def _CheckPythonModuleVersion( self, module_name, module_object, version_property, minimum_version, maximum_version): """Checks the version of a Python module. Args: module_object (module): Python module. module_name (str): name of the Python module. version_property (str): version attribute or function. minimum_version (str): minimum version. maximum_version (str): maximum version. Returns: tuple: containing: bool: True if the Python module is available and conforms to the minimum required version, False otherwise. str: status message. """ module_version = None if not version_property.endswith('()'): module_version = getattr(module_object, version_property, None) else: version_method = getattr( module_object, version_property[:-2], None) if version_method: module_version = version_method() if not module_version: return False, ( f'unable to determine version information for: {module_name:s}') # Make sure the module version is a string. module_version = f'{module_version!s}' # Split the version string and convert every digit into an integer. # A string compare of both version strings will yield an incorrect result. # Strip any semantic suffixes such as a1, b1, pre, post, rc, dev. module_version = self._VERSION_NUMBERS_REGEX.findall(module_version)[0] if module_version[-1] == '.': module_version = module_version[:-1] try: module_version_map = list( map(int, self._VERSION_SPLIT_REGEX.split(module_version))) except ValueError: return False, ( f'unable to parse module version: {module_name:s} {module_version:s}') if minimum_version: try: minimum_version_map = list( map(int, self._VERSION_SPLIT_REGEX.split(minimum_version))) except ValueError: return False, ( f'unable to parse minimum version: {module_name:s} ' f'{minimum_version:s}') if module_version_map < minimum_version_map: return False, ( f'{module_name:s} version: {module_version!s} is too old, ' f'{minimum_version!s} or later required') if maximum_version: try: maximum_version_map = list( map(int, self._VERSION_SPLIT_REGEX.split(maximum_version))) except ValueError: return False, ( f'unable to parse maximum version: {module_name:s} ' f'{maximum_version:s}') if module_version_map > maximum_version_map: return False, ( f'{module_name:s} version: {module_version!s} is too recent, ' f'{maximum_version!s} or earlier required') return True, f'{module_name:s} version: {module_version!s}' def _ImportPythonModule(self, module_name): """Imports a Python module. Args: module_name (str): name of the module. Returns: module: Python module or None if the module cannot be imported. """ try: module_object = list(map(__import__, [module_name]))[0] except ImportError: return None # If the module name contains dots get the upper most module object. if '.' in module_name: for submodule_name in module_name.split('.')[1:]: module_object = getattr(module_object, submodule_name, None) return module_object def _PrintCheckDependencyStatus( self, dependency, result, status_message, verbose_output=True): """Prints the check dependency status. Args: dependency (DependencyDefinition): dependency definition. result (bool): True if the Python module is available and conforms to the minimum required version, False otherwise. status_message (str): status message. verbose_output (Optional[bool]): True if output should be verbose. """ if not result or dependency.is_optional: if dependency.is_optional: status_indicator = '[OPTIONAL]' else: status_indicator = '[FAILURE]' print(f'{status_indicator:s}\t{status_message:s}') elif verbose_output: print(f'[OK]\t\t{status_message:s}') def CheckDependencies(self, verbose_output=True): """Checks the availability of the dependencies. Args: verbose_output (Optional[bool]): True if output should be verbose. Returns: bool: True if the dependencies are available, False otherwise. """ print('Checking availability and versions of dependencies.') check_result = True for _, dependency in sorted(self.dependencies.items()): if dependency.skip_check: continue result, status_message = self._CheckPythonModule(dependency) if not result and not dependency.is_optional: check_result = False self._PrintCheckDependencyStatus( dependency, result, status_message, verbose_output=verbose_output) if check_result and not verbose_output: print('[OK]') print('') return check_result def CheckTestDependencies(self, verbose_output=True): """Checks the availability of the dependencies when running tests. Args: verbose_output (Optional[bool]): True if output should be verbose. Returns: bool: True if the dependencies are available, False otherwise. """ if not self.CheckDependencies(verbose_output=verbose_output): return False print('Checking availability and versions of test dependencies.') check_result = True for dependency in sorted( self._test_dependencies.values(), key=lambda dependency: dependency.name): if dependency.skip_check: continue result, status_message = self._CheckPythonModule(dependency) if not result and not dependency.is_optional: check_result = False self._PrintCheckDependencyStatus( dependency, result, status_message, verbose_output=verbose_output) if check_result and not verbose_output: print('[OK]') print('') return check_result ================================================ FILE: utils/update_release.sh ================================================ #!/bin/bash # # Script that makes changes in preparation of a new release, such as updating # the version and documentation. EXIT_FAILURE=1; EXIT_SUCCESS=0; VERSION=$(date -u +"%Y%m%d") # Update the Python module version. sed "s/__version__ = '[0-9]*'/__version__ = '${VERSION}'/" -i winregrc/__init__.py # Update the version in the pyproject configuration. sed "s/version = \"[0-9]*\"/version = \"${VERSION}\"/" -i pyproject.toml # Ensure shebangs of Python scripts are consistent. find . -name \*.py -exec sed '1s?^#!.*$?#!/usr/bin/env python3?' -i {} \; # Update the version in the dpkg configuration files. DPKG_DATE=$(date -R) cat > config/dpkg/changelog << EOT winreg-kb (${VERSION}-1) unstable; urgency=low * Auto-generated -- Joachim Metz ${DPKG_DATE} EOT # Regenerate the API documentation. tox -edocs exit ${EXIT_SUCCESS}; ================================================ FILE: winreg-kb.ini ================================================ [project] name: winreg-kb status: experimental name_description: Windows Registry knowledge base (winreg-kb) maintainer: Joachim Metz homepage_url: https://github.com/libyal/winreg-kb git_url: https://github.com/libyal/winreg-kb.git description_short: Windows Registry resources (winregrc) description_long: winregrc is a Python module part of winreg-kb to allow reuse of Windows Registry resources. ================================================ FILE: winregrc/__init__.py ================================================ """Windows Registry resources (winregrc).""" __version__ = '20260413' ================================================ FILE: winregrc/appcompatcache.py ================================================ """Application Compatibility Cache collector.""" import logging from dtfabric.runtime import data_maps as dtfabric_data_maps from winregrc import data_format from winregrc import errors from winregrc import interface class AppCompatCacheHeader: """Application Compatibility Cache header. Attributes: number_of_cached_entries (int): number of cached entries. header_size (int): header size. """ def __init__(self): """Initializes an Application Compatibility Cache header.""" super().__init__() self.number_of_cached_entries = 0 self.header_size = 0 class AppCompatCacheCachedEntry: """Application Compatibility Cache cached entry. Attributes: cached_entry_size (int): size of the cached entry. data (bytes): data of the cached entry. file_size (int): size of file corresponding to the cached entry. insertion_flags (int): insertion flags of the cached entry. last_modification_time (int): last modification timestamp of the file corresponding to the cached entry. last_update_time (int): last update timestamp the cached entry. shim_flags (int): shim flags of the cached entry. path (str): path of the cached entry. """ def __init__(self): """Initializes an Application Compatibility Cache cached entry.""" super().__init__() self.cached_entry_size = 0 self.data = None self.file_size = None self.insertion_flags = None self.last_modification_time = None self.last_update_time = None self.shim_flags = None self.path = None class AppCompatCacheDataParser(data_format.BinaryDataFormat): """Application Compatibility Cache data parser.""" _DEFINITION_FILE = 'appcompatcache.yaml' _FORMAT_TYPE_2000 = 1 _FORMAT_TYPE_XP = 2 _FORMAT_TYPE_2003 = 3 _FORMAT_TYPE_VISTA = 4 _FORMAT_TYPE_7 = 5 _FORMAT_TYPE_8 = 6 _FORMAT_TYPE_10 = 7 _HEADER_SIGNATURES = { # AppCompatCache format signature used in Windows XP. 0xdeadbeef: _FORMAT_TYPE_XP, # AppCompatCache format signature used in Windows 2003, Vista and 2008. 0xbadc0ffe: _FORMAT_TYPE_2003, # AppCompatCache format signature used in Windows 7 and 2008 R2. 0xbadc0fee: _FORMAT_TYPE_7, # AppCompatCache format used in Windows 8.0 and 8.1. 0x00000080: _FORMAT_TYPE_8, # AppCompatCache format used in Windows 10 0x00000030: _FORMAT_TYPE_10, 0x00000034: _FORMAT_TYPE_10} _HEADER_DATA_TYPE_MAP_NAMES = { _FORMAT_TYPE_XP: 'appcompatcache_header_xp_32bit', _FORMAT_TYPE_2003: 'appcompatcache_header_2003', _FORMAT_TYPE_VISTA: 'appcompatcache_header_vista', _FORMAT_TYPE_7: 'appcompatcache_header_7', _FORMAT_TYPE_8: 'appcompatcache_header_8', _FORMAT_TYPE_10: 'appcompatcache_header_10'} _SUPPORTED_FORMAT_TYPES = frozenset(_HEADER_DATA_TYPE_MAP_NAMES.keys()) # AppCompatCache format used in Windows 8.0. _CACHED_ENTRY_SIGNATURE_8_0 = b'00ts' # AppCompatCache format used in Windows 8.1. _CACHED_ENTRY_SIGNATURE_8_1 = b'10ts' def __init__(self, debug=False, output_writer=None): """Initializes an Application Compatibility Cache data parser. Args: debug (Optional[bool]): True if debug information should be written. output_writer (Optional[OutputWriter]): output writer. """ super().__init__( debug=debug, output_writer=output_writer) self._cached_entry_data_type_map = None def _DebugPrintCachedEntryXP(self, cached_entry): """Prints Windows XP AppCompatCache cached entry value debug information. Args: cached_entry (appcompatcache_cached_entry_xp_32bit): Windows XP AppCompatCache cached entry. """ # TODO: have dtFabric handle string conversion. string_size = 0 for string_index in range(0, 528, 2): if (cached_entry.path[string_index] == 0 and cached_entry.path[string_index + 1] == 0): break string_size += 2 path = bytearray(cached_entry.path[0:string_size]).decode('utf-16-le') self._DebugPrintValue('Path', path) self._DebugPrintDecimalValue('File size', cached_entry.file_size) self._DebugPrintFiletimeValue( 'Last update time', cached_entry.last_update_time) def _DebugPrintCachedEntry2003(self, cached_entry): """Prints Windows 2003 AppCompatCache cached entry value debug information. Args: cached_entry_common (appcompatcache_cached_entry_2003_32bit| appcompatcache_cached_entry_2003_64bit| appcompatcache_cached_entry_vista_32bit| appcompatcache_cached_entry_vista_64bit| appcompatcache_cached_entry_7_32bit| appcompatcache_cached_entry_7_64bit): Windows 2003, Vista or 7 AppCompatCache cached entry. """ self._DebugPrintDecimalValue('Path size', cached_entry.path_size) self._DebugPrintDecimalValue( 'Maximum path size', cached_entry.maximum_path_size) self._DebugPrintValue('Path offset', f'0x{cached_entry.path_offset:08x}') if hasattr(cached_entry, 'file_size'): self._DebugPrintDecimalValue('File size', cached_entry.file_size) if hasattr(cached_entry, 'insertion_flags'): self._DebugPrintValue( 'Insertion flags', f'0x{cached_entry.insertion_flags:08x}') if hasattr(cached_entry, 'shim_flags'): self._DebugPrintValue('Shim flags', f'0x{cached_entry.shim_flags:08x}') if hasattr(cached_entry, 'data_offset'): self._DebugPrintValue('Data offset', f'0x{cached_entry.data_offset:08x}') if hasattr(cached_entry, 'data_size'): self._DebugPrintDecimalValue('Data size', cached_entry.data_size) # pylint: disable=missing-type-doc def _DebugPrintCachedEntry8(self, cached_entry_header, cached_entry_body): """Prints Windows 8 AppCompatCache cached entry value debug information. Args: cached_entry_header (appcompatcache_cached_entry_header_8): Windows 8 or 10 AppCompatCache cached entry header. cached_entry_body (appcompatcache_cached_entry_header_8_0| appcompatcache_cached_entry_header_8_1| appcompatcache_cached_entry_header_10): Windows 8.0, 8.1 or 10 AppCompatCache cached entry body. """ self._DebugPrintValue( 'Signature', cached_entry_header.signature.decode('ascii')) self._DebugPrintValue('Unknown1', f'0x{cached_entry_header.unknown1:08x}') self._DebugPrintDecimalValue( 'Cached entry data size', cached_entry_header.cached_entry_data_size) self._DebugPrintDecimalValue('Path size', cached_entry_body.path_size) self._DebugPrintValue('Path', cached_entry_body.path.rstrip('\x00')) if hasattr(cached_entry_body, 'insertion_flags'): self._DebugPrintValue( 'Insertion flags', f'0x{cached_entry_body.insertion_flags:08x}') if hasattr(cached_entry_body, 'shim_flags'): self._DebugPrintValue( 'Shim flags', f'0x{cached_entry_body.shim_flags:08x}') if hasattr(cached_entry_body, 'unknown1'): self._DebugPrintValue('Unknown1', f'0x{cached_entry_body.unknown1:04x}') self._DebugPrintFiletimeValue( 'Last modification time', cached_entry_body.last_modification_time) self._DebugPrintDecimalValue('Data size', cached_entry_body.data_size) # pylint: disable=missing-type-doc def _DebugPrintHeader(self, format_type, header): """Prints AppCompatCache header value debug information. Args: format_type (int): AppCompatCache format type. header (appcompatcache_header_xp_32bit|appcompatcache_header_vista| appcompatcache_header_7|appcompatcache_header_8| appcompatcache_header_10): AppCompatCache header. """ if format_type == self._FORMAT_TYPE_10: self._DebugPrintDecimalValue('Header size', header.signature) else: self._DebugPrintValue('Signature', f'0x{header.signature:08x}') if format_type in ( self._FORMAT_TYPE_XP, self._FORMAT_TYPE_2003, self._FORMAT_TYPE_VISTA, self._FORMAT_TYPE_7, self._FORMAT_TYPE_10): self._DebugPrintDecimalValue( 'Number of cached entries', header.number_of_cached_entries) if format_type == self._FORMAT_TYPE_XP: if self._debug: self._DebugPrintValue( 'Number of LRU entries', f'0x{header.number_of_lru_entries:08x}') self._DebugPrintValue('Unknown1', f'0x{header.unknown1:08x}') elif format_type == self._FORMAT_TYPE_8: self._DebugPrintValue('Unknown1', f'0x{header.unknown1:08x}') if format_type != self._FORMAT_TYPE_XP: self._DebugPrintText('\n') def _GetCachedEntryDataTypeMap( self, format_type, value_data, cached_entry_offset): """Determines the cached entry data type map. Args: format_type (int): format type. value_data (bytes): value data. cached_entry_offset (int): offset of the first cached entry data relative to the start of the value data. Returns: dtfabric.DataTypeMap: data type map which contains a data type definition, such as a structure, that can be mapped onto binary data or None if the data type map is not defined. Raises: ParseError: if the cached entry data type map cannot be determined. """ if format_type not in self._SUPPORTED_FORMAT_TYPES: raise errors.ParseError(f'Unsupported format type: {format_type:d}') data_type_map_name = '' if format_type == self._FORMAT_TYPE_XP: data_type_map_name = 'appcompatcache_cached_entry_xp_32bit' elif format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10): data_type_map_name = 'appcompatcache_cached_entry_header_8' else: cached_entry = self._ParseCommon2003CachedEntry( value_data, cached_entry_offset) # Assume the entry is 64-bit if the 32-bit path offset is 0 and # the 64-bit path offset is set. if (cached_entry.path_offset_32bit == 0 and cached_entry.path_offset_64bit != 0): number_of_bits = '64' else: number_of_bits = '32' if format_type == self._FORMAT_TYPE_2003: data_type_map_name = ( f'appcompatcache_cached_entry_2003_{number_of_bits:s}bit') elif format_type == self._FORMAT_TYPE_VISTA: data_type_map_name = ( f'appcompatcache_cached_entry_vista_{number_of_bits:s}bit') elif format_type == self._FORMAT_TYPE_7: data_type_map_name = ( f'appcompatcache_cached_entry_7_{number_of_bits:s}bit') return self._GetDataTypeMap(data_type_map_name) def _ParseCommon2003CachedEntry(self, value_data, cached_entry_offset): """Parses the cached entry structure common for Windows 2003, Vista and 7. Args: value_data (bytes): value data. cached_entry_offset (int): offset of the first cached entry data relative to the start of the value data. Returns: appcompatcache_cached_entry_2003_common: cached entry structure common for Windows 2003, Windows Vista and Windows 7. Raises: ParseError: if the value data could not be parsed. """ cached_entry_data = value_data[cached_entry_offset:] data_type_map = self._GetDataTypeMap( 'appcompatcache_cached_entry_2003_common') try: cached_entry = self._ReadStructureFromByteStream( cached_entry_data, cached_entry_offset, data_type_map, 'cached entry') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse cached entry value with error: {exception!s}') if cached_entry.path_size > cached_entry.maximum_path_size: raise errors.ParseError('Path size value out of bounds.') path_end_of_string_size = ( cached_entry.maximum_path_size - cached_entry.path_size) if cached_entry.path_size == 0 or path_end_of_string_size != 2: raise errors.ParseError('Unsupported path size values.') return cached_entry def CheckSignature(self, value_data): """Parses and validates the signature. Args: value_data (bytes): value data. Returns: int: format type or None if format could not be determined. Raises: ParseError: if the value data could not be parsed. """ data_type_map = self._GetDataTypeMap('uint32le') try: signature = self._ReadStructureFromByteStream( value_data, 0, data_type_map, 'signature') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse signature value with error: {exception!s}') format_type = self._HEADER_SIGNATURES.get(signature) if format_type == self._FORMAT_TYPE_2003: # TODO: determine which format version is used (2003 or Vista). return self._FORMAT_TYPE_2003 if format_type == self._FORMAT_TYPE_8: cached_entry_signature = value_data[signature:signature + 4] if cached_entry_signature in ( self._CACHED_ENTRY_SIGNATURE_8_0, self._CACHED_ENTRY_SIGNATURE_8_1): return self._FORMAT_TYPE_8 elif format_type == self._FORMAT_TYPE_10: # Windows 10 uses the same cache entry signature as Windows 8.1 cached_entry_signature = value_data[signature:signature + 4] if cached_entry_signature == self._CACHED_ENTRY_SIGNATURE_8_1: return self._FORMAT_TYPE_10 return format_type def ParseCachedEntry( self, format_type, value_data, cached_entry_index, cached_entry_offset): """Parses a cached entry. Args: format_type (int): format type. value_data (bytes): value data. cached_entry_index (int): cached entry index. cached_entry_offset (int): offset of the first cached entry data relative to the start of the value data. Returns: AppCompatCacheCachedEntry: cached entry. Raises: ParseError: if the value data could not be parsed. """ if not self._cached_entry_data_type_map: self._cached_entry_data_type_map = self._GetCachedEntryDataTypeMap( format_type, value_data, cached_entry_offset) if not self._cached_entry_data_type_map: raise errors.ParseError('Unable to determine cached entry data type.') cached_entry_size = self._cached_entry_data_type_map.GetSizeHint() cached_entry_end_offset = cached_entry_offset + cached_entry_size cached_entry_data = value_data[cached_entry_offset:cached_entry_end_offset] if self._debug: if format_type not in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10): description = f'Cached entry: {cached_entry_index:d} data' self._DebugPrintData(description, cached_entry_data) try: cached_entry = self._ReadStructureFromByteStream( cached_entry_data, cached_entry_offset, self._cached_entry_data_type_map, 'cached entry') except (ValueError, errors.ParseError) as exception: if self._debug: if format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10): description = f'Cached entry: {cached_entry_index:d} header data' self._DebugPrintData(description, cached_entry_data) raise errors.ParseError( f'Unable to parse cached entry value with error: {exception!s}') if format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10): if cached_entry.signature not in ( self._CACHED_ENTRY_SIGNATURE_8_0, self._CACHED_ENTRY_SIGNATURE_8_1): if self._debug: description = f'Cached entry: {cached_entry_index:d} header data' self._DebugPrintData(description, cached_entry_data) raise errors.ParseError('Unsupported cache entry signature') cached_entry_object = AppCompatCacheCachedEntry() data_offset = 0 data_size = 0 if format_type == self._FORMAT_TYPE_XP: if self._debug: self._DebugPrintCachedEntryXP(cached_entry) # TODO: have dtFabric handle string conversion. string_size = 0 for string_index in range(0, 528, 2): if (cached_entry.path[string_index] == 0 and cached_entry.path[string_index + 1] == 0): break string_size += 2 last_modification_time = cached_entry.last_modification_time path = bytearray(cached_entry.path[0:string_size]).decode('utf-16-le') cached_entry_object.last_update_time = cached_entry.last_update_time elif format_type in ( self._FORMAT_TYPE_2003, self._FORMAT_TYPE_VISTA, self._FORMAT_TYPE_7): if self._debug: self._DebugPrintCachedEntry2003(cached_entry) last_modification_time = cached_entry.last_modification_time if format_type in (self._FORMAT_TYPE_VISTA, self._FORMAT_TYPE_7): cached_entry_object.insertion_flags = cached_entry.insertion_flags cached_entry_object.shim_flags = cached_entry.shim_flags path_size = cached_entry.path_size maximum_path_size = cached_entry.maximum_path_size path_offset = cached_entry.path_offset if path_offset > 0 and path_size > 0: path_size += path_offset maximum_path_size += path_offset if self._debug: self._DebugPrintData( 'Path data', value_data[path_offset:maximum_path_size]) path = value_data[path_offset:path_size].decode('utf-16-le') if self._debug: self._DebugPrintValue('Path', path) if format_type == self._FORMAT_TYPE_7: data_offset = cached_entry.data_offset data_size = cached_entry.data_size elif format_type in (self._FORMAT_TYPE_8, self._FORMAT_TYPE_10): cached_entry_data_size = cached_entry.cached_entry_data_size cached_entry_size = 12 + cached_entry_data_size cached_entry_end_offset = cached_entry_offset + cached_entry_size cached_entry_data = value_data[ cached_entry_offset:cached_entry_end_offset] if self._debug: description = f'Cached entry: {cached_entry_index:d} data' self._DebugPrintData(description, cached_entry_data) if format_type == self._FORMAT_TYPE_10: data_type_map_name = 'appcompatcache_cached_entry_body_10' elif cached_entry.signature == self._CACHED_ENTRY_SIGNATURE_8_0: data_type_map_name = 'appcompatcache_cached_entry_body_8_0' elif cached_entry.signature == self._CACHED_ENTRY_SIGNATURE_8_1: data_type_map_name = 'appcompatcache_cached_entry_body_8_1' else: data_type_map_name = None data_type_map = self._GetDataTypeMap(data_type_map_name) context = dtfabric_data_maps.DataTypeMapContext() try: cached_entry_body = self._ReadStructureFromByteStream( cached_entry_data[12:], cached_entry_offset + 12, data_type_map, 'cached entry body', context=context) except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse cached entry body with error: {exception!s}') if self._debug: self._DebugPrintCachedEntry8(cached_entry, cached_entry_body) last_modification_time = cached_entry_body.last_modification_time path = cached_entry_body.path if format_type == self._FORMAT_TYPE_8: cached_entry_object.insertion_flags = cached_entry_body.insertion_flags cached_entry_object.shim_flags = cached_entry_body.shim_flags data_offset = cached_entry_offset + context.byte_size data_size = cached_entry_body.data_size if self._debug: self._DebugPrintText('\n') cached_entry_object.cached_entry_size = cached_entry_size cached_entry_object.file_size = getattr(cached_entry, 'file_size', None) cached_entry_object.last_modification_time = last_modification_time cached_entry_object.path = path if data_size > 0: cached_entry_object.data = value_data[data_offset:data_offset + data_size] if self._debug: self._DebugPrintData('Data', cached_entry_object.data) return cached_entry_object def ParseHeader(self, format_type, value_data): """Parses the header. Args: format_type (int): format type. value_data (bytes): value data. Returns: AppCompatCacheHeader: header. Raises: ParseError: if the value data could not be parsed. """ data_type_map_name = self._HEADER_DATA_TYPE_MAP_NAMES.get(format_type) if not data_type_map_name: raise errors.ParseError(f'Unsupported format type: {format_type:d}') data_type_map = self._GetDataTypeMap(data_type_map_name) context = dtfabric_data_maps.DataTypeMapContext() try: header = self._ReadStructureFromByteStream( value_data, 0, data_type_map, 'header', context=context) except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse header value with error: {exception!s}') header_data_size = context.byte_size if format_type == self._FORMAT_TYPE_10: header_data_size = header.signature cache_header = AppCompatCacheHeader() cache_header.header_size = header_data_size cache_header.number_of_cached_entries = getattr( header, 'number_of_cached_entries', None) if self._debug: self._DebugPrintHeader(format_type, header) if format_type == self._FORMAT_TYPE_XP: if self._debug: self._DebugPrintText('LRU entries:') data_offset = 16 number_of_lru_entries = header.number_of_lru_entries if 0 <= number_of_lru_entries <= 96: data_type_map = self._GetDataTypeMap('uint32le') for lru_entry_index in range(number_of_lru_entries): try: lru_entry = self._ReadStructureFromByteStream( value_data[data_offset:data_offset + 4], data_offset, data_type_map, 'LRU entry') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse LRU entry value with error: {exception!s}') data_offset += 4 if self._debug: offset_value = 400 + (lru_entry * 552) description = f'LRU entry: {lru_entry_index:d}' value_string = f'{lru_entry:d} (offset: 0x{offset_value:08x})' self._DebugPrintValue(description, value_string) if self._debug: self._DebugPrintText('\n') if self._debug: self._DebugPrintData('Unknown data', value_data[data_offset:400]) self._cached_entry_data_type_map = None return cache_header class AppCompatCacheCollector(interface.WindowsRegistryKeyCollector): """Application Compatibility Cache collector. Attributes: cached_entries (list[AppCompatCacheCachedEntry]): cached entries. """ def __init__(self, debug=False, output_writer=None): """Initializes a Application Compatibility Cache collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._parser = AppCompatCacheDataParser( debug=self._debug, output_writer=output_writer) self._output_writer = output_writer self.cached_entries = [] def _CollectAppCompatCacheFromKey(self, app_compat_cache_key): """Collects Application Compatibility Cache from a Windows Registry key. Args: app_compat_cache_key (dfwinreg.WinRegistryKey): Application Compatibility Cache Windows Registry key. Returns: bool: True if the Application Compatibility Cache key was found, False if not. """ value = app_compat_cache_key.GetValueByName('AppCompatCache') if not value: logging.warning( f'Missing AppCompatCache value in key: {app_compat_cache_key.path:s}') return True value_data = value.data value_data_size = len(value.data) # TODO: add non debug output if self._debug: self._output_writer.WriteDebugData('Value data:\n', value_data) format_type = self._parser.CheckSignature(value_data) if not format_type: logging.warning('Unsupported signature.') return True cache_header = self._parser.ParseHeader(format_type, value_data) # On Windows Vista and 2008 when the cache is empty it will # only consist of the header. if value_data_size <= cache_header.header_size: return True cached_entry_offset = cache_header.header_size cached_entry_index = 0 while cached_entry_offset < value_data_size: cached_entry = self._parser.ParseCachedEntry( format_type, value_data, cached_entry_index, cached_entry_offset) self.cached_entries.append(cached_entry) cached_entry_offset += cached_entry.cached_entry_size cached_entry_index += 1 if (cache_header.number_of_cached_entries != 0 and cached_entry_index >= cache_header.number_of_cached_entries): break return True def Collect(self, registry, all_control_sets=False): """Collects the Application Compatibility Cache. Args: registry (dfwinreg.WinRegistry): Windows Registry. all_control_sets (Optional[bool]): True if the services should be collected from all control sets instead of only the current control set. Returns: bool: True if the Application Compatibility Cache key was found, False if not. """ result = False if all_control_sets: system_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\System\\') if not system_key: return result for control_set_key in system_key.GetSubkeys(): if control_set_key.name.startswith('ControlSet'): # Windows XP app_compat_cache_key = control_set_key.GetSubkeyByPath( 'Control\\Session Manager\\AppCompatibility') if app_compat_cache_key: if self._CollectAppCompatCacheFromKey(app_compat_cache_key): result = True # Windows 2003 and later app_compat_cache_key = control_set_key.GetSubkeyByPath( 'Control\\Session Manager\\AppCompatCache') if app_compat_cache_key: if self._CollectAppCompatCacheFromKey(app_compat_cache_key): result = True else: # Windows XP key_path = ( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\' 'Session Manager\\AppCompatibility') try: app_compat_cache_key = registry.GetKeyByPath(key_path) except RuntimeError: app_compat_cache_key = None if app_compat_cache_key: if self._CollectAppCompatCacheFromKey(app_compat_cache_key): result = True # Windows 2003 and later key_path = ( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\' 'Session Manager\\AppCompatCache') try: app_compat_cache_key = registry.GetKeyByPath(key_path) except RuntimeError: app_compat_cache_key = None if app_compat_cache_key: if self._CollectAppCompatCacheFromKey(app_compat_cache_key): result = True return result ================================================ FILE: winregrc/appcompatcache.yaml ================================================ # dtFabric format specification. --- name: appcompatcache type: format description: Application Compatibility Cache format --- name: byte type: integer attributes: format: unsigned size: 1 units: bytes --- name: uint16 type: integer attributes: format: unsigned size: 2 units: bytes --- name: uint32 type: integer attributes: format: unsigned size: 4 units: bytes --- name: uint64 type: integer attributes: format: unsigned size: 8 units: bytes --- name: uint16le type: integer attributes: byte_order: little-endian format: unsigned size: 2 units: bytes --- name: uint32le type: integer attributes: byte_order: little-endian format: unsigned size: 4 units: bytes --- name: uint64le type: integer attributes: byte_order: little-endian format: unsigned size: 8 units: bytes --- name: wchar16 type: character attributes: size: 2 units: bytes --- name: appcompatcache_header_xp_32bit type: structure description: Windows XP 32-bit AppCompatCache header. attributes: byte_order: little-endian members: - name: signature data_type: uint32 - name: number_of_cached_entries data_type: uint32 - name: number_of_lru_entries data_type: uint32 - name: unknown1 data_type: uint32 - name: lru_entries type: sequence element_data_type: uint32 number_of_elements: 96 --- name: appcompatcache_cached_entry_xp_32bit type: structure description: Windows XP 32-bit AppCompatCache cached entry. attributes: byte_order: little-endian members: - name: path type: sequence element_data_type: byte number_of_elements: 528 - name: last_modification_time data_type: uint64 - name: file_size data_type: uint64 - name: last_update_time data_type: uint64 --- name: appcompatcache_header_2003 type: structure description: Windows 2003 AppCompatCache header. attributes: byte_order: little-endian members: - name: signature data_type: uint32 - name: number_of_cached_entries data_type: uint32 --- name: appcompatcache_cached_entry_2003_common type: structure description: Windows 2003, Vista, 7 common AppCompatCache cached entry. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: maximum_path_size data_type: uint16 - name: path_offset_32bit data_type: uint32 - name: path_offset_64bit data_type: uint64 --- name: appcompatcache_cached_entry_2003_32bit type: structure description: Windows 2003 32-bit AppCompatCache cached entry. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: maximum_path_size data_type: uint16 - name: path_offset data_type: uint32 - name: last_modification_time data_type: uint64 - name: file_size data_type: uint64 --- name: appcompatcache_cached_entry_2003_64bit type: structure description: Windows 2003 64-bit AppCompatCache cached entry. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: maximum_path_size data_type: uint16 - name: unknown1 data_type: uint32 - name: path_offset data_type: uint64 - name: last_modification_time data_type: uint64 - name: file_size data_type: uint64 --- name: appcompatcache_header_vista type: structure description: Windows Vista and 2008 AppCompatCache header. attributes: byte_order: little-endian members: - name: signature data_type: uint32 - name: number_of_cached_entries data_type: uint32 --- name: appcompatcache_cached_entry_vista_32bit type: structure description: Windows Vista and 2008 32-bit AppCompatCache cached entry. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: maximum_path_size data_type: uint16 - name: path_offset data_type: uint32 - name: last_modification_time data_type: uint64 - name: insertion_flags data_type: uint32 - name: shim_flags data_type: uint32 --- name: appcompatcache_cached_entry_vista_64bit type: structure description: Windows Vista and 2008 64-bit AppCompatCache cached entry. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: maximum_path_size data_type: uint16 - name: unknown1 data_type: uint32 - name: path_offset data_type: uint64 - name: last_modification_time data_type: uint64 - name: insertion_flags data_type: uint32 - name: shim_flags data_type: uint32 --- name: appcompatcache_header_7 type: structure description: Windows 7 AppCompatCache header. attributes: byte_order: little-endian members: - name: signature data_type: uint32 - name: number_of_cached_entries data_type: uint32 - name: unknown1 type: sequence element_data_type: byte number_of_elements: 120 --- name: appcompatcache_cached_entry_7_32bit type: structure description: Windows 7 and 2008 R2 32-bit AppCompatCache cached entry. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: maximum_path_size data_type: uint16 - name: path_offset data_type: uint32 - name: last_modification_time data_type: uint64 - name: insertion_flags data_type: uint32 - name: shim_flags data_type: uint32 - name: data_size data_type: uint32 - name: data_offset data_type: uint32 --- name: appcompatcache_cached_entry_7_64bit type: structure description: Windows 7 and 2008 R2 64-bit AppCompatCache cached entry. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: maximum_path_size data_type: uint16 - name: unknown1 data_type: uint32 - name: path_offset data_type: uint64 - name: last_modification_time data_type: uint64 - name: insertion_flags data_type: uint32 - name: shim_flags data_type: uint32 - name: data_size data_type: uint64 - name: data_offset data_type: uint64 --- name: appcompatcache_header_8 type: structure description: Windows 8 AppCompatCache header. attributes: byte_order: little-endian members: - name: signature data_type: uint32 - name: unknown1 data_type: uint32 - name: unknown2 type: sequence element_data_type: byte number_of_elements: 120 --- name: appcompatcache_cached_entry_header_8 type: structure description: Windows 8 and 10 AppCompatCache header. attributes: byte_order: little-endian members: - name: signature type: stream element_data_type: byte number_of_elements: 4 - name: unknown1 data_type: uint32 - name: cached_entry_data_size data_type: uint32 --- name: appcompatcache_cached_entry_body_8_0 type: structure description: Windows 8.0 AppCompatCache body. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: path type: string encoding: utf-16-le element_data_type: wchar16 elements_data_size: appcompatcache_cached_entry_body_8_0.path_size - name: insertion_flags data_type: uint32 - name: shim_flags data_type: uint32 - name: last_modification_time data_type: uint64 - name: data_size data_type: uint32 --- name: appcompatcache_cached_entry_body_8_1 type: structure description: Windows 8.1 AppCompatCache body. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: path type: string encoding: utf-16-le element_data_type: wchar16 elements_data_size: appcompatcache_cached_entry_body_8_1.path_size - name: insertion_flags data_type: uint32 - name: shim_flags data_type: uint32 - name: unknown1 data_type: uint16 - name: last_modification_time data_type: uint64 - name: data_size data_type: uint32 --- name: appcompatcache_cached_entry_body_10 type: structure description: Windows 10 AppCompatCache body. attributes: byte_order: little-endian members: - name: path_size data_type: uint16 - name: path type: string encoding: utf-16-le element_data_type: wchar16 elements_data_size: appcompatcache_cached_entry_body_10.path_size - name: last_modification_time data_type: uint64 - name: data_size data_type: uint32 --- name: appcompatcache_header_10 type: structure description: Windows 10 AppCompatCache header. attributes: byte_order: little-endian members: - name: signature data_type: uint32 - name: unknown1 data_type: uint32 - name: unknown2 type: sequence element_data_type: byte number_of_elements: 28 - name: number_of_cached_entries data_type: uint32 - name: unknown3 type: sequence element_data_type: byte number_of_elements: 8 ================================================ FILE: winregrc/application_identifiers.py ================================================ """Windows application identifiers (AppID) collector.""" from winregrc import interface class ApplicationIdentifier: """Application identifier. Attributes: description (str): description. guid (str): identifier. """ def __init__(self, guid, description): """Initializes an application identifier. Args: guid (str): identifier. description (str): description. """ super().__init__() self.description = description self.guid = guid class ApplicationIdentifiersCollector(interface.WindowsRegistryKeyCollector): """Windows application identifiers collector.""" _APPLICATION_IDENTIFIERS_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Classes\\AppID') def _CollectApplicationIdentifiers(self, application_identifiers_key): """Collects Windows application identifiers (AppID). Args: application_identifiers_key (dfwinreg.WinRegistryKey): application identifiers Windows Registry key. Yields: ApplicationIdentifier: an application identifier. """ for subkey in application_identifiers_key.GetSubkeys(): name = subkey.name.lower() # Ignore subkeys that are not formatted as {%GUID%} if len(name) == 38 and name[0] == '{' and name[37] == '}': description = self._GetValueFromKey(subkey, '') yield ApplicationIdentifier(name, description) def Collect(self, registry): """Collects Windows application identifiers (AppID). Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: ApplicationIdentifier: an application identifier. """ application_identifiers_key = registry.GetKeyByPath( self._APPLICATION_IDENTIFIERS_KEY_PATH) if application_identifiers_key: yield from self._CollectApplicationIdentifiers( application_identifiers_key) ================================================ FILE: winregrc/cached_credentials.py ================================================ """Domain cached credentials collector.""" import codecs import struct import pyfcrypto import pyhmac from winregrc import hexdump from winregrc import interface class CachedCredentialsKeyCollector(interface.WindowsRegistryKeyCollector): """Domain cached credentials key collector.""" _CREDENTIALS_CACHE_KEY_PATH = 'HKEY_LOCAL_MACHINE\\Security\\Cache' _NL_KEY_MATERIAL_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Security\\Policy\\Secrets\\NL$KM\\CurrVal') _LSA_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Lsa') _POLICY_ENCRYPTION_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Security\\Policy\\PolSecretEncryptionKey') _ODD_PARITY_TABLE = [ 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, 110, 112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, 127, 128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, 143, 145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, 158, 161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174, 176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191, 193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206, 208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223, 224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239, 241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, 254] def __init__(self, debug=False, output_writer=None): """Initializes a system key collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._output_writer = output_writer def _DecryptARC4(self, key, data): """Decrypts ARC4 encrypted data. Args: key (str): key used to decrypt the data. data (bytes): data to decrypt. Returns: bytes: decrypted data. """ rc4_context = pyfcrypto.rc4_context() rc4_context.set_key(key) return pyfcrypto.crypt_rc4(rc4_context, data) def _DecryptTripleDES(self, key, data): """Decrypts Triple DES-ECB encrypted data. Args: key (str): key used to decrypt the data. data (bytes): data to decrypt. Returns: bytes: decrypted data. """ des3_context = pyfcrypto.des3_context() des3_context.set_key(key) return pyfcrypto.crypt_des3( des3_context, pyfcrypto.crypt_modes.DECRYPT, data) def _GetBootKey(self, registry): """Retrieves the boot key. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bytes: boot key or None if not found. """ try: lsa_key = registry.GetKeyByPath(self._LSA_KEY_PATH) except RuntimeError: lsa_key = None if not lsa_key: return None lsa_jd_key = lsa_key.GetSubkeyByName('JD') lsa_skew1_key = lsa_key.GetSubkeyByName('Skew1') lsa_gbg_key = lsa_key.GetSubkeyByName('GBG') lsa_data_key = lsa_key.GetSubkeyByName('Data') if None in (lsa_jd_key, lsa_skew1_key, lsa_gbg_key, lsa_data_key): return None lsa_jd_class_name = lsa_jd_key.class_name lsa_skew1_class_name = lsa_skew1_key.class_name lsa_gbg_class_name = lsa_gbg_key.class_name lsa_data_class_name = lsa_data_key.class_name if None in ( lsa_jd_class_name, lsa_skew1_class_name, lsa_gbg_class_name, lsa_data_class_name): return None class_name_string = ''.join([ lsa_jd_class_name, lsa_skew1_class_name, lsa_gbg_class_name, lsa_data_class_name]) scrambled_key = codecs.decode(class_name_string, 'hex') key = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] for index, scrambled_index in enumerate([ 8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]): key[index] = scrambled_key[scrambled_index] return bytes(key) def _GetLSAKey(self, registry, boot_key): """Retrieves the LSA key. Args: registry (dfwinreg.WinRegistry): Windows Registry. boot_key (bytes): boot key. Returns: bytes: LSA key or None if not found. """ policy_encryption_key = registry.GetKeyByPath( self._POLICY_ENCRYPTION_KEY_PATH) if not policy_encryption_key: return None policy_encryption_value = policy_encryption_key.GetValueByName('') if not policy_encryption_value: return None value_data = policy_encryption_value.data digest_context = pyhmac.md5_context() digest_context.update(boot_key) iteration = 0 while iteration < 1000: digest_context.update(value_data[60:76]) iteration += 1 rc4_key = digest_context.finalize() decrypted_data = self._DecryptARC4(rc4_key, value_data[12:60]) return decrypted_data[16:32] def _GetNLKey(self, registry, lsa_key): """Retrieves the NL key. Args: registry (dfwinreg.WinRegistry): Windows Registry. lsa_key (bytes): LSA key. Returns: bytes: NL key or None if not found. """ nl_key_material_key = registry.GetKeyByPath( self._NL_KEY_MATERIAL_KEY_PATH) if not nl_key_material_key: return None nl_key_material_value = nl_key_material_key.GetValueByName('') if not nl_key_material_value: return None key_size = len(lsa_key) value_data = nl_key_material_value.data value_data_size = len(value_data) decrypted_value_data = [] key_offset = 0 for value_data_offset in range(12, value_data_size, 8): key_end_offset = key_offset + 7 value_data_end_offset = value_data_offset + 8 des_key = self._UnpackLSAKey(lsa_key[key_offset:key_end_offset]) decrypted_data = self._DecryptTripleDES( des_key, value_data[value_data_offset:value_data_end_offset]) decrypted_value_data.append(decrypted_data) key_offset = key_end_offset available_key_size = key_size - key_offset if available_key_size < 7: key_offset = available_key_size decrypted_value_data = b''.join(decrypted_value_data) print(hexdump.Hexdump(decrypted_value_data)) (data_size, ) = struct.unpack('> 1, (lsa_key[0] & 0x01) << 6 | lsa_key[1] >> 2, (lsa_key[1] & 0x03) << 5 | lsa_key[2] >> 3, (lsa_key[2] & 0x07) << 4 | lsa_key[3] >> 4, (lsa_key[3] & 0x0f) << 3 | lsa_key[4] >> 5, (lsa_key[4] & 0x1f) << 2 | lsa_key[5] >> 6, (lsa_key[5] & 0x3f) << 1 | lsa_key[6] >> 7, lsa_key[6] & 0x7f] des_key = bytearray([ self._ODD_PARITY_TABLE[value << 1] for value in des_key]) return bytes(des_key) def Collect(self, registry): # pylint: disable=arguments-differ """Collects system information. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the system key was found, False if not. """ credentials_cache_key = registry.GetKeyByPath( self._CREDENTIALS_CACHE_KEY_PATH) if not credentials_cache_key: return False boot_key = self._GetBootKey(registry) if not boot_key: return False lsa_key = self._GetLSAKey(registry, boot_key) if not lsa_key: return False nl_key = self._GetNLKey(registry, lsa_key) if not nl_key: return False for value in credentials_cache_key.GetValues(): if value.name == 'NL$Control': continue rc4_key = pyhmac.md5_calculate_hmac(nl_key, value.data[64:80]) decrypted_data = self._DecryptARC4(rc4_key, value.data[96:]) print(value.name) print(hexdump.Hexdump(value.data)) print(hexdump.Hexdump(decrypted_data)) return True ================================================ FILE: winregrc/catalog.py ================================================ """Catalog collector.""" import re class CatalogKeyDescriptor: """Catalog key descriptor. Attributes: grouped_key_paths (list[str]): paths of Windows Registry keys with similar values. key_path (str): path of Windows Registry key. value_descriptors (tuple[str,str]): pairs of value name and data type. """ def __init__(self): """Initializes a catalog key descriptor.""" super().__init__() self.grouped_key_paths = [] self.key_path = None self.value_descriptors = [] class CatalogCollector: """Catalog collector.""" def __init__(self, group_keys=False): """Initializes a catalog collector. Args: group_keys (bool): group keys with similar values. """ super().__init__() self._group_keys = group_keys def _CollectCatalogKeyDescriptors(self, registry_key): """Collects the catalog key descriptors from a Windows Registry key. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. Yields: CatalogKeyDescriptor: catalog key descriptor. """ key_descriptor = CatalogKeyDescriptor() key_descriptor.key_path = registry_key.path for registry_value in registry_key.GetValues(): value_descriptor = ( registry_value.name or '(default)', registry_value.data_type_string) key_descriptor.value_descriptors.append(value_descriptor) yield key_descriptor for sub_key in registry_key.GetSubkeys(): yield from self._CollectCatalogKeyDescriptors(sub_key) def Collect(self, root_key): """Collects the catalog descriptors from a Windows Registry file. Args: root_key (dfwinreg.WinRegistryKey): root Windows Registry key. Yields: CatalogKeyDescriptor: catalog key descriptor. """ if not self._group_keys: yield from self._CollectCatalogKeyDescriptors(root_key) else: def AlphanumericCompare(key): return (int(text) if text.isdigit() else text.lower() for text in re.split('([0-9]+)', key[0])) key_descriptors_per_value_hash = {} for key_descriptor in self._CollectCatalogKeyDescriptors(root_key): values_hash = hash('\n'.join([ '\t'.join([value_name, data_type_string]) for value_name, data_type_string in sorted( key_descriptor.value_descriptors, key=AlphanumericCompare)])) matching_key_descriptor = key_descriptors_per_value_hash.get( values_hash, None) if matching_key_descriptor: matching_key_descriptor.grouped_key_paths.append( key_descriptor.key_path) else: key_descriptors_per_value_hash[values_hash] = key_descriptor yield from key_descriptors_per_value_hash.values() ================================================ FILE: winregrc/controlpanel_items.py ================================================ """Windows control panel items collector.""" from winregrc import interface class ControlPanelItem: """Control panel item. Attributes: alternate_module_names (list[str]): alternate module names. identifier (str): identifier. module_name (str): module name. """ def __init__(self, identifier, module_name): """Initializes a control panel item. Args: identifier (str): identifier. module_name (str): module name. """ super().__init__() self.alternate_module_names = [] self.identifier = identifier self.module_name = module_name class ControlPanelItemsCollector(interface.WindowsRegistryKeyCollector): """Windows control panel items collector.""" _CONTROL_PANEL_NAMESPACE_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\ControlPanel\\NameSpace') def _CollectControlPanelItems(self, control_panel_namespace_key): """Collects Windows control panel items. Args: control_panel_namespace_key (dfwinreg.WinRegistryKey): control panel namespace Windows Registry key. Yields: ControlPanelItem: a control panel item. """ for subkey in control_panel_namespace_key.GetSubkeys(): if subkey.name[0] == '{' and subkey.name[-1] == '}': identifier = subkey.name.lower() module_name = self._GetValueFromKey(subkey, '') yield ControlPanelItem(identifier, module_name) def Collect(self, registry): """Collects Windows control panel items. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: ControlPanelItem: a control panel item. """ control_panel_namespace_key = registry.GetKeyByPath( self._CONTROL_PANEL_NAMESPACE_KEY_PATH) if control_panel_namespace_key: yield from self._CollectControlPanelItems(control_panel_namespace_key) ================================================ FILE: winregrc/data/observed_shellfolders.yaml ================================================ # winreg-kb shellfolder definitions observed. --- identifier: "{00020d75-0000-0000-c000-000000000046}" name: "Inbox" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{00020d76-0000-0000-c000-000000000046}" name: "Inbox" windows_versions: ["Windows NT4"] --- identifier: "{00c6d95f-329c-409a-81d7-c46c66ea7f33}" name: "Default Location" windows_versions: ["Windows 7"] --- identifier: "{0142e4d0-fb7a-11dc-ba4a-000ffe7ab428}" name: "Biometric Devices (Biometrics)" windows_versions: ["Windows 7", "Windows 8.0"] --- identifier: "{025a5937-a6be-4686-a844-36fe4bec8b6d}" name: "Power Options" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{031e4825-7b94-4dc3-b131-e946b44c8dd5}" name: "Users Libraries" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{04731b67-d933-450a-90e6-4acd2e9408fe}" class_name: CLSID_SearchFolder name: "Search Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}" name: "Taskbar (Notification Area Icons)" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{0875dcb6-c686-4243-9432-adccf0b9f2d7}" name: "Microsoft !OneNote Namespace Extension for Windows Desktop Search" windows_versions: ["Windows 7"] --- identifier: "{0afaced1-e828-11d1-9187-b532f1e9575d}" name: "Folder Shortcut" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{0bd8e793-d371-11d1-b0b5-0060972919d7}" name: "!SolidWorks Enterprise PDM" windows_versions: ["Windows 7"] --- identifier: "{0c39a5cf-1a7a-40c8-ba74-8900e6df5fcd}" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{0cd7a5c0-9f37-11ce-ae65-08002b2e1262}" name: "Cabinet File" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{0df44eaa-ff21-4412-828e-260a8728e7f1}" name: "Taskbar and Start Menu" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{11016101-e366-4d22-bc06-4ada335c892b}" name: "Internet Explorer History and Feeds Shell Data Source for Windows Search" windows_versions: ["Windows XP 32-bit", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{1206f5f1-0569-412c-8fec-3204630dfb70}" name: "Credential Manager" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{13e7f612-f261-4391-bea2-39df4f3fa311}" name: "Windows Desktop Search" windows_versions: ["Windows XP 32-bit"] --- identifier: "{15eae92e-f17a-4431-9f28-805e482dafd4}" name: "Install New Programs (Get Programs)" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{1723d66a-7a12-443e-88c7-05e1bfe79983}" name: "Previous Versions Delegate Folder" windows_versions: ["Windows Vista"] --- identifier: "{17cd9488-1228-4b2f-88ce-4298e93e0966}" name: "Default Programs (Set User Defaults)" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{1a9ba3a0-143a-11cf-8350-444553540000}" name: "Shell Favorite Folder" windows_versions: ["Windows 2000"] --- identifier: "{1d2680c9-0e2a-469d-b787-065558bc7d43}" name: "Fusion Cache" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7"] --- identifier: "{1f3427c8-5c10-4210-aa03-2ee45287d668}" name: "User Pinned" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{1f43a58c-ea28-43e6-9ec4-34574a16ebb7}" name: "Windows Desktop Search MAPI Namespace Extension Class" windows_versions: ["Windows XP 32-bit"] --- identifier: "{1f4de370-d627-11d1-ba4f-00a0c91eedba}" name: "Search Results - Computers (Computer Search Results Folder, Network Computers)" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003"] --- identifier: "{1fa9085f-25a2-489b-85d4-86326eedcd87}" name: "Manage Wireless Networks" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{208d2c60-3aea-1069-a2d7-08002b30309d}" name: "My Network Places (Network)" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{20d04fe0-3aea-1069-a2d8-08002b30309d}" name: "My Computer (Computer)" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{21ec2020-3aea-1069-a2dd-08002b30309d}" name: "Control Panel" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2227a280-3aea-1069-a2de-08002b30309d}" name: "Printers and Faxes (Printers)" windows_versions: ["Windows NT4", "Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- # Found in !RecentPlaces.lnk identifier: "{22877a6d-37a1-461a-91b0-dbda5aaebc99}" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{241d7c96-f8bf-4f85-b01f-e2b043341a4b}" name: "Workspaces Center (Remote Application and Desktop Connections)" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2559a1f0-21d7-11d4-bdaf-00c04f60b9f0}" name: "Search" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2559a1f1-21d7-11d4-bdaf-00c04f60b9f0}" name: "Help and Support" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2559a1f2-21d7-11d4-bdaf-00c04f60b9f0}" name: "Windows Security" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2559a1f3-21d7-11d4-bdaf-00c04f60b9f0}" name: "Run..." windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2559a1f4-21d7-11d4-bdaf-00c04f60b9f0}" name: "Internet" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista"] --- identifier: "{2559a1f5-21d7-11d4-bdaf-00c04f60b9f0}" name: "E-mail" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2559a1f6-21d7-11d4-bdaf-00c04f60b9f0}" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista"] --- identifier: "{2559a1f7-21d7-11d4-bdaf-00c04f60b9f0}" name: "Set Program Access and Defaults" windows_versions: ["Windows XP 32-bit", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{267cf8a9-f4e3-41e6-95b1-af881be130ff}" name: "Location Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{26ee0668-a00a-44d7-9371-beb064c98683}" name: "Control Panel" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2728520d-1ec8-4c68-a551-316b684c4ea7}" name: "Network Setup Wizard" windows_versions: ["Windows XP 32-bit"] --- identifier: "{28803f59-3a75-4058-995f-4ee5503b023c}" name: "Bluetooth Devices" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{289978ac-a101-4341-a817-21eba7fd046d}" name: "Sync Center Conflict Folder" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{289af617-1cc3-42a6-926c-e6a863f0e3ba}" name: "DLNA Media Servers Data Source" windows_versions: ["Windows 8.0"] --- identifier: "{2965e715-eb66-4719-b53f-1672673bbefa}" name: "Results Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{2e9e59c0-b437-4981-a647-9c34b9b90891}" name: "Sync Setup Folder" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{2f6ce85c-f9ee-43ca-90c7-8a9bd53a2467}" name: "File History Data Source" windows_versions: ["Windows 8.0"] --- identifier: "{3080f90d-d7ad-11d9-bd98-0000947b0257}" name: "Show Desktop" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{3080f90e-d7ad-11d9-bd98-0000947b0257}" name: "Window Switcher" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{323ca680-c24d-4099-b94d-446dd2d7249e}" name: "Common Places" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{328b0346-7eaf-4bbe-a479-7cb88a095f5b}" name: "Layout Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{335a31dd-f04b-4d76-a925-d6b47cf360df}" name: "Backup and Restore Center" windows_versions: ["Windows Vista"] --- identifier: "{35786d3c-b075-49b9-88dd-029876e11c01}" name: "Portable Devices" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{36eef7db-88ad-4e81-ad49-0e313f0c35f8}" name: "Windows Update" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{38a98528-6cbf-4ca9-8dc0-b1e1d10f7b1b}" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{3c5c43a3-9ce9-4a9b-9699-2ac0cf6cc4bf}" name: "Configure Wireless Network" windows_versions: ["Windows XP 32-bit"] --- identifier: "{3f6bc534-dfa1-4ab4-ae54-ef25a74e0107}" name: "System Restore" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{4026492f-2f69-46b8-b9bf-5654fc07e423}" name: "Windows Firewall" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{418c8b64-5463-461d-88e0-75e2afa3c6fa}" name: "Explorer Browser Results Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{4234d49b-0245-4df3-b780-3893943456e1}" name: "Applications" windows_versions: ["Windows 8.0"] --- # Found in Sample Music.lnk and Sample Pictures.lnk identifier: "{4336a54d-038b-4685-ab02-99bb52d3fb8b}" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{437ff9c0-a07f-4fa0-af80-84b6c6440a16}" name: "Command Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{450d8fba-ad25-11d0-98a8-0800361b1103}" name: "My Documents" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{48e7caab-b918-4e58-a94d-505519c795dc}" name: "Start Menu Folder" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{5399e694-6ce5-4d6c-8fce-1d8870fdcba0}" name: "Control Panel command object for Start menu and desktop" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- # Found in File Explorer.lnk identifier: "{52205fd8-5dfb-447d-801a-d0b52f2e83e1}" windows_versions: ["Windows 8.0"] --- identifier: "{58e3c745-d971-4081-9034-86e34b30836a}" name: "Speech Recognition Options" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{59031a47-3f72-44a7-89c5-5595fe6b30ee}" name: "Shared Documents Folder (Users Files)" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{5ea4f148-308c-46d7-98a9-49041b1dd468}" name: "Mobility Center Control Panel" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{60632754-c523-4b62-b45c-4172da012619}" name: "User Accounts" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{63da6ec0-2e98-11cf-8d82-444553540000}" name: "Microsoft FTP Folder" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{640167b4-59b0-47a6-b335-a6b3c0695aea}" name: "Portable Media Devices" windows_versions: ["Windows XP 32-bit", "Windows 2003"] --- identifier: "{645ff040-5081-101b-9f08-00aa002f954e}" name: "Recycle Bin" windows_versions: ["Windows NT4", "Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{64693913-1c21-4f30-a98f-4e52906d3b56}" class_name: CLSID_AppInstanceFolder windows_versions: ["Windows 8.0"] --- identifier: "{67718415-c450-4f3c-bf8a-b487642dc39b}" name: "Windows Features" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{6785bfac-9d2d-4be5-b7e2-59937e8fb80a}" name: "Other Users Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{679f85cb-0220-4080-b29b-5540cc05aab6}" name: Quick access windows_versions: [10] --- identifier: "{67ca7650-96e6-4fdd-bb43-a8e774f73a57}" name: "Home Group Control Panel (Home Group)" windows_versions: ["Windows 7", "Windows 8.0"] --- identifier: "{692f0339-cbaa-47e6-b5b5-3b84db604e87}" name: "Extensions Manager Folder" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista"] --- identifier: "{6dfd7c5c-2451-11d3-a299-00c04f8ef6af}" name: "Folder Options" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista"] --- identifier: "{7007acc7-3202-11d1-aad2-00805fc1270e}" name: "Network Connections (Network and Dial-up Connections)" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista"] --- identifier: "{708e1662-b832-42a8-bbe1-0a77121e3908}" name: "Tree property value folder" windows_versions: ["Windows Vista"] --- identifier: "{71d99464-3b6b-475c-b241-e15883207529}" name: "Sync Results Folder" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{72b36e70-8700-42d6-a7f7-c9ab3323ee51}" name: "Search Connector Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{78f3955e-3b90-4184-bd14-5397c15f1efc}" name: "Performance Information and Tools" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{7a9d77bd-5403-11d2-8785-2e0420524153}" name: "User Accounts (Users and Passwords)" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{7b81be6a-ce2b-4676-a29e-eb907a5126c5}" name: "Programs and Features" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{7bd29e00-76c1-11cf-9dd0-00a0c9034933}" name: "Temporary Internet Files" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{7bd29e01-76c1-11cf-9dd0-00a0c9034933}" name: "Temporary Internet Files" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{7be9d83c-a729-4d97-b5a7-1b7313c39e0a}" name: "Programs Folder" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{8060b2e3-c9d7-4a5d-8c6b-ce8eba111328}" name: "Proximity CPL" windows_versions: ["Windows 8.0"] --- identifier: "{8343457c-8703-410f-ba8b-8b026e431743}" name: "Feedback Tool" windows_versions: ["Windows 8.0"] --- identifier: "{85bbd920-42a0-1069-a2e4-08002b30309d}" name: "Briefcase" windows_versions: ["Windows NT4", "Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{863aa9fd-42df-457b-8e4d-0de1b8015c60}" name: "Remote Printers" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{865e5e76-ad83-4dca-a109-50dc2113ce9a}" name: "Programs Folder and Fast Items" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{871c5380-42a0-1069-a2ea-08002b30309d}" name: "Internet Explorer (Homepage)" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{87630419-6216-4ff8-a1f0-143562d16d5c}" name: "Mobile Broadband Profile Settings Editor" windows_versions: ["Windows 7", "Windows 8.0"] --- identifier: "{877ca5ac-cb41-4842-9c69-9136e42d47e2}" name: "File Backup Index" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{88c6c381-2e85-11d0-94de-444553540000}" name: "ActiveX Cache Folder" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{896664f7-12e1-490f-8782-c0835afd98fc}" name: "Libraries delegate folder that appears in Users Files Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{89d83576-6bd1-4c86-9454-beb04e94c819}" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{8e908fc9-becc-40f6-915b-f4ca0e70d03d}" name: "Network and Sharing Center" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{8fd8b88d-30e1-4f25-ac2b-553d3d65f0ea}" name: "DXP" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{9113a02d-00a3-46b9-bc5f-9c04daddd5d7}" name: "Enhanced Storage Data Source" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{93412589-74d4-4e4e-ad0e-e0cb621440fd}" name: "Font Settings" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{9343812e-1c37-4a49-a12e-4b2d810d956b}" name: "Search Home" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{96437431-5a90-4658-a77c-25478734f03e}" name: "Server Manager" windows_versions: ["Windows 2008"] --- identifier: "{96ae8d84-a250-4520-95a5-a47a7e3c548b}" name: "Parental Controls" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{98d99750-0b8a-4c59-9151-589053683d73}" name: "Windows Search Service Media Center Namespace Extension Handler" windows_versions: ["Windows 7", "Windows 8.0"] --- identifier: "{98f275b4-4fff-11e0-89e2-7b86dfd72085}" class_name: CLSID_StartMenuLauncherProviderFolder windows_versions: ["Windows 8.0"] --- identifier: "{992cffa0-f557-101a-88ec-00dd010ccc48}" name: "Network Connections (Network and Dial-up Connections)" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{9a096bb5-9dc3-4d1c-8526-c3cbf991ea4e}" name: "Internet Explorer RSS Feeds Folder" windows_versions: ["Windows XP 32-bit", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{9c60de1e-e5fc-40f4-a487-460851a8d915}" name: "AutoPlay" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{9c73f5e5-7ae7-4e32-a8e8-8d23b85255bf}" name: "Sync Center Folder" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{9db7a13c-f208-4981-8353-73cc61ae2783}" name: "Previous Versions" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{9f433b7c-5f96-4ce1-ac28-aeaa1cc04d7c}" name: "Security Center" windows_versions: ["Windows Vista"] --- identifier: "{9fe63afd-59cf-4419-9775-abcc3849f861}" name: "System Recovery (Recovery)" windows_versions: ["Windows 7", "Windows 8.0"] --- identifier: "{a00ee528-ebd9-48b8-944a-8942113d46ac}" class_name: CLSID_StartMenuCommandingProviderFolder windows_versions: ["Windows 8.0"] --- identifier: "{a3c3d402-e56c-4033-95f7-4885e80b0111}" name: "Previous Versions Results Delegate Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{a5a3563a-5755-4a6f-854e-afa3230b199f}" name: "Library Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{a5e46e3a-8849-11d1-9d8c-00c04fc99d61}" name: "Microsoft Browser Architecture" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista"] --- identifier: "{a6482830-08eb-41e2-84c1-73920c2badb9}" name: "Removable Storage Devices" windows_versions: ["Windows 8.0"] --- identifier: "{a8a91a66-3a7d-4424-8d24-04e180695c7a}" name: "Device Center (Devices and Printers)" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{aee2420f-d50e-405c-8784-363c582bf45a}" name: "Device Pairing Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{afdb1f70-2a4c-11d2-9039-00c04f8eeb3e}" name: "Offline Files Folder" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows 8.0"] --- identifier: "{b155bdf8-02f0-451e-9a26-ae317cfd7779}" name: "Nethood delegate folder (Delegate folder that appears in Computer)" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{b2952b16-0e07-4e5a-b993-58c52cb94cae}" name: "DB Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{b4fb3f98-c1ea-428d-a78a-d1f5659cba93}" name: "Other Users Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{b98a2bea-7d42-4558-8bd1-832f41bac6fd}" name: "Backup And Restore (Backup and Restore Center)" windows_versions: ["Windows 7", "Windows 8.0"] --- identifier: "{bb06c0e4-d293-4f75-8a90-cb05b6477eee}" name: "System" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{bb64f8a7-bee7-4e1a-ab8d-7d8273f7fdb6}" name: "Action Center Control Panel" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{bc476f4c-d9d7-4100-8d4e-e043f6dec409}" name: "Microsoft Browser Architecture" windows_versions: ["Windows XP 32-bit", "Windows Vista"] --- identifier: "{bc48b32f-5910-47f5-8570-5074a8a5636a}" name: "Sync Results Delegate Folder" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{bd7a2e7b-21cb-41b2-a086-b309680c6b7e}" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{bd84b380-8ca2-1069-ab1d-08000948f534}" name: "Microsoft Windows Font Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{bdeadf00-c265-11d0-bced-00a0c90ab50f}" name: "Web Folders" windows_versions: ["Windows 2000", "Windows XP 32-bit"] --- identifier: "{be122a0e-4503-11da-8bde-f66bad1e3f3a}" name: "Windows Anytime Upgrade" windows_versions: ["Windows Vista"] --- identifier: "{bf782cc9-5a52-4a17-806c-2a894ffeeac5}" name: "Language Settings" windows_versions: ["Windows 8.0"] --- identifier: "{c291a080-b400-4e34-ae3f-3d2b9637d56c}" name: "UNCFATShellFolder Class" windows_versions: ["Windows XP 32-bit"] --- identifier: "{c2b136e2-d50e-405c-8784-363c582bf43e}" name: "Device Center Initialization" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{c555438b-3c23-4769-a71f-b6d3d9b6053a}" name: "Display" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{c57a6066-66a3-4d91-9eb9-41532179f0a5}" name: "Application Suggested Locations" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{c58c4893-3be0-4b45-abb5-a63e4b8c8651}" name: "Troubleshooting" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{cb1b7f8c-c50a-4176-b604-9e24dee8d4d1}" name: "Welcome Center (Getting Started)" windows_versions: ["Windows Vista", "Windows 7"] --- identifier: "{d2035edf-75cb-4ef1-95a7-410d9ee17170}" name: "DLNA Content Directory Data Source" windows_versions: ["Windows 8.0"] --- identifier: "{d20ea4e1-3957-11d2-a40b-0c5020524152}" name: "Fonts" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista"] --- identifier: "{d20ea4e1-3957-11d2-a40b-0c5020524153}" name: "Administrative Tools" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{d34a6ca6-62c2-4c34-8a7c-14709c1ad938}" name: "Common Places FS Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{d426cfd0-87fc-4906-98d9-a23f5d515d61}" name: "Windows Search Service Outlook Express Protocol Handler" windows_versions: ["Windows XP 32-bit"] --- identifier: "{d4480a50-ba28-11d1-8e75-00c04fa31a86}" name: "Add Network Place" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{d450a8a1-9568-45c7-9c0e-b4f9fb4537bd}" name: "Installed Updates" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{d555645e-d4f8-4c29-a827-d93c859c4f2a}" name: "Ease of Access (Ease of Access Center)" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{d5b1944e-db4e-482e-b3f1-db05827f0978}" name: "Softex OmniPass Encrypted Folder" windows_versions: ["Windows XP 32-bit"] --- identifier: "{d6277990-4c6a-11cf-8d87-00aa0060f5bf}" name: "Scheduled Tasks" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003"] --- identifier: "{d8559eb9-20c0-410e-beda-7ed416aecc2a}" name: "Windows Defender" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{d9ef8727-cac2-4e60-809e-86f80a666c91}" name: "Secure Startup (BitLocker Drive Encryption)" windows_versions: ["Windows 8.0"] --- identifier: "{daf95313-e44d-46af-be1b-cbacea2c3065}" class_name: CLSID_StartMenuProviderFolder windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{dffacdc5-679f-4156-8947-c5c76bc0b67f}" name: "Delegate folder that appears in Users Files Folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{e17d4fc0-5564-11d1-83f2-00a0c90dc849}" name: "Search Results Folder" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003"] --- identifier: "{e211b736-43fd-11d1-9efb-0000f8757fcd}" name: "Scanners and Cameras" windows_versions: ["Windows XP 32-bit", "Windows 2003"] --- identifier: "{e345f35f-9397-435c-8f95-4e922c26259e}" class_name: CLSID_StartMenuPathCompleteProviderFolder windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{e413d040-6788-4c22-957e-175d1c513a34}" name: "Sync Center Conflict Delegate Folder" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{e773f1af-3a65-4866-857d-846fc9c4598a}" name: "Shell Storage Folder Viewer" windows_versions: ["Windows XP 32-bit", "Windows 2003"] --- identifier: "{e7de9b1a-7533-4556-9484-b26fb486475e}" name: "Network Map" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7"] --- identifier: "{e7e4bc40-e76a-11ce-a9bb-00aa004ae837}" name: "Shell DocObject Viewer" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{e88dcce0-b7b3-11d1-a9f0-00aa0060fa31}" name: "Compressed Folder" windows_versions: ["Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{e95a4861-d57a-4be1-ad0f-35267e261739}" name: "Windows SideShow" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{e9950154-c418-419e-a90a-20c5287ae24b}" name: "Sensors (Location and Other Sensors)" windows_versions: ["Windows 7", "Windows 8.0"] --- identifier: "{ed228fdf-9ea8-4870-83b1-96b02cfe0d52}" name: "My Games (Games Explorer)" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{ed50fc29-b964-48a9-afb3-15ebb9b97f36}" name: "PrintHood delegate folder" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{ed7ba470-8e54-465e-825c-99712043e01c}" name: "All Tasks" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{ed834ed6-4b5a-4bfe-8f11-a626dcb6a921}" name: "Personalization Control Panel" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{edc978d6-4d53-4b2f-a265-5805674be568}" name: "Stream Backed Folder" windows_versions: ["Windows 8.0"] --- identifier: "{f02c1a0d-be21-4350-88b0-7367fc96ef3c}" name: "Computers and Devices" windows_versions: ["Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{f1390a9a-a3f4-4e5d-9c5f-98f3bd8d935c}" name: "Sync Setup Delegate Folder" windows_versions: ["Windows Vista", "Windows 7", "Windows 8.0"] --- identifier: "{f3f5824c-ad58-4728-af59-a1ebe3392799}" name: "Sticky Notes Namespace Extension for Windows Desktop Search" windows_versions: ["Windows 7", "Windows 8.0"] --- identifier: "{f5175861-2688-11d0-9c5e-00aa00a45957}" name: "Subscription Folder" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{f6b6e965-e9b2-444b-9286-10c9152edbc5}" name: "History Vault" windows_versions: ["Windows 8.0"] --- identifier: "{f8c2ab3b-17bc-41da-9758-339d7dbf2d88}" name: "Previous Versions Results Folder" windows_versions: ["Windows 2008", "Windows 7", "Windows 8.0"] --- identifier: "{f90c627b-7280-45db-bc26-cce7bdd620a4}" name: "All Tasks" windows_versions: ["Windows 8.0"] --- identifier: "{f942c606-0914-47ab-be56-1321b8035096}" name: "Storage Spaces" windows_versions: ["Windows 8.0"] --- identifier: "{fb0c9c8a-6c50-11d1-9f1d-0000f8757fcd}" name: "Scanners & Cameras" windows_versions: ["Windows XP 32-bit", "Windows 2003"] --- identifier: "{fbf23b42-e3f0-101b-8488-00aa003e56f8}" name: "Internet Explorer" windows_versions: ["Windows NT4", "Windows 2000", "Windows XP 32-bit", "Windows 2003"] --- identifier: "{fe1290f0-cfbd-11cf-a330-00aa00c16e65}" name: "Directory" windows_versions: ["Windows 2000"] --- identifier: "{ff393560-c2a7-11cf-bff4-444553540000}" name: "History" windows_versions: ["Windows 2000", "Windows XP 32-bit", "Windows 2003", "Windows Vista", "Windows 2008", "Windows 7", "Windows 8.0"] ================================================ FILE: winregrc/data_format.py ================================================ """Binary data format.""" import os from dfdatetime import filetime as dfdatetime_filetime from dtfabric import errors as dtfabric_errors from dtfabric.runtime import fabric as dtfabric_fabric from winregrc import errors class BinaryDataFormat: """Binary data format.""" # The dtFabric definition file, which must be overwritten by a subclass. _DEFINITION_FILE = None # Preserve the absolute path value of __file__ in case it is changed # at run-time. _DEFINITION_FILES_PATH = os.path.dirname(__file__) _HEXDUMP_CHARACTER_MAP = [ '.' if byte < 0x20 or byte > 0x7e else chr(byte) for byte in range(256)] def __init__(self, debug=False, output_writer=None): """Initializes a binary data format. Args: debug (Optional[bool]): True if debug information should be written. output_writer (Optional[OutputWriter]): output writer. """ super().__init__() self._data_type_maps = {} self._debug = debug self._fabric = self._ReadDefinitionFile(self._DEFINITION_FILE) self._output_writer = output_writer def _DebugPrintData(self, description, data): """Prints data for debugging. Args: description (str): description. data (bytes): data. """ if self._output_writer: self._output_writer.WriteText(f'{description:s}:\n') value_string = self._FormatDataInHexadecimal(data) self._output_writer.WriteText(value_string) def _DebugPrintDecimalValue(self, description, value): """Prints a decimal value for debugging. Args: description (str): description. value (int): value. """ self._DebugPrintValue(description, f'{value:d}') def _DebugPrintFiletimeValue(self, description, value): """Prints a FILETIME timestamp value for debugging. Args: description (str): description. value (object): value. """ if value == 0: date_time_string = 'Not set (0)' elif value == 0x7fffffffffffffff: date_time_string = 'Never (0x7fffffffffffffff)' else: date_time = dfdatetime_filetime.Filetime(timestamp=value) date_time_string = date_time.CopyToDateTimeString() if date_time_string: date_time_string = f'{date_time_string:s} UTC' else: date_time_string = f'0x{value:08x}' self._DebugPrintValue(description, date_time_string) def _DebugPrintStructureObject(self, structure_object, debug_info): """Prints structure object debug information. Args: structure_object (object): structure object. debug_info (list[tuple[str, str, int]]): debug information. """ text = self._FormatStructureObject(structure_object, debug_info) self._output_writer.WriteText(text) def _DebugPrintText(self, text): """Prints text for debugging. Args: text (str): text. """ if self._output_writer: self._output_writer.DebugPrintText(text) def _DebugPrintValue(self, description, value): """Prints a value for debugging. Args: description (str): description. value (object): value. """ if self._output_writer: text = self._FormatValue(description, value) self._output_writer.WriteText(text) def _FormatDataInHexadecimal(self, data): """Formats data in a hexadecimal representation. Args: data (bytes): data. Returns: str: hexadecimal representation of the data. """ in_group = False previous_hexadecimal_string = None lines = [] data_size = len(data) for block_index in range(0, data_size, 16): data_string = data[block_index:block_index + 16] hexadecimal_byte_values = [] printable_values = [] for byte_value in data_string: if isinstance(byte_value, str): byte_value = ord(byte_value) hexadecimal_byte_values.append(f'{byte_value:02x}') printable_value = self._HEXDUMP_CHARACTER_MAP[byte_value] printable_values.append(printable_value) remaining_size = 16 - len(data_string) if remaining_size == 0: whitespace = '' elif remaining_size >= 8: whitespace = ' ' * ((3 * remaining_size) - 1) else: whitespace = ' ' * (3 * remaining_size) hexadecimal_string_part1 = ' '.join(hexadecimal_byte_values[0:8]) hexadecimal_string_part2 = ' '.join(hexadecimal_byte_values[8:16]) hexadecimal_string = ( f'{hexadecimal_string_part1:s} {hexadecimal_string_part2:s}' f'{whitespace:s}') if (previous_hexadecimal_string is not None and previous_hexadecimal_string == hexadecimal_string and block_index + 16 < data_size): if not in_group: in_group = True lines.append('...') else: printable_string = ''.join(printable_values) lines.append( f'0x{block_index:08x} {hexadecimal_string:s} ' f'{printable_string:s}') in_group = False previous_hexadecimal_string = hexadecimal_string lines.extend(['', '']) return '\n'.join(lines) def _FormatIntegerAsDecimal(self, integer): """Formats an integer as a decimal. Args: integer (int): integer. Returns: str: integer formatted as a decimal. """ return f'{integer:d}' def _FormatIntegerAsFiletime(self, integer): """Formats an integer as a FILETIME date and time value. Args: integer (int): integer. Returns: str: integer formatted as a FILETIME date and time value. """ if integer == 0: return 'Not set (0)' if integer == 0x7fffffffffffffff: return 'Never (0x7fffffffffffffff)' date_time = dfdatetime_filetime.Filetime(timestamp=integer) date_time_string = date_time.CopyToDateTimeString() if not date_time_string: return f'0x{integer:08x}' return f'{date_time_string:s} UTC' def _FormatIntegerAsHexadecimal2(self, integer): """Formats an integer as an 2-digit hexadecimal. Args: integer (int): integer. Returns: str: integer formatted as an 2-digit hexadecimal. """ return f'0x{integer:02x}' def _FormatIntegerAsHexadecimal4(self, integer): """Formats an integer as an 4-digit hexadecimal. Args: integer (int): integer. Returns: str: integer formatted as an 4-digit hexadecimal. """ return f'0x{integer:04x}' def _FormatIntegerAsHexadecimal8(self, integer): """Formats an integer as an 8-digit hexadecimal. Args: integer (int): integer. Returns: str: integer formatted as an 8-digit hexadecimal. """ return f'0x{integer:08x}' def _FormatStructureObject(self, structure_object, debug_info): """Formats a structure object debug information. Args: structure_object (object): structure object. debug_info (list[tuple[str, str, int]]): debug information. Returns: str: structure object debug information. """ lines = [] attribute_value = '' for attribute_name, description, value_format_callback in debug_info: attribute_value = getattr(structure_object, attribute_name, None) if attribute_value is None: continue value_format_function = None if value_format_callback: value_format_function = getattr(self, value_format_callback, None) if value_format_function: attribute_value = value_format_function(attribute_value) if isinstance(attribute_value, str) and '\n' in attribute_value: text = '' if description is not None: text = f'{description:s}:\n' text = ''.join([text, attribute_value]) else: text = self._FormatValue(description, attribute_value) lines.append(text) if not attribute_value or attribute_value[:-2] != '\n\n': lines.append('\n') return ''.join(lines) def _FormatValue(self, description, value): """Formats a value for debugging. Args: description (str): description. value (object): value. Returns: str: formatted value. """ alignment, _ = divmod(len(description), 8) alignment_string = '\t' * (8 - alignment + 1) return f'{description:s}{alignment_string:s}: {value!s}\n' def _GetDataTypeMap(self, name): """Retrieves a data type map defined by the definition file. The data type maps are cached for reuse. Args: name (str): name of the data type as defined by the definition file. Returns: dtfabric.DataTypeMap: data type map which contains a data type definition, such as a structure, that can be mapped onto binary data. """ data_type_map = self._data_type_maps.get(name) if not data_type_map: data_type_map = self._fabric.CreateDataTypeMap(name) self._data_type_maps[name] = data_type_map return data_type_map def _ReadDefinitionFile(self, filename): """Reads a dtFabric definition file. Args: filename (str): name of the dtFabric definition file. Returns: dtfabric.DataTypeFabric: data type fabric which contains the data format data type maps of the data type definition, such as a structure, that can be mapped onto binary data or None if no filename is provided. """ if not filename: return None path = os.path.join(self._DEFINITION_FILES_PATH, filename) with open(path, 'rb') as file_object: definition = file_object.read() return dtfabric_fabric.DataTypeFabric(yaml_definition=definition) def _ReadStructureFromByteStream( self, byte_stream, file_offset, data_type_map, description, context=None): """Reads a structure from a byte stream. Args: byte_stream (bytes): byte stream. file_offset (int): offset of the structure data relative to the start of the file-like object. data_type_map (dtfabric.DataTypeMap): data type map of the structure. description (str): description of the structure. context (Optional[dtfabric.DataTypeMapContext]): data type map context. Returns: object: structure values object. Raises: ParseError: if the structure cannot be read. ValueError: if file-like object or data type map is missing. """ if not byte_stream: raise ValueError('Missing byte stream.') if not data_type_map: raise ValueError('Missing data type map.') try: return data_type_map.MapByteStream(byte_stream, context=context) except (dtfabric_errors.ByteStreamTooSmallError, dtfabric_errors.MappingError) as exception: raise errors.ParseError(( f'Unable to map {description:s} data at offset: 0x{file_offset:08x} ' f'with error: {exception!s}')) ================================================ FILE: winregrc/delegatefolders.py ================================================ """Windows delegate folders collector.""" from winregrc import interface class DelegateFolder: """Delegate folder. Attributes: identifier (str): identifier. name (str): name. namespace (str): namespace. """ def __init__(self, identifier, name, namespace): """Initializes a delegate folder. Args: identifier (str): identifier. name (str): name. namespace (str): namespace. """ super().__init__() self.identifier = identifier self.name = name self.namespace = namespace class DelegateFoldersCollector(interface.WindowsRegistryKeyCollector): """Windows delegate folders collector.""" _EXPLORER_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer') def _CollectDelegateFolders(self, delegate_folders_key, namespace): """Collects Windows delegate folders. Args: delegate_folders_key (dfwinreg.WinRegistryKey): delegate folders Windows Registry key. namespace (str): namespace. Yields: DelegateFolder: a delegate folder. """ for subkey in delegate_folders_key.GetSubkeys(): name = self._GetValueFromKey(subkey, '') yield DelegateFolder(subkey.name, name, namespace) def Collect(self, registry): """Collects Windows delegate folders. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: DelegateFolder: a delegate folder. """ explorer_key = registry.GetKeyByPath(self._EXPLORER_KEY_PATH) if explorer_key: for subkey in explorer_key.GetSubkeys(): delegate_folders_key = subkey.GetSubkeyByPath( 'NameSpace\\DelegateFolders') if delegate_folders_key: yield from self._CollectDelegateFolders( delegate_folders_key, subkey.name) ================================================ FILE: winregrc/environment_variables.py ================================================ """Environment variables collector.""" from winregrc import interface class EnvironmentVariable: """Environment variable. Attributes: name (str): name. value (str): value. """ def __init__(self, name, value): """Initializes an environment variable. Args: name (str): name. value (str): value. """ super().__init__() self.name = name self.value = value class EnvironmentVariablesCollector(interface.WindowsRegistryKeyCollector): """Environment variables collector.""" _ENVIRONMENT_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\' 'Session Manager\\Environment') _PROFILELIST_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\' 'ProfileList') _WINDOWS_CURRENTVERSION_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion') _WINDOWS_NT_CURRENTVERSION_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion') _PROFILELIST_KEY_VALUE_MAPPINGS = { 'AllUsersProfile': '%AllUsersProfile%', 'ProgramData': '%ProgramData%', 'Public': '%Public%'} _WINDOWS_KEY_VALUE_MAPPINGS = { 'CommonFilesDir': '%CommonProgramFiles%', 'CommonFilesDir (x86)': '%CommonProgramFiles(x86)%', 'CommonW6432Dir': '%CommonProgramW6432%', 'ProgramFilesDir': '%ProgramFiles%', 'ProgramFilesDir (x86)': '%ProgramFiles(x86)%', 'ProgramW6432Dir': '%ProgramW6432%'} _WINDOWS_NT_KEY_VALUE_MAPPINGS = { 'SystemRoot': '%SystemRoot%'} def _CollectEnvironmentVariablesFromEnvironmentKey(self, registry_key): """Collects environment variables. Args: registry_key (dfwinreg.WinRegistryKey): environment Windows Registry key. Yields: EnvironmentVariable: an environment variable. """ for registry_value in registry_key.GetValues(): value_string = registry_value.GetDataAsObject() yield EnvironmentVariable(f'%{registry_value.name:s}%', value_string) def _CollectEnvironmentVariablesWithMappings(self, registry_key, mappings): """Collects environment variables. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. Yields: EnvironmentVariable: an environment variable. """ for value_name, environment_variable_name in mappings.items(): registry_value = registry_key.GetValueByName(value_name) if registry_value: value_string = registry_value.GetDataAsObject() yield EnvironmentVariable(environment_variable_name, value_string) def Collect(self, registry): """Collects environment variables. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: EnvironmentVariable: an environment variable. """ registry_key = registry.GetKeyByPath(self._ENVIRONMENT_KEY_PATH) if registry_key: yield from self._CollectEnvironmentVariablesFromEnvironmentKey( registry_key) registry_key = registry.GetKeyByPath(self._PROFILELIST_KEY_PATH) if registry_key: yield from self._CollectEnvironmentVariablesWithMappings( registry_key, self._PROFILELIST_KEY_VALUE_MAPPINGS) registry_key = registry.GetKeyByPath(self._WINDOWS_CURRENTVERSION_KEY_PATH) if registry_key: yield from self._CollectEnvironmentVariablesWithMappings( registry_key, self._WINDOWS_KEY_VALUE_MAPPINGS) registry_key = registry.GetKeyByPath( self._WINDOWS_NT_CURRENTVERSION_KEY_PATH) if registry_key: yield from self._CollectEnvironmentVariablesWithMappings( registry_key, self._WINDOWS_NT_KEY_VALUE_MAPPINGS) ================================================ FILE: winregrc/errors.py ================================================ """The error objects.""" class Error(Exception): """The error interface.""" class ParseError(Error): """Error that is raised when value data cannot be parsed.""" ================================================ FILE: winregrc/eventlog_providers.py ================================================ """Windows Event Log providers collector.""" from winregrc import interface class EventLogProvider: """Windows Event Log provider. Attributes: additional_identifier (str): additional identifier of the provider, contains a GUID. category_message_files (set[str]): paths of the category message files. event_message_files (set[str]): paths of the event message files. identifier (str): identifier of the provider, contains a GUID. log_sources (list[str]): names of the corresponding Event Log sources. log_types (list[str]): Windows Event Log types. name (str): name of the provider. parameter_message_files (set[str]): paths of the parameter message files. """ def __init__(self): """Initializes a Windows Event Log provider.""" super().__init__() self.additional_identifier = None self.category_message_files = set() self.event_message_files = set() self.identifier = None self.log_sources = [] self.log_types = [] self.name = None self.parameter_message_files = set() class EventLogProvidersCollector(interface.WindowsRegistryKeyCollector): """Windows Event Log providers collector.""" _SERVICES_EVENTLOG_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\EventLog') _WINEVT_PUBLISHERS_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'WINEVT\\Publishers') def _CollectEventLogProviders( self, services_eventlog_key, winevt_publishers_key): """Collects Windows Event Log providers. Args: services_eventlog_key (dfwinreg.WinRegistryKey): a Services\\EventLog Windows Registry. winevt_publishers_key (dfwinreg.WinRegistryKey): a WINEVT\\Publishers Windows Registry. Yields: EventLogProvider: an Event Log provider. """ event_log_providers_per_identifier = {} event_log_providers_per_name = {} for event_log_provider in self._CollectEventLogProvidersFromPublishersKeys( winevt_publishers_key): provider_identifier = event_log_provider.identifier existing_event_log_provider = event_log_providers_per_identifier.get( provider_identifier, None) if existing_event_log_provider: self._MergeEventLogProviders( existing_event_log_provider, event_log_provider) else: event_log_providers_per_identifier[provider_identifier] = ( event_log_provider) if event_log_provider.name: event_log_providers_per_name[event_log_provider.name] = ( event_log_provider) event_log_providers_per_log_source = {} for event_log_provider in self._CollectEventLogProvidersFromServicesKey( services_eventlog_key): provider_identifier = event_log_provider.identifier if provider_identifier: existing_event_log_provider = event_log_providers_per_identifier.get( provider_identifier, None) if existing_event_log_provider: self._MergeEventLogProviders( existing_event_log_provider, event_log_provider) continue log_source = event_log_provider.log_sources[0] existing_event_log_provider = event_log_providers_per_name.get( log_source, None) if existing_event_log_provider: if (provider_identifier and provider_identifier != existing_event_log_provider.identifier): existing_event_log_provider.additional_identifier = ( provider_identifier) self._MergeEventLogProviders( existing_event_log_provider, event_log_provider) continue event_log_providers_per_log_source[log_source] = event_log_provider event_log_providers = list(event_log_providers_per_identifier.values()) event_log_providers.extend(event_log_providers_per_log_source.values()) for event_log_provider in sorted( event_log_providers, key=self._GetEventLogProviderSortedKey): event_log_provider.category_message_files = self._NormalizeMessageFiles( event_log_provider.category_message_files) event_log_provider.event_message_files = self._NormalizeMessageFiles( event_log_provider.event_message_files) event_log_provider.parameter_message_files = self._NormalizeMessageFiles( event_log_provider.parameter_message_files) yield event_log_provider def _CollectEventLogProvidersFromPublishersKeys(self, winevt_publishers_key): """Collects Windows Event Log providers from a WINEVT publishers key. Args: winevt_publishers_key (dfwinreg.WinRegistryKey): WINEVT publishers key. Yield: EventLogProvider: Event Log provider. """ if winevt_publishers_key: for guid_key in winevt_publishers_key.GetSubkeys(): event_log_provider = EventLogProvider() event_log_provider.identifier = guid_key.name.lower() event_log_provider.name = self._GetValueFromKey(guid_key, '') event_message_files = self._GetMessageFilePathsFromKey( guid_key, 'MessageFileName') event_log_provider.event_message_files = event_message_files # TODO: add support for ResourceFileName value # TODO: add support for ParameterFileName value yield event_log_provider def _CollectEventLogProvidersFromServicesKey(self, services_eventlog_key): """Collects Windows Event Log providers from a services Event Log key. Args: services_eventlog_key (dfwinreg.WinRegistryKey): services Event Log key. Yield: EventLogProvider: Event Log provider. """ if services_eventlog_key: for log_type_key in services_eventlog_key.GetSubkeys(): for provider_key in log_type_key.GetSubkeys(): provider_identifier = self._GetValueFromKey( provider_key, 'ProviderGuid', default_value='') provider_identifier = provider_identifier.lower() event_log_provider = EventLogProvider() event_log_provider.identifier = provider_identifier or None event_log_provider.log_sources = [provider_key.name] event_log_provider.log_types = [log_type_key.name] category_message_files = self._GetMessageFilePathsFromKey( provider_key, 'CategoryMessageFile') event_log_provider.category_message_files = category_message_files event_message_files = self._GetMessageFilePathsFromKey( provider_key, 'EventMessageFile') event_log_provider.event_message_files = event_message_files parameter_message_files = self._GetMessageFilePathsFromKey( provider_key, 'ParameterMessageFile') event_log_provider.parameter_message_files = parameter_message_files yield event_log_provider def _GetEventLogProviderSortedKey(self, event_log_provider): """Retrieves a key to sort Event Log providers on. Args: event_log_provider (EventLogProvider): Event Log provider. Returns: str: key to sort Event Log providers on. """ if not event_log_provider.log_sources: return event_log_provider.name or '' return event_log_provider.log_sources[0] def _GetMessageFilePathsFromKey(self, registry_key, value_name): """Retrieves a value as a list of message file paths. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. value_name (str): name of the value. Returns: set[str]: paths of message files. """ message_files = set() registry_value = registry_key.GetValueByName(value_name) if registry_value: value_string = registry_value.GetDataAsObject() for path in value_string.split(';'): path = path.strip() if path: message_files.add(path) return message_files def _MergeEventLogProviders( self, first_event_log_provider, second_event_log_provider): """Merges the information of the second Event Log provider into the first. Args: first_event_log_provider (EventLogProvider): first Event Log provider. second_event_log_provider (EventLogProvider): second Event Log provider. """ for log_source in second_event_log_provider.log_sources: if log_source not in first_event_log_provider.log_sources: first_event_log_provider.log_sources.append(log_source) for log_type in second_event_log_provider.log_types: if log_type not in first_event_log_provider.log_types: first_event_log_provider.log_types.append(log_type) first_event_log_provider.category_message_files.update( second_event_log_provider.category_message_files) first_event_log_provider.event_message_files.update( second_event_log_provider.event_message_files) first_event_log_provider.parameter_message_files.update( second_event_log_provider.parameter_message_files) def _NormalizeMessageFiles(self, message_files): """Normalizes the message files. Args: message_files (list[str]): paths of the message files. Returns: set[str]: normalized paths of the message files. """ normalized_message_files = set() paths_lower = set() for path in message_files: path_lower = path.lower() if path_lower not in paths_lower: paths_lower.add(path_lower) normalized_message_files.add(path) return normalized_message_files def Collect(self, registry): """Collects Windows Event Log providers from a Windows Registry. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: generator[EventLogProvider]: Event Log provider generator. """ # TODO: add support to collect Event Log providers from all control sets. services_eventlog_key = registry.GetKeyByPath( self._SERVICES_EVENTLOG_KEY_PATH) winevt_publishers_key = registry.GetKeyByPath( self._WINEVT_PUBLISHERS_KEY_PATH) return self._CollectEventLogProviders( services_eventlog_key, winevt_publishers_key) ================================================ FILE: winregrc/filters.py ================================================ """The Windows Registry key and value filters.""" import abc class BaseWindowsRegistryKeyFilter: """Windows Registry key filter interface.""" # Note that redundant-returns-doc is broken for pylint 1.7.x # pylint: disable=redundant-returns-doc @property def key_paths(self): """List of key paths defined by the filter.""" return [] @abc.abstractmethod def Match(self, registry_key): """Determines if a Windows Registry key matches the filter. Args: registry_key (dfwinreg.WinRegistryKey): a Windows Registry key. Returns: bool: True if a match, False otherwise. """ class WindowsRegistryKeyPathFilter(BaseWindowsRegistryKeyFilter): """Windows Registry key path filter.""" _CONTROL_SET_PREFIX = ( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet') # This list must be ordered with most specific matches first. _WOW64_PREFIXES = [ 'HKEY_CURRENT_USER\\Software\\Classes', 'HKEY_CURRENT_USER\\Software', 'HKEY_LOCAL_MACHINE\\Software\\Classes', 'HKEY_LOCAL_MACHINE\\Software'] def __init__(self, key_path): """Initializes a Windows Registry key filter. Args: key_path (str): key path. """ super().__init__() key_path.rstrip('\\') self._key_path = key_path key_path = key_path.upper() self._key_path_upper = key_path self._wow64_key_path = None self._wow64_key_path_upper = None if key_path.startswith(self._CONTROL_SET_PREFIX.upper()): self._key_path_prefix, _, self._key_path_suffix = key_path.partition( 'CurrentControlSet'.upper()) else: self._key_path_prefix = None self._key_path_suffix = None # Handle WoW64 Windows Registry key redirection. # Also see: # https://msdn.microsoft.com/en-us/library/windows/desktop/ # ms724072%28v=vs.85%29.aspx # https://msdn.microsoft.com/en-us/library/windows/desktop/ # aa384253(v=vs.85).aspx wow64_prefix = None for key_path_prefix in self._WOW64_PREFIXES: if key_path.startswith(key_path_prefix.upper()): wow64_prefix = key_path_prefix break if wow64_prefix: key_path_suffix = self._key_path[len(wow64_prefix):] if key_path_suffix.startswith('\\'): key_path_suffix = key_path_suffix[1:] self._wow64_key_path = '\\'.join([ wow64_prefix, 'Wow6432Node', key_path_suffix]) self._wow64_key_path_upper = self._wow64_key_path.upper() @property def key_paths(self): """Retrieves the key paths defined by the filter. Returns: list[str]: key paths defined by the filter. """ if self._wow64_key_path: return [self._key_path, self._wow64_key_path] return [self._key_path] def Match(self, registry_key): """Determines if a Windows Registry key matches the filter. Args: registry_key (dfwinreg.WinRegistryKey): a Windows Registry key. Returns: bool: True if a match, False otherwise. """ key_path = registry_key.path.upper() if self._key_path_prefix and self._key_path_suffix: if (key_path.startswith(self._key_path_prefix) and key_path.endswith(self._key_path_suffix)): key_path_segment = key_path[ len(self._key_path_prefix):-len(self._key_path_suffix)] if key_path_segment.startswith('ControlSet'.upper()): try: control_set = int(key_path_segment[10:], 10) except ValueError: control_set = None # TODO: check if control_set is in bounds. return control_set is not None return key_path in (self._key_path_upper, self._wow64_key_path_upper) class WindowsRegistryKeyPathPrefixFilter(BaseWindowsRegistryKeyFilter): """Windows Registry key path prefix filter.""" def __init__(self, key_path_prefix): """Initializes a Windows Registry key filter. Args: key_path_prefix (str): key path prefix. """ super().__init__() self._key_path_prefix = key_path_prefix def Match(self, registry_key): """Determines if a Windows Registry key matches the filter. Args: registry_key (dfwinreg.WinRegistryKey): a Windows Registry key. Returns: bool: True if a match, False otherwise. """ return registry_key.path.startsswith(self._key_path_prefix) class WindowsRegistryKeyPathSuffixFilter(BaseWindowsRegistryKeyFilter): """Windows Registry key path suffix filter.""" def __init__(self, key_path_suffix): """Initializes a Windows Registry key filter. Args: key_path_suffix (str): key path suffix. """ super().__init__() self._key_path_suffix = key_path_suffix def Match(self, registry_key): """Determines if a Windows Registry key matches the filter. Args: registry_key (dfwinreg.WinRegistryKey): a Windows Registry key. Returns: bool: True if a match, False otherwise. """ return registry_key.path.endswith(self._key_path_suffix) class WindowsRegistryKeyWithValuesFilter(BaseWindowsRegistryKeyFilter): """Windows Registry key with values filter.""" _EMPTY_SET = frozenset() def __init__(self, value_names): """Initializes a Windows Registry key filter. Args: value_names (list[str]): value names that should be present in the key. """ super().__init__() self._value_names = frozenset(value_names) def Match(self, registry_key): """Determines if a Windows Registry key matches the filter. Args: registry_key (dfwinreg.WinRegistryKey): a Windows Registry key. Returns: bool: True if a match, False otherwise. """ value_names = frozenset([ registry_value.name for registry_value in registry_key.GetValues()]) return self._value_names.issubset(value_names) ================================================ FILE: winregrc/hexdump.py ================================================ """Function to provide hexadecimal representation of data.""" _HEXDUMP_CHARACTER_MAP = [ '.' if byte < 0x20 or byte > 0x7e else chr(byte) for byte in range(256)] def Hexdump(data): """Formats data in a hexadecimal representation. Args: data (byte): data. Returns: str: hexadecimal representation of the data. """ in_group = False previous_hexadecimal_string = None lines = [] data_size = len(data) for block_index in range(0, data_size, 16): data_string = data[block_index:block_index + 16] hexadecimal_byte_values = [] printable_values = [] for byte_value in data_string: if isinstance(byte_value, str): byte_value = ord(byte_value) hexadecimal_byte_values.append(f'{byte_value:02x}') printable_value = _HEXDUMP_CHARACTER_MAP[byte_value] printable_values.append(printable_value) remaining_size = 16 - len(data_string) if remaining_size == 0: whitespace = '' elif remaining_size >= 8: whitespace = ' ' * ((3 * remaining_size) - 1) else: whitespace = ' ' * (3 * remaining_size) hexadecimal_string_part1 = ' '.join(hexadecimal_byte_values[0:8]) hexadecimal_string_part2 = ' '.join(hexadecimal_byte_values[8:16]) hexadecimal_string = ( f'{hexadecimal_string_part1:s} {hexadecimal_string_part2:s}' f'{whitespace:s}') if (previous_hexadecimal_string is not None and previous_hexadecimal_string == hexadecimal_string and block_index + 16 < data_size): if not in_group: in_group = True lines.append('...') else: printable_string = ''.join(printable_values) lines.append( f'0x{block_index:08x} {hexadecimal_string:s} {printable_string:s}') in_group = False previous_hexadecimal_string = hexadecimal_string lines.extend(['', '']) return '\n'.join(lines) ================================================ FILE: winregrc/interface.py ================================================ """Windows Registry key and value collector.""" class WindowsRegistryKeyCollector: """Windows Registry key and value collector.""" def __init__(self, debug=False): """Initializes a Windows Registry key and value collector. Args: debug (Optional[bool]): True if debug information should be printed. """ super().__init__() self._debug = debug def _GetStringValueFromKey( self, registry_key, value_name, default_value=None): """Retrieves a string value from a Registry value. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. value_name (str): name of the value. default_value (Optional[str]): default value. Returns: str: value or the default value if not available. """ if not registry_key: return default_value registry_value = registry_key.GetValueByName(value_name) if not registry_value: return default_value if not registry_value.DataIsString(): return default_value return registry_value.GetDataAsObject() def _GetValueDataFromKey(self, registry_key, value_name): """Retrieves the value data from a Registry value. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. value_name (str): name of the value. Returns: bytes: value data or None if not available. """ if not registry_key: return None registry_value = registry_key.GetValueByName(value_name) if not registry_value: return None return registry_value.data def _GetValueFromKey(self, registry_key, value_name, default_value=None): """Retrieves a value from a Registry value. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. value_name (str): name of the value. default_value (Optional[str]): default value. Returns: str: value or the default value if not available. """ if not registry_key: return default_value registry_value = registry_key.GetValueByName(value_name) if not registry_value: return default_value return registry_value.GetDataAsObject() ================================================ FILE: winregrc/knownfolders.py ================================================ """Windows known folders collector.""" from winregrc import interface class KnownFolder: """Known folder. Attributes: alternate_display_names (list[str]): alternate display names. identifier (str): identifier. localized_display_name (str): localized display name. display_name (str): display name. """ def __init__(self, identifier, display_name, localized_display_name): """Initializes a known folder. Args: identifier (str): identifier. display_name (str): display name. localized_display_name (str): localized display name. """ super().__init__() self.alternate_display_names = [] self.identifier = identifier self.localized_display_name = localized_display_name self.display_name = display_name class KnownFoldersCollector(interface.WindowsRegistryKeyCollector): """Windows known folders collector.""" _FOLDER_DESCRIPTIONS_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\FolderDescriptions') def _CollectKnownFolders(self, folder_descriptions_key): """Collects Windows known folders. Args: folder_descriptions_key (dfwinreg.WinRegistryKey): folder descriptions Windows Registry key. Yields: KnownFolder: a known folder. """ for subkey in folder_descriptions_key.GetSubkeys(): identifier = subkey.name.lower() display_name = self._GetValueFromKey(subkey, 'Name') localized_display_name = self._GetValueFromKey(subkey, 'LocalizedName') yield KnownFolder(identifier, display_name, localized_display_name) def Collect(self, registry): """Collects Windows known folders. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: KnownFolder: a known folder. """ folder_descriptions_key = registry.GetKeyByPath( self._FOLDER_DESCRIPTIONS_KEY_PATH) if folder_descriptions_key: yield from self._CollectKnownFolders(folder_descriptions_key) ================================================ FILE: winregrc/mounted_devices.py ================================================ """Windows mounted devices collector.""" from winregrc import data_format from winregrc import errors class MountedDevice: """Mounted device. Attributes: device (str): device. disk_identity (int): MBR disk identity. identifier (str): identifier. partition_identifier (str): GPT partition identifier. partition_offset (int): MBR partition offset. """ def __init__(self, identifier): """Initializes a mounted device. Args: identifier (str): identifier. """ super().__init__() self.device = None self.disk_identity = None self.identifier = identifier self.partition_identifier = None self.partition_offset = None class MountedDevicesCollector(data_format.BinaryDataFormat): """Windows mounted devices collector.""" _DEFINITION_FILE = 'mounted_devices.yaml' _MOUNTED_DEVICES_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\System\\MountedDevices') def _ParseMountedDevicesValue(self, registry_value): """Parses a Windows mounted devices Windows Registry value. Args: registry_value (dfwinreg.WinRegistryValue): a mounted devices Windows Registry value. Returns: MountedDevice: a mounted device. Raises: ParseError: if the value could not be parsed. """ mounted_device = MountedDevice(registry_value.name) value_data_size = len(registry_value.data) if value_data_size == 12: data_type_map = self._GetDataTypeMap('mounted_devices_mbr_partition') try: partition_values = self._ReadStructureFromByteStream( registry_value.data, 0, data_type_map, 'Mounted devices MBR partition values') except (ValueError, errors.ParseError) as exception: raise errors.ParseError(( f'Unable to parse Mounted devices MBR partition values with ' f'error: {exception!s}')) mounted_device.disk_identity = partition_values.disk_identity mounted_device.partition_offset = partition_values.partition_offset elif value_data_size == 24: data_type_map = self._GetDataTypeMap('mounted_devices_gpt_partition') try: partition_values = self._ReadStructureFromByteStream( registry_value.data, 0, data_type_map, 'Mounted devices GPT partition values') except (ValueError, errors.ParseError) as exception: raise errors.ParseError(( f'Unable to parse Mounted devices GPT partition values with ' f'error: {exception!s}')) mounted_device.partition_identifier = ( partition_values.partition_identifier) else: mounted_device.device = registry_value.data.decode('utf-16-le') return mounted_device def Collect(self, registry): """Collects Windows mounted devices. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: MountedDevice: a mounted device. Raises: ParseError: if a mounted devices value could not be parsed. """ mounted_devices_key = registry.GetKeyByPath(self._MOUNTED_DEVICES_KEY_PATH) if mounted_devices_key: for registry_value in mounted_devices_key.GetValues(): yield self._ParseMountedDevicesValue(registry_value) ================================================ FILE: winregrc/mounted_devices.yaml ================================================ # dtFabric format specification. --- name: mounted_devices type: format description: Windows Registry mounted devices format --- name: byte type: integer attributes: format: unsigned size: 1 units: bytes --- name: uint32 type: integer attributes: format: unsigned size: 4 units: bytes --- name: uint64 type: integer attributes: format: unsigned size: 8 units: bytes --- name: mounted_devices_gpt_partition type: structure description: Mounted devices GPT partition value data attributes: byte_order: little-endian members: - name: signature type: stream element_data_type: byte number_of_elements: 8 value: "DMIO:ID:" - name: partition_identifier type: uuid --- name: mounted_devices_mbr_partition type: structure description: Mounted devices MBR partition value data attributes: byte_order: little-endian members: - name: disk_identity data_type: uint32 - name: partition_offset data_type: uint64 ================================================ FILE: winregrc/mru.py ================================================ """Most Recently Used (MRU) collector.""" from dtfabric.runtime import data_maps as dtfabric_data_maps from winregrc import data_format from winregrc import errors class MostRecentlyUsedEntry: """Most Recently Used (MRU) entry. Attributes: key_path (str): path of the Windows Registry key. shell_item_data (bytes): Shell Item data. shell_item_list_data (bytes): Shell Item list data. string (str): string. value_name (str): name of the Windows Registry value. """ def __init__( self, key_path=None, shell_item_data=None, shell_item_list_data=None, string=None, value_name=None): """Initializes a Most Recently Used (MRU) entry. Args: key_path (Optional[str]): path of the Windows Registry key. shell_item_data (Optional[bytes]): Shell Item data. shell_item_list_data (Optional[bytes]): Shell Item list data. string (Optional[str]): string. value_name (Optional[str]): name of the Windows Registry value. """ super().__init__() self.key_path = key_path self.shell_item_data = shell_item_data self.shell_item_list_data = shell_item_list_data self.string = string self.value_name = value_name class MostRecentlyUsedCollector(data_format.BinaryDataFormat): """Most Recently Used (MRU) collector. Attributes: mru_entries (list[MostRecentlyUsedEntry]): most recently used (MRU) entries. """ _DEFINITION_FILE = 'mru.yaml' _OPENSAVE_MRU_KEY_PATH = ( 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\ComDlg32\\OpenSaveMRU').upper() _SHELL_ITEM_MRU_KEY_PATHS = [ ('HKEY_CURRENT_USER\\Local Settings\\Software\\Microsoft\\Windows\\' 'Shell\\BagMRU'), ('HKEY_CURRENT_USER\\Local Settings\\Software\\Microsoft\\Windows\\' 'ShellNoRoam\\BagMRU'), 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\BagMRU', ('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\ShellNoRoam\\' 'BagMRU'), ('HKEY_CURRENT_USER\\Software\\Classes\\Local Settings\\Software\\' 'Microsoft\\Windows\\Shell\\BagMRU'), ('HKEY_CURRENT_USER\\Software\\Classes\\Local Settings\\Software\\' 'Microsoft\\Windows\\ShellNoRoam\\BagMRU'), ('HKEY_CURRENT_USER\\Software\\Classes\\Wow6432Node\\Local Settings\\' 'Software\\Microsoft\\Windows\\Shell\\BagMRU'), ('HKEY_CURRENT_USER\\Software\\Classes\\Wow6432Node\\Local Settings\\' 'Software\\Microsoft\\Windows\\ShellNoRoam\\BagMRU')] _SHELL_ITEM_MRU_KEY_PATHS = [ key_path.upper() for key_path in _SHELL_ITEM_MRU_KEY_PATHS] _SHELL_ITEM_LIST_MRU_KEY_PATHS = [ ('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\DesktopStreamMRU'), ('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\ComDlg32\\OpenSavePidlMRU'), ('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\StreamMRU'), ('HKEY_CURRENT_USER\\Software\\Classes\\Software\\Microsoft\\Windows\\' 'CurrentVersion\\Explorer\\StreamMRU')] _SHELL_ITEM_LIST_MRU_KEY_PATHS = [ key_path.upper() for key_path in _SHELL_ITEM_LIST_MRU_KEY_PATHS] _STRING_AND_SHELL_ITEM_MRU_KEY_PATHS = [ ('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\RecentDocs')] _STRING_AND_SHELL_ITEM_MRU_KEY_PATHS = [ key_path.upper() for key_path in _STRING_AND_SHELL_ITEM_MRU_KEY_PATHS] _STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS = [ ('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\ComDlg32\\LastVisitedPidlMRU')] _STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS = [ key_path.upper() for key_path in _STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS] def __init__(self, debug=False, output_writer=None): """Initializes a Most Recently Used (MRU) collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._output_writer = output_writer self.mru_entries = [] def _InKeyPaths(self, key_path, key_paths): """Checks if a specific key path is defined in a list of key paths. Args: key_path (str): Windows Registry key path. key_paths (list[str]): list of Windows Registry key paths in upper case. Returns: bool: True if the key path is defined in the list of key paths. """ key_path = key_path.upper() for matching_key_path in key_paths: if key_path.startswith(matching_key_path): return True return False def _ProcessKey(self, registry_key): """Processes a Windows Registry key. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. Returns: bool: True if a Most Recently Used (MRU) key was found, False if not. """ result = False value_names = [ registry_value.name for registry_value in registry_key.GetValues()] if 'MRUList' in value_names: if self._ProcessKeyWithMRUListValue(registry_key): result = True elif 'MRUListEx' in value_names: if self._ProcessKeyWithMRUListExValue(registry_key): result = True for subkey in registry_key.GetSubkeys(): if self._ProcessKey(subkey): result = True return result def _ProcessKeyWithMRUListValue(self, registry_key): """Processes a Windows Registry key that contains a MRUList value. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. Returns: bool: True if a Most Recently Used (MRU) key was found, False if not. Raises: ParseError: if the MRUList value could not be parsed. """ registry_value = registry_key.GetValueByName('MRUList') data_type_map = self._GetDataTypeMap('mrulist_entries') context = dtfabric_data_maps.DataTypeMapContext(values={ 'data_size': len(registry_value.data)}) try: mrulist_entries = self._ReadStructureFromByteStream( registry_value.data, 0, data_type_map, 'MRUList entries', context=context) except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse MRUList entries with error: {exception!s}') mrulist = set([]) recovered_mrulist = set([]) is_recovered = False for entry_letter in mrulist_entries: if entry_letter == 0: is_recovered = True entry_letter = chr(entry_letter) if is_recovered: recovered_mrulist.add(entry_letter) else: mrulist.add(entry_letter) result = False for registry_value in registry_key.GetValues(): if registry_value.name in ( 'MRUList', 'NodeSlot', 'NodeSlots', 'ViewStream'): continue if self._debug: self._output_writer.WriteText( f'Key: {registry_key.path:s}\nValue: {registry_value.name:s}\n') if self._InKeyPaths(registry_key.path, self._SHELL_ITEM_MRU_KEY_PATHS): self._ProcessMRUEntryShellItem( registry_key.path, registry_value.name, registry_value.data) elif self._InKeyPaths( registry_key.path, self._SHELL_ITEM_LIST_MRU_KEY_PATHS): self._ProcessMRUEntryShellItemList( registry_key.path, registry_value.name, registry_value.data) elif self._InKeyPaths( registry_key.path, self._STRING_AND_SHELL_ITEM_MRU_KEY_PATHS): self._ProcessMRUEntryStringAndShellItem( registry_key.path, registry_value.name, registry_value.data) elif self._InKeyPaths( registry_key.path, self._STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS): self._ProcessMRUEntryStringAndShellItemList( registry_key.path, registry_value.name, registry_value.data) else: self._ProcessMRUEntryString( registry_key.path, registry_value.name, registry_value.data) result = True return result def _ProcessKeyWithMRUListExValue(self, registry_key): """Processes a Windows Registry key that contains a MRUListEx value. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. Returns: bool: True if a Most Recently Used (MRU) key was found, False if not. Raises: ParseError: if the MRUListEx value could not be parsed. """ # TODO: determine what trailing data is in: # HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ # ComDlg32\CIDSizeMRU registry_value = registry_key.GetValueByName('MRUListEx') data_type_map = self._GetDataTypeMap('mrulistex_entries') context = dtfabric_data_maps.DataTypeMapContext(values={ 'data_size': len(registry_value.data)}) try: mrulistex_entries = self._ReadStructureFromByteStream( registry_value.data, 0, data_type_map, 'MRUListEx entries', context=context) except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse MRUListEx entries with error: {exception!s}') mrulistex = set([]) recovered_mrulistex = set([]) is_recovered = False for entry_number in mrulistex_entries: if entry_number == 0: is_recovered = True if is_recovered: recovered_mrulistex.add(entry_number) else: mrulistex.add(entry_number) result = False for registry_value in registry_key.GetValues(): if registry_value.name in ( 'MRUListEx', 'NodeSlot', 'NodeSlots', 'ViewStream'): continue if self._debug: self._output_writer.WriteText( f'Key: {registry_key.path:s}\nValue: {registry_value.name:s}\n') if self._InKeyPaths(registry_key.path, self._SHELL_ITEM_MRU_KEY_PATHS): self._ProcessMRUEntryShellItem( registry_key.path, registry_value.name, registry_value.data) elif self._InKeyPaths( registry_key.path, self._SHELL_ITEM_LIST_MRU_KEY_PATHS): self._ProcessMRUEntryShellItemList( registry_key.path, registry_value.name, registry_value.data) elif self._InKeyPaths( registry_key.path, self._STRING_AND_SHELL_ITEM_MRU_KEY_PATHS): self._ProcessMRUEntryStringAndShellItem( registry_key.path, registry_value.name, registry_value.data) elif self._InKeyPaths( registry_key.path, self._STRING_AND_SHELL_ITEM_LIST_MRU_KEY_PATHS): self._ProcessMRUEntryStringAndShellItemList( registry_key.path, registry_value.name, registry_value.data) else: self._ProcessMRUEntryString( registry_key.path, registry_value.name, registry_value.data) result = True return result def _ProcessMRUEntryShellItem(self, key_path, value_name, value_data): """Processes a shell item MRUEntry. Args: key_path (str): path of the Windows Registry key. value_name (str): name of the Windows Registry value. value_data (bytes): Windows Registry value data. """ if self._debug: self._output_writer.WriteDebugData('Shell item data', value_data) mru_entry = MostRecentlyUsedEntry( key_path=key_path, shell_item_data=value_data, value_name=value_name) self.mru_entries.append(mru_entry) def _ProcessMRUEntryShellItemList(self, key_path, value_name, value_data): """Processes a shell item list MRUEntry. Args: key_path (str): path of the Windows Registry key. value_name (str): name of the Windows Registry value. value_data (bytes): Windows Registry value data. """ if self._debug: self._output_writer.WriteDebugData('Shell item list data', value_data) mru_entry = MostRecentlyUsedEntry( key_path=key_path, shell_item_list_data=value_data, value_name=value_name) self.mru_entries.append(mru_entry) def _ProcessMRUEntryString(self, key_path, value_name, value_data): """Processes a string MRUEntry. Args: key_path (str): path of the Windows Registry key. value_name (str): name of the Windows Registry value. value_data (bytes): Windows Registry value data. """ value_data_size = len(value_data) data_offset = 0 for data_offset in range(0, value_data_size, 2): if value_data[data_offset:data_offset + 2] == b'\0\0': data_offset += 2 break if self._debug: self._output_writer.WriteDebugData( 'String data', value_data[0:data_offset]) string = value_data[0:data_offset - 2].decode('utf-16-le') if self._debug: self._output_writer.WriteValue('String', string) if self._debug and data_offset < value_data_size: self._output_writer.WriteDebugData( 'Trailing data', value_data[data_offset:]) mru_entry = MostRecentlyUsedEntry( key_path=key_path, string=string, value_name=value_name) self.mru_entries.append(mru_entry) def _ProcessMRUEntryStringAndShellItem( self, key_path, value_name, value_data): """Processes a string and shell item MRUEntry. Args: key_path (str): path of the Windows Registry key. value_name (str): name of the Windows Registry value. value_data (bytes): Windows Registry value data. """ value_data_size = len(value_data) data_offset = 0 for data_offset in range(0, value_data_size, 2): if value_data[data_offset:data_offset + 2] == b'\0\0': data_offset += 2 break if self._debug: self._output_writer.WriteDebugData( 'String data', value_data[0:data_offset]) string = value_data[0:data_offset - 2].decode('utf-16-le') if self._debug: self._output_writer.WriteValue('String', string) if data_offset < value_data_size: if self._debug: self._output_writer.WriteDebugData( 'Shell item data', value_data[data_offset:]) mru_entry = MostRecentlyUsedEntry( key_path=key_path, shell_item_data=value_data[data_offset:], string=string, value_name=value_name) self.mru_entries.append(mru_entry) def _ProcessMRUEntryStringAndShellItemList( self, key_path, value_name, value_data): """Processes a string and shell item list MRUEntry. Args: key_path (str): path of the Windows Registry key. value_name (str): name of the Windows Registry value. value_data (bytes): Windows Registry value data. """ value_data_size = len(value_data) data_offset = 0 for data_offset in range(0, value_data_size, 2): if value_data[data_offset:data_offset + 2] == b'\0\0': data_offset += 2 break if self._debug: self._output_writer.WriteDebugData( 'String data', value_data[0:data_offset]) string = value_data[0:data_offset - 2].decode('utf-16-le') if self._debug: self._output_writer.WriteValue('String', string) if data_offset < value_data_size: if self._debug: self._output_writer.WriteDebugData( 'Shell item list data', value_data[data_offset:]) mru_entry = MostRecentlyUsedEntry( key_path=key_path, shell_item_list_data=value_data[data_offset:], string=string, value_name=value_name) self.mru_entries.append(mru_entry) def Collect(self, registry): # pylint: disable=arguments-differ """Collects Most Recently Used (MRU) entries. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if a Most Recently Used (MRU) key was found, False if not. """ result = False current_user_key = registry.GetKeyByPath('HKEY_CURRENT_USER') if current_user_key: if self._ProcessKey(current_user_key): result = True if not result: # Fallback for if source is a single UsrClass.dat file. current_user_classes_key = registry.GetKeyByPath( 'HKEY_CURRENT_USER\\Software\\Classes') if current_user_classes_key: if self._ProcessKey(current_user_classes_key): result = True return result ================================================ FILE: winregrc/mru.yaml ================================================ # dtFabric format specification. --- name: mru type: format description: Most recently used (MRU) formats --- name: byte type: integer attributes: format: unsigned size: 1 units: bytes --- name: uint16 type: integer attributes: format: unsigned size: 2 units: bytes --- name: int32 type: integer attributes: format: signed size: 4 units: bytes --- name: wchar16 type: character attributes: size: 2 units: bytes --- name: mrulist_entries type: sequence description: MRUList entries element_data_type: uint16 elements_data_size: data_size --- name: mrulistex_entries type: sequence description: MRUListEx entries element_data_type: int32 elements_data_size: data_size --- name: utf16le_string type: string encoding: utf-16-le element_data_type: wchar16 elements_terminator: "\x00\x00" ================================================ FILE: winregrc/msie_zone_info.py ================================================ """Microsoft Internet Explorer (MSIE) zone information collector.""" from winregrc import interface class MSIEZoneInformation: """MSIE zone information. Attributes: control (str): control. control_value (int|str): value to which the control is set. zone (str): identifier of the zone to which the control applies. zone_name (str): name of the zone to which the control applies. """ def __init__(self, zone, zone_name, control, control_value): """Initializes MSIE zone information. Args: zone (str): identifier of the zone to which the control applies. zone_name (str): name of the zone to which the control applies. control (str): control. control_value (int|str): value to which the control is set. """ super().__init__() self.control = control self.control_value = control_value self.zone = zone self.zone_name = zone_name class MSIEZoneInformationCollector(interface.WindowsRegistryKeyCollector): """MSIE zone information collector.""" _LOCKDOWN_KEY_PATHS = [ # HKEY_CURRENT_USER ('HKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Internet Explorer\\' 'Main\\FeatureControl\\FEATURE_LOCALMACHINE_LOCKDOWN'), ('HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Main\\' 'FeatureControl\\FEATURE_LOCALMACHINE_LOCKDOWN'), # HKEY_LOCAL_MACHINE ('HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\' 'Internet Explorer\\Main\\FeatureControl\\' 'FEATURE_LOCALMACHINE_LOCKDOWN'), ('HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Internet Explorer\\Main\\' 'FeatureControl\\FEATURE_LOCALMACHINE_LOCKDOWN'), # HKEY_LOCAL_MACHINE WoW64 ('HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Policies\\Microsoft\\' 'Internet Explorer\\Main\\FeatureControl\\' 'FEATURE_LOCALMACHINE_LOCKDOWN'), ('HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Microsoft\\' 'Internet Explorer\\Main\\FeatureControl\\' 'FEATURE_LOCALMACHINE_LOCKDOWN')] _ZONES_KEY_PATHS = [ # HKEY_CURRENT_USER ('HKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Windows\\' 'CurrentVersion\\Internet Settings\\Zones'), ('HKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Windows\\' 'CurrentVersion\\Internet Settings\\Lockdown_Zones'), ('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Internet Settings\\Zones'), ('HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Internet Settings\\Lockdown_Zones'), # HKEY_LOCAL_MACHINE ('HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\' 'CurrentVersion\\Internet Settings\\Zones'), ('HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\' 'CurrentVersion\\Internet Settings\\Lockdown_Zones'), ('HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Internet Settings\\Zones'), ('HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Internet Settings\\Lockdown_Zones'), # HKEY_LOCAL_MACHINE WoW64 ('HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Policies\\Microsoft\\' 'Windows\\CurrentVersion\\Internet Settings\\Zones'), ('HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Policies\\Microsoft\\' 'Windows\\CurrentVersion\\Internet Settings\\Lockdown_Zones'), ('HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Microsoft\\Windows\\' 'CurrentVersion\\Internet Settings\\Zones'), ('HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Microsoft\\Windows\\' 'CurrentVersion\\Internet Settings\\Lockdown_Zones')] def _CollectZoneInformationFromLockdownKey(self, lockdown_key): """Collects MSIE zone information from a lockdown key. Args: lockdown_key (dfwinreg.WinRegistryKey): lockdown Windows Registry key. """ program_name = 'iexplore.exe' program_value = lockdown_key.GetValueByName(program_name) if program_value: value = program_value.GetDataAsObject() else: value = 0 if self._debug: if value == 1: print(f'Local Machine lockdown for {program_name:s}: True') else: print(f'Local Machine lockdown for {program_name:s}: False') print('') # TODO: implement. def _CollectZoneInformationFromZonesKey(self, zones_key): """Collects MSIE zone information from a zones key. Args: zones_key (dfwinreg.WinRegistryKey): zones Windows Registry key. Yields: MSIEZoneInformation: MSIE zone information. """ for zone_key in zones_key.GetSubkeys(): zone_name = self._GetValueFromKey(zone_key, 'DisplayName') for setting_value in zone_key.GetValues(): # The 'Description' value contains a description of the zone. # The 'PMDisplayName' value contains the display name of the zone in # protected mode. if setting_value.name in ( None, 'Description', 'DisplayName', 'PMDisplayName'): continue if len(setting_value.name) == 4 and setting_value.name != 'Icon': if len(setting_value.data) != 4: value_string = setting_value.data.encode('hex') else: value_string = setting_value.GetDataAsObject() else: value_string = None yield MSIEZoneInformation( zone_key.name, zone_name, setting_value.name, value_string) def Collect(self, registry): """Collects the MSIE zone information. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: MSIEZoneInformation: MSIE zone information. """ for key_path in self._LOCKDOWN_KEY_PATHS: lockdown_key = registry.GetKeyByPath(key_path) if lockdown_key: # TODO: do something with information in lockdown key self._CollectZoneInformationFromLockdownKey(lockdown_key) # TODO: check for value Policies\\Microsoft\\Windows\\CurrentVersion\\ # Internet Settings\\Security_HKEY_LOCAL_MACHINE_only and its data # if not exists or 0, not enabled if 1 only HKLM policy applies for key_path in self._ZONES_KEY_PATHS: zones_key = registry.GetKeyByPath(key_path) if zones_key: yield from self._CollectZoneInformationFromZonesKey(zones_key) ================================================ FILE: winregrc/output_writers.py ================================================ """Output writer.""" import abc from dfdatetime import fat_date_time as dfdatetime_fat_date_time from dfdatetime import filetime as dfdatetime_filetime from winregrc import hexdump class OutputWriter: """Output writer interface.""" # Note that redundant-returns-doc is broken for pylint 1.7.x # pylint: disable=redundant-returns-doc _HEXDUMP_CHARACTER_MAP = [ '.' if byte < 0x20 or byte > 0x7e else chr(byte) for byte in range(256)] def _FormatDataInHexadecimal(self, data): """Formats data in a hexadecimal representation. Args: data (bytes): data. Returns: str: hexadecimal representation of the data. """ in_group = False previous_hexadecimal_string = None lines = [] data_size = len(data) for block_index in range(0, data_size, 16): data_string = data[block_index:block_index + 16] hexadecimal_byte_values = [] printable_values = [] for byte_value in data_string: if isinstance(byte_value, str): byte_value = ord(byte_value) hexadecimal_byte_values.append(f'{byte_value:02x}') printable_value = self._HEXDUMP_CHARACTER_MAP[byte_value] printable_values.append(printable_value) remaining_size = 16 - len(data_string) if remaining_size == 0: whitespace = '' elif remaining_size >= 8: whitespace = ' ' * ((3 * remaining_size) - 1) else: whitespace = ' ' * (3 * remaining_size) hexadecimal_string_part1 = ' '.join(hexadecimal_byte_values[0:8]) hexadecimal_string_part2 = ' '.join(hexadecimal_byte_values[8:16]) hexadecimal_string = ( f'{hexadecimal_string_part1:s} {hexadecimal_string_part2:s}' f'{whitespace:s}') if (previous_hexadecimal_string is not None and previous_hexadecimal_string == hexadecimal_string and block_index + 16 < data_size): if not in_group: in_group = True lines.append('...') else: printable_string = ''.join(printable_values) lines.append( f'0x{block_index:08x} {hexadecimal_string:s} ' f'{printable_string:s}') in_group = False previous_hexadecimal_string = hexadecimal_string lines.extend(['', '']) return '\n'.join(lines) def _FormatFATDateTimeValue(self, value): """Formats a FAT date time value. Args: value (int): FAT date time value. Returns: str: date time string. """ if not value: date_time_string = 'Not set (0)' else: date_time = dfdatetime_fat_date_time.FATDateTime(fat_date_time=value) date_time_string = date_time.CopyToDateTimeString() if not date_time_string: date_time_string = f'0x{value:04x}' return date_time_string def _FormatFiletimeValue(self, value): """Formats a FILETIME timestamp value. Args: value (int): FILETIME timestamp value. Returns: str: date time string. """ if value == 0: date_time_string = 'Not set (0)' elif value == 0x7fffffffffffffff: date_time_string = 'Never (0x7fffffffffffffff)' else: date_time = dfdatetime_filetime.Filetime(timestamp=value) date_time_string = date_time.CopyToDateTimeString() if date_time_string: date_time_string = f'{date_time_string:s} UTC' else: date_time_string = f'0x{value:08x}' return date_time_string @abc.abstractmethod def Close(self): """Closes the output writer.""" def DebugPrintData(self, description, data): """Prints data for debugging. Args: description (str): description. data (bytes): data. """ self.WriteText(f'{description:s}:\n') value_string = self._FormatDataInHexadecimal(data) self.WriteText(value_string) def DebugPrintValue(self, description, value): """Prints a value for debugging. Args: description (str): description. value (object): value. """ alignment, _ = divmod(len(description), 8) alignment_string = '\t' * (8 - alignment + 1) self.WriteText(f'{description:s}{alignment_string:s}: {value!s}\n') def DebugPrintText(self, text): """Prints text for debugging. Args: text (str): text. """ self.WriteText(text) @abc.abstractmethod def Open(self): """Opens the output writer. Returns: bool: True if successful or False if not. """ @abc.abstractmethod def WriteDebugData(self, description, data): """Writes data for debugging. Args: description (str): description. data (bytes): data to write. """ @abc.abstractmethod def WriteIntegerValueAsDecimal(self, description, value): """Writes an integer value as decimal. Args: description (str): description. value (int): value to write. """ @abc.abstractmethod def WriteFiletimeValue(self, description, value): """Writes a FILETIME timestamp value. Args: description (str): description. value (str): value to write. """ @abc.abstractmethod def WriteText(self, text): """Writes text. Args: text (str): text to write. """ @abc.abstractmethod def WriteValue(self, description, value): """Writes a value. Args: description (str): description. value (str): value to write. """ class StdoutOutputWriter(OutputWriter): """Stdout output writer.""" def Close(self): """Closes the output writer.""" return def Open(self): """Opens the output writer. Returns: bool: True if successful or False if not. """ return True def WriteDebugData(self, description, data): """Writes data for debugging. Args: description (str): description. data (bytes): data. """ self.WriteText(description) self.WriteText('\n') hexdump_text = hexdump.Hexdump(data) self.WriteText(hexdump_text) def WriteFiletimeValue(self, description, value): """Writes a FILETIME timestamp value. Args: description (str): description. value (int): FILETIME timestamp value. """ date_time_string = self._FormatFiletimeValue(value) self.WriteValue(description, date_time_string) def WriteIntegerValueAsDecimal(self, description, value): """Writes an integer value as decimal. Args: description (str): description. value (int): integer value. """ self.WriteValue(description, f'{value:d}') def WriteText(self, text): """Writes text. Args: text (str): text to write. """ print(text, end='') def WriteValue(self, description, value): """Writes a value. Args: description (str): description. value (object): value. """ description_no_tabs = description.replace('\t', ' ' * 8) alignment, _ = divmod(len(description_no_tabs), 8) alignment_string = '\t' * (8 - alignment + 1) self.WriteText(f'{description:s}{alignment_string:s}: {value!s}\n') ================================================ FILE: winregrc/profiles.py ================================================ """Windows user profiles collector.""" from winregrc import interface class UserProfile: """User profile. Attributes: profile_path (str): path of the users profile. security_identifier (str): security identifier of the user. """ def __init__(self, security_identifier, profile_path): """Initializes an user profile. Args: security_identifier (str): security identifier of the user. profile_path (str): path of the users profile. """ super().__init__() self.profile_path = profile_path self.security_identifier = security_identifier class UserProfilesCollector(interface.WindowsRegistryKeyCollector): """Windows user profiles collector.""" _PROFILE_LIST_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\' 'ProfileList') def _CollectUserProfiles(self, profile_list_key): """Collects user profiles. Args: profile_list_key (dfwinreg.WinRegistryKey): profile list Windows Registry. Yields: UserProfile: an user profile. """ for subkey in profile_list_key.GetSubkeys(): profile_image_path = self._GetValueFromKey(subkey, 'ProfileImagePath') yield UserProfile(subkey.name, profile_image_path) def Collect(self, registry): """Collects user profiles. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: UserProfile: an user profile. """ profile_list_key = registry.GetKeyByPath(self._PROFILE_LIST_KEY_PATH) if profile_list_key: yield from self._CollectUserProfiles(profile_list_key) ================================================ FILE: winregrc/programscache.py ================================================ """Windows Programs Cache information collector.""" import logging import uuid from dtfabric.runtime import data_maps as dtfabric_data_maps import pyfwsi from winregrc import data_format from winregrc import errors from winregrc import interface class ProgramsCacheDataParser(data_format.BinaryDataFormat): """Programs Cache data parser.""" _DEFINITION_FILE = 'programscache.yaml' def _DebugPrintEntryFooter(self, entry_footer): """Prints entry footer value debug information. Args: entry_footer (programscache_entry_footer): entry footer. """ self._DebugPrintValue('Sentinel', f'0x{entry_footer.sentinel:02x}') def _DebugPrintEntryHeader(self, entry_header): """Prints entry header value debug information. Args: entry_header (programscache_entry_header): entry header. """ self._DebugPrintDecimalValue('Entry data size', entry_header.data_size) def _DebugPrintHeader(self, header): """Prints header value debug information. Args: header (programscache_header): header. """ self._DebugPrintDecimalValue('Format version', header.format_version) def _DebugPrintShellItem(self, shell_item): """Prints shell item value debug information. Args: shell_item (pyfwsi.shell_item): shell item. """ self._DebugPrintValue( 'Shell item class type', f'0x{shell_item.class_type:02x}') value_string = getattr(shell_item, 'name', '') self._DebugPrintValue('Shell item name', value_string) def _ParseEntryFooter(self, value_data, value_data_offset): """Parses an entry footer from the value data. Args: value_data (bytes): value data. value_data_offset (int): offset of the entry footer relative to the start of the value data. Returns: tuple: containing: programscache_entry_footer: entry footer. int: entry footer data size. Raises: ParseError: if the entry footer could not be parsed. """ data_type_map = self._GetDataTypeMap('programscache_entry_footer') data_size = data_type_map.GetSizeHint() if self._debug: self._DebugPrintData( 'Entry footer data', value_data[value_data_offset:value_data_offset + data_size]) try: entry_footer = self._ReadStructureFromByteStream( value_data[value_data_offset:], value_data_offset, data_type_map, 'entry footer') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse entry footer value with error: {exception!s}') if self._debug: self._DebugPrintEntryFooter(entry_footer) return entry_footer, data_size def _ParseHeader(self, value_data): """Parses a header from the value data. Args: value_data (bytes): value data. Returns: tuple: containing: programscache_header: header. int: header data size. Raises: ParseError: if the header could not be parsed. """ data_type_map = self._GetDataTypeMap('programscache_header') data_size = data_type_map.GetSizeHint() if self._debug: self._DebugPrintData('Header data', value_data[:data_size]) try: header = self._ReadStructureFromByteStream( value_data, 0, data_type_map, 'header') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse header value with error: {exception!s}') if self._debug: self._DebugPrintHeader(header) if header.format_version not in (1, 9, 12, 19): raise errors.ParseError('Unsupported format.') return header, data_size def Parse(self, value_data): """Parses the value data. Args: value_data (bytes): value data. Raises: ParseError: if the value data could not be parsed. """ if self._debug: self._DebugPrintData('Value data', value_data) header, value_data_offset = self._ParseHeader(value_data) if header.format_version == 1: value_data_offset += 4 elif header.format_version == 9: data_type_map = self._GetDataTypeMap('programscache_header9') context = dtfabric_data_maps.DataTypeMapContext() try: header9 = self._ReadStructureFromByteStream( value_data[value_data_offset:], value_data_offset, data_type_map, 'header9', context=context) except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse header9 value with error: {exception!s}') value_data_offset += context.byte_size if self._debug: self._DebugPrintValue('Unknown1', f'0x{header9.unknown1:08x}') elif header.format_version in (12, 19): uuid_object = uuid.UUID(bytes_le=value_data[4:20]) value_data_offset += 16 if self._debug: self._DebugPrintValue('Known folder identifier', f'{uuid_object!s}') sentinel = 0 if header.format_version != 9: entry_footer, data_size = self._ParseEntryFooter( value_data, value_data_offset) value_data_offset += data_size sentinel = entry_footer.sentinel if self._debug: self._DebugPrintText('\n') value_data_size = len(value_data) while sentinel in (0, 1): if value_data_offset >= value_data_size: break data_type_map = self._GetDataTypeMap('programscache_entry_header') context = dtfabric_data_maps.DataTypeMapContext() try: entry_header = self._ReadStructureFromByteStream( value_data[value_data_offset:], value_data_offset, data_type_map, 'entry header', context=context) except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse entry header value with error: {exception!s}') if self._debug: self._DebugPrintValue('Entry data offset', f'0x{value_data_offset:08x}') self._DebugPrintEntryHeader(entry_header) value_data_offset += context.byte_size entry_data_size = entry_header.data_size shell_item_list = pyfwsi.item_list() shell_item_list.copy_from_byte_stream(value_data[value_data_offset:]) for shell_item in iter(shell_item_list.items): if self._debug: self._DebugPrintShellItem(shell_item) value_data_offset += entry_data_size entry_footer, data_size = self._ParseEntryFooter( value_data, value_data_offset) value_data_offset += data_size if self._debug: self._DebugPrintText('\n') if entry_footer.sentinel == 2 and value_data_offset < value_data_size: # TODO: determine the logic to this value. while ord(value_data[value_data_offset]) != 0x00: value_data_offset += 1 value_data_offset += 7 entry_footer, data_size = self._ParseEntryFooter( value_data, value_data_offset) value_data_offset += data_size if self._debug: self._DebugPrintText('\n') if value_data_offset < value_data_size: self._DebugPrintValue( 'Trailing data offset', f'0x{value_data_offset:08x}') self._DebugPrintData( 'Trailing data:', value_data[value_data_offset:]) class ProgramsCacheCollector(interface.WindowsRegistryKeyCollector): """Windows program cache collector.""" _STARTPAGE_KEY_PATH = ( 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\StartPage') _STARTPAGE2_KEY_PATH = ( 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\StartPage2') def __init__(self, debug=False, output_writer=None): """Initializes a Windows program cache collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._parser = ProgramsCacheDataParser( debug=debug, output_writer=output_writer) def _CollectProgramsCacheFromValue(self, registry, key_path, value_name): """Collects Programs Cache from a Windows Registry value. Args: registry (dfwinreg.WinRegistry): Windows Registry. key_path (str): path of the Programs Cache key. value_name (str): name of the Programs Cache value. Returns: bool: True if the Programs Cache information key was found, False if not. """ startpage_key = registry.GetKeyByPath(key_path) if not startpage_key: return False value = startpage_key.GetValueByName(value_name) if not value: logging.warning(f'Missing {value_name:s} value in key: {key_path:s}') return True self._parser.Parse(value.data) return True def Collect(self, registry): # pylint: disable=arguments-differ """Collects the Programs Cache information. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the Programs Cache information key was found, False if not. """ result = False if self._CollectProgramsCacheFromValue( registry, self._STARTPAGE_KEY_PATH, 'ProgramsCache'): result = True if self._CollectProgramsCacheFromValue( registry, self._STARTPAGE2_KEY_PATH, 'ProgramsCache'): result = True if self._CollectProgramsCacheFromValue( registry, self._STARTPAGE2_KEY_PATH, 'ProgramsCacheSMP'): result = True if self._CollectProgramsCacheFromValue( registry, self._STARTPAGE2_KEY_PATH, 'ProgramsCacheTBP'): result = True return result ================================================ FILE: winregrc/programscache.yaml ================================================ # dtFabric format specification. --- name: programcache type: format description: Programs Cache format --- name: uint8 type: integer attributes: format: unsigned size: 1 units: bytes --- name: uint16 type: integer attributes: format: unsigned size: 2 units: bytes --- name: uint32 type: integer attributes: format: unsigned size: 4 units: bytes --- name: programscache_header type: structure attributes: byte_order: little-endian members: - name: format_version data_type: uint32 --- name: programscache_header9 type: structure attributes: byte_order: little-endian members: - name: unknown1 data_type: uint16 --- name: programscache_entry_header type: structure attributes: byte_order: little-endian members: - name: data_size data_type: uint32 --- name: programscache_entry_footer type: structure attributes: byte_order: little-endian members: - name: sentinel data_type: uint8 ================================================ FILE: winregrc/sam.py ================================================ """Security Accounts Manager (SAM) collector.""" import pyfwnt from dfdatetime import filetime as dfdatetime_filetime from dfdatetime import semantic_time as dfdatetime_semantic_time from winregrc import data_format from winregrc import errors from winregrc import interface class UserAccount: """User account. Attributes: account_expiration_time (dfdatetime.DateTimeValues): account expiration date and time. codepage (str): code page. comment (str): comment. full_name (str): full name. last_login_time (dfdatetime.DateTimeValues): last log-in date and time. last_password_failure_time (dfdatetime.DateTimeValues): last password failure date and time. last_password_set_time (dfdatetime.DateTimeValues): last password set date and time. name (str): name number_of_logons (int): number of log-ons. number_of_password_failures (int): number of password failures. primary_gid (int): primary group identifier (GID). rid (str): relative identifier (RID). user_account_control_flags (int): user account control flags. user_comment (str): user comment. username (str): username. """ def __init__(self): """Initializes an user account.""" super().__init__() self.account_expiration_time = None self.codepage = None self.comment = None self.full_name = None self.last_login_time = None self.last_password_failure_time = None self.last_password_set_time = None self.name = None self.number_of_logons = None self.number_of_password_failures = None self.primary_gid = None self.rid = None self.user_account_control_flags = None self.user_comment = None self.username = None class SecurityAccountManagerDataParser(data_format.BinaryDataFormat): """Security Accounts Manager (SAM) data parser.""" _DEFINITION_FILE = 'sam.yaml' _USER_INFORMATION_DESCRIPTORS = [ 'security descriptor', 'username', 'full name', 'comment', 'user comment', 'unknown1', 'home directory', 'home directory connect', 'script path', 'profile path', 'workstations', 'hours allowed', 'unknown2', 'LM hash', 'NTLM hash', 'unknown3', 'unknown4'] _USER_ACCOUNT_CONTROL_FLAGS = { 0x00000001: 'USER_ACCOUNT_DISABLED', 0x00000002: 'USER_HOME_DIRECTORY_REQUIRED', 0x00000004: 'USER_PASSWORD_NOT_REQUIRED', 0x00000008: 'USER_TEMP_DUPLICATE_ACCOUNT', 0x00000010: 'USER_NORMAL_ACCOUNT', 0x00000020: 'USER_MNS_LOGON_ACCOUNT', 0x00000040: 'USER_INTERDOMAIN_TRUST_ACCOUNT', 0x00000080: 'USER_WORKSTATION_TRUST_ACCOUNT', 0x00000100: 'USER_SERVER_TRUST_ACCOUNT', 0x00000200: 'USER_DONT_EXPIRE_PASSWORD', 0x00000400: 'USER_ACCOUNT_AUTO_LOCKED', 0x00000800: 'USER_ENCRYPTED_TEXT_PASSWORD_ALLOWED', 0x00001000: 'USER_SMARTCARD_REQUIRED', 0x00002000: 'USER_TRUSTED_FOR_DELEGATION', 0x00004000: 'USER_NOT_DELEGATED', 0x00008000: 'USER_USE_DES_KEY_ONLY', 0x00010000: 'USER_DONT_REQUIRE_PREAUTH', 0x00020000: 'USER_PASSWORD_EXPIRED', 0x00040000: 'USER_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION', 0x00080000: 'USER_NO_AUTH_DATA_REQUIRED', 0x00100000: 'USER_PARTIAL_SECRETS_ACCOUNT', 0x00200000: 'USER_USE_AES_KEYS'} _DEBUG_INFO_C_VALUE = [ ('format_version', 'Format version', '_FormatIntegerAsDecimal'), ('unknown1', 'Unknown1', '_FormatIntegerAsHexadecimal2'), ('unknown2', 'Unknown1', '_FormatIntegerAsHexadecimal4'), ('security_descriptor_size', 'Security descriptor size', '_FormatIntegerAsDecimal'), ('unknown3', 'Unknown1', '_FormatIntegerAsHexadecimal2'), ('unknown4', 'Unknown1', '_FormatIntegerAsHexadecimal2'), ('security_descriptor', 'Security descriptor', '_FormatSecurityDescriptor')] _DEBUG_INFO_F_VALUE = [ ('major_version', 'Major version', '_FormatIntegerAsDecimal'), ('minor_version', 'Minor version', '_FormatIntegerAsDecimal'), ('unknown1', 'Unknown1', '_FormatIntegerAsHexadecimal8'), ('last_login_time', 'Last login time', '_FormatIntegerAsFiletime'), ('unknown2', 'Unknown2', '_FormatIntegerAsHexadecimal8'), ('last_password_set_time', 'Last password set time', '_FormatIntegerAsFiletime'), ('account_expiration_time', 'Account expiration time', '_FormatIntegerAsFiletime'), ('last_password_failure_time', 'Last password failure time', '_FormatIntegerAsFiletime'), ('rid', 'Relative identifier (RID)', '_FormatIntegerAsDecimal'), ('primary_gid', 'Primary group identifier (GID)', '_FormatIntegerAsDecimal'), ('user_account_control_flags', 'User account control flags', '_FormatIntegerAsHexadecimal8'), ('user_account_control_flags', None, '_FormatUserAccountControlFlags'), ('country_code', 'Country code', '_FormatIntegerAsHexadecimal4'), ('codepage', 'Codepage', '_FormatIntegerAsDecimal'), ('number_of_password_failures', 'Number of password failures', '_FormatIntegerAsDecimal'), ('number_of_logons', 'Number of logons', '_FormatIntegerAsDecimal'), ('unknown6', 'Unknown6', '_FormatIntegerAsHexadecimal8'), ('unknown7', 'Unknown7', '_FormatIntegerAsHexadecimal8'), ('unknown8', 'Unknown8', '_FormatIntegerAsHexadecimal8')] def _DebugPrintUserInformationDescriptor( self, index, descriptor, descriptor_data_offset, descriptor_data): """Prints an user information descriptor. Args: index (int): index of the user information descriptor. descriptor (user_information_descriptor): user information descriptor. descriptor_data_offset (int): offset of the descriptor data relative from the start of the V value data. descriptor_data (bytes): descriptor data. """ descriptor_index = index + 1 self._DebugPrintText( f'User information descriptor: {descriptor_index:d}:\n') value_string = self._USER_INFORMATION_DESCRIPTORS[index] self._DebugPrintValue('Description', value_string) self._DebugPrintValue('Offset', ( f'0x{descriptor.offset:08x} (0x{descriptor_data_offset:08x})')) self._DebugPrintDecimalValue('Size', descriptor.size) self._DebugPrintValue('Unknown1', f'0x{descriptor.unknown1:08x}') self._DebugPrintData('Data', descriptor_data) # pylint: disable=no-member,using-constant-test def _FormatSecurityDescriptor(self, security_descriptor_data): """Formats security descriptor. Args: security_descriptor_data (bytes): security descriptor data. Returns: str: formatted security descriptor. """ fwnt_descriptor = pyfwnt.security_descriptor() fwnt_descriptor.copy_from_byte_stream(security_descriptor_data) lines = [] if fwnt_descriptor.owner: identifier_string = fwnt_descriptor.owner.get_string() lines.append(f'\tOwner: {identifier_string:s}') if fwnt_descriptor.group: identifier_string = fwnt_descriptor.group.get_string() lines.append(f'\tGroup: {identifier_string:s}') # TODO: format SACL # TODO: format DACL lines.append('') return '\n'.join(lines) # pylint: enable=no-member,using-constant-test def _FormatUserAccountControlFlags(self, user_account_control_flags): """Formats user account control flags. Args: user_account_control_flags (int): user account control flags. Returns: str: formatted user account control flags. """ lines = [] if user_account_control_flags: for flag, identifier in sorted( self._USER_ACCOUNT_CONTROL_FLAGS.items()): if flag & user_account_control_flags: lines.append(f'\t{identifier:s} (0x{flag:08x})') lines.append('') lines.append('') return '\n'.join(lines) def ParseCValue(self, value_data): """Parses the C value data. Args: value_data (bytes): F value data. Raises: ParseError: if the value data could not be parsed. """ data_type_map = self._GetDataTypeMap('c_value') try: c_value = self._ReadStructureFromByteStream( value_data, 0, data_type_map, 'C value') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse C value with error: {exception!s}') if self._debug: self._DebugPrintStructureObject(c_value, self._DEBUG_INFO_C_VALUE) def _ParseFiletime(self, filetime): """Parses a FILETIME timestamp value. Args: filetime (int): a FILETIME timestamp value. Returns: dfdatetime.DateTimeValues: date and time values. """ if filetime == 0: return dfdatetime_semantic_time.SemanticTime(string='Not set') if filetime == 0x7fffffffffffffff: return dfdatetime_semantic_time.SemanticTime(string='Never') return dfdatetime_filetime.Filetime(timestamp=filetime) def ParseFValue(self, value_data, user_account): """Parses the F value data. Args: value_data (bytes): F value data. user_account (UserAccount): user account. Raises: ParseError: if the value data could not be parsed. """ data_type_map = self._GetDataTypeMap('f_value') try: f_value = self._ReadStructureFromByteStream( value_data, 0, data_type_map, 'F value') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse F value with error: {exception!s}') # TODO: change FILETIME timestamps into date time values. # date_time = self._ParseFiletime(f_value.last_login_time) user_account.last_login_time = f_value.last_login_time user_account.last_password_set_time = f_value.last_password_set_time user_account.account_expiration_time = f_value.account_expiration_time user_account.last_password_failure_time = f_value.last_password_failure_time user_account.rid = f_value.rid user_account.primary_gid = f_value.primary_gid user_account.user_account_control_flags = f_value.user_account_control_flags user_account.codepage = f_value.codepage user_account.number_of_password_failures = ( f_value.number_of_password_failures) user_account.number_of_logons = f_value.number_of_logons if self._debug: self._DebugPrintStructureObject(f_value, self._DEBUG_INFO_F_VALUE) def ParseVValue(self, value_data, user_account): """Parses the V value data. Args: value_data (bytes): V value data. user_account (UserAccount): user account. Raises: ParseError: if the value data could not be parsed. """ data_type_map = self._GetDataTypeMap('v_value') try: v_value = self._ReadStructureFromByteStream( value_data, 0, data_type_map, 'V value') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse V value with error: {exception!s}') for index in range(0, 17): user_information_descriptor = v_value[index] data_start_offset = user_information_descriptor.offset + 0xcc data_end_offset = data_start_offset + user_information_descriptor.size descriptor_data = value_data[data_start_offset:data_end_offset] if self._debug: self._DebugPrintUserInformationDescriptor( index, user_information_descriptor, data_start_offset, descriptor_data) if index == 0: if self._debug: value_string = self._FormatSecurityDescriptor(descriptor_data) self._DebugPrintText('Security descriptor:\n') self._DebugPrintText(value_string) self._DebugPrintText('\n') elif index == 1: user_account.username = descriptor_data.decode( 'utf-16-le').rstrip('\x00') if self._debug: self._DebugPrintValue('Username', user_account.username) self._DebugPrintText('\n') elif index == 2: user_account.full_name = descriptor_data.decode( 'utf-16-le').rstrip('\x00') if self._debug: self._DebugPrintValue('Full name', user_account.full_name) self._DebugPrintText('\n') elif index == 3: user_account.comment = descriptor_data.decode( 'utf-16-le').rstrip('\x00') if self._debug: self._DebugPrintValue('Comment', user_account.comment) self._DebugPrintText('\n') elif index == 4: user_account.user_comment = descriptor_data.decode( 'utf-16-le').rstrip('\x00') if self._debug: self._DebugPrintValue( 'User comment', user_account.user_comment) self._DebugPrintText('\n') if self._debug: self._DebugPrintText('\n') class SecurityAccountManagerCollector(interface.WindowsRegistryKeyCollector): """Security Accounts Manager (SAM) collector. Attributes: user_accounts (list[UserAccount]): user accounts. """ _USERS_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\SAM\\SAM\\Domains\\Account\\Users') def __init__(self, debug=False, output_writer=None): """Initializes a Security Accounts Manager (SAM) collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._parser = SecurityAccountManagerDataParser( debug=debug, output_writer=output_writer) self.user_accounts = [] def Collect(self, registry): # pylint: disable=arguments-differ """Collects the Security Accounts Manager (SAM) information. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the Security Accounts Manager (SAM) information key was found, False if not. """ main_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\SAM\\SAM') if not main_key: return False c_value = main_key.GetValueByName('C') if c_value: self._parser.ParseCValue(c_value.data) users_key = registry.GetKeyByPath(self._USERS_KEY_PATH) if not users_key: return False for subkey in users_key.GetSubkeys(): if subkey.name == 'Names': continue user_account = UserAccount() f_value = subkey.GetValueByName('F') if f_value: self._parser.ParseFValue(f_value.data, user_account) v_value = subkey.GetValueByName('V') if v_value: self._parser.ParseVValue(v_value.data, user_account) self.user_accounts.append(user_account) return True ================================================ FILE: winregrc/sam.yaml ================================================ # dtFabric format specification. --- name: sam type: format description: Security Accounts Manager (SAM) format --- name: byte type: integer attributes: format: unsigned size: 1 units: bytes --- name: uint16 type: integer attributes: format: unsigned size: 2 units: bytes --- name: uint32 type: integer attributes: format: unsigned size: 4 units: bytes --- name: uint64 type: integer attributes: format: unsigned size: 8 units: bytes --- name: c_value type: structure description: Security Accounts Manager C value. attributes: byte_order: little-endian members: - name: format_version data_type: uint16 - name: unknown1 data_type: uint16 - name: unknown2 data_type: uint32 - name: security_descriptor_size data_type: uint32 - name: unknown3 data_type: uint16 - name: unknown4 data_type: uint16 - name: security_descriptor type: stream element_data_type: byte elements_data_size: c_value.security_descriptor_size --- name: f_value type: structure description: Security Accounts Manager F value. attributes: byte_order: little-endian members: - name: major_version data_type: uint16 - name: minor_version data_type: uint16 - name: unknown1 data_type: uint32 - name: last_login_time data_type: uint64 - name: unknown2 data_type: uint64 - name: last_password_set_time data_type: uint64 - name: account_expiration_time data_type: uint64 - name: last_password_failure_time data_type: uint64 - name: rid data_type: uint32 - name: primary_gid data_type: uint32 - name: user_account_control_flags data_type: uint32 - name: country_code data_type: uint16 - name: codepage data_type: uint16 - name: number_of_password_failures data_type: uint16 - name: number_of_logons data_type: uint16 - name: unknown6 data_type: uint32 - name: unknown7 data_type: uint32 - name: unknown8 data_type: uint32 --- name: user_information_descriptor type: structure description: Security Accounts Manager user information descriptor. attributes: byte_order: little-endian members: - name: offset data_type: uint32 - name: size data_type: uint32 - name: unknown1 data_type: uint32 --- name: v_value type: sequence description: Security Accounts Manager V value. element_data_type: user_information_descriptor number_of_elements: 17 ================================================ FILE: winregrc/scripts/__init__.py ================================================ ================================================ FILE: winregrc/scripts/appcompatcache.py ================================================ #!/usr/bin/env python3 """Script to extract Application Compatibility Cache information.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import appcompatcache from winregrc import output_writers from winregrc import volume_scanner def Main(): """Entry point of console script to extract AppCompatCache information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Application Compatibility Cache information from ' 'a SYSTEM Registry file.')) argument_parser.add_argument( '--all', dest='all_control_sets', action='store_true', default=False, help=( 'Process all control sets instead of only the current control set.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SYSTEM Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 try: collector_object = appcompatcache.AppCompatCacheCollector( debug=options.debug, output_writer=output_writer) # TODO: change collector to generate AppCompatCacheCachedEntry has_results = collector_object.Collect( scanner.registry, all_control_sets=options.all_control_sets) if has_results: for cached_entry in collector_object.cached_entries: output_writer.WriteFiletimeValue( 'Last modification time', cached_entry.last_modification_time) output_writer.WriteValue('Path', cached_entry.path) output_writer.WriteText('\n') finally: output_writer.Close() if not has_results: print('No application compatibility cache entries found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/application_identifiers.py ================================================ #!/usr/bin/env python3 """Script to extract Windows application identifiers (AppID).""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import application_identifiers from winregrc import output_writers from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteApplicationIdentifier(self, application_identifier): """Writes an application identifier to the output. Args: application_identifier (ApplicationIdentifier): application identifier. """ self.WriteValue( application_identifier.guid, application_identifier.description) def Main(): """Entry point of console script to extract Windows AppIDs. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the Windows application identifiers (AppID) from the Windows ' 'Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 collector_object = application_identifiers.ApplicationIdentifiersCollector( debug=options.debug) output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: has_results = False for application_identifier in collector_object.Collect(scanner.registry): output_writer_object.WriteApplicationIdentifier(application_identifier) has_results = True finally: output_writer_object.Close() if not has_results: print('No Windows application identifiers (AppID) found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/cached_credentials.py ================================================ #!/usr/bin/env python3 """Script to extract cached credentials.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import cached_credentials from winregrc import output_writers from winregrc import volume_scanner def Main(): """Entry point of console script to extract cached credentials. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the cached credentials from a SECURITY Registry file.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help=( 'enable debug output.')) argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SECURITY and SYSTEM Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 if scanner.IsSingleFileRegistry(): print('Both SECURITY and SYSYEM Registry files are required.') print('') return 1 # TODO: map collector to available Registry keys. collector_object = cached_credentials.CachedCredentialsKeyCollector( debug=options.debug, output_writer=output_writer) result = collector_object.Collect(scanner.registry) if not result: print('No Cache key found.') else: output_writer.WriteText('\n') output_writer.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/catalog.py ================================================ #!/usr/bin/env python3 """Script to extract a catalog of Windows Registry keys and values.""" import argparse import logging import re import sys from dfwinreg import creg as dfwinreg_creg from dfwinreg import regf as dfwinreg_regf from dfwinreg import registry as dfwinreg_registry from winregrc import catalog from winregrc import output_writers class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteKeyPath(self, key_path): """Writes a key path to the output. Args: key_path (str): key path. """ self.WriteText(f'{key_path:s}\n') def WriteValueDescriptor(self, value_name, value_data_type): """Writes a value descriptor to the output. Args: value_name (str): name of the value. value_data_type (str): data type of the value. """ self.WriteText(f'\t{value_name:s}\t{value_data_type:s}\n') def Main(): """Entry point of console script to extract Windows Registry catalogs. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts a catalog of Windows Registry keys and values.')) argument_parser.add_argument( '--group_keys', '--group-keys', dest='group_keys', action='store_true', default=False, help='Group keys with similar values.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help='path of a Windows Registry file.') options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') with open(options.source, 'rb') as file_object: try: registry_file = dfwinreg_regf.REGFWinRegistryFile() registry_file.Open(file_object) except OSError: registry_file = None if not registry_file: try: registry_file = dfwinreg_creg.CREGWinRegistryFile() registry_file.Open(file_object) except OSError: registry_file = None if not registry_file: print('Unable to open Windows Registry file.') return 1 # Using dfWinReg to determine Windows native key paths if available. registry = dfwinreg_registry.WinRegistry() key_path_prefix = registry.GetRegistryFileMapping(registry_file) registry_file.SetKeyPathPrefix(key_path_prefix) root_key = registry_file.GetRootKey() output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 collector_object = catalog.CatalogCollector(group_keys=options.group_keys) def AlphanumericCompare(key): return (int(text) if text.isdigit() else text.lower() for text in re.split('([0-9]+)', key[0])) try: has_results = False for key_descriptor in collector_object.Collect(root_key): output_writer_object.WriteKeyPath(key_descriptor.key_path) for key_path in key_descriptor.grouped_key_paths: output_writer_object.WriteKeyPath(key_path) for value_name, data_type_string in sorted( key_descriptor.value_descriptors, key=AlphanumericCompare): output_writer_object.WriteValueDescriptor( value_name, data_type_string) if options.group_keys: output_writer_object.WriteText('\n') has_results = True finally: output_writer_object.Close() if not has_results: print('No keys and values found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/controlpanel_items.py ================================================ #!/usr/bin/env python3 """Script to extract Windows control panel items from the Windows Registry.""" import argparse import logging import sys import yaml from winregrc import controlpanel_items from winregrc import output_writers from winregrc import versions from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" _WINDOWS_VERSIONS_KEY_FUNCTION = versions.WindowsVersions.KeyFunction def WriteHeader(self): """Writes the header to stdout.""" print('# winreg-kb controlpanel items definitions') def WriteKnownFolder(self, control_panel_item, windows_versions): """Writes the control panel item to stdout. Args: control_panel_item (KnownFolder): the control panel item. windows_versions (list[str]): the Windows versions. """ print('---') print(f'identifier: "{control_panel_item.identifier:s}"') if control_panel_item.module_name: print(f'module_name: "{control_panel_item.module_name:s}"') if control_panel_item.alternate_module_names: alternate_module_names = ', '.join([ f'"{name:s}"' for name in control_panel_item.alternate_module_names]) print(f'alternate_module_names: [{alternate_module_names:s}]') windows_versions = ', '.join([f'"{version:s}"' for version in sorted( windows_versions, key=self._WINDOWS_VERSIONS_KEY_FUNCTION)]) print(f'windows_versions: [{windows_versions:s}]') def Main(): """Entry point of console script to extract control panel items. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Windows control panel items from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( '-w', '--windows_version', '--windows-version', dest='windows_version', action='store', metavar='VERSION', default=None, help='string that identifies the Windows version.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') try: with open(options.source, 'r', encoding='utf-8') as file_object: source_definitions = list(yaml.safe_load_all(file_object)) except (SyntaxError, UnicodeDecodeError, yaml.parser.ParserError): source_definitions = [{ 'source': options.source, 'windows_version': options.windows_version}] mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.username = ['none'] volume_scanner_options.volumes = ['none'] control_panel_item_per_identifier = {} windows_versions_per_control_panel_item = {} for source_definition in source_definitions: source_path = source_definition['source'] logging.info(f'Processing: {source_path:s}') if not scanner.ScanForWindowsVolume( source_path, options=volume_scanner_options): logging.error(( f'Unable to retrieve the volume with the Windows directory from: ' f'{source_path:s}.')) continue collector_object = controlpanel_items.ControlPanelItemsCollector( debug=options.debug) # TODO: determine Windows version from source. windows_version = source_definition['windows_version'] for item in collector_object.Collect(scanner.registry): # TODO: compare attributes with existing item. existing_item = control_panel_item_per_identifier.get( item.identifier, None) # Ignore a module name that is the same as the identifier. if (item.module_name and item.module_name.lower() == item.identifier): item.module_name = None if not existing_item: control_panel_item_per_identifier[item.identifier] = item elif not existing_item.module_name: existing_item.module_name = item.module_name elif (item.module_name and item.module_name != existing_item.module_name and item.module_name not in existing_item.alternate_module_names): existing_item.alternate_module_names.append(item.module_name) if item.identifier not in ( windows_versions_per_control_panel_item): windows_versions_per_control_panel_item[item.identifier] = [] if windows_version: windows_versions_per_control_panel_item[item.identifier].append( windows_version) if not control_panel_item_per_identifier: print('No control panel items found.') return 0 output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: output_writer_object.WriteHeader() for identifier, windows_versions in sorted( windows_versions_per_control_panel_item.items()): control_panel_item = control_panel_item_per_identifier[identifier] output_writer_object.WriteKnownFolder( control_panel_item, windows_versions) finally: output_writer_object.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/delegatefolders.py ================================================ #!/usr/bin/env python3 """Script to extract Windows delegate folders from the Windows Registry.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import delegatefolders from winregrc import output_writers from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteDelegateFolder(self, delegate_folder): """Writes a delegate folder to the output. Args: delegate_folder (DelegateFolder): delegate folder. """ self.WriteValue('Identifier', delegate_folder.identifier) self.WriteValue('Name', delegate_folder.name) self.WriteValue('Namespace', delegate_folder.namespace) self.WriteText('\n') def Main(): """Entry point of console script to extract Windows delegate folders. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Windows delegate folders from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of a ' 'storage media image containing the C:\\Windows directory, or the ' 'path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 collector_object = delegatefolders.DelegateFoldersCollector( debug=options.debug) output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: has_results = False for delegate_folder in collector_object.Collect(scanner.registry): output_writer_object.WriteDelegateFolder(delegate_folder) has_results = True finally: output_writer_object.Close() if not has_results: print('No Windows delegate folders found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/environment_variables.py ================================================ #!/usr/bin/env python3 """Script to extract environment variables.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import environment_variables from winregrc import output_writers from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteEnvironmentVariable(self, environment_variable): """Writes an environment variable to the output. Args: environment_variable (EnvironmentVariable): environment variable. """ self.WriteValue(environment_variable.name, environment_variable.value) def Main(): """Entry point of console script to extract environment variables. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the environment variables from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 collector_object = environment_variables.EnvironmentVariablesCollector( debug=options.debug) output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: has_results = False for environment_variable in sorted( collector_object.Collect(scanner.registry), key=lambda environment_variable: environment_variable.name): output_writer_object.WriteEnvironmentVariable(environment_variable) has_results = True finally: output_writer_object.Close() if not has_results: print('No environment variables found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/eventlog_providers.py ================================================ #!/usr/bin/env python3 """Script to extract Windows Event Log providers from the Windows Registry.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import eventlog_providers from winregrc import output_writers from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteEventLogProvider(self, eventlog_provider): """Writes a Event Log provider to the output. Args: eventlog_provider (EventLogProvider): Event Log provider. """ if eventlog_provider.name: self.WriteText(f'Name\t\t\t\t: {eventlog_provider.name:s}\n') if eventlog_provider.identifier: self.WriteText(f'Identifier\t\t\t: {eventlog_provider.identifier:s}\n') if eventlog_provider.additional_identifier: self.WriteText(( f'Additional identifier\t\t: ' f'{eventlog_provider.additional_identifier:s}\n')) for index, log_type in enumerate(sorted(eventlog_provider.log_types)): if index == 0: text = f'Log type(s)\t\t\t: {log_type:s}\n' else: text = f'\t\t\t\t: {log_type:s}\n' self.WriteText(text) for index, log_source in enumerate(sorted(eventlog_provider.log_sources)): if index == 0: text = f'Log source(s)\t\t\t: {log_source:s}\n' else: text = f'\t\t\t\t: {log_source:s}\n' self.WriteText(text) for index, path in enumerate(sorted(( eventlog_provider.category_message_files))): if index == 0: text = f'Category message file(s)\t: {path:s}\n' else: text = f'\t\t\t\t: {path:s}\n' self.WriteText(text) for index, path in enumerate(sorted(( eventlog_provider.event_message_files))): if index == 0: text = f'Event message file(s)\t\t: {path:s}\n' else: text = f'\t\t\t\t: {path:s}\n' self.WriteText(text) for index, path in enumerate(sorted(( eventlog_provider.parameter_message_files))): if index == 0: text = f'Parameter message file(s)\t: {path:s}\n' else: text = f'\t\t\t\t: {path:s}\n' self.WriteText(text) self.WriteText('\n') def Main(): """Entry point of console script to extract Event Log providers. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Windows Event Log providers from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=('path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE or SYSTEM Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 collector_object = eventlog_providers.EventLogProvidersCollector( debug=options.debug) output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: has_results = False for eventlog_provider in collector_object.Collect(scanner.registry): output_writer_object.WriteEventLogProvider(eventlog_provider) has_results = True finally: output_writer_object.Close() if not has_results: print('No Windows Event Log providers found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/knownfolders.py ================================================ #!/usr/bin/env python3 """Script to extract Windows known folders from the Windows Registry.""" import argparse import logging import sys import yaml from winregrc import knownfolders from winregrc import output_writers from winregrc import versions from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" _WINDOWS_VERSIONS_KEY_FUNCTION = versions.WindowsVersions.KeyFunction def WriteHeader(self): """Writes the header to stdout.""" print('# winreg-kb knownfolder definitions') def WriteKnownFolder(self, known_folder, windows_versions): """Writes the known folder to stdout. Args: known_folder (KnownFolder): the known folder. windows_versions (list[str]): the Windows versions. """ print('---') print(f'identifier: "{known_folder.identifier:s}"') # TODO: escape \ in display name print(f'display_name: "{known_folder.display_name:s}"') if known_folder.localized_display_name: # TODO: escape \ in localized display_name print( f'localized_display_name: "{known_folder.localized_display_name:s}"') if known_folder.alternate_display_names: alternate_display_names = ', '.join([ f'"{name:s}"' for name in known_folder.alternate_display_names]) print(f'alternate_display_names: [{alternate_display_names:s}]') windows_versions = ', '.join([f'"{version:s}"' for version in sorted( windows_versions, key=self._WINDOWS_VERSIONS_KEY_FUNCTION)]) print(f'windows_versions: [{windows_versions:s}]') def Main(): """Entry point of console script to extract known folders. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Windows known folders from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( '-w', '--windows_version', '--windows-version', dest='windows_version', action='store', metavar='VERSION', default=None, help='string that identifies the Windows version.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') try: with open(options.source, 'r', encoding='utf-8') as file_object: source_definitions = list(yaml.safe_load_all(file_object)) except (SyntaxError, UnicodeDecodeError, yaml.parser.ParserError): source_definitions = [{ 'source': options.source, 'windows_version': options.windows_version}] mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.username = ['none'] volume_scanner_options.volumes = ['none'] known_folder_per_identifier = {} windows_versions_per_known_folder = {} for source_definition in source_definitions: source_path = source_definition['source'] logging.info(f'Processing: {source_path:s}') if not scanner.ScanForWindowsVolume( source_path, options=volume_scanner_options): logging.error(( f'Unable to retrieve the volume with the Windows directory from: ' f'{source_path:s}.')) continue collector_object = knownfolders.KnownFoldersCollector(debug=options.debug) # TODO: determine Windows version from source. windows_version = source_definition['windows_version'] for known_folder in collector_object.Collect(scanner.registry): # TODO: compare attributes with existing with known folder. existing_known_folder = known_folder_per_identifier.get( known_folder.identifier, None) if not existing_known_folder: known_folder_per_identifier[known_folder.identifier] = known_folder elif not existing_known_folder.display_name: existing_known_folder.display_name = known_folder.display_name elif (known_folder.display_name and known_folder.display_name != existing_known_folder.display_name and known_folder.display_name not in ( existing_known_folder.alternate_display_names)): existing_known_folder.alternate_display_names.append( known_folder.display_name) if known_folder.identifier not in windows_versions_per_known_folder: windows_versions_per_known_folder[known_folder.identifier] = [] if windows_version: windows_versions_per_known_folder[known_folder.identifier].append( windows_version) if not known_folder_per_identifier: print('No known folders found.') return 0 output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: output_writer_object.WriteHeader() for identifier, windows_versions in sorted( windows_versions_per_known_folder.items()): known_folder = known_folder_per_identifier[identifier] output_writer_object.WriteKnownFolder(known_folder, windows_versions) finally: output_writer_object.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/mounted_devices.py ================================================ #!/usr/bin/env python3 """Script to extract Windows mounted devices.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import mounted_devices from winregrc import output_writers from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteMountedDevice(self, mounted_device): """Writes a mounted device to the output. Args: mounted_device (MountedDevice): mounted device. """ self.WriteText(f'Identifier\t\t\t: {mounted_device.identifier:s}\n') if mounted_device.disk_identity: self.WriteText( f'MBR disk identity\t\t: 0x{mounted_device.disk_identity:08x}\n') self.WriteText(( f'MBR partition offset\t\t: {mounted_device.partition_offset:d} ' f'(0x{mounted_device.partition_offset:08x})\n')) elif mounted_device.partition_identifier: self.WriteText(( f'GPT partition identifier\t: ' f'{mounted_device.partition_identifier!s}\n')) elif mounted_device.device: self.WriteText(f'Device\t\t\t\t: {mounted_device.device:s}\n') self.WriteText('\n') def Main(): """Entry point of console script to extract Windows mounted devices. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Windows mounted devices from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 collector_object = mounted_devices.MountedDevicesCollector( debug=options.debug) output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: has_results = False for mounted_device in collector_object.Collect(scanner.registry): output_writer_object.WriteMountedDevice(mounted_device) has_results = True finally: output_writer_object.Close() if not has_results: print('No Windows mounted devices found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/mru.py ================================================ #!/usr/bin/env python3 """Script to extract Most Recently Used (MRU) information.""" import argparse import logging import sys from dfvfs.lib import errors as dfvfs_errors import pyfwps import pyfwsi from winregrc import mru from winregrc import output_writers from winregrc import shell_property_keys from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def _WritePropertyStore(self, fwps_store): """Writes a property store to stdout. Args: fwps_store (pyfwps.store): property store. Raises: RuntimeError: if a property value type is not supported. """ for fwps_set in iter(fwps_store.sets): for fwps_record in iter(fwps_set.records): if fwps_record.value_type == 0x0001: value_string = '' elif fwps_record.value_type in (0x0003, 0x0013, 0x0014, 0x0015): value_string = str(fwps_record.get_data_as_integer()) elif fwps_record.value_type in (0x0008, 0x001e, 0x001f): value_string = fwps_record.get_data_as_string() elif fwps_record.value_type == 0x000b: value_string = str(fwps_record.get_data_as_boolean()) elif fwps_record.value_type == 0x0040: filetime = fwps_record.get_data_as_integer() value_string = self._FormatFiletimeValue(filetime) elif fwps_record.value_type == 0x0042: # TODO: add support value_string = '' elif fwps_record.value_type == 0x0048: value_string = fwps_record.get_data_as_guid() elif fwps_record.value_type & 0xf000 == 0x1000: # TODO: add support value_string = '' else: raise RuntimeError( f'Unsupported value type: 0x{fwps_record.value_type:04x}') if fwps_record.entry_name: entry_string = fwps_record.entry_name else: entry_string = f'{fwps_record.entry_type:d}' property_key = f'{{{fwps_set.identifier:s}}}/{entry_string:s}' shell_property_key = shell_property_keys.SHELL_PROPERTY_KEYS.get( property_key, 'Unknown') self.WriteText( f'\tProperty: {property_key:s} ({shell_property_key:s})\n') self.WriteValue( f'\t\tValue (0x{fwps_record.value_type:04x})', value_string) def _WriteShellItem(self, fwsi_item): """Writes a shell item to stdout. Args: fwsi_item (pyfwsi.item): Shell item. """ if isinstance(fwsi_item, pyfwsi.compressed_folder): shell_item_type = 'Compressed Folder' elif isinstance(fwsi_item, pyfwsi.control_panel_category): shell_item_type = 'Control Panel Category' elif isinstance(fwsi_item, pyfwsi.control_panel_item): shell_item_type = 'Control Panel Item' elif isinstance(fwsi_item, pyfwsi.file_entry): shell_item_type = 'File Entry' elif isinstance(fwsi_item, pyfwsi.network_location): shell_item_type = 'Network Location' elif isinstance(fwsi_item, pyfwsi.root_folder): shell_item_type = 'Root Folder' elif isinstance(fwsi_item, pyfwsi.users_property_view): shell_item_type = 'Users Property View' elif isinstance(fwsi_item, pyfwsi.volume): shell_item_type = 'Volume' else: shell_item_type = f'Unknown (0x{fwsi_item.class_type:02x})' self.WriteValue('\tItem type', shell_item_type) if fwsi_item.delegate_folder_identifier: self.WriteValue( '\tDelegate folder', fwsi_item.delegate_folder_identifier) if isinstance(fwsi_item, pyfwsi.compressed_folder): self._WriteShellItemCompressedFolder(fwsi_item) elif isinstance(fwsi_item, pyfwsi.control_panel_category): self._WriteShellItemControlPanelCategory(fwsi_item) elif isinstance(fwsi_item, pyfwsi.control_panel_item): self._WriteShellItemControlPanelItem(fwsi_item) elif isinstance(fwsi_item, pyfwsi.file_entry): self._WriteShellItemFileEntry(fwsi_item) elif isinstance(fwsi_item, pyfwsi.network_location): self._WriteShellItemNetworkLocation(fwsi_item) elif isinstance(fwsi_item, pyfwsi.root_folder): self.WriteValue( '\tRoot shell folder identifier', fwsi_item.shell_folder_identifier) elif isinstance(fwsi_item, pyfwsi.users_property_view): self._WriteShellItemUsersPropertyView(fwsi_item) elif isinstance(fwsi_item, pyfwsi.volume): self._WriteShellItemVolume(fwsi_item) if fwsi_item.number_of_extension_blocks: self.WriteValue( '\tNumber of extension blocks', f'{fwsi_item.number_of_extension_blocks:d}') for index, extension_block in enumerate(fwsi_item.extension_blocks): display_index = index + 1 self.WriteText(f'Extension block: {display_index:d}\n') # TODO: print human readable description of signature self.WriteValue('\tSignature', f'0x{extension_block.signature:04x}') if isinstance(extension_block, pyfwsi.file_entry_extension): fat_date_time = extension_block.get_creation_time_as_integer() date_time_string = self._FormatFATDateTimeValue(fat_date_time) self.WriteValue('\tCreation time', date_time_string) fat_date_time = extension_block.get_access_time_as_integer() date_time_string = self._FormatFATDateTimeValue(fat_date_time) self.WriteValue('\tAccess time', date_time_string) self.WriteValue('\tLong name', extension_block.long_name) if extension_block.localized_name: self.WriteValue( '\tLocalized name', extension_block.localized_name) file_reference = extension_block.file_reference if file_reference is not None: if file_reference > 0x1000000000000: mft_entry = file_reference & 0xffffffffffff sequence_number = file_reference >> 48 file_reference = f'{mft_entry:d}-{sequence_number:d}' else: file_reference = f'0x{file_reference:04x}' self.WriteValue('\tFile reference', file_reference) # TODO: add support for other extension blocks self.WriteText('\n') def _WriteShellItemCompressedFolder(self, fwsi_item): """Writes a compressed folder shell item to stdout. Args: fwsi_item (pyfwsi.compressed_folder): compressed folder shell item. """ self.WriteValue('\tName', fwsi_item.name) def _WriteShellItemControlPanelCategory(self, fwsi_item): """Writes a control panel category shell item to stdout. Args: fwsi_item (pyfwsi.control_panel_category): control panel category shell item. """ self.WriteValue( '\tControl panel category identifier', f'{fwsi_item.identifier:d}') def _WriteShellItemControlPanelItem(self, fwsi_item): """Writes a control panel item shell item to stdout. Args: fwsi_item (pyfwsi.control_panel_item): control panel item shell item. """ self.WriteValue('\tControl panel item identifier', fwsi_item.identifier) def _WriteShellItemFileEntry(self, fwsi_item): """Writes a file entry shell item to stdout. Args: fwsi_item (pyfwsi.file_entry): File entry shell item. """ self.WriteValue('\tFile size', f'{fwsi_item.file_size:d}') fat_date_time = fwsi_item.get_modification_time_as_integer() date_time_string = self._FormatFATDateTimeValue(fat_date_time) self.WriteValue('\tModification time', date_time_string) self.WriteValue( '\tFile attribute flags', f'0x08{fwsi_item.file_attribute_flags:08x}') self.WriteValue('\tName', fwsi_item.name) def _WriteShellItemNetworkLocation(self, fwsi_item): """Writes a network location shell item to stdout. Args: fwsi_item (pyfwsi.network_location): network location shell item. """ self.WriteValue('\tNetwork location', fwsi_item.location) if fwsi_item.description: self.WriteValue('\tDescription', fwsi_item.description) if fwsi_item.comments: self.WriteValue('\tComments', fwsi_item.comments) def _WriteShellItemUsersPropertyView(self, fwsi_item): """Writes an users property view item to stdout. Args: fwsi_item (pyfwsi.users_property_view): users property view shell item. """ if fwsi_item.property_store_data: fwps_store = pyfwps.store() fwps_store.copy_from_byte_stream(fwsi_item.property_store_data) self._WritePropertyStore(fwps_store) def _WriteShellItemVolume(self, fwsi_item): """Writes a volume shell item to stdout. Args: fwsi_item (pyfwsi.volume): volume shell item. """ if fwsi_item.name: self.WriteValue('\tVolume name', fwsi_item.name) if fwsi_item.identifier: self.WriteValue('\tVolume identifier', fwsi_item.identifier) if fwsi_item.shell_folder_identifier: self.WriteValue( '\tVolume shell folder identifier', fwsi_item.shell_folder_identifier) def WriteShellItem(self, fwsi_item): """Writes a shell item to stdout. Args: fwsi_item (pyfwsi.item): Shell item. """ self.WriteText('Shell item:\n') self._WriteShellItem(fwsi_item) def WriteShellItemList(self, fwsi_item_list): """Writes a shell item list to stdout. Args: fwsi_item_list (pyfwsi.item_list): Shell item list. """ self.WriteText('Shell item list:\n') self.WriteValue('\tNumber of items', fwsi_item_list.number_of_items) self.WriteText('\n') for item_index, fwsi_item in enumerate(fwsi_item_list.items): display_item_index = item_index + 1 self.WriteText(f'Shell item: {display_item_index:d}\n') self._WriteShellItem(fwsi_item) def Main(): """Entry point of console script to extract Most Recently Used information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Most Recently Used information from a NTUSER.DAT Registry ' 'file.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( '-u', '--username', dest='username', action='store', metavar='USERNAME', default=None, help='username within a storage media image.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a NTUSER.DAT or UsrClass.dat Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer = StdoutWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.username = options.username volume_scanner_options.volumes = ['none'] try: result = scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options) except dfvfs_errors.ScannerError as exception: print(f'[ERROR] {exception!s}', file=sys.stderr) print('') return 1 except KeyboardInterrupt: print('Aborted by user.', file=sys.stderr) print('') return 1 if not result: print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 collector_object = mru.MostRecentlyUsedCollector( debug=options.debug, output_writer=output_writer) # TODO: change collector to generate MostRecentlyUsedEntry result = collector_object.Collect(scanner.registry) if not result: print('No Most Recently Used key found.') return 0 for mru_entry in collector_object.mru_entries: output_writer.WriteValue('Key path', mru_entry.key_path) output_writer.WriteValue('Value name', mru_entry.value_name) if mru_entry.string: output_writer.WriteValue('String', mru_entry.string) output_writer.WriteText('\n') if mru_entry.shell_item_data: fwsi_item = pyfwsi.item() fwsi_item.copy_from_byte_stream(mru_entry.shell_item_data) output_writer.WriteShellItem(fwsi_item) elif mru_entry.shell_item_list_data: shell_item_list = pyfwsi.item_list() shell_item_list.copy_from_byte_stream(mru_entry.shell_item_list_data) output_writer.WriteShellItemList(shell_item_list) output_writer.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/msie_zone_info.py ================================================ #!/usr/bin/env python3 """Script to extract MSIE zone information.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import msie_zone_info from winregrc import output_writers from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" _DEFAULT_ZONE_NAMES = { '0': 'My Computer', '1': 'Local Intranet', '2': 'Trusted sites', '3': 'Internet', '4': 'Restricted sites'} # Sources: # http://support.microsoft.com/kb/182569 # http://technet.microsoft.com/en-us/library/cc783259(v=ws.10).aspx _CONTROL_DESCRIPTIONS = { '1001': 'Download signed ActiveX controls', '1004': 'Download unsigned ActiveX controls', '1200': 'Run ActiveX controls and plug-ins', '1201': ('Initialize and script ActiveX controls not marked as safe for ' 'scripting'), '1206': 'Allow scripting of Internet Explorer Web browser control', '1207': 'Reserved', '1208': 'Allow previously unused ActiveX controls to run without prompt', '1209': 'Allow Scriptlets', '120A': 'Override Per-Site (domain-based) ActiveX restrictions', '120B': 'Override Per-Site (domain-based) ActiveX restrictions', '1400': 'Active scripting', '1402': 'Scripting of Java applets', '1405': 'Script ActiveX controls marked as safe for scripting', '1406': 'Access data sources across domains', '1407': 'Allow Programmatic clipboard access', '1408': 'Reserved', '1601': 'Submit non-encrypted form data', '1604': 'Font download', '1605': 'Run Java', '1606': 'Userdata persistence', '1607': 'Navigate sub-frames across different domains', '1608': 'Allow META REFRESH', '1609': 'Display mixed content', '160A': 'Include local directory path when uploading files to a server', '1800': 'Installation of desktop items', '1802': 'Drag and drop or copy and paste files', '1803': 'File Download', '1804': 'Launching programs and files in an IFRAME', '1805': 'Launching programs and files in webview', '1806': 'Launching applications and unsafe files', '1807': 'Reserved', '1808': 'Reserved', '1809': 'Use Pop-up Blocker', '180A': 'Reserved', '180B': 'Reserved', '180C': 'Reserved', '180D': 'Reserved', '1A00': 'Logon', '1A02': 'Allow persistent cookies that are stored on your computer', '1A03': 'Allow per-session cookies (not stored)', '1A04': ('Don\'t prompt for client certificate selection when no ' 'certificates or only one certificate exists'), '1A05': 'Allow 3rd party persistent cookies', '1A06': 'Allow 3rd party session cookies', '1A10': 'Privacy Settings', '1C00': 'Java permissions', '1E05': 'Software channel permissions', '1F00': 'Reserved', '2000': 'Binary and script behaviors', '2001': 'Run components signed with Authenticode', '2004': 'Run components not signed with Authenticode', '2100': 'Open files based on content, not file extension', '2101': ('Web sites in less privileged web content zone can navigate ' 'into this zone'), '2102': ('Allow script initiated windows without size or position ' 'constraints'), '2103': 'Allow status bar updates via script', '2104': 'Allow websites to open windows without address or status bars', '2105': 'Allow websites to prompt for information using scripted windows', '2200': 'Automatic prompting for file downloads', '2201': 'Automatic prompting for ActiveX controls', '2300': 'Allow web pages to use restricted protocols for active content', '2301': 'Use Phishing Filter', '2400': '.NET Framework: XAML browser applications', '2401': '.NET Framework: XPS documents', '2402': '.NET Framework: Loose XAML', '2500': 'Turn on Protected Mode [Vista only setting]', '2600': 'Enable .NET Framework setup'} _CONTROL_VALUES_COMMON_ENABLE = { 0x00000000: 'Enable', 0x00000001: 'Prompt', 0x00000003: 'Disable', 0x00010000: 'Administrator approved'} _CONTROL_VALUES_COMMON_SAFETY = { 0x00010000: 'High safety', 0x00020000: 'Medium safety', 0x00030000: 'Low safety'} _CONTROL_VALUES_1A00 = { 0x00000000: 'Automatic logon with current user name and password', 0x00010000: 'Prompt for user name and password', 0x00020000: 'Automatic logon only in Intranet zone', 0x00030000: 'Anonymous logon'} _CONTROL_VALUES_1C00 = { 0x00000000: 'Disable Java', 0x00010000: 'High safety', 0x00020000: 'Medium safety', 0x00030000: 'Low safety', 0x00800000: 'Custom'} def _GetControlValueDescription(self, control, control_value): """Retrieves the description of a specific control value. Args: control (str): control. control_value (str): value to which the control is set. Returns: str: description of the control value or None if not available. """ if control in ( '1001', '1004', '1200', '1201', '1400', '1402', '1405', '1406', '1407', '1601', '1604', '1606', '1607', '1608', '1609', '1800', '1802', '1803', '1804', '1809', '1A04', '2000', '2001', '2004', '2100', '2101', '2102', '2200', '2201', '2300'): return self._CONTROL_VALUES_COMMON_ENABLE.get(control_value) if control == '1A00': return self._CONTROL_VALUES_1A00.get(control_value) if control == '1C00': return self._CONTROL_VALUES_1C00.get(control_value) if control == '1E05': return self._CONTROL_VALUES_COMMON_SAFETY.get(control_value) return None def WriteZoneInformation(self, zone_information): """Writes MSIE zone information to the output. Args: zone_information (MSIEZoneInformation): MSIE zone information. """ zone_name = zone_information.zone_name if not zone_name: zone_name = self._DEFAULT_ZONE_NAMES.get(zone_information.zone) if zone_name: text = f'Zone\t\t\t: {zone_information.zone:s} ({zone_name:s})\n' else: text = f'Zone\t\t\t: {zone_information.zone:s}\n' self.WriteText(text) control_description = self._CONTROL_DESCRIPTIONS.get( zone_information.control, None) if control_description: text = (f'Control\t\t\t: {zone_information.control:s} ' f'({control_description:s})\n') else: text = f'Control\t\t\t: {zone_information.control:s}\n' self.WriteText(text) control_value_description = self._GetControlValueDescription( zone_information.control, zone_information.control_value) if control_value_description: text = (f'Value\t\t\t: {zone_information.control_value!s} ' f'({control_value_description:s})\n') else: text = f'Value\t\t\t: {zone_information.control_value!s}\n' self.WriteText(text) self.WriteText('\n') def Main(): """Entry point of console script to extract MSIE zone information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the MSIE zone information from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a NTUSER.DAT or SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 collector_object = msie_zone_info.MSIEZoneInformationCollector( debug=options.debug) output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: has_results = False for zone_information in collector_object.Collect(scanner.registry): output_writer_object.WriteZoneInformation(zone_information) has_results = True finally: output_writer_object.Close() if not has_results: print('No MSIE zone information found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/profiles.py ================================================ #!/usr/bin/env python3 """Script to extract user profiles.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import profiles from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteUserProfile(self, user_profile): """Writes an user profile to the output. Args: user_profile (UserProfile): user profile. """ self.WriteText(( f'{user_profile.security_identifier:s}: ' f'{user_profile.home_directory:s}\n')) def Main(): """Entry point of console script to extract user profiles. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the user profiles from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = profiles.UserProfilesCollector( debug=options.debug) output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: has_results = False for user_profile in collector_object.Collect(scanner.registry): output_writer_object.WriteUserProfile(user_profile) has_results = True if has_results: output_writer_object.WriteText('\n') finally: output_writer_object.Close() if not has_results: print('No user profiles found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/programscache.py ================================================ #!/usr/bin/env python3 """Script to extract the program cache.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import programscache from winregrc import volume_scanner def Main(): """Entry point of console script to extract the program cache. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the program cache from a NTUSER.DAT Registry file.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a NTUSER.DAT Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') # TODO: add support to select user. mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 try: collector_object = programscache.ProgramsCacheCollector( debug=options.debug, output_writer=output_writer) # TODO: change collector to generate ProgramCacheEntry has_results = collector_object.Collect(scanner.registry) finally: output_writer.Close() if not has_results: print('No program cache entries found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/sam.py ================================================ #!/usr/bin/env python3 """Script to extract Security Account Manager (SAM) information.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import sam from winregrc import volume_scanner def Main(): """Entry point of console script to extract SAM information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Security Account Manager information from a SAM Registry ' 'file.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SAM Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = sam.SecurityAccountManagerCollector( debug=options.debug, output_writer=output_writer) result = collector_object.Collect(scanner.registry) if not result: output_writer.WriteText('No Security Account Manager key found.') output_writer.WriteText('') else: for user_account in collector_object.user_accounts: output_writer.WriteValue('Username', user_account.username) output_writer.WriteValue('Relative identifier (RID)', user_account.rid) output_writer.WriteValue( 'Primary group identifier', user_account.primary_gid) if user_account.full_name: output_writer.WriteValue('Full name', user_account.full_name) if user_account.comment: output_writer.WriteValue('Comment', user_account.comment) if user_account.user_comment: output_writer.WriteValue('User comment', user_account.user_comment) output_writer.WriteFiletimeValue( 'Last log-in time', user_account.last_login_time) output_writer.WriteFiletimeValue( 'Last password set time', user_account.last_password_set_time) output_writer.WriteFiletimeValue( 'Account expiration time', user_account.account_expiration_time) output_writer.WriteFiletimeValue( 'Last password failure time', user_account.last_password_failure_time) output_writer.WriteValue( 'Number of log-ons', user_account.number_of_logons) output_writer.WriteValue( 'Number of password failures', user_account.number_of_password_failures) if user_account.codepage: output_writer.WriteValue('Codepage', user_account.codepage) output_writer.WriteText('\n') output_writer.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/services.py ================================================ """Script to extract services information.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import services from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def __init__(self, use_tsv=False): """Initializes a stdout output writer. Args: use_tsv (bool): True if the output should in tab separated values. """ super().__init__() self._printed_header = False self._use_tsv = use_tsv def WriteWindowsService(self, service): """Writes the Windows service to stdout. Args: service (WindowsService): Windows service. """ service_type_description = '' if service.service_type: service_type_description = service.GetServiceTypeDescription() start_value_description = '' if service.start_value is not None: start_value_description = service.GetStartValueDescription() if self._use_tsv: if not self._printed_header: print('\t'.join([ 'Service', 'Type', 'Display name', 'Description', 'Executable', 'Start'])) self._printed_header = True service_display_name = service.display_name or '' service_description = service.description or '' service_image_path = service.image_path or '' print('\t'.join([ service.name, service_type_description, service_display_name, service_description, service_image_path, start_value_description])) else: print(f'{service.name:s}') if service.service_type: print(f'\tType\t\t\t: {service_type_description:s}') if service.display_name: print(f'\tDisplay name\t\t: {service.display_name:s}') if service.description: print(f'\tDescription\t\t: {service.description:s}') if service.image_path: print(f'\tExecutable\t\t: {service.image_path:s}') if service.object_name: object_name_description = service.GetObjectNameDescription() print(f'\t{object_name_description:s}\t\t: {service.object_name:s}') if service.start_value is not None: print(f'\tStart\t\t\t: {start_value_description:s}') print('') def Main(): """Entry point of console script to extract services information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the services information from a SYSTEM Registry file.')) argument_parser.add_argument( '--all', dest='all_control_sets', action='store_true', default=False, help=( 'Process all control sets instead of only the current control set.')) argument_parser.add_argument( '--diff', dest='diff_control_sets', action='store_true', default=False, help='Only list differences between control sets.') argument_parser.add_argument( '--tsv', dest='use_tsv', action='store_true', default=False, help='Use tab separated value (TSV) output.') argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SYSTEM Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 collector_object = services.WindowsServicesCollector(debug=options.debug) output_writer_object = StdoutWriter(use_tsv=options.use_tsv) if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: if options.diff_control_sets: has_results = collector_object.Compare( scanner.registry, output_writer_object) else: has_results = False for windows_service in collector_object.Collect( scanner.registry, all_control_sets=options.all_control_sets): output_writer_object.WriteWindowsService(windows_service) has_results = True finally: output_writer_object.Close() if not has_results: print('No Services key found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/shellfolders.py ================================================ #!/usr/bin/env python3 """Script to extract shell folder identifiers.""" import argparse import logging import sys import yaml from winregrc import output_writers from winregrc import shellfolders from winregrc import versions from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" _WINDOWS_VERSIONS_KEY_FUNCTION = versions.WindowsVersions.KeyFunction def WriteHeader(self): """Writes the header to stdout.""" print('# winreg-kb shellfolder definitions') def WriteShellFolder(self, shell_folder, windows_versions): """Writes the shell folder to stdout. Args: shell_folder (WindowsShellFolder): the shell folder. windows_versions (list[str]): the Windows versions. """ print('---') print(f'identifier: "{shell_folder.identifier:s}"') if shell_folder.class_name: print(f'class_name: {shell_folder.class_name:s}') name = shell_folder.name if '\\' in name: name = name.replace('\\', '\\\\') if shell_folder.name: print(f'name: "{name:s}"') if shell_folder.alternate_names: alternate_names = ', '.join([ f'"{name:s}"' for name in shell_folder.alternate_names]) print(f'alternate_names: [{alternate_names:s}]') windows_versions = ', '.join([f'"{version:s}"' for version in sorted( windows_versions, key=self._WINDOWS_VERSIONS_KEY_FUNCTION)]) print(f'windows_versions: [{windows_versions:s}]') def Main(): """Entry point of console script to extract shell folder identifiers. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the shell folder identifiers from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( '-w', '--windows_version', '--windows-version', dest='windows_version', action='store', metavar='VERSION', default=None, help='string that identifies the Windows version.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of a ' 'storage media image containing the C:\\Windows directory, or the ' 'path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') try: with open(options.source, 'r', encoding='utf-8') as file_object: source_definitions = list(yaml.safe_load_all(file_object)) except (SyntaxError, UnicodeDecodeError, yaml.parser.ParserError): source_definitions = [{ 'source': options.source, 'windows_version': options.windows_version}] mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.username = ['none'] volume_scanner_options.volumes = ['none'] shell_folder_per_identifier = {} windows_versions_per_shell_folder = {} for source_definition in source_definitions: source_path = source_definition['source'] logging.info(f'Processing: {source_path:s}') if not scanner.ScanForWindowsVolume( source_path, options=volume_scanner_options): logging.error(( f'Unable to retrieve the volume with the Windows directory from: ' f'{source_path:s}.')) continue # TODO: map collector to available Registry keys. collector_object = shellfolders.ShellFoldersCollector( debug=options.debug) # TODO: determine Windows version from source. windows_version = source_definition['windows_version'] for shell_folder in collector_object.Collect(scanner.registry): # TODO: compare attributes with existing with shell folder. existing_shell_folder = shell_folder_per_identifier.get( shell_folder.identifier, None) if not existing_shell_folder: shell_folder_per_identifier[shell_folder.identifier] = shell_folder elif not existing_shell_folder.name: existing_shell_folder.name = shell_folder.name elif (shell_folder.name and shell_folder.name != existing_shell_folder.name and shell_folder.name not in existing_shell_folder.alternate_names): existing_shell_folder.alternate_names.append(shell_folder.name) if windows_version: if shell_folder.identifier not in windows_versions_per_shell_folder: windows_versions_per_shell_folder[shell_folder.identifier] = [] windows_versions_per_shell_folder[shell_folder.identifier].append( windows_version) if not shell_folder_per_identifier: print('No shell folder identifiers found.') return 0 output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: output_writer_object.WriteHeader() for identifier, windows_versions in sorted( windows_versions_per_shell_folder.items()): shell_folder = shell_folder_per_identifier[identifier] output_writer_object.WriteShellFolder(shell_folder, windows_versions) finally: output_writer_object.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/srum_extensions.py ================================================ #!/usr/bin/env python3 """Script to extract System Resource Usage Monitor (SRUM) extensions.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import srum_extensions from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteSRUMExtension(self, srum_extension): """Writes a SRUM extension to the output. Args: srum_extension (SRUMExtension): SRUM extension. """ self.WriteText(f'{srum_extension.guid:s}\t{srum_extension.dll_name:s}\n') def Main(): """Entry point of console script to extract SRUM extensions. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the User Assist information from a NTUSER.DAT Registry file.')) argument_parser.add_argument( '--codepage', dest='codepage', action='store', metavar='CODEPAGE', default='cp1252', help='the codepage of the extended ASCII strings.') argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a NTUSER.DAT Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = srum_extensions.SRUMExtensionsCollector( debug=options.debug) result = collector_object.Collect(scanner.registry, output_writer_object) if not result: print('No SRUM extensions key found.') output_writer_object.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/sysinfo.py ================================================ #!/usr/bin/env python3 """Script to extract system information.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import sysinfo from winregrc import volume_scanner def Main(): """Entry point of console script to extract system information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the system information from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help=( 'enable debug output.')) argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = sysinfo.SystemInfoCollector( debug=options.debug, output_writer=output_writer) result = collector_object.Collect(scanner.registry) if not result: print('No Current Version key found.') else: output_writer.WriteValue( 'Product name', collector_object.system_information.product_name) output_writer.WriteValue( 'Product identifier', collector_object.system_information.product_identifier) output_writer.WriteValue( 'Current version', collector_object.system_information.current_version) output_writer.WriteValue( 'Current type', collector_object.system_information.current_type) output_writer.WriteValue( 'Current build number', collector_object.system_information.current_build_number) output_writer.WriteValue( 'CSD version', collector_object.system_information.csd_version) output_writer.WriteValue( 'Registered organization', collector_object.system_information.registered_organization) output_writer.WriteValue( 'Registered owner', collector_object.system_information.registered_owner) date_time_value = collector_object.system_information.installation_date date_time_string = date_time_value.CopyToDateTimeString() output_writer.WriteValue('Installation date', date_time_string) output_writer.WriteValue( 'Path name', collector_object.system_information.path_name) output_writer.WriteValue( '%SystemRoot%', collector_object.system_information.system_root) output_writer.WriteText('\n') output_writer.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/syskey.py ================================================ #!/usr/bin/env python3 """Script to extract system key.""" import argparse import codecs import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import syskey from winregrc import volume_scanner def Main(): """Entry point of console script to extract system key. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the system key from a SYSTEM Registry file.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help=( 'enable debug output.')) argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SYSTEM Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = syskey.SystemKeyCollector( debug=options.debug, output_writer=output_writer) result = collector_object.Collect(scanner.registry) if not result: print('No LSA key found.') else: boot_key = codecs.encode(collector_object.system_key.boot_key, 'hex') output_writer.WriteValue('Boot key', boot_key.decode('ascii')) output_writer.WriteText('\n') output_writer.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/task_cache.py ================================================ #!/usr/bin/env python3 """Script to extract Task Scheduler Task Cache information.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import task_cache from winregrc import volume_scanner def Main(): """Entry point of console script to extract Scheduler Task Cache information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts Task Scheduler Task Cache information from the Windows ' 'Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = task_cache.TaskCacheCollector( debug=options.debug, output_writer=output_writer) result = collector_object.Collect(scanner.registry) if not result: print('No Task Cache key found.') output_writer.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/time_zones.py ================================================ #!/usr/bin/env python3 """Script to extract tize zone information from the Windows Registry.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import time_zones from winregrc import output_writers from winregrc import volume_scanner class CSVFileWriter(output_writers.OutputWriter): """CSV file output writer.""" # pylint: disable=abstract-method def __init__(self, path): """Initializes a CSV file output writer. Args: path (str): path of the CSV file to write to. """ super().__init__() self._file_object = None self._path = path def Close(self): """Closes the output writer.""" self._file_object.close() self._file_object = None def Open(self): """Opens the output writer. Returns: bool: True if successful or False if not. """ # self._file_object = open(self._path, 'wt', encoding='utf-8') self._file_object = open(self._path, 'at', encoding='utf-8') # pylint: disable=consider-using-with return 0 def WriteTimeZone(self, time_zone): """Writes a time zone to the output. Args: time_zone (TimeZone): time zone. """ hours_from_utc, minutes_from_utc = divmod(time_zone.offset, 60) if hours_from_utc < 0: hours_from_utc *= -1 sign = '-' else: sign = '+' self._file_object.write(( f'{time_zone.name:s},{sign:s}{hours_from_utc:02d}:' f'{minutes_from_utc:02d}\n')) def WriteText(self, text): """Writes text. Args: text (str): text to write. """ return class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" def WriteTimeZone(self, time_zone): """Writes a time zone to the output. Args: time_zone (TimeZone): time zone. """ hours_from_utc, minutes_from_utc = divmod(time_zone.offset, 60) if hours_from_utc < 0: hours_from_utc *= -1 sign = '-' else: sign = '+' self.WriteText(( f'{time_zone.name:s}\t{sign:s}{hours_from_utc:02d}:' f'{minutes_from_utc:02d}\n')) def Main(): """Entry point of console script to extract tize zone information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts time zone information for the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( '--csv', dest='csv_file', action='store', metavar='time_zones.csv', default=None, help='path of the CSV file to write to.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') if options.csv_file: output_writer_object = CSVFileWriter(options.csv_file) else: output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = time_zones.TimeZonesCollector(debug=options.debug) result = collector_object.Collect(scanner.registry, output_writer_object) if not result: print('No "Time Zones" key found.') output_writer_object.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/type_libraries.py ================================================ #!/usr/bin/env python3 """Script to extract type libraries.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import type_libraries from winregrc import volume_scanner def Main(): """Entry point of console script to extract type libraries. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the type libraries from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SOFTWARE Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = type_libraries.TypeLibrariesCollector( debug=options.debug, output_writer=output_writer) result = collector_object.Collect(scanner.registry) if not result: print('No TypeLib key found.') else: for type_library in collector_object.type_libraries: print((f'{type_library.identifier:s}\t{type_library.version:s}\t' f'{type_library.description:s}\t' f'{type_library.typelib_filename:s}')) output_writer.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/usbstor.py ================================================ #!/usr/bin/env python3 """Script to extract USB storage devices.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import usbstor from winregrc import volume_scanner class StdoutWriter(output_writers.StdoutOutputWriter): """Stdout output writer.""" _PROPERTY_IDENTIFIERS_PER_SET = { '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}': { '00000004': 'System.Devices.NumaNode'}, '{83da6326-97a6-4088-9453-a1923f573b29}': { '00000006': 'System.Devices.SessionId', # DEVPKEY_Device_InstallDate '00000064': 'System.Devices.InstallDate', # DEVPKEY_Device_FirstInstallDate '00000065': 'System.Devices.FirstInstallDate', # DEVPKEY_Device_LastArrivalDate '00000066': 'System.Devices.LastArrivalDate', # DEVPKEY_Device_LastRemovalDate '00000067': 'System.Devices.LastRemovalDate'}, '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}': { '00000002': 'System.Drivers.AssemblyDate', '00000003': 'System.Drivers.Version', '00000004': 'System.Drivers.Description', '00000005': 'System.Drivers.InfPath', '00000006': 'System.Drivers.InfSection', '00000007': 'System.Drivers.InfSectionExt', '00000008': 'System.Drivers.MatchingDeviceId', '00000009': 'System.Drivers.Provider', '0000000a': 'System.Drivers.PropPageProvider', '0000000b': 'System.Drivers.CoInstallers', '0000000c': 'System.Drivers.ResourcePickerTags', '0000000d': 'System.Drivers.ResourcePickerExceptions', '0000000e': 'System.Drivers.Rank', '0000000f': 'System.Drivers.LogoLevel'}} def WriteUserProfile(self, storage_device): """Writes an USB storage device to the output. Args: storage_device (UserProfile): USB storage device. """ self.WriteText(f'Key path\t: {storage_device.key_path:s}\n') self.WriteText(f'Device type\t: {storage_device.device_type:s}\n') self.WriteText(f'Display name\t: {storage_device.display_name:s}\n') self.WriteText(f'Product\t\t: {storage_device.product:s}\n') if storage_device.revision: self.WriteText(f'Revision\t: {storage_device.revision:s}\n') if storage_device.vendor: self.WriteText(f'Vendor\t\t: {storage_device.vendor:s}\n') if storage_device.properties: self.WriteText('Properties:\n') for storage_device_property in storage_device.properties: self.WriteText(( f'\t{storage_device_property.property_set:s} ' f'{storage_device_property.identifier:s}')) description = self._PROPERTY_IDENTIFIERS_PER_SET.get( storage_device_property.property_set, {}).get( storage_device_property.identifier, None) if description: self.WriteText(f' ({description:s})') self.WriteText(f' (0x{storage_device_property.value_type:08x})') value = storage_device_property.value if storage_device_property.value_type == 0x00000007: self.WriteText(f': 0x{value:08x}\n') elif storage_device_property.value_type == 0x00000010: value = value.CopyToDateTimeStringISO8601() self.WriteText(f': {value:s}\n') else: self.WriteText(f': {value!s}\n') self.WriteText('\n') def Main(): """Entry point of console script to extract USB storage devices. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the USB storage devices from the Windows Registry.')) argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a SYSTEM Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = usbstor.USBStorageDeviceCollector(debug=options.debug) output_writer_object = StdoutWriter() if not output_writer_object.Open(): print('Unable to open output writer.') print('') return 1 try: has_results = False for storage_device in collector_object.Collect(scanner.registry): output_writer_object.WriteUserProfile(storage_device) has_results = True finally: output_writer_object.Close() if not has_results: print('No USB storage devices found.') return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/scripts/userassist.py ================================================ #!/usr/bin/env python3 """Script to extract UserAssist information.""" import argparse import logging import sys from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from winregrc import output_writers from winregrc import userassist from winregrc import volume_scanner def Main(): """Entry point of console script to extract UserAssist information. Returns: int: exit code that is provided to sys.exit(). """ argument_parser = argparse.ArgumentParser(description=( 'Extracts the UserAssist information from a NTUSER.DAT Registry file.')) argument_parser.add_argument( '--codepage', dest='codepage', action='store', metavar='CODEPAGE', default='cp1252', help='the codepage of the extended ASCII strings.') argument_parser.add_argument( '-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug output.') argument_parser.add_argument( 'source', nargs='?', action='store', metavar='PATH', default=None, help=( 'path of the volume containing C:\\Windows, the filename of ' 'a storage media image containing the C:\\Windows directory, ' 'or the path of a NTUSER.DAT Registry file.')) options = argument_parser.parse_args() if not options.source: print('Source value is missing.') print('') argument_parser.print_help() print('') return 1 logging.basicConfig( level=logging.INFO, format='[%(levelname)s] %(message)s') output_writer = output_writers.StdoutOutputWriter() if not output_writer.Open(): print('Unable to open output writer.') print('') return 1 mediator = volume_scanner.WindowsRegistryVolumeScannerMediator() scanner = volume_scanner.WindowsRegistryVolumeScanner(mediator=mediator) volume_scanner_options = dfvfs_volume_scanner.VolumeScannerOptions() volume_scanner_options.partitions = ['all'] volume_scanner_options.snapshots = ['none'] volume_scanner_options.volumes = ['none'] if not scanner.ScanForWindowsVolume( options.source, options=volume_scanner_options): print((f'Unable to retrieve the volume with the Windows directory from: ' f'{options.source:s}.')) print('') return 1 # TODO: map collector to available Registry keys. collector_object = userassist.UserAssistCollector( debug=options.debug, output_writer=output_writer) result = collector_object.Collect(scanner.registry) if not result: print('No UserAssist key found.') else: guid = None for user_assist_entry in collector_object.user_assist_entries: if user_assist_entry.guid != guid: print(f'GUID\t\t: {user_assist_entry.guid:s}') guid = user_assist_entry.guid print(f'Name\t\t: {user_assist_entry.name:s}') print(f'Original name\t: {user_assist_entry.value_name:s}') print('') output_writer.Close() return 0 if __name__ == '__main__': sys.exit(Main()) ================================================ FILE: winregrc/services.py ================================================ """Windows services and drivers collector.""" from winregrc import interface class WindowsService: """Windows service. Attributes: description (str): service description. display_name (str): display name. image_path (str): image path. name (str): name. object_name (str): object name service_type (str): service type. start_value (str): start value. """ _OBJECT_NAME_DESCRIPTIONS = { 0x00000010: 'Account name', 0x00000020: 'Account name', 0x00000110: 'Account name', } _SERVICE_TYPE_DESCRIPTIONS = { 0x00000001: 'Kernel device driver', 0x00000002: 'File system driver', 0x00000004: 'Adapter arguments', 0x00000010: 'Stand-alone service', 0x00000020: 'Shared service', } _START_VALUE_DESCRIPTIONS = { 0x00000000: 'Boot', 0x00000001: 'System', 0x00000002: 'Automatic', 0x00000003: 'On demand', 0x00000004: 'Disabled', } def __init__( self, name, service_type, display_name, description, image_path, object_name, start_value): """Initializes a Windows service. Args: name (str): name. service_type (str): service type. display_name (str): display name. description (str): service description. image_path (str): image path. object_name (str): object name start_value (str): start value. """ super().__init__() self.description = description self.display_name = display_name self.image_path = image_path self.name = name self.object_name = object_name self.service_type = service_type self.start_value = start_value def __eq__(self, other): """Determines the current Windows service is equal to the other. Returns: bool: True if equal. """ return ( other is not None and self.description == other.description and self.display_name == other.display_name and self.image_path == other.image_path and self.name == other.name and self.object_name == other.object_name and self.service_type == other.service_type and self.start_value == other.start_value) def __ne__(self, other): """Determines the current Windows service is not equal to the other. Returns: bool: True if not equal. """ return ( other is None or self.description != other.description or self.display_name != other.display_name or self.image_path != other.image_path or self.name != other.name or self.object_name != other.object_name or self.service_type != other.service_type or self.start_value != other.start_value) def GetObjectNameDescription(self): """Retrieves the object name description. Return: str: object name description. """ return self._OBJECT_NAME_DESCRIPTIONS.get(self.service_type, 'Object name') def GetServiceTypeDescription(self): """Retrieves the service type description. Return: str: service type description. """ return self._SERVICE_TYPE_DESCRIPTIONS.get( self.service_type, f'Unknown 0x{self.service_type:08x}') def GetStartValueDescription(self): """Retrieves the start value description. Return: str: start value description. """ return self._START_VALUE_DESCRIPTIONS.get( self.start_value, f'Unknown 0x{self.start_value:08x}') class WindowsServicesCollector(interface.WindowsRegistryKeyCollector): """Windows services and drivers collector.""" def _CollectWindowsServicesFromServicesKey(self, services_key): """Collects the Windows services from a services key. Args: services_key (dfwinreg.WinRegistryKey): services Windows Registry key. Yields: WindowsService: a Windows service. """ for service_key in services_key.GetSubkeys(): display_name = self._GetStringValueFromKey(service_key, 'DisplayName') description = self._GetValueFromKey(service_key, 'Description') image_path = self._GetValueFromKey(service_key, 'ImagePath') object_name = self._GetValueFromKey(service_key, 'ObjectName') start_value = self._GetValueFromKey(service_key, 'Start') type_value = self._GetValueFromKey(service_key, 'Type') yield WindowsService( service_key.name, type_value, display_name, description, image_path, object_name, start_value) def _CollectWindowsServicesFromSystemKey(self, system_key): """Collects the Windows services from a system key. Args: system_key (dfwinreg.WinRegistryKey): system Windows Registry key. Yields: WindowsService: a Windows service. """ for control_set_key in system_key.GetSubkeys(): if control_set_key.name.startswith('ControlSet'): services_key = control_set_key.GetSubkeyByName('Services') if services_key: yield from self._CollectWindowsServicesFromServicesKey(services_key) def Collect(self, registry, all_control_sets=False): """Collects Windows services and drivers. Args: registry (dfwinreg.WinRegistry): Windows Registry. all_control_sets (Optional[bool]): True if the services should be collected from all control sets instead of only the current control set. Yields: WindowsService: a Windows service. """ if all_control_sets: system_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\System') if system_key: yield from self._CollectWindowsServicesFromSystemKey(system_key) else: services_key = registry.GetKeyByPath( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services') if services_key: yield from self._CollectWindowsServicesFromServicesKey(services_key) def Compare(self, registry, output_writer): """Compares services in the different control sets. Args: registry (dfwinreg.WinRegistry): Windows Registry. output_writer (OutputWriter): output writer. Returns: bool: True if the services key was found, False if not. """ system_key = registry.GetKeyByPath('HKEY_LOCAL_MACHINE\\System') if not system_key: return False result = False control_sets = [] service_names = set() for control_set_key in system_key.GetSubkeys(): if control_set_key.name.startswith('ControlSet'): services_key = control_set_key.GetSubkeyByName('Services') if not services_key: continue result = True services = {} for windows_service in self._CollectWindowsServicesFromServicesKey( services_key): if windows_service.name in services: # TODO: print warning. continue windows_service_name = windows_service.name.lower() service_names.add(windows_service_name) services[windows_service_name] = windows_service control_sets.append(services) number_of_control_sets = len(control_sets) for name in service_names: services_diff = set() windows_service = control_sets[0].get(name) for control_set_index in range(1, number_of_control_sets): control_set = control_sets[control_set_index] compare_windows_service = control_set.get(name) if windows_service != compare_windows_service: services_diff.add(windows_service) services_diff.add(compare_windows_service) for windows_service in services_diff: if not windows_service: if self._debug: print('Not defined') else: output_writer.WriteWindowsService(windows_service) return result ================================================ FILE: winregrc/shell_property_keys.py ================================================ #!/usr/bin/env python3 """Windows serialized property to shell property key mappings. This file was generated by the winsps-kb project. """ SHELL_PROPERTY_KEYS = { '{00000000-0000-0000-0000-000000000000}/0': 'PKEY_Null', '{000214a1-0000-0000-c000-000000000046}/9': 'PKEY_Status', '{00bc20a3-bd48-4085-872c-a88d77f5097e}/105': ( 'PKEY_Music_ComposerSortOverride'), '{00f23377-7ac6-4b7a-8443-345e731fa57a}/10': ( 'PKEY_PhotoAcquire_DuplicateDetectionID'), '{00f23377-7ac6-4b7a-8443-345e731fa57a}/2': ( 'PKEY_PhotoAcquire_RelativePathname'), '{00f23377-7ac6-4b7a-8443-345e731fa57a}/3': ( 'PKEY_PhotoAcquire_FinalFilename'), '{00f23377-7ac6-4b7a-8443-345e731fa57a}/4': 'PKEY_PhotoAcquire_GroupTag', '{00f23377-7ac6-4b7a-8443-345e731fa57a}/5': ( 'PKEY_PhotoAcquire_TransferResult'), '{00f23377-7ac6-4b7a-8443-345e731fa57a}/6': ( 'PKEY_PhotoAcquire_OriginalFilename'), '{00f23377-7ac6-4b7a-8443-345e731fa57a}/7': ( 'PKEY_PhotoAcquire_CameraSequenceNumber'), '{00f23377-7ac6-4b7a-8443-345e731fa57a}/8': ( 'PKEY_PhotoAcquire_IntermediateFile'), '{00f23377-7ac6-4b7a-8443-345e731fa57a}/9': 'PKEY_PhotoAcquire_SkipImport', '{00f58a38-c54b-4c40-8696-97235980eae1}/100': 'PKEY_Calendar_Resources', '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/101': ( 'PKEY_Contact_JobInfo1YomiCompanyName'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/102': ( 'PKEY_Contact_JobInfo1CompanyName'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/103': 'PKEY_Contact_JobInfo1Title', '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/104': ( 'PKEY_Contact_JobInfo1OfficeLocation'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/105': ( 'PKEY_Contact_JobInfo1Manager'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/106': ( 'PKEY_Contact_JobInfo1Department'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/107': ( 'PKEY_Contact_JobInfo2YomiCompanyName'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/108': ( 'PKEY_Contact_JobInfo2CompanyName'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/109': 'PKEY_Contact_JobInfo2Title', '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/110': ( 'PKEY_Contact_JobInfo2OfficeLocation'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/112': ( 'PKEY_Contact_JobInfo2Manager'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/113': ( 'PKEY_Contact_JobInfo2Department'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/114': ( 'PKEY_Contact_JobInfo3YomiCompanyName'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/115': ( 'PKEY_Contact_JobInfo3CompanyName'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/116': 'PKEY_Contact_JobInfo3Title', '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/117': ( 'PKEY_Contact_JobInfo3OfficeLocation'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/118': ( 'PKEY_Contact_JobInfo3Manager'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/119': ( 'PKEY_Contact_JobInfo3Department'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/120': ( 'PKEY_Contact_JobInfo1CompanyAddress'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/121': ( 'PKEY_Contact_JobInfo2CompanyAddress'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/123': ( 'PKEY_Contact_JobInfo3CompanyAddress'), '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/124': 'PKEY_Contact_Webpage2', '{00f63dd8-22bd-4a5d-ba34-5cb0b9bdcb03}/125': 'PKEY_Contact_Webpage3', '{026e516e-b814-414b-83cd-856d6fef4822}/2': ( 'PKEY_DeviceInterface_FriendlyName'), '{026e516e-b814-414b-83cd-856d6fef4822}/3': 'PKEY_DeviceInterface_Enabled', '{026e516e-b814-414b-83cd-856d6fef4822}/4': ( 'PKEY_Devices_InterfaceClassGuid'), '{026e516e-b814-414b-83cd-856d6fef4822}/6': ( 'PKEY_Devices_RestrictedInterface'), '{026e516e-b814-414b-83cd-856d6fef4822}/9': 'PKEY_Devices_SchematicName', '{029c0252-5b86-46c7-aca0-2769ffc8e3d4}/100': 'PKEY_GPS_LatitudeRef', '{02b0f689-a914-4e45-821d-1dda452ed2c4}/100': 'PKEY_GPS_LongitudeNumerator', '{03089873-8ee8-4191-bd60-d31f72b7900b}/100': ( 'PKEY_Contact_DisplayOtherPhoneNumbers'), '{0337ecec-39fb-4581-a0bd-4c4cc51e9914}/100': ( 'PKEY_Photo_ApertureNumerator'), '{048658ad-2db8-41a4-bbb6-ac1ef1207eb1}/100': 'PKEY_ItemClassType', '{06704b0c-e830-4c81-9178-91e4e95a80a0}/2': ( 'PKEY_Devices_NotificationStore'), '{06704b0c-e830-4c81-9178-91e4e95a80a0}/3': 'PKEY_Devices_Notification', '{084d8a0a-e6d5-40de-bf1f-c8820e7c877c}/100': 'PKEY_Task_CompletionStatus', '{08a65aa1-f4c9-43dd-9ddf-a33d8e7ead85}/100': ( 'PKEY_Contact_HomeAddressCountry'), '{08c0c253-a154-4746-9005-82de5317148b}/1': 'PKEY_FunctionInstance', '{08c7cc5f-60f2-4494-ad75-55e3e0b5add0}/100': 'PKEY_Task_Owner', '{08f6d7c2-e3f2-44fc-af1e-5aa5c81a2d3e}/100': 'PKEY_Photo_MaxAperture', '{0933f3f5-4786-4f46-a8e8-d64dd37fa521}/100': ( 'PKEY_Photo_FocalPlaneXResolutionDenominator'), '{09429607-582d-437f-84c3-de93a2b24c3c}/100': ( 'PKEY_Calendar_OptionalAttendeeNames'), '{09edd5b6-b301-43c5-9990-d00302effd46}/100': 'PKEY_Media_AverageLevel', '{0a7b84ef-0c27-463f-84ef-06c5070001be}/10': ( 'PKEY_DeviceInterface_PrinterName'), '{0adef160-db3f-4308-9a21-06237b16fa2a}/100': ( 'PKEY_Contact_HomeAddressStreet'), '{0b48f35a-be6e-4f17-b108-3c4073d1669a}/15': 'PKEY_Device_PrinterURL', '{0b63e343-9ccc-11d0-bcdb-00805fccce04}/12': ( 'PKEY_Search_UrlToIndexWithModificationTime'), '{0b63e343-9ccc-11d0-bcdb-00805fccce04}/2': 'PKEY_Search_UrlToIndex', '{0b63e343-9ccc-11d0-bcdb-00805fccce04}/23': ( 'PKEY_Search_IsClosedDirectory'), '{0b63e343-9ccc-11d0-bcdb-00805fccce04}/24': 'PKEY_Search_IsFullyContained', '{0b63e350-9ccc-11d0-bcdb-00805fccce04}/5': 'PKEY_MIMEType', '{0b63e350-9ccc-11d0-bcdb-00805fccce04}/8': 'PKEY_Search_GatherTime', '{0b8bb018-2725-4b44-92ba-7933aeb2dde7}/2': ( 'PKEY_Contact_AccountPictureDynamicVideo'), '{0b8bb018-2725-4b44-92ba-7933aeb2dde7}/3': ( 'PKEY_Contact_AccountPictureLarge'), '{0b8bb018-2725-4b44-92ba-7933aeb2dde7}/4': ( 'PKEY_Contact_AccountPictureSmall'), '{0ba7d6c3-568d-4159-ab91-781a91fb71e5}/100': ( 'PKEY_Calendar_RequiredAttendeeAddresses'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/11': ( 'PKEY_Devices_AepContainer_IsPresent'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/12': ( 'PKEY_Devices_AepContainer_ContainerId'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/13': ( 'PKEY_Devices_AepContainer_ProtocolIds'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/2': ( 'PKEY_Devices_AepContainer_Children'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/3': ( 'PKEY_Devices_AepContainer_CanPair'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/4': ( 'PKEY_Devices_AepContainer_IsPaired'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/6': ( 'PKEY_Devices_AepContainer_Manufacturer'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/7': ( 'PKEY_Devices_AepContainer_ModelName'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/8': ( 'PKEY_Devices_AepContainer_ModelIds'), '{0bba1ede-7566-4f47-90ec-25fc567ced2a}/9': ( 'PKEY_Devices_AepContainer_Categories'), '{0be1c8e7-1981-4676-ae14-fdd78f05a6e7}/100': 'PKEY_Message_SenderAddress', '{0c73b141-39d6-4653-a683-cab291eaf95b}/2': 'PKEY_Supplemental_AlbumID', '{0c73b141-39d6-4653-a683-cab291eaf95b}/3': 'PKEY_Supplemental_ResourceId', '{0c840a88-b043-466d-9766-d4b26da3fa77}/100': ( 'PKEY_Photo_SubjectDistanceDenominator'), '{0cb2bf5a-9ee7-4a86-8222-f01e07fdadaf}/100': ( 'PKEY_PropGroup_PhotoAdvanced'), '{0cef7d53-fa64-11d1-a203-0000f81fedee}/3': 'PKEY_FileDescription', '{0cef7d53-fa64-11d1-a203-0000f81fedee}/4': 'PKEY_FileVersion', '{0cef7d53-fa64-11d1-a203-0000f81fedee}/5': 'PKEY_InternalName', '{0cef7d53-fa64-11d1-a203-0000f81fedee}/6': 'PKEY_OriginalFileName', '{0cef7d53-fa64-11d1-a203-0000f81fedee}/7': 'PKEY_Software_ProductName', '{0cef7d53-fa64-11d1-a203-0000f81fedee}/9': 'PKEY_Trademarks', '{0cf8fb02-1837-42f1-a697-a7017aa289b9}/100': 'PKEY_GPS_DOP', '{0da41cfa-d224-4a18-ae2f-596158db4b3a}/100': 'PKEY_Message_SenderName', '{0f55cde2-4f49-450d-92c1-dcd16301b1b7}/100': 'PKEY_GPS_LatitudeDecimal', '{10984e0a-f9f2-4321-b7ef-baf195af4319}/100': 'PKEY_ParentalRatingReason', '{10b24595-41a2-4e20-93c2-5761c1395f32}/100': ( 'PKEY_GPS_ImgDirectionDenominator'), '{10dabe05-32aa-4c29-bf1a-63e2d220587f}/100': 'PKEY_Image_ImageID', '{11d6336b-38c4-4ec9-84d6-eb38d0b150af}/100': ( 'PKEY_Contact_OtherEmailAddresses'), '{125491f4-818f-46b2-91b5-d537753617b2}/100': 'PKEY_GPS_Status', '{13673f42-a3d6-49f6-b4da-ae46e0c5237c}/2': 'PKEY_Devices_DevObjectType', '{13eb7ffc-ec89-4346-b19d-ccc6f1784223}/101': ( 'PKEY_Music_AlbumTitleSortOverride'), '{14977844-6b49-4aad-a714-a4513bf60460}/100': 'PKEY_Contact_FirstName', '{149c0b69-2c2d-48fc-808f-d318d78c4636}/2': 'PKEY_Volume_IsMappedDrive', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/18248': 'PKEY_Photo_Event', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/18258': 'PKEY_DateImported', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/259': 'PKEY_Image_Compression', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/271': ( 'PKEY_Photo_CameraManufacturer'), '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/272': 'PKEY_Photo_CameraModel', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/273': ( 'PKEY_Photo_CameraSerialNumber'), '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/274': 'PKEY_Photo_Orientation', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/305': 'PKEY_SoftwareUsed', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/33434': 'PKEY_Photo_ExposureTime', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/33437': 'PKEY_Photo_FNumber', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/34850': ( 'PKEY_Photo_ExposureProgram'), '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/34855': 'PKEY_Photo_ISOSpeed', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/36867': 'PKEY_Photo_DateTaken', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37377': 'PKEY_Photo_ShutterSpeed', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37378': 'PKEY_Photo_Aperture', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37380': 'PKEY_Photo_ExposureBias', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37382': ( 'PKEY_Photo_SubjectDistance'), '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37383': 'PKEY_Photo_MeteringMode', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37384': 'PKEY_Photo_LightSource', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37385': 'PKEY_Photo_Flash', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/37386': 'PKEY_Photo_FocalLength', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/40961': 'PKEY_Image_ColorSpace', '{14b81da1-0135-4d31-96d9-6cbfc9671a99}/41483': 'PKEY_Photo_FlashEnergy', '{14c83a99-0b3f-44b7-be4c-a178d3990564}/2': ( 'PKEY_DeviceInterfaceClass_DefaultInterface'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/10': ( 'PKEY_Devices_WiFiDirect_Services'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/11': ( 'PKEY_Devices_WiFiDirect_SupportedChannelList'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/12': ( 'PKEY_Devices_WiFiDirect_InformationElements'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/13': ( 'PKEY_Devices_WiFiDirect_DeviceAddress'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/2': ( 'PKEY_Devices_WiFiDirect_InterfaceAddress'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/3': ( 'PKEY_Devices_WiFiDirect_InterfaceGuid'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/4': ( 'PKEY_Devices_WiFiDirect_GroupId'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/5': ( 'PKEY_Devices_WiFiDirect_IsConnected'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/6': ( 'PKEY_Devices_WiFiDirect_IsVisible'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/7': ( 'PKEY_Devices_WiFiDirect_IsLegacyDevice'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/8': ( 'PKEY_Devices_WiFiDirect_MiracastVersion'), '{1506935d-e3e7-450f-8637-82233ebe5f6e}/9': ( 'PKEY_Devices_WiFiDirect_IsMiracastLcpSupported'), '{16473c91-d017-4ed9-ba4d-b6baa55dbcf8}/100': 'PKEY_GPS_ImgDirection', '{16cbb924-6500-473b-a5be-f1599bcbe413}/100': ( 'PKEY_Photo_DigitalZoomNumerator'), '{16e634ee-2bff-497b-bd8a-4341ad39eeb9}/100': ( 'PKEY_GPS_LatitudeDenominator'), '{16ea4042-d6f4-4bca-8349-7c78d30fb333}/100': ( 'PKEY_Photo_ShutterSpeedNumerator'), '{176dc63c-2688-4e89-8143-a347800f25e9}/20': 'PKEY_Contact_HomeTelephone', '{176dc63c-2688-4e89-8143-a347800f25e9}/25': ( 'PKEY_Contact_PrimaryTelephone'), '{176dc63c-2688-4e89-8143-a347800f25e9}/35': 'PKEY_Contact_MobileTelephone', '{176dc63c-2688-4e89-8143-a347800f25e9}/47': 'PKEY_Contact_Birthday', '{176dc63c-2688-4e89-8143-a347800f25e9}/48': ( 'PKEY_Contact_PrimaryEmailAddress'), '{176dc63c-2688-4e89-8143-a347800f25e9}/6': 'PKEY_Contact_JobTitle', '{176dc63c-2688-4e89-8143-a347800f25e9}/65': 'PKEY_Contact_HomeAddressCity', '{176dc63c-2688-4e89-8143-a347800f25e9}/69': 'PKEY_Contact_PersonalTitle', '{176dc63c-2688-4e89-8143-a347800f25e9}/7': 'PKEY_Contact_OfficeLocation', '{176dc63c-2688-4e89-8143-a347800f25e9}/71': 'PKEY_Contact_MiddleName', '{176dc63c-2688-4e89-8143-a347800f25e9}/73': 'PKEY_Contact_Suffix', '{176dc63c-2688-4e89-8143-a347800f25e9}/74': 'PKEY_Contact_NickName', '{176dc63c-2688-4e89-8143-a347800f25e9}/75': 'PKEY_Contact_Prefix', '{182c1ea6-7c1c-4083-ab4b-ac6c9f4ed128}/100': 'PKEY_GPS_DestLongitudeRef', '{188c1f91-3c40-4132-9ec5-d8b03b72a8a2}/100': ( 'PKEY_Calendar_ResponseStatus'), '{18bbd425-ecfd-46ef-b612-7b4a6034eda0}/100': ( 'PKEY_Contact_PrimaryAddressPostalCode'), '{19b51fa6-1f92-4a5c-ab48-7df0abd67444}/100': 'PKEY_Image_ResolutionUnit', '{1a701bf6-478c-4361-83ab-3701bb053c58}/100': 'PKEY_Photo_Brightness', '{1a9ba605-8e7c-4d11-ad7d-a50ada18ba1b}/2': 'PKEY_Message_Participants', '{1b5439e7-eba1-4af8-bdd7-7af1d4549493}/100': 'PKEY_RecordedTV_StationName', '{1b97738a-fdfc-462f-9d93-1957e08be90c}/100': 'PKEY_Photo_FNumberNumerator', '{1ce0d6bc-536c-4600-b0dd-7e0c66b350d5}/8': 'PKEY_History_SelectionCount', '{1ce0d6bc-536c-4600-b0dd-7e0c66b350d5}/9': ( 'PKEY_History_TargetUrlHostName'), '{1d6179a6-a876-4031-b013-3347b2b64dc8}/100': ( 'PKEY_Photo_FocalPlaneYResolutionDenominator'), '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/0': 'PKEY_AudioEndPoint_Type', '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/1': ( 'PKEY_AudioEndpoint_Ext_UiClsid'), '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/2': ( 'PKEY_AudioEndpoint_Association'), '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/3': ( 'PKEY_AudioEndpoint_PhysicalSpeakers'), '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/4': 'PKEY_AudioEndpoint_GUID', '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/5': ( 'PKEY_AudioEndpoint_Disable_SysFx'), '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/6': ( 'PKEY_AudioEndpoint_FullRangeSpeakers'), '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/7': ( 'PKEY_AudioEndpoint_Supports_EventDriven_Mode'), '{1da5d803-d492-4edd-8c23-e0c0ffee7f0e}/8': ( 'PKEY_AudioEndpoint_JackSubType'), '{1e005ee6-bf27-428b-b01c-79676acd2870}/100': 'PKEY_Document_Division', '{1e3ee840-bc2b-476c-8237-2acd1a839b22}/3': 'PKEY_Kind', '{1e3ee840-bc2b-476c-8237-2acd1a839b22}/6': 'PKEY_FullText', '{1e81a3f8-a30f-4247-b9ee-1d0368a9425c}/2': 'PKEY_DataObjectFormat', '{1f856a9f-6900-4aba-9505-2d5f1b4d66cb}/100': 'PKEY_Message_ToDoFlags', '{1f8844e1-24ad-4508-9dfd-5326a415ce02}/100': ( 'PKEY_Image_CompressedBitsPerPixelDenominator'), '{22704da4-c6b2-4a99-8e56-f16df8c92599}/100': 'PKEY_GPS_VersionID', '{2425166f-5642-4864-992f-98fd98f294c3}/100': ( 'PKEY_IdentityProvider_Picture'), '{2579e5d0-1116-4084-bd9a-9b4f7cb4df5e}/100': 'PKEY_Audio_PeakValue', '{257e44e2-9031-4323-ac38-85c552871b2e}/100': ( 'PKEY_Photo_ExposureTimeNumerator'), '{2598d2fb-5569-4367-95df-5cd3a177e1a5}/100': 'PKEY_PropGroup_Origin', '{259abffc-50a7-47ce-af08-68c9a7d73366}/10': 'PKEY_DeviceClass_NoUseClass', '{259abffc-50a7-47ce-af08-68c9a7d73366}/11': ( 'PKEY_DeviceClass_DefaultService'), '{259abffc-50a7-47ce-af08-68c9a7d73366}/12': 'PKEY_DeviceClass_IconPath', '{259abffc-50a7-47ce-af08-68c9a7d73366}/2': 'PKEY_DeviceClass_Name', '{259abffc-50a7-47ce-af08-68c9a7d73366}/3': 'PKEY_DeviceClass_ClassName', '{259abffc-50a7-47ce-af08-68c9a7d73366}/4': 'PKEY_DeviceClass_Icon', '{259abffc-50a7-47ce-af08-68c9a7d73366}/5': ( 'PKEY_DeviceClass_ClassInstaller'), '{259abffc-50a7-47ce-af08-68c9a7d73366}/6': ( 'PKEY_DeviceClass_PropPageProvider'), '{259abffc-50a7-47ce-af08-68c9a7d73366}/7': ( 'PKEY_DeviceClass_NoInstallClass'), '{259abffc-50a7-47ce-af08-68c9a7d73366}/8': ( 'PKEY_DeviceClass_NoDisplayClass'), '{259abffc-50a7-47ce-af08-68c9a7d73366}/9': ( 'PKEY_DeviceClass_SilentInstall'), '{26dc287c-6e3d-4bd3-b2b0-6a26ba2e346d}/2': 'PKEY_StatusBarViewItemCount', '{26dc287c-6e3d-4bd3-b2b0-6a26ba2e346d}/3': ( 'PKEY_StatusBarSelectedItemCount'), '{276d7bb0-5b34-4fb0-aa4b-158ed12a1809}/100': 'PKEY_Document_ClientID', '{2804d469-788f-48aa-8570-71b9c187e138}/100': 'PKEY_PropGroup_Audio', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/0': 'PKEY_FindData', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/11': 'PKEY_ItemType', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/12': 'PKEY_FileCount', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/14': 'PKEY_TotalFileSize', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/2': 'PKEY_DescriptionID', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/24': 'PKEY_ParsingName', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/25': 'PKEY_SFGAOFlags', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/29': 'PKEY_ContainedItems', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/30': 'PKEY_ParsingPath', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/33': 'PKEY_IsSendToTarget', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/37': 'PKEY_ItemSubType', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/5': 'PKEY_ComputerName', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/6': 'PKEY_NamespaceCLSID', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/8': 'PKEY_ItemPathDisplayNarrow', '{28636aa6-953d-11d2-b5d6-00c04fd918d0}/9': 'PKEY_PerceivedType', '{293ca35a-09aa-4dd2-b180-1fe245728a52}/100': 'PKEY_Calendar_Duration', '{2a785ba9-8d23-4ded-82e6-60a350c86a10}/100': 'PKEY_Photo_Contrast', '{2b1b801e-c0c1-4987-9ec5-72fa89814787}/100': 'PKEY_Identity_PrimarySid', '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/1': ( 'PKEY_DeviceInterface_Bluetooth_DeviceAddress'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/11': ( 'PKEY_DeviceInterface_Bluetooth_LastConnectedTime'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/12': ( 'PKEY_Devices_Aep_Bluetooth_LastSeenTime'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/2': ( 'PKEY_DeviceInterface_Bluetooth_ServiceGuid'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/3': ( 'PKEY_DeviceInterface_Bluetooth_Flags'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/4': ( 'PKEY_DeviceInterface_Bluetooth_Manufacturer'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/5': ( 'PKEY_DeviceInterface_Bluetooth_ModelNumber'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/6': ( 'PKEY_DeviceInterface_Bluetooth_VendorId'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/7': ( 'PKEY_DeviceInterface_Bluetooth_VendorId'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/8': ( 'PKEY_DeviceInterface_Bluetooth_ProductId'), '{2bd67d8b-8beb-48d5-87e0-6cda3428040a}/9': ( 'PKEY_DeviceInterface_Bluetooth_ProductVersion'), '{2bda47da-08c6-4fe1-80bc-a72fc517c5d0}/100': ( 'PKEY_GPS_DestDistanceNumerator'), '{2be9260a-2012-4742-a555-f41b638b7dcb}/2': ( 'PKEY_Devices_Notifications_NewMessage'), '{2c53c813-fb63-4e22-a1ab-0b331ca1e273}/100': ( 'PKEY_RecordedTV_NetworkAffiliation'), '{2ca2dae6-eddc-407d-bef1-773942abfa95}/100': 'PKEY_GPS_MapDatum', '{2cbaa8f5-d81f-47ca-b17a-f8d822300131}/100': 'PKEY_DateAcquired', '{2dad1eb7-816d-40d3-9ec3-c9773be2aade}/100': 'PKEY_GPS_AltitudeNumerator', '{2e4b640d-5019-46d8-8881-55414cc5caa0}/100': 'PKEY_Media_DateEncoded', '{305bc615-dca1-44a5-9fd4-10c0ba79412e}/100': ( 'PKEY_Photo_FocalLengthDenominator'), '{3143bf7c-80a8-4854-8880-e2e40189bdd0}/100': ( 'PKEY_Message_AttachmentContents'), '{315b9c8d-80a9-4ef9-ae16-8e746da51d70}/100': 'PKEY_Calendar_IsRecurring', '{318a6b45-087f-4dc2-b8cc-05359551fc9e}/100': 'PKEY_Photo_RelatedSoundFile', '{31b37743-7c5e-4005-93e6-e953f92b82e9}/2': ( 'PKEY_Devices_WiFiDirectServices_ServiceAddress'), '{31b37743-7c5e-4005-93e6-e953f92b82e9}/3': ( 'PKEY_Devices_WiFiDirectServices_ServiceName'), '{31b37743-7c5e-4005-93e6-e953f92b82e9}/4': ( 'PKEY_Devices_WiFiDirectServices_ServiceInformation'), '{31b37743-7c5e-4005-93e6-e953f92b82e9}/5': ( 'PKEY_Devices_WiFiDirectServices_AdvertisementId'), '{31b37743-7c5e-4005-93e6-e953f92b82e9}/6': ( 'PKEY_Devices_WiFiDirectServices_ServiceConfigMethods'), '{31b37743-7c5e-4005-93e6-e953f92b82e9}/7': ( 'PKEY_Devices_WiFiDirectServices_RequestServiceInformation'), '{32ce38b2-2c9a-41b1-9bc5-b3784394aa44}/2': ( 'PKEY_EdgeGesture_DisableTouchWhenFullscreen'), '{33dcf22b-28d5-464c-8035-1ee9efd25278}/100': 'PKEY_GPS_LongitudeRef', '{341796f1-1df9-4b1c-a564-91bdefa43877}/100': ( 'PKEY_Photo_PhotometricInterpretation'), '{346c8bd1-2e6a-4c45-89a4-61b78e8e700f}/100': 'PKEY_IsIncomplete', '{35dbe6fe-44c3-4400-aaae-d2c799c407e8}/100': 'PKEY_GPS_TrackRef', '{3602c812-0f3b-45f0-85ad-603468d69423}/100': 'PKEY_GPS_Date', '{3633de59-6825-4381-a49b-9f6ba13a1471}/2': 'PKEY_Devices_PlaybackState', '{3633de59-6825-4381-a49b-9f6ba13a1471}/3': 'PKEY_Devices_PlaybackTitle', '{3633de59-6825-4381-a49b-9f6ba13a1471}/4': ( 'PKEY_Devices_RemainingDuration'), '{3633de59-6825-4381-a49b-9f6ba13a1471}/5': ( 'PKEY_Devices_PlaybackPositionPercent'), '{364028da-d895-41fe-a584-302b1bb70a76}/100': ( 'PKEY_Contact_DisplayBusinessPhoneNumbers'), '{364b6fa9-37ab-482a-be2b-ae02f60d4318}/100': ( 'PKEY_Image_CompressedBitsPerPixel'), '{38965063-edc8-4268-8491-b7723172cf29}/100': 'PKEY_Contact_EmailAddress2', '{38d43380-d418-4830-84d5-46935a81c5c6}/32': ( 'PKEY_Security_AllowedEnterpriseDataProtectionIdentities'), '{39a7f922-477c-48de-8bc8-b28441e342e3}/100': 'PKEY_Project', '{39b77f4f-a104-4863-b395-2db2ad8f7bc1}/100': ( 'PKEY_Contact_ConnectedServiceDisplayName'), '{3a372292-7fca-49a7-99d5-e47bb2d4e7ab}/100': ( 'PKEY_GPS_DestLatitudeDenominator'), '{3b2ce006-5e61-4fde-bab8-9b8aac9b26df}/5': 'PKEY_Devices_Aep_ProtocolId', '{3b2ce006-5e61-4fde-bab8-9b8aac9b26df}/8': 'PKEY_Devices_Aep_AepId', '{3c8cee58-d4f0-4cf9-b756-4e5d24447bcd}/100': 'PKEY_Contact_Gender', '{3c8cee58-d4f0-4cf9-b756-4e5d24447bcd}/101': 'PKEY_Contact_GenderValue', '{3f08e66f-2f44-4bb9-a682-ac35d2562322}/100': 'PKEY_Image_CompressionText', '{3f8472b5-e0af-4db2-8071-c53fe76ae7ce}/100': 'PKEY_DueDate', '{402b5934-ec5a-48c3-93e6-85e86a2d934e}/100': ( 'PKEY_Contact_BusinessAddressCity'), '{41cf5ae0-f75a-4806-bd87-59c7d9248eb9}/100': 'PKEY_FileName', '{425d69e5-48ad-4900-8d80-6eb6b8d0ac86}/100': ( 'PKEY_GPS_DestLongitudeDenominator'), '{428040ac-a177-4c8a-9760-f6f761227f9a}/100': ( 'PKEY_Communication_DateItemExpires'), '{42864dfd-9da4-4f77-bded-4aad7b256735}/100': ( 'PKEY_Photo_GainControlDenominator'), '{4321918b-f69e-470d-a5de-4d88c75ad24b}/19': ( 'PKEY_DeviceClass_UpperFilters'), '{4321918b-f69e-470d-a5de-4d88c75ad24b}/20': ( 'PKEY_DeviceClass_LowerFilters'), '{4321918b-f69e-470d-a5de-4d88c75ad24b}/25': 'PKEY_DeviceClass_Security', '{4321918b-f69e-470d-a5de-4d88c75ad24b}/26': 'PKEY_DeviceClass_SecuritySDS', '{4321918b-f69e-470d-a5de-4d88c75ad24b}/27': 'PKEY_DeviceClass_DevType', '{4321918b-f69e-470d-a5de-4d88c75ad24b}/28': 'PKEY_DeviceClass_Exclusive', '{4321918b-f69e-470d-a5de-4d88c75ad24b}/29': ( 'PKEY_DeviceClass_Characteristics'), '{4340a6c5-93fa-4706-972c-7b648008a5a7}/10': 'PKEY_Device_Siblings', '{4340a6c5-93fa-4706-972c-7b648008a5a7}/2': 'PKEY_Device_DevNodeStatus', '{4340a6c5-93fa-4706-972c-7b648008a5a7}/3': 'PKEY_Device_ProblemCode', '{4340a6c5-93fa-4706-972c-7b648008a5a7}/4': 'PKEY_Device_EjectionRelations', '{4340a6c5-93fa-4706-972c-7b648008a5a7}/5': 'PKEY_Device_RemovalRelations', '{4340a6c5-93fa-4706-972c-7b648008a5a7}/6': 'PKEY_Device_PowerRelations', '{4340a6c5-93fa-4706-972c-7b648008a5a7}/7': 'PKEY_Device_BusRelations', '{4340a6c5-93fa-4706-972c-7b648008a5a7}/8': 'PKEY_Device_Parent', '{4340a6c5-93fa-4706-972c-7b648008a5a7}/9': 'PKEY_Device_Children', '{436f2667-14e2-4feb-b30a-146c53b5b674}/100': 'PKEY_Link_Arguments', '{43f8d7b7-a444-4f87-9383-52271c9b915c}/100': 'PKEY_DateArchived', '{446d16b1-8dad-4870-a748-402ea43d788c}/100': 'PKEY_ThumbnailCacheId', '{446d16b1-8dad-4870-a748-402ea43d788c}/104': 'PKEY_VolumeId', '{446f787f-10c4-41cb-a6c4-4d0343551597}/100': ( 'PKEY_Contact_BusinessAddressState'), '{45eae747-8e2a-40ae-8cbf-ca52aba6152a}/100': 'PKEY_FlagColorText', '{4679c1b5-844d-4590-baf5-f322231f1b81}/100': 'PKEY_GPS_LongitudeDecimal', '{467ee575-1f25-4557-ad4e-b8b58b0d9c15}/100': 'PKEY_GPS_Satellites', '{4684fe97-8765-4842-9c13-f006447b178c}/100': ( 'PKEY_RecordedTV_OriginalBroadcastDate'), '{46ac629d-75ea-4515-867f-6dc4321c5844}/100': 'PKEY_GPS_AltitudeRef', '{46b4e8de-cdb2-440d-885c-1658eb65b914}/100': 'PKEY_Note_ColorText', '{47166b16-364f-4aa0-9f31-e2ab3df449c3}/100': 'PKEY_GPS_DOPNumerator', '{4776cafa-bce4-4cb1-a23e-265e76d8eb11}/100': 'PKEY_Note_Color', '{47a96261-cb4c-4807-8ad3-40b9d9dbc6bc}/100': 'PKEY_GPS_DestLongitude', '{48fd6ec8-8a12-4cdf-a03e-4ec5a511edde}/100': 'PKEY_StartDate', '{49237325-a95a-4f67-b211-816b2d45d2e0}/100': 'PKEY_Photo_Saturation', '{49691c90-7e17-101a-a91c-08002b2ecda9}/21': ( 'PKEY_Search_QueryPropertyHits'), '{49691c90-7e17-101a-a91c-08002b2ecda9}/3': 'PKEY_Search_Rank', '{49691c90-7e17-101a-a91c-08002b2ecda9}/4': 'PKEY_Search_HitCount', '{49691c90-7e17-101a-a91c-08002b2ecda9}/5': 'PKEY_Search_EntryID', '{49691c90-7e17-101a-a91c-08002b2ecda9}/9': 'PKEY_ItemUrl', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/10': 'PKEY_Devices_BatteryLife', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/11': 'PKEY_Devices_ChargingState', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/12': 'PKEY_Devices_StorageCapacity', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/13': ( 'PKEY_Devices_StorageFreeSpace'), '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/14': ( 'PKEY_Devices_StorageFreeSpacePercent'), '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/2': 'PKEY_Devices_SignalStrength', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/22': ( 'PKEY_Devices_BatteryPlusCharging'), '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/23': ( 'PKEY_Devices_BatteryPlusChargingText'), '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/3': 'PKEY_Devices_TextMessages', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/4': 'PKEY_Devices_NewPictures', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/5': 'PKEY_Devices_MissedCalls', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/6': 'PKEY_Devices_Voicemail', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/7': 'PKEY_Devices_NetworkName', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/8': 'PKEY_Devices_NetworkType', '{49cd1f76-5626-4b17-a4e8-18b4aa1a2213}/9': 'PKEY_Devices_Roaming', '{49d1091f-082e-493f-b23f-d2308aa9668c}/100': 'PKEY_PropList_NonPersonal', '{4c6bf15c-4c03-4aac-91f5-64c0f852bcf4}/2': ( 'PKEY_DeviceInterface_Serial_UsbVendorId'), '{4c6bf15c-4c03-4aac-91f5-64c0f852bcf4}/3': ( 'PKEY_DeviceInterface_Serial_UsbProductId'), '{4c6bf15c-4c03-4aac-91f5-64c0f852bcf4}/4': ( 'PKEY_DeviceInterface_Serial_PortName'), '{4d1ebee8-0803-4774-9842-b77db50265e9}/2': 'PKEY_Storage_Portable', '{4d1ebee8-0803-4774-9842-b77db50265e9}/3': 'PKEY_Storage_RemovableMedia', '{4d1ebee8-0803-4774-9842-b77db50265e9}/4': 'PKEY_Storage_SystemCritical', '{4fc5077e-b686-44be-93e3-86cafe368ccd}/1': 'PKEY_PNPX_Installable', '{4fc5077e-b686-44be-93e3-86cafe368ccd}/2': 'PKEY_PNPX_Associated', '{4fc5077e-b686-44be-93e3-86cafe368ccd}/3': 'PKEY_PNPX_CompatibleTypes', '{4fc5077e-b686-44be-93e3-86cafe368ccd}/4': 'PKEY_PNPX_InstallState', '{4fffe4d0-914f-4ac4-8d6f-c9c61de169b1}/100': ( 'PKEY_Photo_FocalPlaneYResolution'), '{502cfeab-47eb-459c-b960-e6d8728f7701}/100': 'PKEY_ZoneIdentifier', '{502cfeab-47eb-459c-b960-e6d8728f7701}/101': ( 'PKEY_LastWriterPackageFamilyName'), '{502cfeab-47eb-459c-b960-e6d8728f7701}/102': 'PKEY_AppZoneIdentifier', '{5068bcdf-d697-4d85-8c53-1f1cdab01763}/100': ( 'PKEY_Contact_DisplayHomePhoneNumbers'), '{508161fa-313b-43d5-83a1-c1accf68622c}/100': 'PKEY_Contact_OtherAddress', '{51236583-0c4a-4fe8-b81f-166aec13f510}/100': ( 'PKEY_Devices_AppPackageFamilyName'), '{51236583-0c4a-4fe8-b81f-166aec13f510}/123': 'PKEY_Devices_GlyphIcon', '{51ec3f47-dd50-421d-8769-334f50424b1e}/100': 'PKEY_Photo_SharpnessText', '{53da57cf-62c0-45c4-81de-7610bcefd7f5}/100': ( 'PKEY_Calendar_ShowTimeAsText'), '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}/1': 'PKEY_Numa_Proximity_Domain', '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}/5': 'PKEY_Devices_Present', '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}/6': 'PKEY_Devices_DeviceHasProblem', '{540b947e-8b40-45bc-a8a2-6a0b894cbda2}/9': ( 'PKEY_Devices_PhysicalDeviceLocation'), '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/10': 'PKEY_CONFIGUI_TOOLTIPS', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/11': 'PKEY_CONFIGUI_ICON', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/12': 'PKEY_CONFIGUI_MENUITEM_NOUI', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/13': 'PKEY_CONFIGUI_MENUITEM', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/2': 'PKEY_CONFIGUI_INSTANCEID', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/3': 'PKEY_CONFIGUI_CLSID', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/4': 'PKEY_CONFIGUI_CONTENTTYPE', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/5': 'PKEY_CONFIGUI_CAPABILITIES', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/6': ( 'PKEY_CONFIGUI_SUPPORTED_ARCHITECTURE'), '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/7': 'PKEY_CONFIGUI_IS_GLOBAL', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/8': 'PKEY_CONFIGUI_NAME', '{554b24ea-e8e3-45ba-9352-dfb561e171e4}/9': 'PKEY_CONFIGUI_DESCRIPTION', '{55e98597-ad16-42e0-b624-21599a199838}/100': ( 'PKEY_Photo_ExposureTimeDenominator'), '{560c36c0-503a-11cf-baa1-00004c752a9a}/2': 'PKEY_Search_AutoSummary', '{560c36c0-503a-11cf-baa1-00004c752a9a}/3': ( 'PKEY_Search_QueryFocusedSummary'), '{560c36c0-503a-11cf-baa1-00004c752a9a}/4': ( 'PKEY_Search_QueryFocusedSummaryWithFallback'), '{56310920-2491-4919-99ce-eadb06fafdb2}/100': ( 'PKEY_Contact_BusinessHomePage'), '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/100': 'PKEY_Music_AlbumID', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/11': 'PKEY_Music_Genre', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/12': 'PKEY_Music_Lyrics', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/13': 'PKEY_Music_AlbumArtist', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/2': 'PKEY_Music_Artist', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/33': ( 'PKEY_Music_ContentGroupDescription'), '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/34': 'PKEY_Music_InitialKey', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/35': 'PKEY_Music_BeatsPerMinute', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/36': 'PKEY_Music_Conductor', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/37': 'PKEY_Music_PartOfSet', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/38': 'PKEY_Media_SubTitle', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/39': 'PKEY_Music_Mood', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/4': 'PKEY_Music_AlbumTitle', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/5': 'PKEY_Media_Year', '{56a3372e-ce9c-11d2-9f0e-006097c686f6}/7': 'PKEY_Music_TrackNumber', '{56c90e9d-9d46-4963-886f-2e1cd9a694ef}/100': ( 'PKEY_Contact_HomeEmailAddresses'), '{59569556-0a08-4212-95b9-fae2ad6413db}/2': ( 'PKEY_Devices_Notifications_NewVoicemail'), '{59d49e61-840f-4aa9-a939-e2099b7f6399}/100': 'PKEY_GPS_ProcessingMethod', '{59dde9f2-5253-40ea-9a8b-479e96c6249a}/100': 'PKEY_Photo_ContrastText', '{5bf396d4-5eb2-466f-bde9-2fb3f2361d6e}/100': 'PKEY_Calendar_ShowTimeAs', '{5cbf2787-48cf-4208-b90e-ee5e5d420294}/2': 'PKEY_Link_TargetUrl', '{5cbf2787-48cf-4208-b90e-ee5e5d420294}/21': 'PKEY_Link_Description', '{5cbf2787-48cf-4208-b90e-ee5e5d420294}/23': 'PKEY_Link_DateVisited', '{5cbf2787-48cf-4208-b90e-ee5e5d420294}/7': 'PKEY_History_VisitCount', '{5cda5fc8-33ee-4ff3-9094-ae7bd8868c4d}/100': 'PKEY_IsDeleted', '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/10': ( 'PKEY_DefaultSaveLocationDisplay'), '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/2': 'PKEY_IsPinnedToNameSpaceTree', '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/3': 'PKEY_IsDefaultSaveLocation', '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/4': 'PKEY_IsSearchOnlyItem', '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/5': ( 'PKEY_IsDefaultNonOwnerSaveLocation'), '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/6': 'PKEY_OwnerSID', '{5d76b67f-9b3d-44bb-b6ae-25da4f638a67}/8': 'PKEY_IsLocationSupported', '{5da84765-e3ff-4278-86b0-a27967fbdd03}/100': 'PKEY_IsFlagged', '{5dc2253f-5e11-4adf-9cfe-910dd01e3e70}/100': 'PKEY_Contact_Hobbies', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/10': 'PKEY_Hardware_DriverProvider', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/11': 'PKEY_Hardware_DriverDate', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/2': 'PKEY_Hardware_Name', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/3': 'PKEY_Hardware_Icon', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4096': 'PKEY_Hardware_Status', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4097': 'PKEY_Hardware_Devinst', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4098': 'PKEY_Hardware_Image', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4099': 'PKEY_Hardware_Function', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/4100': ( 'PKEY_Hardware_ShellAttributes'), '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/5': ( 'PKEY_Hardware_DisplayAttribute'), '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/6': 'PKEY_Hardware_Manufacturer', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/7': 'PKEY_Hardware_Model', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/8': 'PKEY_Hardware_SerialNumber', '{5eaf3ef2-e0ca-4598-bf06-71ed1d9dd953}/9': 'PKEY_Hardware_DriverVersion', '{5f5aff6a-37e5-4780-97ea-80c7565cf535}/34': ( 'PKEY_Security_EncryptionOwners'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/10': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_Audio'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/11': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_Telephony'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/12': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_Information'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/2': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Major'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/3': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Minor'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/4': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_LimitedDiscovery'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/5': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_Positioning'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/6': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_Networking'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/7': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_Rendering'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/8': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_Capturing'), '{5fbd34cd-561a-412e-ba98-478a6b0fef1d}/9': ( 'PKEY_Devices_Aep_Bluetooth_Cod_Services_ObjectXfer'), '{61478c08-b600-4a84-bbe4-e99c45f0a072}/100': 'PKEY_Photo_SaturationText', '{61872cf7-6b5e-4b4b-ac2d-59da84459248}/100': 'PKEY_PropGroup_Media', '{6336b95e-c7a7-426d-86fd-7ae3d39c84b4}/100': 'PKEY_Photo_WhiteBalanceText', '{635e9051-50a5-4ba2-b9db-4ed056c77296}/100': 'PKEY_Contact_FullName', '{63c25b20-96be-488f-8788-c09c407ad812}/100': ( 'PKEY_Contact_PrimaryAddressStreet'), '{6444048f-4c8b-11d1-8b70-080036b11a03}/12': 'PKEY_Media_FrameCount', '{6444048f-4c8b-11d1-8b70-080036b11a03}/13': 'PKEY_Image_Dimensions', '{6444048f-4c8b-11d1-8b70-080036b11a03}/3': 'PKEY_Image_HorizontalSize', '{6444048f-4c8b-11d1-8b70-080036b11a03}/4': 'PKEY_Image_VerticalSize', '{6444048f-4c8b-11d1-8b70-080036b11a03}/5': ( 'PKEY_Image_HorizontalResolution'), '{6444048f-4c8b-11d1-8b70-080036b11a03}/6': 'PKEY_Image_VerticalResolution', '{6444048f-4c8b-11d1-8b70-080036b11a03}/7': 'PKEY_Image_BitDepth', '{64440490-4c8b-11d1-8b70-080036b11a03}/10': 'PKEY_Audio_Compression', '{64440490-4c8b-11d1-8b70-080036b11a03}/2': 'PKEY_Audio_Format', '{64440490-4c8b-11d1-8b70-080036b11a03}/3': 'PKEY_Media_Duration', '{64440490-4c8b-11d1-8b70-080036b11a03}/4': 'PKEY_Audio_EncodingBitrate', '{64440490-4c8b-11d1-8b70-080036b11a03}/5': 'PKEY_Audio_SampleRate', '{64440490-4c8b-11d1-8b70-080036b11a03}/6': 'PKEY_Audio_SampleSize', '{64440490-4c8b-11d1-8b70-080036b11a03}/7': 'PKEY_Audio_ChannelCount', '{64440490-4c8b-11d1-8b70-080036b11a03}/8': 'PKEY_Audio_StreamNumber', '{64440490-4c8b-11d1-8b70-080036b11a03}/9': 'PKEY_Audio_StreamName', '{64440491-4c8b-11d1-8b70-080036b11a03}/10': 'PKEY_Video_Compression', '{64440491-4c8b-11d1-8b70-080036b11a03}/100': 'PKEY_Video_IsSpherical', '{64440491-4c8b-11d1-8b70-080036b11a03}/11': 'PKEY_Video_StreamNumber', '{64440491-4c8b-11d1-8b70-080036b11a03}/2': 'PKEY_Video_StreamName', '{64440491-4c8b-11d1-8b70-080036b11a03}/3': 'PKEY_Video_FrameWidth', '{64440491-4c8b-11d1-8b70-080036b11a03}/4': 'PKEY_Video_FrameHeight', '{64440491-4c8b-11d1-8b70-080036b11a03}/42': ( 'PKEY_Video_HorizontalAspectRatio'), '{64440491-4c8b-11d1-8b70-080036b11a03}/43': 'PKEY_Video_TotalBitrate', '{64440491-4c8b-11d1-8b70-080036b11a03}/44': 'PKEY_Video_FourCC', '{64440491-4c8b-11d1-8b70-080036b11a03}/45': ( 'PKEY_Video_VerticalAspectRatio'), '{64440491-4c8b-11d1-8b70-080036b11a03}/46': 'PKEY_Video_TranscodedForSync', '{64440491-4c8b-11d1-8b70-080036b11a03}/6': 'PKEY_Video_FrameRate', '{64440491-4c8b-11d1-8b70-080036b11a03}/8': 'PKEY_Video_EncodingBitrate', '{64440491-4c8b-11d1-8b70-080036b11a03}/9': 'PKEY_Video_SampleSize', '{64440491-4c8b-11d1-8b70-080036b11a03}/98': 'PKEY_Video_IsStereo', '{64440491-4c8b-11d1-8b70-080036b11a03}/99': 'PKEY_Video_Orientation', '{64440492-4c8b-11d1-8b70-080036b11a03}/100': 'PKEY_Media_EpisodeNumber', '{64440492-4c8b-11d1-8b70-080036b11a03}/101': 'PKEY_Media_SeasonNumber', '{64440492-4c8b-11d1-8b70-080036b11a03}/11': 'PKEY_Copyright', '{64440492-4c8b-11d1-8b70-080036b11a03}/12': 'PKEY_ShareUserRating', '{64440492-4c8b-11d1-8b70-080036b11a03}/13': 'PKEY_Media_ClassPrimaryID', '{64440492-4c8b-11d1-8b70-080036b11a03}/14': 'PKEY_Media_ClassSecondaryID', '{64440492-4c8b-11d1-8b70-080036b11a03}/15': 'PKEY_Media_DVDID', '{64440492-4c8b-11d1-8b70-080036b11a03}/16': 'PKEY_Media_MCDI', '{64440492-4c8b-11d1-8b70-080036b11a03}/17': ( 'PKEY_Media_MetadataContentProvider'), '{64440492-4c8b-11d1-8b70-080036b11a03}/18': ( 'PKEY_Media_ContentDistributor'), '{64440492-4c8b-11d1-8b70-080036b11a03}/19': 'PKEY_Music_Composer', '{64440492-4c8b-11d1-8b70-080036b11a03}/20': 'PKEY_Video_Director', '{64440492-4c8b-11d1-8b70-080036b11a03}/21': 'PKEY_ParentalRating', '{64440492-4c8b-11d1-8b70-080036b11a03}/22': 'PKEY_Media_Producer', '{64440492-4c8b-11d1-8b70-080036b11a03}/23': 'PKEY_Media_Writer', '{64440492-4c8b-11d1-8b70-080036b11a03}/24': 'PKEY_Media_CollectionGroupID', '{64440492-4c8b-11d1-8b70-080036b11a03}/25': 'PKEY_Media_CollectionID', '{64440492-4c8b-11d1-8b70-080036b11a03}/26': 'PKEY_Media_ContentID', '{64440492-4c8b-11d1-8b70-080036b11a03}/27': ( 'PKEY_Media_CreatorApplication'), '{64440492-4c8b-11d1-8b70-080036b11a03}/28': ( 'PKEY_Media_CreatorApplicationVersion'), '{64440492-4c8b-11d1-8b70-080036b11a03}/30': 'PKEY_Media_Publisher', '{64440492-4c8b-11d1-8b70-080036b11a03}/31': 'PKEY_Music_Period', '{64440492-4c8b-11d1-8b70-080036b11a03}/32': 'PKEY_Media_AuthorUrl', '{64440492-4c8b-11d1-8b70-080036b11a03}/33': 'PKEY_Media_PromotionUrl', '{64440492-4c8b-11d1-8b70-080036b11a03}/34': 'PKEY_Media_UserWebUrl', '{64440492-4c8b-11d1-8b70-080036b11a03}/35': ( 'PKEY_Media_UniqueFileIdentifier'), '{64440492-4c8b-11d1-8b70-080036b11a03}/36': 'PKEY_Media_EncodedBy', '{64440492-4c8b-11d1-8b70-080036b11a03}/37': 'PKEY_Media_EncodingSettings', '{64440492-4c8b-11d1-8b70-080036b11a03}/38': 'PKEY_Media_ProtectionType', '{64440492-4c8b-11d1-8b70-080036b11a03}/39': 'PKEY_Media_ProviderRating', '{64440492-4c8b-11d1-8b70-080036b11a03}/40': 'PKEY_Media_ProviderStyle', '{64440492-4c8b-11d1-8b70-080036b11a03}/41': 'PKEY_Media_UserNoAutoInfo', '{64440492-4c8b-11d1-8b70-080036b11a03}/42': 'PKEY_Media_SeriesName', '{64440492-4c8b-11d1-8b70-080036b11a03}/47': ( 'PKEY_Media_ThumbnailLargePath'), '{64440492-4c8b-11d1-8b70-080036b11a03}/48': 'PKEY_Media_ThumbnailLargeUri', '{64440492-4c8b-11d1-8b70-080036b11a03}/49': ( 'PKEY_Media_ThumbnailSmallPath'), '{64440492-4c8b-11d1-8b70-080036b11a03}/50': 'PKEY_Media_ThumbnailSmallUri', '{64440492-4c8b-11d1-8b70-080036b11a03}/9': 'PKEY_Rating', '{644d37b4-e1b3-4bad-b099-7e7c04966aca}/100': 'PKEY_Contact_EmailAddress3', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12288': 'PKEY_Devices_FriendlyName', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12289': 'PKEY_PNPX_FirmwareVersion', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12290': 'PKEY_PNPX_SerialNumber', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12292': 'PKEY_PNPX_DeviceCategory', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12293': ( 'PKEY_PNPX_DeviceCategory_Desc'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12294': 'PKEY_PNPX_PhysicalAddress', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12295': ( 'PKEY_PNPX_NetworkInterfaceLuid'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12296': ( 'PKEY_PNPX_NetworkInterfaceGuid'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12297': 'PKEY_Devices_IpAddress', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/12304': ( 'PKEY_PNPX_Category_Desc_NonPlural'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/16384': ( 'PKEY_Devices_ServiceAddress'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/16385': 'PKEY_Devices_ServiceId', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/16386': 'PKEY_PNPX_ServiceTypes', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/20480': 'PKEY_PNPX_DomainName', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/20481': 'PKEY_PNPX_MachineName', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/20482': 'PKEY_PNPX_ShareName', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/24576': 'PKEY_SSDP_AltLocationInfo', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/24577': 'PKEY_SSDP_DevLifeTime', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/24578': ( 'PKEY_SSDP_NetworkInterface'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/28672': 'PKEY_PNPX_Removable', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/28673': 'PKEY_PNPX_SecureChannel', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/28674': ( 'PKEY_PNPX_CompactSignature'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/28688': 'PKEY_PNPX_IPBusEnumerated', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4096': 'PKEY_PNPX_GlobalIdentity', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4097': 'PKEY_PNPX_Types', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4098': 'PKEY_PNPX_Scopes', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4099': 'PKEY_PNPX_XAddrs', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4100': 'PKEY_PNPX_MetadataVersion', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4101': 'PKEY_PNPX_ID', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4102': 'PKEY_PNPX_RemoteAddress', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/4103': 'PKEY_PNPX_RootProxy', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8192': ( 'PKEY_DeviceDisplay_Manufacturer'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8193': 'PKEY_PNPX_ManufacturerUrl', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8194': ( 'PKEY_DeviceDisplay_ModelName'), '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8195': 'PKEY_Devices_ModelNumber', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8196': 'PKEY_PNPX_ModelUrl', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8197': 'PKEY_PNPX_Upc', '{656a3bb3-ecc0-43fd-8477-4ae0404a96cd}/8198': ( 'PKEY_Devices_PresentationUrl'), '{65a98875-3c80-40ab-abbc-efdaf77dbee2}/100': 'PKEY_AcquisitionID', '{660e04d6-81ab-4977-a09f-82313113ab26}/100': 'PKEY_Contact_HomeFaxNumber', '{6614ef48-4efe-4424-9eda-c79f404edf3e}/2': ( 'PKEY_Devices_Notifications_MissedCall'), '{668cdfa5-7a1b-4323-ae4b-e527393a1d81}/100': 'PKEY_SourceItem', '{67df94de-0ca7-4d6f-b792-053a3e4f03cf}/100': 'PKEY_FlagColor', '{6845cc72-1b71-48c3-af86-b09171a19b14}/3': ( 'PKEY_Devices_DialProtocol_InstalledApplications'), '{68dd6094-7216-40f1-a029-43fe7127043f}/100': 'PKEY_PropGroup_Music', '{6a15e5a0-0a1e-4cd7-bb8c-d2f1b0c929bc}/100': ( 'PKEY_Contact_BusinessTelephone'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/10': ( 'PKEY_Devices_AepContainer_SupportsRendering'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/11': ( 'PKEY_Devices_AepContainer_SupportsCapturing'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/12': ( 'PKEY_Devices_AepContainer_SupportsObjectTransfer'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/13': ( 'PKEY_Devices_AepContainer_SupportsTelephony'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/14': ( 'PKEY_Devices_AepContainer_SupportsInformation'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/2': ( 'PKEY_Devices_AepContainer_SupportsAudio'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/3': ( 'PKEY_Devices_AepContainer_SupportsVideo'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/4': ( 'PKEY_Devices_AepContainer_SupportsImages'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/5': ( 'PKEY_Devices_AepContainer_SupportedUriSchemes'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/6': ( 'PKEY_Devices_AepContainer_DialProtocol_InstalledApplications'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/7': ( 'PKEY_Devices_AepContainer_SupportsLimitedDiscovery'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/8': ( 'PKEY_Devices_AepContainer_SupportsPositioning'), '{6af55d45-38db-4495-acb0-d4728a3b8314}/9': ( 'PKEY_Devices_AepContainer_SupportsNetworking'), '{6afe7437-9bcd-49c7-80fe-4a5c65fa5874}/104': 'PKEY_Music_DiscNumber', '{6b223b6a-162e-4aa9-b39f-05d678fc6d77}/100': ( 'PKEY_Music_SynchronizedLyrics'), '{6b8b68f6-200b-47ea-8d25-d8050f57339f}/100': 'PKEY_Photo_FlashText', '{6b8da074-3b5c-43bc-886f-0a2cdce00b6f}/100': 'PKEY_ItemName', '{6bdd1fc6-810f-11d0-bec7-08002be2092f}/2': 'PKEY_Devices_WiaDeviceType', '{6d217f6d-3f6a-4825-b470-5f03ca2fbe9b}/100': 'PKEY_Photo_ProgramMode', '{6d24888f-4718-4bda-afed-ea0fb4386cd8}/100': 'PKEY_OfflineStatus', '{6d6d5d49-265d-4688-9f4e-1fdd33e7cc83}/100': 'PKEY_Identity_InternetSid', '{6d748de2-8d38-4cc3-ac60-f009b057c557}/12': ( 'PKEY_RecordedTV_IsClosedCaptioningAvailable'), '{6d748de2-8d38-4cc3-ac60-f009b057c557}/13': ( 'PKEY_RecordedTV_IsRepeatBroadcast'), '{6d748de2-8d38-4cc3-ac60-f009b057c557}/14': 'PKEY_RecordedTV_IsSAP', '{6d748de2-8d38-4cc3-ac60-f009b057c557}/15': ( 'PKEY_RecordedTV_DateContentExpires'), '{6d748de2-8d38-4cc3-ac60-f009b057c557}/16': ( 'PKEY_RecordedTV_IsATSCContent'), '{6d748de2-8d38-4cc3-ac60-f009b057c557}/17': 'PKEY_RecordedTV_IsDTVContent', '{6d748de2-8d38-4cc3-ac60-f009b057c557}/18': 'PKEY_RecordedTV_IsHDContent', '{6d748de2-8d38-4cc3-ac60-f009b057c557}/2': 'PKEY_RecordedTV_EpisodeName', '{6d748de2-8d38-4cc3-ac60-f009b057c557}/3': ( 'PKEY_RecordedTV_ProgramDescription'), '{6d748de2-8d38-4cc3-ac60-f009b057c557}/4': 'PKEY_RecordedTV_Credits', '{6d748de2-8d38-4cc3-ac60-f009b057c557}/5': ( 'PKEY_RecordedTV_StationCallSign'), '{6d748de2-8d38-4cc3-ac60-f009b057c557}/7': 'PKEY_RecordedTV_ChannelNumber', '{6e682923-7f7b-4f0c-a337-cfca296687bf}/100': ( 'PKEY_Contact_OtherAddressCity'), '{6ebe6946-2321-440a-90f0-c043efd32476}/100': ( 'PKEY_Photo_BrightnessDenominator'), '{6fa20de6-d11c-4d9d-a154-64317628c12d}/100': 'PKEY_ExpandoProperties', '{702926f4-44a6-43e1-ae71-45627116893b}/100': 'PKEY_GPS_TrackNumerator', '{713d1703-a2e2-49f5-9214-56472ef3da5c}/2': ( 'PKEY_DeviceClass_ClassCoInstallers'), '{71724756-3e74-4432-9b59-e7b2f668a593}/2': ( 'PKEY_Devices_AepService_FriendlyName'), '{71724756-3e74-4432-9b59-e7b2f668a593}/3': ( 'PKEY_Devices_AepService_ServiceClassId'), '{71724756-3e74-4432-9b59-e7b2f668a593}/4': ( 'PKEY_Devices_AepService_ContainerId'), '{71b377d6-e570-425f-a170-809fae73e54e}/100': ( 'PKEY_Contact_OtherAddressState'), '{7268af55-1ce4-4f6e-a41f-b6e4ef10e4a9}/100': 'PKEY_Contact_Profession', '{72fab781-acda-43e5-b155-b2434f85e678}/100': 'PKEY_DateCompleted', '{72fc5ba4-24f9-4011-9f3f-add27afad818}/100': 'PKEY_Calendar_ReminderTime', '{730fb6dd-cf7c-426b-a03f-bd166cc9ee24}/100': ( 'PKEY_Contact_BusinessAddress'), '{738bf284-1d87-420b-92cf-5834bf6ef9ed}/100': ( 'PKEY_Photo_ExposureBiasNumerator'), '{744c8242-4df5-456c-ab9e-014efb9021e3}/100': ( 'PKEY_Calendar_OrganizerAddress'), '{745baf0e-e5c1-4cfb-8a1b-d031a0a52393}/100': ( 'PKEY_Photo_DigitalZoomDenominator'), '{74a7de49-fa11-4d3d-a006-db7e08675916}/100': 'PKEY_Identity_ProviderID', '{76c09943-7c33-49e3-9e7e-cdba872cfada}/100': 'PKEY_GPS_Track', '{776b6b3b-1e3d-4b0c-9a0e-8fbaf2a8492a}/100': ( 'PKEY_Photo_FocalLengthNumerator'), '{78342dcb-e358-4145-ae9a-6bfe4e0f9f51}/100': ( 'PKEY_GPS_AltitudeDenominator'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/100': ( 'PKEY_DeviceDisplay_DeviceFunctionSubRank'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/101': ( 'PKEY_DeviceDisplay_AlwaysShowDeviceAsConnected'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/256': ( 'PKEY_Devices_DeviceInstanceId'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/51': 'PKEY_DeviceDisplay_Address', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/52': 'PKEY_Devices_DiscoveryMethod', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/53': ( 'PKEY_DeviceDisplay_IsEncrypted'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/54': ( 'PKEY_DeviceDisplay_IsAuthenticated'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/55': 'PKEY_Devices_IsConnected', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/56': 'PKEY_Devices_Paired', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/57': 'PKEY_DeviceDisplay_Icon', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/65': 'PKEY_DeviceDisplay_Version', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/66': 'PKEY_DeviceDisplay_Last_Seen', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/67': ( 'PKEY_DeviceDisplay_Last_Connected'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/68': ( 'PKEY_DeviceDisplay_IsShowInDisconnectedState'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/70': ( 'PKEY_DeviceDisplay_IsLocalMachine'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/71': 'PKEY_Devices_MetadataPath', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/72': ( 'PKEY_DeviceDisplay_IsMetadataSearchInProgress'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/73': ( 'PKEY_DeviceDisplay_MetadataChecksum'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/74': ( 'PKEY_DeviceDisplay_IsNotInterestingForDisplay'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/76': ( 'PKEY_DeviceDisplay_LaunchDeviceStageOnDeviceConnect'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/77': ( 'PKEY_DeviceDisplay_LaunchDeviceStageFromExplorer'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/78': ( 'PKEY_DeviceDisplay_BaselineExperienceId'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/79': ( 'PKEY_DeviceDisplay_IsDeviceUniquelyIdentifiable'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/80': ( 'PKEY_DeviceDisplay_AssociationArray'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/81': ( 'PKEY_DeviceDisplay_DeviceDescription1'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/82': ( 'PKEY_DeviceDisplay_DeviceDescription2'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/83': ( 'PKEY_DeviceDisplay_IsNotWorkingProperly'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/84': 'PKEY_Devices_IsSharedDevice', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/85': ( 'PKEY_Devices_IsNetworkConnected'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/86': ( 'PKEY_DeviceDisplay_IsDefaultDevice'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/87': ( 'PKEY_DeviceDisplay_MetadataCabinet'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/88': ( 'PKEY_DeviceDisplay_RequiresPairingElevation'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/89': ( 'PKEY_DeviceDisplay_ExperienceId'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/90': 'PKEY_Devices_CategoryIds', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/91': ( 'PKEY_DeviceDisplay_Category_Desc_Singular'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/92': 'PKEY_Devices_CategoryPlural', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/93': ( 'PKEY_DeviceDisplay_Category_Icon'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/94': 'PKEY_Devices_CategoryGroup', '{78c34fc8-104a-4aca-9ea4-524d52996e57}/95': ( 'PKEY_DeviceDisplay_CategoryGroup_Icon'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/97': ( 'PKEY_DeviceDisplay_PrimaryCategory'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/98': ( 'PKEY_DeviceDisplay_UnpairUninstall'), '{78c34fc8-104a-4aca-9ea4-524d52996e57}/99': ( 'PKEY_DeviceDisplay_RequiresUninstallElevation'), '{7996efb2-29c1-4898-be83-4a3646e06fac}/0': 'PKEY_Endpoint_Enable_LFX_AEC', '{79d94e82-4d79-45aa-821a-74858b4e4ca6}/2': ( 'PKEY_Devices_AepService_IoT_ServiceInterfaces'), '{7a7d76f4-b630-4bd7-95ff-37cc51a975c9}/2': 'PKEY_Link_TargetExtension', '{7abcf4f8-7c3f-4988-ac91-8d2c2e97eca5}/100': ( 'PKEY_GPS_DestBearingDenominator'), '{7b03b546-fa4f-4a52-a2fe-03d5311e5865}/100': ( 'PKEY_Search_ExtendedProperties'), '{7b9f6399-0a3f-4b12-89bd-4adc51c918af}/100': ( 'PKEY_Contact_HomeAddressPostOfficeBox'), '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/10': 'PKEY_Sync_Status', '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/13': 'PKEY_Sync_Comments', '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/2': 'PKEY_Sync_HandlerCollectionID', '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/23': 'PKEY_Sync_ProgressPercentage', '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/24': 'PKEY_Sync_State', '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/3': 'PKEY_Sync_HandlerID', '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/6': 'PKEY_Sync_ItemID', '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/8': 'PKEY_Sync_HandlerType', '{7bd5533e-af15-44db-b8c8-bd6624e1d032}/9': 'PKEY_Sync_HandlerTypeLabel', '{7d122d5a-ae5e-4335-8841-d71e7ce72f53}/100': 'PKEY_GPS_SpeedDenominator', '{7d683fc9-d155-45a8-bb1f-89d19bcb792f}/100': 'PKEY_Identity_DisplayName', '{7ddaaad1-ccc8-41ae-b750-b2cb8031aea2}/100': 'PKEY_GPS_LatitudeNumerator', '{7f73d4e1-91e3-4490-9fba-5e86680a5748}/0': 'PKEY_Endpoint_Enable_GFX', '{7fd7259d-16b4-4135-9f97-7c96ecd2fa9e}/100': 'PKEY_PropGroup_Message', '{7fe3aa27-2648-42f3-89b0-454e5cb150c3}/100': 'PKEY_Photo_ProgramModeText', '{80497100-8c73-48b9-aad9-ce387e19c56e}/2': 'PKEY_Device_Reported', '{80497100-8c73-48b9-aad9-ce387e19c56e}/3': 'PKEY_Device_Legacy', '{807b653a-9e91-43ef-8f97-11ce04ee20c5}/100': 'PKEY_Communication_Suffix', '{80d81ea6-7473-4b0c-8216-efc11a2c4c8b}/2': 'PKEY_Devices_ModelId', '{80f41eb8-afc4-4208-aa5f-cce21a627281}/100': ( 'PKEY_Contact_ConnectedServiceIdentities'), '{813f4124-34e6-4d17-ab3e-6b1f3c2247a1}/100': 'PKEY_Photo_MakerNoteOffset', '{818d3b4c-2bbf-40e9-a438-9361b0ffc427}/0': ( 'PKEY_Endpoint_Enable_LFX_BEAMFORMING'), '{821437d6-9eab-4765-a589-3b1cbbd22a61}/100': ( 'PKEY_Photo_PhotometricInterpretationText'), '{827edb4f-5b73-44a7-891d-fdffabea35ca}/100': 'PKEY_GPS_Altitude', '{83a6347e-6fe4-4f40-ba9c-c4865240d1f4}/100': ( 'PKEY_Communication_FollowupIconIndex'), '{83da6326-97a6-4088-9453-a1923f573b29}/9': ( 'PKEY_DeviceDisplay_InstallInProgress'), '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/10': 'PKEY_PROVIDER_TOOLTIPS', '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/11': 'PKEY_PROVIDER_ICON', '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/2': 'PKEY_PROVIDER_INSTANCEID', '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/3': 'PKEY_PROVIDER_CLSID', '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/4': 'PKEY_PROVIDER_CONFIGUI', '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/5': 'PKEY_PROVIDER_CONTENTTYPE', '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/6': 'PKEY_PROVIDER_CAPABILITIES', '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/7': ( 'PKEY_PROVIDER_SUPPORTED_ARCHITECTURE'), '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/8': 'PKEY_PROVIDER_NAME', '{84179e61-60f6-4c1c-88ed-f1c531b32bda}/9': 'PKEY_PROVIDER_DESCRIPTION', '{841e4f90-ff59-4d16-8947-e81bbffab36d}/16': 'PKEY_Software_DateLastUsed', '{847c66de-b8d6-4af9-abc3-6f4f926bc039}/14': ( 'PKEY_DeviceInterface_PrinterDriverDirectory'), '{84d8f337-981d-44b3-9615-c7596dba17e3}/100': 'PKEY_Contact_EmailAddresses', '{8589e481-6040-473d-b171-7fa89c2708ed}/100': ( 'PKEY_Contact_CompanyMainTelephone'), '{8619a4b6-9f4d-4429-8c0f-b996ca59e335}/100': ( 'PKEY_Communication_SecurityFlags'), '{86d40b4d-9069-443c-819a-2a54090dccec}/11': 'PKEY_Tile_LongDisplayName', '{86d40b4d-9069-443c-819a-2a54090dccec}/12': ( 'PKEY_Tile_Square150x150LogoPath'), '{86d40b4d-9069-443c-819a-2a54090dccec}/13': ( 'PKEY_Tile_Wide310x150LogoPath'), '{86d40b4d-9069-443c-819a-2a54090dccec}/14': 'PKEY_Tile_Flags', '{86d40b4d-9069-443c-819a-2a54090dccec}/15': 'PKEY_Tile_BadgeLogoPath', '{86d40b4d-9069-443c-819a-2a54090dccec}/16': 'PKEY_Tile_SuiteDisplayName', '{86d40b4d-9069-443c-819a-2a54090dccec}/17': 'PKEY_Tile_SuiteSortName', '{86d40b4d-9069-443c-819a-2a54090dccec}/18': ( 'PKEY_Tile_DisplayNameLanguage'), '{86d40b4d-9069-443c-819a-2a54090dccec}/19': ( 'PKEY_Tile_Square310x310LogoPath'), '{86d40b4d-9069-443c-819a-2a54090dccec}/2': 'PKEY_Tile_SmallLogoPath', '{86d40b4d-9069-443c-819a-2a54090dccec}/20': ( 'PKEY_Tile_Square70x70LogoPath'), '{86d40b4d-9069-443c-819a-2a54090dccec}/21': 'PKEY_Tile_FencePost', '{86d40b4d-9069-443c-819a-2a54090dccec}/22': 'PKEY_Tile_InstallProgress', '{86d40b4d-9069-443c-819a-2a54090dccec}/23': 'PKEY_Tile_EncodedTargetPath', '{86d40b4d-9069-443c-819a-2a54090dccec}/4': 'PKEY_Tile_Background', '{86d40b4d-9069-443c-819a-2a54090dccec}/5': 'PKEY_Tile_Foreground', '{8727cfff-4868-4ec6-ad5b-81b98521d1ab}/100': 'PKEY_GPS_Latitude', '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/1': 'PKEY_Pairing_ListItemText', '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/16': ( 'PKEY_Pairing_IsWifiOnlyDevice'), '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/2': ( 'PKEY_Pairing_ListItemDescription'), '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/3': 'PKEY_Pairing_ListItemIcon', '{8807cae6-7db6-4f10-8ee4-435eaa1392bc}/4': 'PKEY_Pairing_ListItemDefault', '{880f70a2-6082-47ac-8aab-a739d1a300c3}/151': 'PKEY_Devices_SharedTooltip', '{880f70a2-6082-47ac-8aab-a739d1a300c3}/152': ( 'PKEY_Devices_NetworkedTooltip'), '{880f70a2-6082-47ac-8aab-a739d1a300c3}/153': 'PKEY_Devices_DefaultTooltip', '{88190b80-4684-11da-a26a-0002b3988e81}/1': 'PKEY_WCN_Version', '{88190b81-4684-11da-a26a-0002b3988e81}/2': 'PKEY_WCN_RequestType', '{88190b82-4684-11da-a26a-0002b3988e81}/3': 'PKEY_WCN_AuthType', '{88190b83-4684-11da-a26a-0002b3988e81}/4': 'PKEY_WCN_EncryptType', '{88190b84-4684-11da-a26a-0002b3988e81}/5': 'PKEY_WCN_ConnType', '{88190b85-4684-11da-a26a-0002b3988e81}/6': 'PKEY_WCN_ConfigMethods', '{88190b86-4684-11da-a26a-0002b3988e81}/7': 'PKEY_WCN_DeviceType', '{88190b87-4684-11da-a26a-0002b3988e81}/8': 'PKEY_WCN_RfBand', '{88190b88-4684-11da-a26a-0002b3988e81}/9': 'PKEY_WCN_AssocState', '{88190b89-4684-11da-a26a-0002b3988e81}/10': 'PKEY_WCN_ConfigError', '{88190b89-4684-11da-a26a-0002b3988e81}/11': 'PKEY_WCN_ConfigState', '{88190b89-4684-11da-a26a-0002b3988e81}/12': 'PKEY_WCN_DevicePasswordId', '{88190b89-4684-11da-a26a-0002b3988e81}/13': 'PKEY_WCN_OSVersion', '{88190b8a-4684-11da-a26a-0002b3988e81}/14': 'PKEY_WCN_VendorExtension', '{88190b8b-4684-11da-a26a-0002b3988e81}/15': 'PKEY_WCN_RegistrarType', '{88190b8b-4684-11da-a26a-0002b3988e81}/16': 'PKEY_WCN_DeviceType_Category', '{88190b8b-4684-11da-a26a-0002b3988e81}/17': ( 'PKEY_WCN_DeviceType_SubCategoryOUI'), '{88190b8b-4684-11da-a26a-0002b3988e81}/18': ( 'PKEY_WCN_DeviceType_SubCategory'), '{88190b8b-4684-11da-a26a-0002b3988e81}/32': 'PKEY_WCN_SSID', '{8859a284-de7e-4642-99ba-d431d044b1ec}/100': ( 'PKEY_PropGroup_MediaAdvanced'), '{8943b373-388c-4395-b557-bc6dbaffafdb}/2': ( 'PKEY_Devices_AudioDevice_RawProcessingSupported'), '{8943b373-388c-4395-b557-bc6dbaffafdb}/3': ( 'PKEY_Devices_AudioDevice_Microphone_SensitivityInDbfs'), '{8943b373-388c-4395-b557-bc6dbaffafdb}/4': ( 'PKEY_Devices_AudioDevice_Microphone_SignalToNoiseRatioInDb'), '{8943b373-388c-4395-b557-bc6dbaffafdb}/5': ( 'PKEY_Devices_AudioDevice_Microphone_SensitivityInDbfs2'), '{8969b275-9475-4e00-a887-ff93b8b41e44}/100': 'PKEY_PropGroup_Description', '{897b3694-fe9e-43e6-8066-260f590c0100}/2': ( 'PKEY_Contact_JA_CompanyNamePhonetic'), '{897b3694-fe9e-43e6-8066-260f590c0100}/3': ( 'PKEY_Contact_JA_FirstNamePhonetic'), '{897b3694-fe9e-43e6-8066-260f590c0100}/4': ( 'PKEY_Contact_JA_LastNamePhonetic'), '{8a2f99f9-3c37-465d-a8d7-69777a246d0c}/2': 'PKEY_Link_FeedItemLocalId', '{8a2f99f9-3c37-465d-a8d7-69777a246d0c}/5': 'PKEY_Link_TargetUrlHostName', '{8a2f99f9-3c37-465d-a8d7-69777a246d0c}/6': 'PKEY_Link_TargetUrlPath', '{8af4961c-f526-43e5-aa81-db768219178d}/100': ( 'PKEY_Photo_SubjectDistanceNumerator'), '{8afcc170-8a46-4b53-9eee-90bae7151e62}/100': ( 'PKEY_Contact_HomeAddressPostalCode'), '{8b26ea41-058f-43f6-aecc-4035681ce977}/100': ( 'PKEY_Contact_OtherAddressPostOfficeBox'), '{8c3b93a4-baed-1a83-9a32-102ee313f6eb}/100': 'PKEY_Identity_Blob', '{8c7ed206-3f8a-4827-b3ab-ae9e1faefc6c}/2': 'PKEY_Devices_ContainerId', '{8c7ed206-3f8a-4827-b3ab-ae9e1faefc6c}/4': ( 'PKEY_Devices_InLocalMachineContainer'), '{8e531030-b960-4346-ae0d-66bc9a86fb94}/100': ( 'PKEY_Communication_Direction'), '{8e8ecf7c-b7b8-4eb8-a63f-0ee715c96f9e}/100': ( 'PKEY_Photo_GainControlNumerator'), '{8f167568-0aae-4322-8ed9-6055b7b0e398}/100': ( 'PKEY_Contact_OtherAddressCountry'), '{8f367200-c270-457c-b1d4-e07c5bcd90c7}/100': 'PKEY_Contact_LastName', '{8fdc6dea-b929-412b-ba90-397a257465fe}/100': 'PKEY_Contact_CarTelephone', '{900a403b-097b-4b95-8ae2-071fdaeeb118}/100': 'PKEY_PropGroup_Advanced', '{90197ca7-fd8f-4e8c-9da3-b57e1e609295}/100': 'PKEY_RatingText', '{908696c7-8f87-44f2-80ed-a8c1c6894575}/2': 'PKEY_LibraryLocationsCount', '{9098f33c-9a7d-48a8-8de5-2e1227a64e91}/100': ( 'PKEY_Message_ProofInProgress'), '{90e5e14e-648b-4826-b2aa-acaf790e3513}/10': 'PKEY_IsEncrypted', '{91eff6f3-2e27-42ca-933e-7c999fbe310b}/100': ( 'PKEY_Contact_BusinessFaxNumber'), '{93112f89-c28b-492f-8a9d-4be2062cee8a}/100': ( 'PKEY_Photo_ExposureIndexDenominator'), '{95beb1fc-326d-4644-b396-cd3ed90e6ddf}/100': 'PKEY_Journal_EntryType', '{95c656c1-2abf-4148-9ed3-9ec602e3b7cd}/100': ( 'PKEY_Contact_OtherAddressPostalCode'), '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/2': ( 'PKEY_DeviceInterface_WinUsb_UsbVendorId'), '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/3': ( 'PKEY_DeviceInterface_WinUsb_UsbProductId'), '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/4': ( 'PKEY_DeviceInterface_WinUsb_UsbClass'), '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/5': ( 'PKEY_DeviceInterface_WinUsb_UsbSubClass'), '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/6': ( 'PKEY_DeviceInterface_WinUsb_UsbProtocol'), '{95e127b5-79cc-4e83-9c9e-8422187b3e0e}/7': ( 'PKEY_DeviceInterface_WinUsb_DeviceInterfaceClasses'), '{9660c283-fc3a-4a08-a096-eed3aac46da2}/100': 'PKEY_Contact_DataSuppliers', '{967b5af8-995a-46ed-9e11-35b3c5b9782d}/100': 'PKEY_Photo_ExposureIndex', '{972e333e-ac7e-49f1-8adf-a70d07a9bcab}/100': 'PKEY_GPS_AreaInformation', '{9744311e-7951-4b2e-b6f0-ecb293cac119}/5': ( 'PKEY_Devices_AepService_Bluetooth_CacheMode'), '{9744311e-7951-4b2e-b6f0-ecb293cac119}/6': ( 'PKEY_Devices_AepService_Bluetooth_GattService_Device'), '{9744311e-7951-4b2e-b6f0-ecb293cac119}/7': ( 'PKEY_Devices_AepService_Bluetooth_RfcommService_CacheMode'), '{9744311e-7951-4b2e-b6f0-ecb293cac119}/8': ( 'PKEY_Devices_AepService_Bluetooth_RfcommService_Device'), '{97b0ad89-df49-49cc-834e-660974fd755b}/100': 'PKEY_Contact_Label', '{98f98354-617a-46b8-8560-5b1b64bf1f89}/100': 'PKEY_Contact_HomeAddress', '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/1': ( 'PKEY_Devices_Aep_Bluetooth_Le_Appearance'), '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/4': ( 'PKEY_Devices_Aep_Bluetooth_Le_AddressType'), '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/5': ( 'PKEY_Devices_Aep_Bluetooth_Le_Appearance_Category'), '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/6': ( 'PKEY_Devices_Aep_Bluetooth_Le_Appearance_Subcategory'), '{995ef0b0-7eb3-4a8b-b9ce-068bb3f4af69}/8': ( 'PKEY_Devices_Aep_Bluetooth_Le_IsConnectable'), '{9973d2b5-bfd8-438a-ba94-5349b293181a}/100': 'PKEY_PropGroup_Calendar', '{9a8ebb75-6458-4e82-bacb-35c0095b03bb}/100': ( 'PKEY_Photo_TranscodedForSync'), '{9a93244d-a7ad-4ff8-9b99-45ee4cc09af6}/100': ( 'PKEY_Contact_AssistantTelephone'), '{9a9bc088-4f6d-469e-9919-e705412040f9}/100': 'PKEY_Message_IsFwdOrReply', '{9ab84393-2a0f-4b75-bb22-7279786977cb}/100': 'PKEY_GPS_DestBearingRef', '{9ad5badb-cea7-4470-a03d-b84e51b9949e}/100': 'PKEY_Contact_Anniversary', '{9aebae7a-9644-487d-a92c-657585ed751a}/100': ( 'PKEY_Media_SubscriptionContentId'), '{9b174b34-40ff-11d2-a27e-00c04fc30871}/4': 'PKEY_FileOwner', '{9b174b35-40ff-11d2-a27e-00c04fc30871}/10': 'PKEY_Volume_IsRoot', '{9b174b35-40ff-11d2-a27e-00c04fc30871}/2': 'PKEY_FreeSpace', '{9b174b35-40ff-11d2-a27e-00c04fc30871}/3': 'PKEY_Capacity', '{9b174b35-40ff-11d2-a27e-00c04fc30871}/4': 'PKEY_Volume_FileSystem', '{9b174b35-40ff-11d2-a27e-00c04fc30871}/5': 'PKEY_PercentFull', '{9b174b35-40ff-11d2-a27e-00c04fc30871}/7': ( 'PKEY_Computer_DecoratedFreeSpace'), '{9bc2c99b-ac71-4127-9d1c-2596d0d7dcb7}/100': ( 'PKEY_GPS_DestDistanceDenominator'), '{9c1fcf74-2d97-41ba-b4ae-cb2e3661a6e4}/5': 'PKEY_Priority', '{9c1fcf74-2d97-41ba-b4ae-cb2e3661a6e4}/8': 'PKEY_Message_HasAttachments', '{9cb0c358-9d7a-46b1-b466-dcc6f1a3d93d}/100': ( 'PKEY_Contact_DisplayMobilePhoneNumbers'), '{9d1d7cc5-5c39-451c-86b3-928e2d18cc47}/100': 'PKEY_GPS_DestLatitude', '{9d2408b6-3167-422b-82b0-f583b7a7cfe3}/100': 'PKEY_Contact_SpouseName', '{9e7d118f-b314-45a0-8cfb-d654b917c9e9}/100': ( 'PKEY_Photo_BrightnessNumerator'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/10': ( 'PKEY_AppUserModel_BestShortcut'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/11': 'PKEY_AppUserModel_IsDualMode', '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/12': ( 'PKEY_AppUserModel_StartPinOption'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/13': 'PKEY_AppUserModel_Relevance', '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/14': ( 'PKEY_AppUserModel_HostEnvironment'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/15': ( 'PKEY_AppUserModel_PackageInstallPath'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/16': ( 'PKEY_AppUserModel_RecordState'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/17': ( 'PKEY_AppUserModel_PackageFamilyName'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/18': ( 'PKEY_AppUserModel_InstalledBy'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/19': 'PKEY_AppUserModel_ParentID', '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/2': ( 'PKEY_AppUserModel_RelaunchCommand'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/20': ( 'PKEY_AppUserModel_ActivationContext'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/21': ( 'PKEY_AppUserModel_PackageFullName'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/22': ( 'PKEY_AppUserModel_PackageRelativeApplicationID'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/23': ( 'PKEY_AppUserModel_ExcludedFromLauncher'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/25': 'PKEY_AppUserModel_RunFlags', '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/26': ( 'PKEY_AppUserModel_ToastActivatorCLSID'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/27': ( 'PKEY_AppUserModel_DestListProvidedTitle'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/28': ( 'PKEY_AppUserModel_DestListProvidedDescription'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/29': ( 'PKEY_AppUserModel_DestListLogoUri'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/3': ( 'PKEY_AppUserModel_RelaunchIconResource'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/30': ( 'PKEY_AppUserModel_DestListProvidedGroupName'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/4': ( 'PKEY_AppUserModel_RelaunchDisplayNameResource'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/5': 'PKEY_AppUserModel_ID', '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/6': ( 'PKEY_AppUserModel_IsDestListSeparator'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/7': ( 'PKEY_AppUserModel_IsDestListLink'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/8': ( 'PKEY_AppUserModel_ExcludeFromShowInNewInstall'), '{9f4c2855-9f79-4b39-a8d0-e1d42de1d5f3}/9': ( 'PKEY_AppUserModel_PreventPinning'), '{a00742a1-cd8c-4b37-95ab-70755587767a}/3': ( 'PKEY_DeviceInterface_PrinterEnumerationFlag'), '{a015ed5d-aaea-4d58-8a86-3c586920ea0b}/100': 'PKEY_GPS_MeasureMode', '{a06992b3-8caf-4ed7-a547-b259e32ac9fc}/100': 'PKEY_Search_Store', '{a09f084e-ad41-489f-8076-aa5be3082bca}/100': 'PKEY_SimpleRating', '{a0be94c5-50ba-487b-bd35-0654be8881ed}/100': 'PKEY_GPS_DOPDenominator', '{a0e00ee1-f0c7-4d41-b8e7-26a7bd8d38b0}/2': ( 'PKEY_Devices_Notifications_StorageFull'), '{a0e00ee1-f0c7-4d41-b8e7-26a7bd8d38b0}/3': ( 'PKEY_Devices_Notification_StorageFullLinkText'), '{a0e74609-b84d-4f49-b860-462bd9971f98}/100': ( 'PKEY_Photo_FocalLengthInFilm'), '{a1829ea2-27eb-459e-935d-b2fad7b07762}/2': ( 'PKEY_Devices_MicrophoneArray_Geometry'), '{a19fb7a9-024b-4371-a8bf-4d29c3e4e9c9}/100': ( 'PKEY_Contact_ConnectedServiceSupportedActions'), '{a26f4afc-7346-4299-be47-eb1ae613139f}/100': 'PKEY_Identity', '{a26f4afc-7346-4299-be47-eb1ae613139f}/16': ( 'PKEY_Identity_KeyProviderName'), '{a26f4afc-7346-4299-be47-eb1ae613139f}/17': ( 'PKEY_Identity_KeyProviderContext'), '{a2e541c5-4440-4ba8-867e-75cfc06828cd}/100': ( 'PKEY_Photo_FocalPlaneYResolutionNumerator'), '{a3250282-fb6d-48d5-9a89-dbcace75cccf}/100': ( 'PKEY_GPS_DestLongitudeNumerator'), '{a35996ab-11cf-4935-8b61-a6761081ecdf}/12': ( 'PKEY_Devices_Aep_DeviceAddress'), '{a35996ab-11cf-4935-8b61-a6761081ecdf}/16': 'PKEY_Devices_Aep_IsPaired', '{a35996ab-11cf-4935-8b61-a6761081ecdf}/17': 'PKEY_Devices_Aep_Category', '{a35996ab-11cf-4935-8b61-a6761081ecdf}/3': 'PKEY_Devices_Aep_ModelName', '{a35996ab-11cf-4935-8b61-a6761081ecdf}/4': 'PKEY_Devices_Aep_ModelId', '{a35996ab-11cf-4935-8b61-a6761081ecdf}/5': 'PKEY_Devices_Aep_Manufacturer', '{a35996ab-11cf-4935-8b61-a6761081ecdf}/6': ( 'PKEY_Devices_Aep_SignalStrength'), '{a35996ab-11cf-4935-8b61-a6761081ecdf}/7': 'PKEY_Devices_Aep_IsConnected', '{a35996ab-11cf-4935-8b61-a6761081ecdf}/9': 'PKEY_Devices_Aep_IsPresent', '{a399aac7-c265-474e-b073-ffce57721716}/2': ( 'PKEY_Devices_AepService_Bluetooth_ServiceGuid'), '{a3b29791-7713-4e1d-bb40-17db85f01831}/100': 'PKEY_ImportanceText', '{a4108708-09df-4377-9dfc-6d99986d5a67}/100': 'PKEY_Identity_IsMeIdentity', '{a45c254e-df1c-4efd-8020-67d146a850e0}/10': 'PKEY_Devices_ClassGuid', '{a45c254e-df1c-4efd-8020-67d146a850e0}/11': 'PKEY_Device_Driver', '{a45c254e-df1c-4efd-8020-67d146a850e0}/12': 'PKEY_Device_ConfigFlags', '{a45c254e-df1c-4efd-8020-67d146a850e0}/13': ( 'PKEY_Devices_DeviceManufacturer'), '{a45c254e-df1c-4efd-8020-67d146a850e0}/14': 'PKEY_Device_FriendlyName', '{a45c254e-df1c-4efd-8020-67d146a850e0}/15': 'PKEY_Device_LocationInfo', '{a45c254e-df1c-4efd-8020-67d146a850e0}/16': 'PKEY_Device_PDOName', '{a45c254e-df1c-4efd-8020-67d146a850e0}/17': ( 'PKEY_Devices_DeviceCapabilities'), '{a45c254e-df1c-4efd-8020-67d146a850e0}/18': 'PKEY_Device_UINumber', '{a45c254e-df1c-4efd-8020-67d146a850e0}/19': 'PKEY_Device_UpperFilters', '{a45c254e-df1c-4efd-8020-67d146a850e0}/2': 'PKEY_AudioEndPoint_Interface', '{a45c254e-df1c-4efd-8020-67d146a850e0}/20': 'PKEY_Device_LowerFilters', '{a45c254e-df1c-4efd-8020-67d146a850e0}/21': 'PKEY_Device_BusTypeGuid', '{a45c254e-df1c-4efd-8020-67d146a850e0}/22': 'PKEY_Device_LegacyBusType', '{a45c254e-df1c-4efd-8020-67d146a850e0}/23': 'PKEY_Device_BusNumber', '{a45c254e-df1c-4efd-8020-67d146a850e0}/24': 'PKEY_Device_EnumeratorName', '{a45c254e-df1c-4efd-8020-67d146a850e0}/25': 'PKEY_Device_Security', '{a45c254e-df1c-4efd-8020-67d146a850e0}/26': 'PKEY_Device_SecuritySDS', '{a45c254e-df1c-4efd-8020-67d146a850e0}/27': 'PKEY_Device_DevType', '{a45c254e-df1c-4efd-8020-67d146a850e0}/28': 'PKEY_Device_Exclusive', '{a45c254e-df1c-4efd-8020-67d146a850e0}/29': 'PKEY_Device_Characteristics', '{a45c254e-df1c-4efd-8020-67d146a850e0}/3': 'PKEY_Devices_HardwareIds', '{a45c254e-df1c-4efd-8020-67d146a850e0}/30': 'PKEY_Device_Address', '{a45c254e-df1c-4efd-8020-67d146a850e0}/31': ( 'PKEY_Device_UINumberDescFormat'), '{a45c254e-df1c-4efd-8020-67d146a850e0}/32': 'PKEY_Device_PowerData', '{a45c254e-df1c-4efd-8020-67d146a850e0}/33': 'PKEY_Device_RemovalPolicy', '{a45c254e-df1c-4efd-8020-67d146a850e0}/34': ( 'PKEY_Device_RemovalPolicyDefault'), '{a45c254e-df1c-4efd-8020-67d146a850e0}/35': ( 'PKEY_Device_RemovalPolicyOverride'), '{a45c254e-df1c-4efd-8020-67d146a850e0}/36': 'PKEY_Device_InstallState', '{a45c254e-df1c-4efd-8020-67d146a850e0}/37': 'PKEY_Devices_LocationPaths', '{a45c254e-df1c-4efd-8020-67d146a850e0}/4': 'PKEY_Device_CompatibleIds', '{a45c254e-df1c-4efd-8020-67d146a850e0}/6': 'PKEY_Device_Service', '{a45c254e-df1c-4efd-8020-67d146a850e0}/9': 'PKEY_Device_Class', '{a4aaa5b7-1ad0-445f-811a-0f8f6e67f6b5}/100': 'PKEY_GPS_ImgDirectionRef', '{a5477f61-7a82-4eca-9dde-98b69b2479b3}/100': ( 'PKEY_RecordedTV_RecordingTime'), '{a6744477-c237-475b-a075-54f34498292a}/100': ( 'PKEY_Communication_TaskStatusText'), '{a6f360d2-55f9-48de-b909-620e090a647c}/100': 'PKEY_IsFlaggedComplete', '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/101': ( 'PKEY_Contact_HomeAddress1Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/102': ( 'PKEY_Contact_HomeAddress1Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/103': ( 'PKEY_Contact_HomeAddress1Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/104': ( 'PKEY_Contact_HomeAddress1Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/105': ( 'PKEY_Contact_HomeAddress1PostalCode'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/106': ( 'PKEY_Contact_HomeAddress2Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/107': ( 'PKEY_Contact_HomeAddress2Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/108': ( 'PKEY_Contact_HomeAddress2Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/109': ( 'PKEY_Contact_HomeAddress2Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/110': ( 'PKEY_Contact_HomeAddress2PostalCode'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/111': ( 'PKEY_Contact_HomeAddress3Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/112': ( 'PKEY_Contact_HomeAddress3Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/113': ( 'PKEY_Contact_HomeAddress3Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/114': ( 'PKEY_Contact_HomeAddress3Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/115': ( 'PKEY_Contact_HomeAddress3PostalCode'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/116': ( 'PKEY_Contact_BusinessAddress1Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/117': ( 'PKEY_Contact_BusinessAddress1Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/118': ( 'PKEY_Contact_BusinessAddress1Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/119': ( 'PKEY_Contact_BusinessAddress1Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/120': ( 'PKEY_Contact_BusinessAddress1PostalCode'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/121': ( 'PKEY_Contact_BusinessAddress2Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/122': ( 'PKEY_Contact_BusinessAddress2Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/123': ( 'PKEY_Contact_BusinessAddress2Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/124': ( 'PKEY_Contact_BusinessAddress2Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/125': ( 'PKEY_Contact_BusinessAddress2PostalCode'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/126': ( 'PKEY_Contact_BusinessAddress3Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/127': ( 'PKEY_Contact_BusinessAddress3Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/128': ( 'PKEY_Contact_BusinessAddress3Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/129': ( 'PKEY_Contact_BusinessAddress3Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/130': ( 'PKEY_Contact_BusinessAddress3PostalCode'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/131': ( 'PKEY_Contact_OtherAddress1Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/132': ( 'PKEY_Contact_OtherAddress1Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/133': ( 'PKEY_Contact_OtherAddress1Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/134': ( 'PKEY_Contact_OtherAddress1Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/135': ( 'PKEY_Contact_OtherAddress1PostalCode'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/136': ( 'PKEY_Contact_OtherAddress2Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/137': ( 'PKEY_Contact_OtherAddress2Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/138': ( 'PKEY_Contact_OtherAddress2Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/139': ( 'PKEY_Contact_OtherAddress2Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/140': ( 'PKEY_Contact_OtherAddress2PostalCode'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/141': ( 'PKEY_Contact_OtherAddress3Street'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/142': ( 'PKEY_Contact_OtherAddress3Locality'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/143': ( 'PKEY_Contact_OtherAddress3Region'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/144': ( 'PKEY_Contact_OtherAddress3Country'), '{a7b6f596-d678-4bc1-b05f-0203d27e8aa1}/145': ( 'PKEY_Contact_OtherAddress3PostalCode'), '{a7fe0840-1344-46f0-8d37-52ed712a4bf9}/100': ( 'PKEY_ParentalRatingsOrganization'), '{a82d9ee7-ca67-4312-965e-226bcea85023}/100': 'PKEY_Message_Flags', '{a8a74b92-361b-4e9a-b722-7c4a7330a312}/100': 'PKEY_Identity_ProviderData', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/10': ( 'PKEY_Device_DriverPropPageProvider'), '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/11': ( 'PKEY_Device_DriverCoInstallers'), '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/12': ( 'PKEY_Device_ResourcePickerTags'), '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/13': ( 'PKEY_Device_ResourcePickerExceptions'), '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/14': 'PKEY_Device_DriverRank', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/15': 'PKEY_Device_DriverLogoLevel', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/17': 'PKEY_Device_NoConnectSound', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/18': ( 'PKEY_Device_GenericDriverInstalled'), '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/2': 'PKEY_Device_DriverDate', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/3': 'PKEY_Device_DriverVersion', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/4': 'PKEY_Device_DriverDesc', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/5': 'PKEY_Device_DriverInfPath', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/6': 'PKEY_Device_DriverInfSection', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/7': ( 'PKEY_Device_DriverInfSectionExt'), '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/8': 'PKEY_Device_MatchingDeviceId', '{a8b865dd-2e3d-4094-ad97-e593a70c75d6}/9': 'PKEY_Device_DriverProvider', '{a93eae04-6804-4f24-ac81-09b266452118}/100': 'PKEY_GPS_DestDistance', '{a94688b6-7d9f-4570-a648-e3dfc0ab2b3f}/100': 'PKEY_OfflineAvailability', '{a988f78b-07b6-4f47-9c9f-25409534cdee}/0': 'PKEY_Endpoint_Enable_LFX', '{a9ea193c-c511-498a-a06b-58e2776dcc28}/100': 'PKEY_Photo_OrientationText', '{aaa660f9-9865-458e-b484-01bc7fe3973e}/100': 'PKEY_Calendar_OrganizerName', '{aabaf6c9-e0c5-4719-8585-57b103e584fe}/100': ( 'PKEY_Photo_FlashManufacturer'), '{aaf16bac-2b55-45e6-9f6d-415eb94910df}/100': ( 'PKEY_Contact_TTYTDDTelephone'), '{aaf4ee25-bd3b-4dd7-bfc4-47f77bb00f6d}/100': 'PKEY_GPS_Differential', '{ab205e50-04b7-461c-a18c-2f233836e627}/100': ( 'PKEY_Photo_ExposureBiasDenominator'), '{acc9ce3d-c213-4942-8b48-6d0820f21c6d}/100': 'PKEY_GPS_SpeedNumerator', '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/2': 'PKEY_DRM_IsProtected', '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/3': 'PKEY_DRM_Description', '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/4': 'PKEY_DRM_PlayCount', '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/5': 'PKEY_DRM_DatePlayStarts', '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/6': 'PKEY_DRM_DatePlayExpires', '{aeac19e4-89ae-4508-b9b7-bb867abee2ed}/7': 'PKEY_DRM_IsDisabled', '{afc47170-14f5-498c-8f30-b0d19be449c6}/11': ( 'PKEY_DeviceInterface_PrinterDriverName'), '{afd97640-86a3-4210-b67c-289c41aabe55}/2': ( 'PKEY_Devices_SafeRemovalRequired'), '{b0b87314-fcf6-4feb-8dff-a50da6af561c}/100': ( 'PKEY_Contact_BusinessAddressCountry'), '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/2': 'PKEY_FilePlaceholderStatus', '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/3': ( 'PKEY_StorageProviderFileIdentifier'), '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/4': ( 'PKEY_StorageProviderFileVersion'), '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/5': ( 'PKEY_StorageProviderFileChecksum'), '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/6': ( 'PKEY_StorageProviderFileVersionWaterline'), '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/7': ( 'PKEY_StorageProviderCallerVersionInformation'), '{b2f9b9d6-fec4-4dd5-94d7-8957488c807b}/8': 'PKEY_StorageProviderFileFlags', '{b33af30b-f552-4584-936c-cb93e5cda29f}/100': ( 'PKEY_Calendar_RequiredAttendeeNames'), '{b3f8fa53-0004-438e-9003-51a46e139bfc}/5': 'PKEY_SupportFormat_OEMFormat', '{b3f8fa53-0004-438e-9003-51a46e139bfc}/6': 'PKEY_Endpoint_Name', '{b5c84c9e-5927-46b5-a3cc-933c21b78469}/100': ( 'PKEY_Contact_ConnectedServiceName'), '{b725f130-47ef-101a-a5f1-02608c9eebac}/10': 'PKEY_DisplayName', '{b725f130-47ef-101a-a5f1-02608c9eebac}/12': 'PKEY_Size', '{b725f130-47ef-101a-a5f1-02608c9eebac}/13': 'PKEY_FileAttributes', '{b725f130-47ef-101a-a5f1-02608c9eebac}/14': 'PKEY_DateModified', '{b725f130-47ef-101a-a5f1-02608c9eebac}/15': 'PKEY_DateCreated', '{b725f130-47ef-101a-a5f1-02608c9eebac}/16': 'PKEY_DateAccessed', '{b725f130-47ef-101a-a5f1-02608c9eebac}/18': 'PKEY_FileAllocationSize', '{b725f130-47ef-101a-a5f1-02608c9eebac}/19': 'PKEY_Search_Contents', '{b725f130-47ef-101a-a5f1-02608c9eebac}/2': 'PKEY_ItemFolderNameDisplay', '{b725f130-47ef-101a-a5f1-02608c9eebac}/21': 'PKEY_FileFRN', '{b725f130-47ef-101a-a5f1-02608c9eebac}/23': 'PKEY_ItemNameSortOverride', '{b725f130-47ef-101a-a5f1-02608c9eebac}/24': ( 'PKEY_ItemNameDisplayWithoutExtension'), '{b725f130-47ef-101a-a5f1-02608c9eebac}/25': 'PKEY_FolderNameDisplay', '{b725f130-47ef-101a-a5f1-02608c9eebac}/4': 'PKEY_ItemTypeText', '{b7b4d61c-5a64-4187-a52e-b1539f359099}/2': ( 'PKEY_Devices_WinPhone8CameraFlags'), '{b812f15d-c2d8-4bbf-bacd-79744346113f}/100': 'PKEY_Photo_TagViewAggregate', '{b96eff7b-35ca-4a35-8607-29e3a54c46ea}/100': 'PKEY_IdentityProvider_Name', '{b9b4b3fc-2b51-4a42-b5d8-324146afcf25}/2': 'PKEY_Link_TargetParsingPath', '{b9b4b3fc-2b51-4a42-b5d8-324146afcf25}/3': 'PKEY_Link_Status', '{b9b4b3fc-2b51-4a42-b5d8-324146afcf25}/5': 'PKEY_Link_Comment', '{b9b4b3fc-2b51-4a42-b5d8-324146afcf25}/8': 'PKEY_Link_TargetSFGAOFlags', '{ba3b1da9-86ee-4b5d-a2a4-a271a429f0cf}/100': ( 'PKEY_GPS_DestBearingNumerator'), '{bc4e71ce-17f9-48d5-bee9-021df0ea5409}/100': ( 'PKEY_Contact_BusinessAddressPostOfficeBox'), '{bccc8a3c-8cef-42e5-9b1c-c69079398bc7}/100': 'PKEY_Message_ToDoTitle', '{bceee283-35df-4d53-826a-f36a3eefc6be}/100': 'PKEY_Search_ContainerHash', '{be1a72c6-9a1d-46b7-afe7-afaf8cef4999}/100': ( 'PKEY_Communication_TaskStatus'), '{be6e176c-4534-4d2c-ace5-31dedac1606b}/100': ( 'PKEY_GPS_LongitudeDenominator'), '{bebe0920-7671-4c54-a3eb-49fddfc191ee}/100': 'PKEY_PropGroup_Video', '{bf53d1c3-49e0-4f7f-8567-5a821d8ac542}/100': ( 'PKEY_Contact_CallbackTelephone'), '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/10': 'PKEY_Devices_Dnssd_Ttl', '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/11': ( 'PKEY_Devices_Dnssd_NetworkAdapterId'), '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/12': ( 'PKEY_Devices_Dnssd_PortNumber'), '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/2': ( 'PKEY_Devices_Dnssd_ServiceName'), '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/3': 'PKEY_Devices_Dnssd_Domain', '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/4': ( 'PKEY_Devices_Dnssd_InstanceName'), '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/5': 'PKEY_Devices_Dnssd_FullName', '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/6': ( 'PKEY_Devices_Dnssd_TextAttributes'), '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/7': 'PKEY_Devices_Dnssd_HostName', '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/8': 'PKEY_Devices_Dnssd_Weight', '{bf79c0ab-bb74-4cee-b070-470b5ae202ea}/9': 'PKEY_Devices_Dnssd_Priority', '{bfee9149-e3e2-49a7-a862-c05988145cec}/100': 'PKEY_Calendar_IsOnline', '{c06238b2-0bf9-4279-a723-25856715cb9d}/100': 'PKEY_Photo_GainControlText', '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/100': 'PKEY_Address_Country', '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/101': 'PKEY_Address_CountryCode', '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/102': 'PKEY_Address_Region', '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/103': 'PKEY_Address_RegionCode', '{c07b4199-e1df-4493-b1e1-de5946fb58f8}/104': 'PKEY_Address_Town', '{c0ac206a-827e-4650-95ae-77e2bb74fcc9}/100': 'PKEY_Contact_MailingAddress', '{c107e191-a459-44c5-9ae6-b952ad4b906d}/100': ( 'PKEY_Photo_MaxApertureNumerator'), '{c2ea046e-033c-4e91-bd5b-d4942f6bbe49}/2': 'PKEY_CreatorAppId', '{c2ea046e-033c-4e91-bd5b-d4942f6bbe49}/3': 'PKEY_CreatorOpenWithUIOptions', '{c4322503-78ca-49c6-9acc-a68e2afd7b6b}/100': 'PKEY_Identity_UserName', '{c449d5cb-9ea4-4809-82e8-af9d59ded6d1}/100': 'PKEY_Music_IsCompilation', '{c4c07f2b-8524-4e66-ae3a-a6235f103beb}/2': ( 'PKEY_Devices_Notification_LowBattery'), '{c4c4dbb2-b593-466b-bbda-d03d27d5e43a}/100': 'PKEY_GPS_Longitude', '{c554493c-c1f7-40c1-a76c-ef8c0614003e}/100': 'PKEY_Contact_TelexNumber', '{c66d4b3c-e888-47cc-b99f-9dca3ee34dea}/100': 'PKEY_GPS_DestBearing', '{c75faa05-96fd-49e7-9cb4-9f601082d553}/100': 'PKEY_EndDate', '{c77724d4-601f-46c5-9b89-c53f93bceb77}/100': ( 'PKEY_Photo_MaxApertureDenominator'), '{c89a23d0-7d6d-4eb8-87d4-776a82d493e5}/100': ( 'PKEY_Contact_HomeAddressState'), '{c8d1920c-01f6-40c0-ac86-2f3a4ad00770}/100': 'PKEY_GPS_TrackDenominator', '{c8ea94f0-a9e3-4969-a94b-9c62a95324e0}/100': ( 'PKEY_Contact_PrimaryAddressCity'), '{c9944a21-a406-48fe-8225-aec7e24c211b}/10': ( 'PKEY_PropList_FileOperationPrompt'), '{c9944a21-a406-48fe-8225-aec7e24c211b}/11': 'PKEY_PropList_ConflictPrompt', '{c9944a21-a406-48fe-8225-aec7e24c211b}/13': ( 'PKEY_PropList_ContentViewModeForBrowse'), '{c9944a21-a406-48fe-8225-aec7e24c211b}/14': ( 'PKEY_PropList_ContentViewModeForSearch'), '{c9944a21-a406-48fe-8225-aec7e24c211b}/17': 'PKEY_InfoTipText', '{c9944a21-a406-48fe-8225-aec7e24c211b}/2': 'PKEY_PropList_FullDetails', '{c9944a21-a406-48fe-8225-aec7e24c211b}/3': 'PKEY_PropList_TileInfo', '{c9944a21-a406-48fe-8225-aec7e24c211b}/4': 'PKEY_PropList_InfoTip', '{c9944a21-a406-48fe-8225-aec7e24c211b}/5': 'PKEY_PropList_QuickTip', '{c9944a21-a406-48fe-8225-aec7e24c211b}/500': ( 'PKEY_LayoutPattern_ContentViewModeForBrowse'), '{c9944a21-a406-48fe-8225-aec7e24c211b}/501': ( 'PKEY_LayoutPattern_ContentViewModeForSearch'), '{c9944a21-a406-48fe-8225-aec7e24c211b}/6': 'PKEY_PropList_PreviewTitle', '{c9944a21-a406-48fe-8225-aec7e24c211b}/8': 'PKEY_PropList_PreviewDetails', '{c9944a21-a406-48fe-8225-aec7e24c211b}/9': ( 'PKEY_PropList_ExtendedTileInfo'), '{c9c141a9-1b4c-4f17-a9d1-f298538cadb8}/2': ( 'PKEY_Devices_AepService_ServiceId'), '{c9c141a9-1b4c-4f17-a9d1-f298538cadb8}/5': ( 'PKEY_Devices_AepService_ProtocolId'), '{c9c141a9-1b4c-4f17-a9d1-f298538cadb8}/6': 'PKEY_Devices_AepService_AepId', '{c9c141a9-1b4c-4f17-a9d1-f298538cadb8}/7': ( 'PKEY_Devices_AepService_ParentAepIsPaired'), '{c9c34f84-2241-4401-b607-bd20ed75ae7f}/100': ( 'PKEY_Communication_HeaderItem'), '{cbf38310-4a17-4310-a1eb-247f0b67593b}/2': ( 'PKEY_DeviceInterface_Hid_UsagePage'), '{cbf38310-4a17-4310-a1eb-247f0b67593b}/3': ( 'PKEY_DeviceInterface_Hid_UsageId'), '{cbf38310-4a17-4310-a1eb-247f0b67593b}/4': ( 'PKEY_DeviceInterface_Hid_IsReadOnly'), '{cbf38310-4a17-4310-a1eb-247f0b67593b}/5': ( 'PKEY_DeviceInterface_Hid_VendorId'), '{cbf38310-4a17-4310-a1eb-247f0b67593b}/6': ( 'PKEY_DeviceInterface_Hid_ProductId'), '{cbf38310-4a17-4310-a1eb-247f0b67593b}/7': ( 'PKEY_DeviceInterface_Hid_VersionNumber'), '{cc301630-b192-4c22-b372-9f4c6d338e07}/100': 'PKEY_PropGroup_General', '{cc6f4f24-6083-4bd4-8754-674d0de87ab8}/100': 'PKEY_Contact_EmailName', '{cd102c9c-5540-4a88-a6f6-64e4981c8cd1}/100': 'PKEY_Contact_AssistantName', '{cd9ed458-08ce-418f-a70e-f912c7bb9c5c}/103': 'PKEY_Message_MessageClass', '{cdbfc167-337e-41d8-af7c-8c09205429c7}/100': ( 'PKEY_ApplicationDefinedProperties'), '{cdedcf30-8919-44df-8f4c-4eb2ffdb8d89}/100': ( 'PKEY_Photo_ExposureIndexNumerator'), '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/2': 'PKEY_Sync_HandlerName', '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/3': 'PKEY_Sync_ItemName', '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/4': 'PKEY_Sync_ConflictDescription', '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/6': ( 'PKEY_Sync_ConflictFirstLocation'), '{ce50c159-2fb8-41fd-be68-d3e042e274bc}/7': ( 'PKEY_Sync_ConflictSecondLocation'), '{cea820b9-ce61-4885-a128-005d9087c192}/100': 'PKEY_GPS_DestLatitudeRef', '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/2': 'PKEY_DrvPkg_Model', '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/3': 'PKEY_DrvPkg_VendorWebSite', '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/4': ( 'PKEY_DrvPkg_DetailedDescription'), '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/5': 'PKEY_DrvPkg_DocumentationLink', '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/6': 'PKEY_DrvPkg_Icon', '{cf73bb51-3abf-44a2-85e0-9a3dc7a12132}/7': 'PKEY_DrvPkg_BrandingIcon', '{cfa31b45-525d-4998-bb44-3f7d81542fa4}/100': 'PKEY_Media_DlnaProfileID', '{cfc08d97-c6f7-4484-89dd-ebef4356fe76}/100': ( 'PKEY_Photo_FocalPlaneXResolution'), '{d042d2a1-927e-40b5-a503-6edbd42a517e}/100': ( 'PKEY_Contact_PhoneNumbersCanonical'), '{d04e05a6-594b-4fb6-a80d-01af5eed7d1d}/0': 'PKEY_SYSFX_Association', '{d04e05a6-594b-4fb6-a80d-01af5eed7d1d}/1': 'PKEY_SYSFX_PreMixClsid', '{d04e05a6-594b-4fb6-a80d-01af5eed7d1d}/2': 'PKEY_SYSFX_PostMixClsid', '{d04e05a6-594b-4fb6-a80d-01af5eed7d1d}/3': 'PKEY_SYSFX_UiClsid', '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/10': 'PKEY_Devices_PrimaryCategory', '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/2': 'PKEY_Devices_InterfacePaths', '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/257': 'PKEY_Devices_Status1', '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/258': 'PKEY_Devices_Status2', '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/259': 'PKEY_Devices_Status', '{d08dd4c0-3a9e-462e-8290-7b636b2576b9}/3': 'PKEY_Devices_FunctionPaths', '{d0a04f0a-462a-48a4-bb2f-3706e88dbd7d}/100': 'PKEY_ItemAuthors', '{d0c7f054-3f72-4725-8527-129a577cb269}/100': 'PKEY_SensitivityText', '{d0dab0ba-368a-4050-a882-6c010fd19a4f}/100': 'PKEY_PropGroup_Content', '{d21a7148-d32c-4624-8900-277210f79c0f}/100': ( 'PKEY_Image_CompressedBitsPerPixelNumerator'), '{d35f743a-eb2e-47f2-a286-844132cb1427}/100': 'PKEY_Photo_EXIFVersion', '{d37d52c6-261c-4303-82b3-08b926ac6f12}/100': ( 'PKEY_Task_BillingInformation'), '{d4729704-8ef1-43ef-9024-2bd381187fd5}/100': 'PKEY_Contact_Children', '{d4bf61b3-442e-4ada-882d-fa7b70c832d9}/6': ( 'PKEY_Devices_Aep_PointOfService_ConnectionTypes'), '{d4d0aa16-9948-41a4-aa85-d97ff9646993}/100': 'PKEY_ItemParticipants', '{d55bae5a-3892-417a-a649-c6ac5aaaeab3}/100': ( 'PKEY_Calendar_OptionalAttendeeAddresses'), '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/10': ( 'PKEY_Document_MultimediaClipCount'), '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/14': 'PKEY_Document_Manager', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/15': 'PKEY_Company', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/2': 'PKEY_Category', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/26': 'PKEY_ContentType', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/27': 'PKEY_ContentStatus', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/28': 'PKEY_Language', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/29': 'PKEY_Document_Version', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/3': ( 'PKEY_Document_PresentationFormat'), '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/4': 'PKEY_Document_ByteCount', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/5': 'PKEY_Document_LineCount', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/6': 'PKEY_Document_ParagraphCount', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/7': 'PKEY_Document_SlideCount', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/8': 'PKEY_Document_NoteCount', '{d5cdd502-2e9c-101b-9397-08002b2cf9ae}/9': ( 'PKEY_Document_HiddenSlideCount'), '{d6304e01-f8f5-4f45-8b15-d024a6296789}/100': 'PKEY_Contact_PagerTelephone', '{d68dbd8a-3374-4b81-9972-3ec30682db3d}/100': 'PKEY_Contact_IMAddress', '{d6942081-d53b-443d-ad47-5e059d9cd27a}/2': 'PKEY_Shell_SFGAOFlagsStrings', '{d6942081-d53b-443d-ad47-5e059d9cd27a}/3': ( 'PKEY_Link_TargetSFGAOFlagsStrings'), '{d6b5b883-18bd-4b4d-b2ec-9e38affeda82}/2': ( 'PKEY_Devices_SmartCards_ReaderKind'), '{d7313ff1-a77a-401c-8c99-3dbdd68add36}/100': 'PKEY_ItemNamePrefix', '{d7750ee0-c6a4-48ec-b53e-b87b52e6d073}/100': 'PKEY_ImageParsingName', '{d7b61c70-6323-49cd-a5fc-c84277162c97}/100': ( 'PKEY_Photo_FlashEnergyDenominator'), '{d98be98b-b86b-4095-bf52-9d23b2e0a752}/100': 'PKEY_PriorityText', '{da520e51-f4e9-4739-ac82-02e0a95c9030}/100': ( 'PKEY_Identity_QualifiedUserName'), '{da5d0862-6e76-4e1b-babd-70021bd25494}/100': 'PKEY_GPS_Speed', '{dabd30ed-0043-4789-a7f8-d013a4736622}/100': ( 'PKEY_ItemFolderPathDisplayNarrow'), '{dc54fd2e-189d-4871-aa01-08c2f57a4abc}/100': 'PKEY_FlagStatusText', '{dc5877c7-225f-45f7-bac7-e81334b6130a}/100': ( 'PKEY_GPS_ImgDirectionNumerator'), '{dc8f80bd-af1e-4289-85b6-3dfc1b493992}/100': 'PKEY_Message_ConversationID', '{dc8f80bd-af1e-4289-85b6-3dfc1b493992}/101': ( 'PKEY_Message_ConversationIndex'), '{dccb10af-b4e2-4b88-95f9-031b4d5ab490}/100': ( 'PKEY_Photo_FocalPlaneXResolutionNumerator'), '{ddd1460f-c0bf-4553-8ce4-10433c908fb0}/100': ( 'PKEY_Contact_BusinessAddressStreet'), '{de00de32-547e-4981-ad4b-542f2e9007d8}/100': 'PKEY_PropGroup_Camera', '{de35258c-c695-4cbc-b982-38b0ad24ced0}/2': 'PKEY_Shell_OmitFromView', '{de41cc29-6971-4290-b472-f59f2e2f31e2}/100': 'PKEY_Media_DateReleased', '{de5ef3c7-46e1-484e-9999-62c5308394c1}/100': ( 'PKEY_Contact_PrimaryAddressPostOfficeBox'), '{de621b8f-e125-43a3-a32d-5665446d632a}/25': ( 'PKEY_Security_EncryptionOwners'), '{dea7c82c-1d89-4a66-9427-a4e3debabcb1}/100': 'PKEY_Journal_Contacts', '{debda43a-37b3-4383-91e7-4498da2995ab}/1': 'PKEY_WNET_Scope', '{debda43a-37b3-4383-91e7-4498da2995ab}/2': 'PKEY_WNET_Type', '{debda43a-37b3-4383-91e7-4498da2995ab}/3': 'PKEY_WNET_DisplayType', '{debda43a-37b3-4383-91e7-4498da2995ab}/4': 'PKEY_WNET_Usage', '{debda43a-37b3-4383-91e7-4498da2995ab}/5': 'PKEY_WNET_LocalName', '{debda43a-37b3-4383-91e7-4498da2995ab}/6': 'PKEY_WNET_RemoteName', '{debda43a-37b3-4383-91e7-4498da2995ab}/7': 'PKEY_WNET_Comment', '{debda43a-37b3-4383-91e7-4498da2995ab}/8': 'PKEY_WNET_Provider', '{deeb2db5-0696-4ce0-94fe-a01f77a45fb5}/102': ( 'PKEY_Music_ArtistSortOverride'), '{df975fd3-250a-4004-858f-34e29a3e37aa}/100': 'PKEY_PropGroup_Contact', '{dfb9a04d-362f-4ca3-b30b-0254b17b5b84}/100': 'PKEY_ParsingBindContext', '{e08805c8-e395-40df-80d2-54f0d6c43154}/100': 'PKEY_Document_DocumentID', '{e1277516-2b5f-4869-89b1-2e585bd38b7a}/100': 'PKEY_Photo_LensModel', '{e13d8975-81c7-4948-ae3f-37cae11e8ff7}/100': ( 'PKEY_Photo_ShutterSpeedDenominator'), '{e1a9a38b-6685-46bd-875e-570dc7ad7320}/100': ( 'PKEY_Photo_ApertureDenominator'), '{e1d4a09e-d758-4cd1-b6ec-34a8b5a73f80}/100': ( 'PKEY_Contact_BusinessAddressPostalCode'), '{e3690a87-0fa8-4a2a-9a9f-fce8827055ac}/100': 'PKEY_PropGroup_Image', '{e3a7d2c1-80fc-4b40-8f34-30ea111bdc2e}/100': 'PKEY_PropGroup_FileSystem', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/10': 'PKEY_IsRead', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/11': 'PKEY_Importance', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/12': 'PKEY_FlagStatus', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/13': 'PKEY_Message_FromAddress', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/14': 'PKEY_Message_FromName', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/15': 'PKEY_Message_Store', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/16': 'PKEY_Message_ToAddress', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/17': 'PKEY_Message_ToName', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/18': 'PKEY_Contact_WebPage', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/19': 'PKEY_Message_DateSent', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/2': 'PKEY_Message_BccAddress', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/20': 'PKEY_Message_DateReceived', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/21': 'PKEY_Message_AttachmentNames', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/3': 'PKEY_Message_BccName', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/4': 'PKEY_Message_CcAddress', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/5': 'PKEY_Message_CcName', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/6': 'PKEY_ItemFolderPathDisplay', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/7': 'PKEY_ItemPathDisplay', '{e3e0584c-b788-4a5a-bb20-7f5a44c9acdd}/9': ( 'PKEY_Communication_AccountName'), '{e4870e26-3cc5-4cd2-ba46-ca0a9a70ed04}/3': 'PKEY_AudioEngine_OEMFormat', '{e4f10a3c-49e6-405d-8288-a23bd4eeaa6c}/100': 'PKEY_FileExtension', '{e53d799d-0f3f-466e-b2ff-74634a3cb7a4}/100': ( 'PKEY_Contact_PrimaryAddressCountry'), '{e55fc3b0-2b60-4220-918e-b21e8bf16016}/100': 'PKEY_Identity_UniqueID', '{e6822fee-8c17-4d62-823c-8e9cfcbd1d5c}/100': ( 'PKEY_Audio_IsVariableBitRate'), '{e6ddcaf7-29c5-4f0a-9a68-d19412ec7090}/100': 'PKEY_Photo_LensManufacturer', '{e7b33238-6584-4170-a5c0-ac25efd9da56}/100': 'PKEY_PropGroup_RecordedTV', '{e7c3fb29-caa7-4f47-8c8b-be59b330d4c5}/2': 'PKEY_Devices_Aep_ContainerId', '{e7c3fb29-caa7-4f47-8c8b-be59b330d4c5}/3': 'PKEY_Devices_Aep_CanPair', '{e8309b6e-084c-49b4-b1fc-90a80331b638}/100': 'PKEY_Photo_PeopleNames', '{e92a2496-223b-4463-a4e3-30eabba79d80}/100': ( 'PKEY_Photo_FNumberDenominator'), '{eaee7f1d-6a33-44d1-9441-5f46def23198}/9': 'PKEY_Device_BIOSVersion', '{ec0b4191-ab0b-4c66-90b6-c6637cdebbab}/100': ( 'PKEY_Communication_PolicyTag'), '{ecf4b6f6-d5a6-433c-bb92-4076650fc890}/100': ( 'PKEY_GPS_DestLatitudeNumerator'), '{ecf7f4c9-544f-4d6d-9d98-8ad79adaf453}/100': 'PKEY_GPS_SpeedRef', '{ed4df2d3-8695-450b-856f-f5c1c53acb66}/100': 'PKEY_GPS_DestDistanceRef', '{ee3d3d8a-5381-4cfa-b13b-aaf66b5f4ec9}/100': 'PKEY_Photo_WhiteBalance', '{eec7b761-6f94-41b1-949f-c729720dd13c}/12': ( 'PKEY_DeviceInterface_PrinterPortName'), '{ef1167eb-cbfc-4341-a568-a7c91a68982c}/2': ( 'PKEY_Devices_WiFi_InterfaceGuid'), '{ef884c5b-2bfe-41bb-aae5-76eedf4f9902}/100': 'PKEY_IsShared', '{ef884c5b-2bfe-41bb-aae5-76eedf4f9902}/200': 'PKEY_SharedWith', '{ef884c5b-2bfe-41bb-aae5-76eedf4f9902}/300': 'PKEY_SharingStatus', '{f04bef95-c585-4197-a2b7-df46fdc9ee6d}/100': 'PKEY_KindText', '{f0f7984d-222e-4ad2-82ab-1dd8ea40e57e}/300': 'PKEY_TitleSortOverride', '{f1176dfe-7138-4640-8b4c-ae375dc70a6d}/100': ( 'PKEY_Contact_PrimaryAddressState'), '{f18dedf3-337f-42c0-9e03-cee08708a8c3}/100': ( 'PKEY_Identity_LogonStatusString'), '{f19f064d-082c-4e27-bc73-6882a1bb8e4c}/0': 'PKEY_AudioEngine_DeviceFormat', '{f1a24aa7-9ca7-40f6-89ec-97def9ffe8db}/100': 'PKEY_Contact_FileAsName', '{f1fdb4af-f78c-466c-bb05-56e92db0b8ec}/103': ( 'PKEY_Music_AlbumArtistSortOverride'), '{f21d9941-81f0-471a-adee-4e74b49217ed}/100': 'PKEY_ProviderItemID', '{f2275480-f782-4291-bd94-f13693513aec}/0': 'PKEY_PropList_XPDetailsPanel', '{f23f425c-71a1-4fa8-922f-678ea4a60408}/100': 'PKEY_IsAttachment', '{f271c659-7e5e-471f-ba25-7f77b286f836}/100': ( 'PKEY_Contact_BusinessEmailAddresses'), '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/10': ( 'PKEY_Document_TotalEditingTime'), '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/11': 'PKEY_Document_DatePrinted', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/12': 'PKEY_Document_DateCreated', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/13': 'PKEY_Document_DateSaved', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/14': 'PKEY_Document_PageCount', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/15': 'PKEY_Document_WordCount', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/16': 'PKEY_Document_CharacterCount', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/17': 'PKEY_Thumbnail', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/18': 'PKEY_ApplicationName', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/19': 'PKEY_Document_Security', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/2': 'PKEY_Title', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/24': 'PKEY_HighKeywords', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/25': 'PKEY_LowKeywords', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/26': 'PKEY_MediumKeywords', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/27': 'PKEY_ThumbnailStream', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/3': 'PKEY_Subject', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/4': 'PKEY_Author', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/5': 'PKEY_Keywords', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/6': 'PKEY_Comment', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/7': 'PKEY_Document_Template', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/8': 'PKEY_Document_LastAuthor', '{f29f85e0-4ff9-1068-ab91-08002b27b3d9}/9': 'PKEY_Document_RevisionNumber', '{f334115e-da1b-4509-9b3d-119504dc7abb}/100': 'PKEY_Document_Contributor', '{f3713ada-90e3-4e11-aae5-fdc17685b9be}/100': 'PKEY_PropGroup_GPS', '{f3d8f40d-50cb-44a2-9718-40cb9119495d}/100': 'PKEY_Contact_Initials', '{f6272d18-cecc-40b1-b26a-3911717aa7bd}/100': 'PKEY_Calendar_Location', '{f628fd8c-7ba8-465a-a65b-c5aa79263a9e}/100': 'PKEY_Photo_MeteringModeText', '{f7db74b4-4287-4103-afba-f1b13dcd75cf}/100': 'PKEY_ItemDate', '{f85bf840-a925-4bc2-b0c4-8e36b598679e}/100': 'PKEY_Photo_DigitalZoom', '{f8d3f6ac-4874-42cb-be59-ab454b30716a}/100': 'PKEY_Sensitivity', '{f8fa7fa3-d12b-4785-8a4e-691a94f7a3e7}/100': 'PKEY_Contact_EmailAddress', '{fa303353-b659-4052-85e9-bcac79549b84}/100': 'PKEY_Photo_MakerNote', '{fa304789-00c7-4d80-904a-1e4dcc7265aa}/100': 'PKEY_Photo_GainControl', '{fb1de864-e06d-47f4-82a6-8a0aef44493c}/2': ( 'PKEY_Devices_AudioDevice_SpeechProcessingSupported'), '{fb3842cd-9e2a-4f83-8fcc-4b0761139ae9}/2': ( 'PKEY_DeviceInterface_Proximity_SupportsNfc'), '{fb8d2d7b-90d1-4e34-bf60-6eac09922bbf}/2': 'PKEY_Winx_Hash', '{fc6976db-8349-4970-ae97-b3c5316a08f0}/100': 'PKEY_Photo_Sharpness', '{fc9f7306-ff8f-4d49-9fb6-3ffe5c0951ec}/100': 'PKEY_Contact_Department', '{fcad3d3d-0858-400f-aaa3-2f66cce2a6bc}/100': ( 'PKEY_Photo_FlashEnergyNumerator'), '{fcc16823-baed-4f24-9b32-a0982117f7fa}/100': ( 'PKEY_Identity_PrimaryEmailAddress'), '{fceff153-e839-4cf3-a9e7-ea22832094b8}/100': ( 'PKEY_FileOfflineAvailabilityStatus'), '{fceff153-e839-4cf3-a9e7-ea22832094b8}/101': 'PKEY_FolderKind', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/103': 'PKEY_SyncTransferStatus', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/104': 'PKEY_TransferPosition', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/105': 'PKEY_TransferSize', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/106': 'PKEY_TransferOrder', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/107': 'PKEY_LastSyncError', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/108': 'PKEY_StorageProviderId', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/109': 'PKEY_StorageProviderError', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/110': 'PKEY_StorageProviderStatus', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/111': ( 'PKEY_StorageProviderShareStatuses'), '{fceff153-e839-4cf3-a9e7-ea22832094b8}/112': ( 'PKEY_StorageProviderFileRemoteUri'), '{fceff153-e839-4cf3-a9e7-ea22832094b8}/113': ( 'PKEY_CachedFileUpdaterContentIdForStream'), '{fceff153-e839-4cf3-a9e7-ea22832094b8}/114': ( 'PKEY_CachedFileUpdaterContentIdForConflictResolution'), '{fceff153-e839-4cf3-a9e7-ea22832094b8}/115': 'PKEY_RemoteConflictingFile', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/117': ( 'PKEY_StorageProviderSharingStatus'), '{fceff153-e839-4cf3-a9e7-ea22832094b8}/128': 'PKEY_LastSyncWarning', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/131': 'PKEY_ContentUri', '{fceff153-e839-4cf3-a9e7-ea22832094b8}/132': 'PKEY_ContentId', '{fd122953-fa93-4ef7-92c3-04c946b2f7c8}/100': 'PKEY_Music_DisplayArtist', '{fdf84370-031a-4add-9e91-0d775f1c6605}/100': 'PKEY_MileageInformation', '{fe83bb35-4d1a-42e2-916b-06f3e1af719e}/100': 'PKEY_Photo_FlashModel', '{fec690b7-5f30-4646-ae47-4caafba884a3}/100': ( 'PKEY_Photo_ExposureProgramText'), '{ff1167eb-cbfc-4341-a568-a7c91a68982c}/2': ( 'PKEY_Devices_Wwan_InterfaceGuid'), '{ff962609-b7d6-4999-862d-95180d529aea}/100': ( 'PKEY_Contact_OtherAddressStreet'), '{ffae9db7-1c8d-43ff-818c-84403aa3732d}/100': ( 'PKEY_SourcePackageFamilyName')} ================================================ FILE: winregrc/shellfolders.py ================================================ """Windows Shell folder collector.""" from winregrc import interface class WindowsShellFolder: """Windows Shell folder. Attributes: alternate_names (list[str]): alternate names. class_name (str): class name (CLSID). identifier (str): identifier (GUID). name (str): name. localized_string (str): localized string of the name. """ def __init__(self, identifier=None, localized_string=None): """Initializes a Windows Shell folder. Args: identifier (Optional[str]): identifier (GUID). localized_string (Optional[str]): localized string of the name. """ super().__init__() self.alternate_names = [] self.class_name = None self.identifier = identifier self.localized_string = localized_string self.name = None class ShellFoldersCollector(interface.WindowsRegistryKeyCollector): """Windows Shell folder collector.""" _CLASS_IDENTIFIERS_KEY_PATH = 'HKEY_LOCAL_MACHINE\\Software\\Classes\\CLSID' def __init__(self, debug=False): """Initializes a Windows Registry key and value collector. Args: debug (Optional[bool]): True if debug information should be printed. """ super().__init__(debug=debug) self._ascii_codepage = 'cp1252' def _CollectShellFolders(self, class_identifiers_key): """Collects Windows Shell folders. Args: class_identifiers_key (dfwinreg.WinRegistry): CLSID Windows Registry. Yields: ShellFolder: a Windows Shell folder. """ for class_identifier_key in class_identifiers_key.GetSubkeys(): shell_folder_identifier = class_identifier_key.name.lower() shell_folder_key = class_identifier_key.GetSubkeyByName('ShellFolder') if shell_folder_key: name = self._GetShellFolderName(class_identifier_key) value = class_identifier_key.GetValueByName('LocalizedString') if value: # The value data type does not have to be a string therefore try to # decode the data as an UTF-16 little-endian string and strip # the trailing end-of-string character localized_string = value.data.decode('utf-16-le').rstrip('\x00') else: localized_string = None shell_folder = WindowsShellFolder( identifier=shell_folder_identifier, localized_string=localized_string) if name and name.startswith('CLSID_'): shell_folder.class_name = name else: shell_folder.name = name yield shell_folder def _GetShellFolderName(self, class_identifier_key): """Retrieves the shell folder name. Args: class_identifier_key (dfwinreg.RegistryKey): class identifier Windows Registry key. Returns: str: shell folder name or None if not available. """ value = class_identifier_key.GetValueByName('') if not value or not value.data: return None # First try to decode the value data as an UTF-16 little-endian string with # end-of-string character try: return value.data.decode('utf-16-le').rstrip('\x00') except UnicodeDecodeError: pass # Next try to decode the value data as an ASCII string with a specific # codepage and end-of-string character. try: return value.data.decode(self._ascii_codepage).rstrip('\x00') except UnicodeDecodeError: pass return None def Collect(self, registry): """Collects Windows Shell folders. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: WindowsShellFolder: a Windows Shell folder. """ # TODO: Add support for per-user shell folders class_identifiers_key = registry.GetKeyByPath( self._CLASS_IDENTIFIERS_KEY_PATH) if class_identifiers_key: yield from self._CollectShellFolders(class_identifiers_key) ================================================ FILE: winregrc/srum_extensions.py ================================================ """System Resource Usage Monitor (SRUM) extension collector.""" from winregrc import interface class SRUMExtension: """System Resource Usage Monitor (SRUM) extension. Attributes: dll_name (str): DLL name. guid (str): identifier. """ def __init__(self, guid, dll_name): """Initializes a System Resource Usage Monitor (SRUM) extension. Args: guid (str): identifier. dll_name (str): DLL name. """ super().__init__() self.guid = guid self.dll_name = dll_name class SRUMExtensionsCollector(interface.WindowsRegistryKeyCollector): """Windows System Resource Usage Monitor (SRUM) extension collector.""" _SRUM_EXTENSIONS_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\' 'SRUM\\Extensions') def Collect(self, registry, output_writer): """Collects the SRUM extensions. Args: registry (dfwinreg.WinRegistry): Windows Registry. output_writer (OutputWriter): output writer. Returns: bool: True if the SRUM extensions key was found, False if not. """ srum_extensions_key = registry.GetKeyByPath(self._SRUM_EXTENSIONS_KEY_PATH) if not srum_extensions_key: return False for subkey in srum_extensions_key.GetSubkeys(): guid = subkey.name.upper() dll_name = self._GetValueFromKey(subkey, 'DllName') srum_extension = SRUMExtension(guid, dll_name) output_writer.WriteSRUMExtension(srum_extension) return True ================================================ FILE: winregrc/sysinfo.py ================================================ """System information collector.""" from dfdatetime import posix_time as dfdatetime_posix_time from dfdatetime import semantic_time as dfdatetime_semantic_time from winregrc import interface class SystemInformation: """System information. Attributes: csd_version (str): CSD version. current_build_number (str): current build number. current_type (str): current type. current_version (str): current version. installation_date (dfdatetime.DateTimeValues): installation date and time. path_name (str): path name. product_identifier (str): product identifier. product_name (str): product name. registered_organization (str): registered organization. registered_owner (str): registered owner. system_root (str): system root path. """ def __init__(self): """Initializes system information.""" super().__init__() self.csd_version = None self.current_build_number = None self.current_type = None self.current_version = None self.installation_date = None self.path_name = None self.product_identifier = None self.product_name = None self.registered_organization = None self.registered_owner = None self.system_root = None class SystemInfoCollector(interface.WindowsRegistryKeyCollector): """System information collector. Attributes: system_information (SystemInformation): system information. """ _CURRENT_VERSION_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion') _STRING_VALUES = { 'CSDVersion': 'csd_version', 'CurrentBuildNumber': 'current_build_number', 'CurrentType': 'current_type', 'CurrentVersion': 'current_version', 'PathName': 'path_name', 'ProductId': 'product_identifier', 'ProductName': 'product_name', 'RegisteredOrganization': 'registered_organization', 'RegisteredOwner': 'registered_owner', 'SystemRoot': 'system_root'} def __init__(self, debug=False, output_writer=None): """Initializes a system information collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._output_writer = output_writer self.system_information = None def _ParseInstallDate(self, registry_value): """Parses the InstallDate value. Args: registry_value (dfwinreg.WinRegistryValue): Windows Registry value. Returns: dfdatetime.PosixTime: installation date and time or None if not available. """ if not registry_value: return None timestamp = registry_value.GetDataAsObject() if not timestamp: return dfdatetime_semantic_time.SemanticTime(string='Not set') return dfdatetime_posix_time.PosixTime(timestamp=timestamp) def Collect(self, registry): # pylint: disable=arguments-differ """Collects system information. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the system information key was found, False if not. """ current_version_key = registry.GetKeyByPath( self._CURRENT_VERSION_KEY_PATH) if not current_version_key: return False self.system_information = SystemInformation() for value_name, attribute_name in self._STRING_VALUES.items(): value_string = self._GetValueFromKey(current_version_key, value_name) setattr(self.system_information, attribute_name, value_string) registry_value = current_version_key.GetValueByName('InstallDate') self.system_information.installation_date = self._ParseInstallDate( registry_value) return True ================================================ FILE: winregrc/syskey.py ================================================ """System key (syskey) collector.""" import codecs from winregrc import interface class SystemKey: """System key. Attributes: boot_key (bytes): boot key. """ def __init__(self): """Initializes a system key.""" super().__init__() self.boot_key = None class SystemKeyCollector(interface.WindowsRegistryKeyCollector): """System key collector. Attributes: system_key (SystemKey): system key. """ _LSA_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Lsa') def __init__(self, debug=False, output_writer=None): """Initializes a system key collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._output_writer = output_writer self.system_key = None def _GetBootKey(self, registry): """Retrieves the boot key. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bytes: boot key or None if not found. """ try: lsa_key = registry.GetKeyByPath(self._LSA_KEY_PATH) except RuntimeError: lsa_key = None if not lsa_key: return None lsa_jd_key = lsa_key.GetSubkeyByName('JD') lsa_skew1_key = lsa_key.GetSubkeyByName('Skew1') lsa_gbg_key = lsa_key.GetSubkeyByName('GBG') lsa_data_key = lsa_key.GetSubkeyByName('Data') if None in (lsa_jd_key, lsa_skew1_key, lsa_gbg_key, lsa_data_key): return None lsa_jd_class_name = lsa_jd_key.class_name lsa_skew1_class_name = lsa_skew1_key.class_name lsa_gbg_class_name = lsa_gbg_key.class_name lsa_data_class_name = lsa_data_key.class_name if None in ( lsa_jd_class_name, lsa_skew1_class_name, lsa_gbg_class_name, lsa_data_class_name): return None class_name_string = ''.join([ lsa_jd_class_name, lsa_skew1_class_name, lsa_gbg_class_name, lsa_data_class_name]) scrambled_key = codecs.decode(class_name_string, 'hex') key = bytearray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) for index, scrambled_index in enumerate([ 8, 5, 4, 2, 11, 9, 13, 3, 0, 6, 1, 12, 14, 10, 15, 7]): key[index] = scrambled_key[scrambled_index] return bytes(key) def Collect(self, registry): # pylint: disable=arguments-differ """Collects system information. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the system key was found, False if not. """ boot_key = self._GetBootKey(registry) if not boot_key: return False self.system_key = SystemKey() self.system_key.boot_key = boot_key return True ================================================ FILE: winregrc/task_cache.py ================================================ """Task Cache collector.""" import logging from dfdatetime import filetime as dfdatetime_filetime from dfdatetime import semantic_time as dfdatetime_semantic_time from dtfabric import errors as dtfabric_errors from winregrc import data_format from winregrc import errors from winregrc import interface class CachedTask: """Cached task. Attributes: identifier (str): identifier. last_registered_time (dfdatetime.DateTimeValues): last registered date and time. launch_time (dfdatetime.DateTimeValues): launch date and time. name (str): name. """ def __init__(self): """Initializes a cached task.""" super().__init__() self.identifier = None self.last_registered_time = None self.launch_time = None self.name = None class TaskCacheDataParser(data_format.BinaryDataFormat): """Task Cache data parser.""" _DEFINITION_FILE = 'task_cache.yaml' def __init__(self, debug=False, output_writer=None): """Initializes a Task Cache data parser. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__() self._debug = debug self._output_writer = output_writer def _ParseFiletime(self, filetime): """Parses a FILETIME timestamp value. Args: filetime (int): a FILETIME timestamp value. Returns: dfdatetime.DateTimeValues: date and time values. """ if filetime == 0: return dfdatetime_semantic_time.SemanticTime(string='Not set') if filetime == 0x7fffffffffffffff: return dfdatetime_semantic_time.SemanticTime(string='Never') return dfdatetime_filetime.Filetime(timestamp=filetime) def ParseDynamicInfo(self, value_data, cached_task): """Parses the DynamicInfo value data. Args: value_data (bytes): DynamicInfo value data. cached_task (CachedTask): cached task. Raises: ParseError: if the value data could not be parsed. """ if self._debug: self._output_writer.WriteDebugData('DynamicInfo value data:', value_data) value_data_size = len(value_data) if value_data_size == 28: data_type_map = self._GetDataTypeMap('dynamic_info_record') elif value_data_size == 36: data_type_map = self._GetDataTypeMap('dynamic_info2_record') else: data_type_map = None if not data_type_map: raise errors.ParseError( f'Unsupported value data size: {value_data_size:d}.') try: dynamic_info = data_type_map.MapByteStream(value_data) except ( dtfabric_errors.ByteStreamTooSmallError, dtfabric_errors.MappingError) as exception: raise errors.ParseError(exception) cached_task.last_registered_time = self._ParseFiletime( dynamic_info.last_registered_time) cached_task.launch_time = self._ParseFiletime( dynamic_info.launch_time) if self._debug: self._output_writer.WriteValue( 'Unknown1', f'0x{dynamic_info.unknown1:08x}') # Note this is likely either the last registered time or # the update time. self._DebugPrintFiletimeValue( 'Last registered time', dynamic_info.last_registered_time) # Note this is likely the launch time. self._DebugPrintFiletimeValue('Launch time', dynamic_info.launch_time) self._output_writer.WriteValue( 'Unknown2', f'0x{dynamic_info.unknown2:08x}') self._output_writer.WriteValue( 'Unknown3', f'0x{dynamic_info.unknown3:08x}') if dynamic_info.unknown_time is not None: self._DebugPrintFiletimeValue('Unknown time', dynamic_info.unknown_time) self._output_writer.WriteText('') class TaskCacheCollector(interface.WindowsRegistryKeyCollector): """Task Cache collector. Attributes: cached_tasks (list[CachedTask]): cached tasks. """ _TASK_CACHE_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\' 'Schedule\\TaskCache') def __init__(self, debug=False, output_writer=None): """Initializes a Task Cache collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._parser = TaskCacheDataParser(debug=debug, output_writer=output_writer) self._output_writer = output_writer self.cached_tasks = [] def _GetIdValue(self, registry_key): """Retrieves the Id value from Task Cache Tree key. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. Yields: tuple[dfwinreg.WinRegistryKey, dfwinreg.WinRegistryValue]: Windows Registry key and value. """ id_value = registry_key.GetValueByName('Id') if id_value: yield registry_key, id_value for subkey in registry_key.GetSubkeys(): for value_key, id_value in self._GetIdValue(subkey): yield value_key, id_value def Collect(self, registry): # pylint: disable=arguments-differ """Collects the Task Cache. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the Task Cache key was found, False if not. """ dynamic_info_size_error_reported = False task_cache_key = registry.GetKeyByPath(self._TASK_CACHE_KEY_PATH) if not task_cache_key: return False tasks_key = task_cache_key.GetSubkeyByName('Tasks') tree_key = task_cache_key.GetSubkeyByName('Tree') if not tasks_key or not tree_key: return False task_guids = {} for subkey in tree_key.GetSubkeys(): for value_key, id_value in self._GetIdValue(subkey): # TODO: improve this check to a regex. # The GUID is in the form {%GUID%} and stored an UTF-16 little-endian # string and should be 78 bytes in size. id_value_data_size = len(id_value.data) if id_value_data_size != 78: logging.error('Unsupported Id value data size: {0:s}.') continue guid_string = id_value.GetDataAsObject() task_guids[guid_string] = value_key.name for subkey in tasks_key.GetSubkeys(): dynamic_info_value = subkey.GetValueByName('DynamicInfo') if not dynamic_info_value: continue cached_task = CachedTask() cached_task.identifier = subkey.name cached_task.name = task_guids.get(subkey.name, subkey.name) if self._debug: if (task_cache_key.last_written_time and task_cache_key.last_written_time.timestamp): self._output_writer.WriteFiletimeValue( 'Last written time', task_cache_key.last_written_time.timestamp) self._output_writer.WriteValue('Task', cached_task.name) self._output_writer.WriteValue('Identifier', cached_task.identifier) self._output_writer.WriteText('') try: self._parser.ParseDynamicInfo(dynamic_info_value.data, cached_task) except errors.ParseError as exception: if not dynamic_info_size_error_reported: logging.error(exception) dynamic_info_size_error_reported = True continue self.cached_tasks.append(cached_task) return True ================================================ FILE: winregrc/task_cache.yaml ================================================ # dtFabric format specification. --- name: task_cache type: format description: Task Scheduler Cache format --- name: uint32 type: integer attributes: format: unsigned size: 4 units: bytes --- name: uint64 type: integer attributes: format: unsigned size: 8 units: bytes --- name: dynamic_info_record type: structure attributes: byte_order: little-endian members: - name: unknown1 data_type: uint32 - name: last_registered_time data_type: uint64 - name: launch_time data_type: uint64 - name: unknown2 data_type: uint32 - name: unknown3 data_type: uint32 --- name: dynamic_info2_record type: structure attributes: byte_order: little-endian members: - name: unknown1 data_type: uint32 - name: last_registered_time data_type: uint64 - name: launch_time data_type: uint64 - name: unknown2 data_type: uint32 - name: unknown3 data_type: uint32 - name: unknown_time data_type: uint64 ================================================ FILE: winregrc/time_zone_information.yaml ================================================ # dtFabric format specification. --- name: time_zone_information type: format description: Time Zone Information (TZI) format --- name: uint16 type: integer attributes: format: unsigned size: 2 units: bytes --- name: int32 type: integer attributes: format: signed size: 4 units: bytes --- name: system_time type: structure members: - name: year data_type: uint16 - name: month data_type: uint16 - name: weekday data_type: uint16 - name: day_of_month data_type: uint16 - name: hours data_type: uint16 - name: minutes data_type: uint16 - name: seconds data_type: uint16 - name: milliseconds data_type: uint16 --- name: tzi_record type: structure description: Time Zone Information (TZI) aliases: ['TIME_ZONE_INFORMATION', '_REG_TZI_FORMAT'] attributes: byte_order: little-endian members: - name: bias aliases: ['Bias'] data_type: int32 - name: standard_bias aliases: ['StandardBias'] data_type: int32 - name: daylight_bias aliases: ['DaylightBias'] data_type: int32 - name: standard_date aliases: ['StandardDate'] data_type: system_time - name: daylight_date aliases: ['DaylightDate'] data_type: system_time ================================================ FILE: winregrc/time_zones.py ================================================ """Windows time zones collector.""" from winregrc import data_format from winregrc import errors from winregrc import interface class TimeZone: """Time zone. Attributes: localized_name (str): localized name. name (str): name. offset (int): time zone offset in number of minutes from UTC. """ def __init__(self, name): """Initializes a time zone. Args: name (str): name. """ super().__init__() self.localized_name = None self.name = name self.offset = 0 class TimeZoneInformationDataParser(data_format.BinaryDataFormat): """Time Zone Information (TZI) data parser.""" _DEBUG_INFO_TZI_RECORD = [ ('bias', 'Bias', '_FormatIntegerAsDecimal'), ('standard_bias', 'Standard bias', '_FormatIntegerAsDecimal'), ('daylight_bias', 'Daylight bias', '_FormatIntegerAsDecimal'), ('standard_date', 'Standard date', '_FormatSystemTime'), ('daylight_date', 'Daylight date', '_FormatSystemTime')] _DEFINITION_FILE = 'time_zone_information.yaml' _MONTHS = [ '', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] _OCCURANCE = ['', '1st', '2nd', '3rd', '4th', 'last'] _WEEKDAYS = [ 'Sunday', 'Monday', 'Tuesday', 'Wednessday', 'Thursday', 'Friday', 'Saturday'] def _FormatSystemTime(self, systemtime): """Formats a SYSTEMTIME structure. Args: systemtime (system_time): SYSTEMTIME structure. Returns: str: formatted SYSTEMTIME structure. """ if systemtime.month and systemtime.day_of_month: occurance = self._OCCURANCE[systemtime.day_of_month] weekday = self._WEEKDAYS[systemtime.weekday] month = self._MONTHS[systemtime.month] if not systemtime.year: return (f'{occurance:s} {weekday:s} of {month:s} at ' f'{systemtime.hours:02d}:{systemtime.minutes:02d}') return (f'{occurance:s} {weekday:s} of {month:s} in {systemtime.year:s} ' f'at {systemtime.hours:02d}:{systemtime.minutes:02d}') return 'Not set' def ParseTZIValue(self, value_data, time_zone): """Parses the TZI value data. Args: value_data (bytes): TZI value data. time_zone (TimeZone): time zone. Raises: ParseError: if the value data could not be parsed. """ data_type_map = self._GetDataTypeMap('tzi_record') try: tzi_record = self._ReadStructureFromByteStream( value_data, 0, data_type_map, 'TZI record') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse TZI record value with error: {exception!s}') if self._debug: self._DebugPrintStructureObject(tzi_record, self._DEBUG_INFO_TZI_RECORD) if tzi_record.standard_bias: time_zone.offset = tzi_record.standard_bias else: time_zone.offset = tzi_record.bias class TimeZonesCollector(interface.WindowsRegistryKeyCollector): """Windows time zones collector.""" _TIME_ZONES_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\' 'Time Zones') def Collect(self, registry, output_writer): """Collects the time zones. Args: registry (dfwinreg.WinRegistry): Windows Registry. output_writer (OutputWriter): output writer. Returns: bool: True if the time zones key was found, False if not. """ time_zones_key = registry.GetKeyByPath(self._TIME_ZONES_KEY_PATH) if not time_zones_key: return False time_zone_information_parser = TimeZoneInformationDataParser( debug=self._debug, output_writer=output_writer) for subkey in time_zones_key.GetSubkeys(): time_zone = TimeZone(subkey.name) if self._debug and output_writer: output_writer.DebugPrintValue('Name', subkey.name) string = self._GetValueFromKey(subkey, 'Display') if string is not None: output_writer.DebugPrintValue('Display', string) string = self._GetValueFromKey(subkey, 'Dlt') if string is not None: output_writer.DebugPrintValue('Dlt', string) string = self._GetValueFromKey(subkey, 'Std') if string is not None: output_writer.DebugPrintValue('Std', string) string = self._GetValueFromKey(subkey, 'MapID') if string is not None: output_writer.DebugPrintValue('MapID', string) string = self._GetValueFromKey(subkey, 'MUI_Display') if string is not None: output_writer.DebugPrintValue('MUI_Display', string) string = self._GetValueFromKey(subkey, 'MUI_Dlt') if string is not None: output_writer.DebugPrintValue('MUI_Dlt', string) string = self._GetValueFromKey(subkey, 'MUI_Std') if string is not None: output_writer.DebugPrintValue('MUI_Std', string) data = self._GetValueDataFromKey(subkey, 'Index') if data is not None: output_writer.DebugPrintData('Index', data) data = self._GetValueDataFromKey(subkey, 'TZI') if self._debug and output_writer and data is not None: output_writer.DebugPrintData('TZI', data) time_zone_information_parser.ParseTZIValue(data, time_zone) if self._debug and output_writer: output_writer.DebugPrintText('\n') output_writer.WriteTimeZone(time_zone) return True ================================================ FILE: winregrc/type_libraries.py ================================================ """Windows type libraries collector.""" from winregrc import interface class TypeLibrary: """Type library. Attributes: description (str): description. identifier (str): identifier. typelib_filename (str): typelib_filename. version (str): version. """ def __init__(self, identifier, version, description, typelib_filename): """Initializes a type library. Args: identifier (str): identifier. version (str): version. description (str): description. typelib_filename (str): typelib_filename. """ super().__init__() self.description = description self.identifier = identifier self.typelib_filename = typelib_filename self.version = version class TypeLibrariesCollector(interface.WindowsRegistryKeyCollector): """Windows type libraries collector. Attributes: type_libraries (list[TypeLibrary]): type libraries. """ _TYPE_LIBRARIES_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\Software\\Classes\\TypeLib') def __init__(self, debug=False, output_writer=None): """Initializes a Windows type libraries collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._output_writer = output_writer self.type_libraries = [] def Collect(self, registry): # pylint: disable=arguments-differ """Collects the type libraries. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the type libraries key was found, False if not. """ type_libraries_key = registry.GetKeyByPath( self._TYPE_LIBRARIES_KEY_PATH) if not type_libraries_key: return False for type_library_key in type_libraries_key.GetSubkeys(): identifier = type_library_key.name.lower() for subkey in type_library_key.GetSubkeys(): if subkey.name in ('FLAGS', 'HELPDIR'): continue description = self._GetValueFromKey(subkey, '') language_key = None for lcid in ('0', '409'): language_key = subkey.GetSubkeyByName(lcid) if language_key: break if not language_key: for language_key in subkey.GetSubkeys(): if language_key.name not in ('FLAGS', 'HELPDIR'): break platform_key = None if language_key: for platform in ('win32', ): platform_key = language_key.GetSubkeyByName(platform) if platform_key: break if not platform_key: platform_key = language_key.GetSubkeyByIndex(0) typelib_filename = self._GetValueFromKey(platform_key, '') type_library = TypeLibrary( identifier, subkey.name, description, typelib_filename) self.type_libraries.append(type_library) return True ================================================ FILE: winregrc/usbstor.py ================================================ """Windows USB storage device collector.""" from dfdatetime import filetime as dfdatetime_filetime from dfdatetime import semantic_time as dfdatetime_semantic_time from winregrc import data_format from winregrc import errors class USBStorageDeviceProperty: """USB storage device property. Attributes: identifier (str): identifier of the property. property_set (str): identifier of the property set. value (object): property value. value_type (int): property value type. """ def __init__(self, property_set, identifier): """Initializes an USB storage device property. Args: property_set (str): identifier of the property set. identifier (str): identifier of the property. """ super().__init__() self.identifier = identifier self.property_set = property_set self.value = None self.value_type = None class USBStorageDevice: """USB storage device. Attributes: device_type (str): type of USB device. display_name (str): display name of the USB device. key_path (str): Windows Registry key path. product (str): product of the USB device. properties (list[USBStorageDeviceProperty]): properties. revision (str): revision number of the USB device. vendor (str): vendor of the USB device. """ def __init__(self): """Initializes an USB storage device.""" super().__init__() self.device_type = None self.display_name = None self.key_path = None self.product = None self.properties = [] self.revision = None self.vendor = None class USBStorageDeviceCollector(data_format.BinaryDataFormat): """Windows USB storage device collector.""" _DEFINITION_FILE = 'usbstor.yaml' _USBSTOR_KEY_PATH = ( 'HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Enum\\USBSTOR') def _CollectUSBStorageDevices(self, usbstor_key): """Collects USB storage devices. Args: usbstor_key (dfwinreg.WinRegistryKey): USB storage Windows Registry key. Yields: USBStorageDevice: an USB storage device. """ for device_key in usbstor_key.GetSubkeys(): yield self._ParseDeviceKey(device_key) def _GetPropertyValueData(self, property_value_key, value_type): """Retrieves a property value data. Args: property_value_key (dfwinreg.WinRegistryKey): property value Windows Registry key. value_type (int): value type. Returns: object: property value data. Raises: ParseError: if the property value data cannot be determined. """ binary_data = self._GetValueDataFromKey(property_value_key, 'Data') if value_type == 0x00000007: data_type_map = self._GetDataTypeMap('uint32le') elif value_type == 0x00000010: data_type_map = self._GetDataTypeMap('uint64le') elif value_type == 0x00000012: data_type_map = self._GetDataTypeMap('utf16le_string') else: raise errors.ParseError(f'Unsupported value type: 0x{value_type:08x}') try: value_data = self._ReadStructureFromByteStream( binary_data, 0, data_type_map, 'data') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse value: Data with error: {exception!s}') if value_type == 0x00000010: value_data = self._ParseFiletime(value_data) return value_data def _GetPropertyValueType(self, property_value_key): """Retrieves a property value type. Args: property_value_key (dfwinreg.WinRegistryKey): property value Windows Registry key. Returns: int: property value type. Raises: ParseError: if the property value type cannot be determined. """ binary_data = self._GetValueDataFromKey(property_value_key, 'Type') data_type_map = self._GetDataTypeMap('uint32le') try: return self._ReadStructureFromByteStream( binary_data, 0, data_type_map, 'type') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse value: Type with error: {exception!s}') def _GetStringValueFromKey( self, registry_key, value_name, default_value=None): """Retrieves a string value from a Registry value. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. value_name (str): name of the value. default_value (Optional[str]): default value. Returns: str: value or the default value if not available. """ if not registry_key: return default_value registry_value = registry_key.GetValueByName(value_name) if not registry_value: return default_value if not registry_value.DataIsString(): return default_value return registry_value.GetDataAsObject() def _GetValueDataFromKey(self, registry_key, value_name): """Retrieves the value data from a Registry value. Args: registry_key (dfwinreg.WinRegistryKey): Windows Registry key. value_name (str): name of the value. Returns: bytes: value data or None if not available. """ if not registry_key: return None registry_value = registry_key.GetValueByName(value_name) if not registry_value: return None return registry_value.data def _ParseDeviceKey(self, device_key): """Parses an USB storage device key. Args: device_key (dfwinreg.WinRegistryKey): USB storage device Windows Registry key. Returns: USBStorageDevice: an USB storage device. """ name_values = device_key.name.split('&') device_type = None product = None revision = None vendor = None number_of_name_values = len(name_values) if number_of_name_values >= 1: device_type = name_values[0] if number_of_name_values >= 2: vendor = name_values[1] if number_of_name_values >= 3: product = name_values[2] if number_of_name_values >= 4: revision = name_values[3] for device_instance_key in device_key.GetSubkeys(): properties = [] properties_key = device_instance_key.GetSubkeyByName('Properties') if properties_key: for property_set_key in properties_key.GetSubkeys(): for property_key in property_set_key.GetSubkeys(): for property_value_key in property_key.GetSubkeys(): storage_device_property = USBStorageDeviceProperty( property_set_key.name, property_key.name) storage_device_property.value_type = self._GetPropertyValueType( property_value_key) storage_device_property.value = self._GetPropertyValueData( property_value_key, storage_device_property.value_type) properties.append(storage_device_property) storage_device = USBStorageDevice() storage_device.device_type = device_type storage_device.display_name = self._GetStringValueFromKey( device_instance_key, 'FriendlyName') storage_device.key_path = device_instance_key.path storage_device.product = product storage_device.properties = properties storage_device.revision = revision storage_device.vendor = vendor return storage_device def _ParseFiletime(self, filetime): """Parses a FILETIME timestamp value. Args: filetime (int): a FILETIME timestamp value. Returns: dfdatetime.DateTimeValues: date and time values. """ if filetime == 0: return dfdatetime_semantic_time.SemanticTime(string='Not set') if filetime == 0x7fffffffffffffff: return dfdatetime_semantic_time.SemanticTime(string='Never') return dfdatetime_filetime.Filetime(timestamp=filetime) def Collect(self, registry): """Collects USB storage devices. Args: registry (dfwinreg.WinRegistry): Windows Registry. Yields: USBStorageDevice: an USB storage device. """ usbstor_key = registry.GetKeyByPath(self._USBSTOR_KEY_PATH) if usbstor_key: yield from self._CollectUSBStorageDevices(usbstor_key) ================================================ FILE: winregrc/usbstor.yaml ================================================ # dtFabric format specification. --- name: usbstor type: format description: USB storage device formats. --- name: uint32le type: integer attributes: byte_order: little-endian format: unsigned size: 4 units: bytes --- name: uint64le type: integer attributes: byte_order: little-endian format: unsigned size: 8 units: bytes --- name: wchar16 type: character attributes: size: 2 units: bytes --- name: utf16le_string type: string encoding: utf-16-le element_data_type: wchar16 elements_terminator: "\x00\x00" ================================================ FILE: winregrc/userassist.py ================================================ """Windows UserAssist information collector.""" import codecs import logging from winregrc import data_format from winregrc import errors from winregrc import interface class UserAssistEntry: """UserAssist entry. Attributes: guid (str): GUID. name (str): name. value_name (str): name of the Windows Registry value. """ def __init__(self, guid=None, name=None, value_name=None): """Initializes an UserAssist entry. Args: guid (Optional[str]): GUID. name (Optional[str]): name. value_name (Optional[str]): name of the Windows Registry value. """ super().__init__() self.guid = guid self.name = name self.value_name = value_name class UserAssistDataParser(data_format.BinaryDataFormat): """UserAssist data parser.""" _DEFINITION_FILE = 'userassist.yaml' # pylint: disable=missing-type-doc def _DebugPrintEntry(self, format_version, user_assist_entry): """Prints UserAssist entry value debug information. Args: format_version (int): format version. user_assist_entry (user_assist_entry_v3|user_assist_entry_v5): UserAssist entry. """ self._DebugPrintValue('Unknown1', f'0x{user_assist_entry.unknown1:08x}') self._DebugPrintDecimalValue( 'Number of executions', user_assist_entry.number_of_executions) if format_version == 5: self._DebugPrintDecimalValue( 'Application focus count', user_assist_entry.application_focus_count) self._DebugPrintDecimalValue( 'Application focus duration', user_assist_entry.application_focus_duration) self._DebugPrintValue('Unknown2', f'{user_assist_entry.unknown2:.2f}') self._DebugPrintValue('Unknown3', f'{user_assist_entry.unknown3:.2f}') self._DebugPrintValue('Unknown4', f'{user_assist_entry.unknown4:.2f}') self._DebugPrintValue('Unknown5', f'{user_assist_entry.unknown5:.2f}') self._DebugPrintValue('Unknown6', f'{user_assist_entry.unknown6:.2f}') self._DebugPrintValue('Unknown7', f'{user_assist_entry.unknown7:.2f}') self._DebugPrintValue('Unknown8', f'{user_assist_entry.unknown8:.2f}') self._DebugPrintValue('Unknown9', f'{user_assist_entry.unknown9:.2f}') self._DebugPrintValue('Unknown10', f'{user_assist_entry.unknown10:.2f}') self._DebugPrintValue('Unknown11', f'{user_assist_entry.unknown11:.2f}') self._DebugPrintValue('Unknown12', f'0x{user_assist_entry.unknown12:08x}') self._DebugPrintFiletimeValue( 'Last execution time', user_assist_entry.last_execution_time) if format_version == 5: self._DebugPrintValue('Unknown13', '0x{user_assist_entry.unknown13:08x}') self._DebugPrintText('\n') # pylint: disable=missing-return-type-doc def ParseEntry(self, format_version, entry_data): """Parses an UserAssist entry. Args: format_version (int): format version. entry_data (bytes): entry data. Returns: user_assist_entry_v3|user_assist_entry_v5: UserAssist entry. Raises: ParseError: if the value data could not be parsed. """ if format_version == 3: data_type_map = self._GetDataTypeMap('user_assist_entry_v3') expected_entry_data_size = 16 elif format_version == 5: data_type_map = self._GetDataTypeMap('user_assist_entry_v5') expected_entry_data_size = 72 else: data_type_map = None expected_entry_data_size = 0 if expected_entry_data_size != len(entry_data): entry_data_size = len(entry_data) raise errors.ParseError(( f'Version: {format_version:d} size mismatch (calculated: ' f'{expected_entry_data_size:d}, stored: {entry_data_size:d}).')) try: user_assist_entry = self._ReadStructureFromByteStream( entry_data, 0, data_type_map, 'UserAssist entry') except (ValueError, errors.ParseError) as exception: raise errors.ParseError( f'Unable to parse UserAssist entry value with error: {exception!s}') if self._debug: self._DebugPrintEntry(format_version, user_assist_entry) return user_assist_entry class UserAssistCollector(interface.WindowsRegistryKeyCollector): """Windows UserAssist information collector. Returns: user_assist_entries (list[UserAssistEntry]): UserAssist entries. """ _USER_ASSIST_KEY = ( 'HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\' 'Explorer\\UserAssist') def __init__(self, debug=False, output_writer=None): """Initializes a Windows UserAssist information collector. Args: debug (Optional[bool]): True if debug information should be printed. output_writer (Optional[OutputWriter]): output writer. """ super().__init__(debug=debug) self._output_writer = output_writer self._parser = UserAssistDataParser( debug=debug, output_writer=output_writer) self.user_assist_entries = [] def _CollectUserAssistFromKey(self, guid_subkey): """Collects the UserAssist information from a GUID sub key. Args: guid_subkey (dfwinreg.WinRegistryKey): UserAssist GUID Registry key. """ version_value = guid_subkey.GetValueByName('Version') if not version_value: logging.warning(f'Missing Version value in sub key: {guid_subkey.name:s}') return format_version = version_value.GetDataAsObject() if self._debug: self._output_writer.WriteValue('GUID', guid_subkey.name) self._output_writer.WriteIntegerValueAsDecimal( 'Format version', format_version) self._output_writer.WriteText('\n') count_subkey = guid_subkey.GetSubkeyByName('Count') for value in count_subkey.GetValues(): if self._debug: self._output_writer.WriteValue('Original name', value.name) try: # Note that Python 2 codecs.decode() does not support keyword arguments # such as encodings='rot-13'. value_name = codecs.decode(value.name, 'rot-13') except UnicodeEncodeError: characters = [] for character in value.name: if ord(character) < 128: try: character = codecs.decode(character, 'rot-13') characters.append(character) except UnicodeEncodeError: characters.append(character) else: characters.append(character) value_name = ''.join(characters) if self._debug: self._output_writer.WriteValue('Converted name', value_name) self._output_writer.WriteDebugData('Value data:', value.data) if value_name != 'UEME_CTLSESSION': user_assist_entry = self._parser.ParseEntry(format_version, value.data) user_assist_entry = UserAssistEntry( guid=guid_subkey.name, name=value_name, value_name=value.name) self.user_assist_entries.append(user_assist_entry) def Collect(self, registry): # pylint: disable=arguments-differ """Collects the UserAssist information. Args: registry (dfwinreg.WinRegistry): Windows Registry. Returns: bool: True if the UserAssist key was found, False if not. """ user_assist_key = registry.GetKeyByPath(self._USER_ASSIST_KEY) if not user_assist_key: return False for guid_subkey in user_assist_key.GetSubkeys(): self._CollectUserAssistFromKey(guid_subkey) return True ================================================ FILE: winregrc/userassist.yaml ================================================ # dtFabric format specification. --- name: userassist type: format description: UserAssist format --- name: float32 type: floating-point attributes: size: 4 units: bytes --- name: uint32 type: integer attributes: format: unsigned size: 4 units: bytes --- name: uint64 type: integer attributes: format: unsigned size: 8 units: bytes --- name: user_assist_entry_v3 type: structure description: UserAssist format version used in Windows 2000, XP, 2003, Vista. attributes: byte_order: little-endian members: - name: unknown1 data_type: uint32 - name: number_of_executions data_type: uint32 - name: last_execution_time data_type: uint64 --- name: user_assist_entry_v5 type: structure description: UserAssist format version used in Windows 2008, 7, 8, 10. attributes: byte_order: little-endian members: - name: unknown1 data_type: uint32 - name: number_of_executions data_type: uint32 - name: application_focus_count data_type: uint32 - name: application_focus_duration data_type: uint32 - name: unknown2 data_type: float32 - name: unknown3 data_type: float32 - name: unknown4 data_type: float32 - name: unknown5 data_type: float32 - name: unknown6 data_type: float32 - name: unknown7 data_type: float32 - name: unknown8 data_type: float32 - name: unknown9 data_type: float32 - name: unknown10 data_type: float32 - name: unknown11 data_type: float32 - name: unknown12 data_type: uint32 - name: last_execution_time data_type: uint64 - name: unknown13 data_type: uint32 ================================================ FILE: winregrc/versions.py ================================================ """Windows versions.""" class WindowsVersions: """Windows versions.""" _SORT_KEY_PER_VERSION = { # TODO: update the dates of the Windows 10 releases. 'Windows 10 (1511)': 2015, 'Windows 10 (1607)': 2015, 'Windows 10 (1703)': 2015, 'Windows 10 (1709)': 2015, 'Windows 10 (1803)': 2015, 'Windows 10 (1809)': 2015, 'Windows 10 (1903)': 2015, 'Windows 10 (1909)': 2015, 'Windows 10 (2004)': 2015, 'Windows 10 (20H2)': 2015, 'Windows 11 (21H2)': 2021, 'Windows 2000': 2000, 'Windows 2003': 2003, 'Windows 2003 R2': 2005, 'Windows 2008': 2008, 'Windows 2008 R2': 2009, 'Windows 2012': 2012, 'Windows 2012 R2': 2013, 'Windows 2016': 2016, 'Windows 2019': 2019, 'Windows 7': 2009, 'Windows 8.0': 2012, 'Windows 8.1': 2013, 'Windows 95': 1995, 'Windows 98': 1998, 'Windows Me': 2000, 'Windows NT4': 1996, 'Windows Vista': 2007, 'Windows XP 32-bit': 2001, 'Windows XP 64-bit': 2005} @classmethod def KeyFunction(cls, windows_version): """Key function for sorting. Args: windows_version (str): Windows version. Returns: tuple[int, str]: sort key and Windows version """ sort_key = cls._SORT_KEY_PER_VERSION.get(windows_version, 9999) return sort_key, windows_version ================================================ FILE: winregrc/volume_scanner.py ================================================ """Windows Registry volume scanner.""" from dfimagetools import windows_registry from dfvfs.helpers import command_line as dfvfs_command_line from dfvfs.helpers import volume_scanner as dfvfs_volume_scanner from dfvfs.lib import definitions as dfvfs_definitions from dfvfs.lib import errors as dfvfs_errors from dfvfs.resolver import resolver as dfvfs_resolver from dfwinreg import interface as dfwinreg_interface from dfwinreg import registry as dfwinreg_registry class VolumeScannerOptions(dfvfs_volume_scanner.VolumeScannerOptions): """Volume scanner options. Attributes: credentials (list[tuple[str, str]]): credentials, per type, to unlock volumes. partitions (list[str]): partition identifiers. scan_mode (str): mode that defines how the VolumeScanner should scan for volumes and snapshots. snapshots (list[str]): snapshot identifiers. username (str): username. volumes (list[str]): volume identifiers, e.g. those of an APFS or LVM volume system. """ def __init__(self): """Initializes volume scanner options.""" super().__init__() self.username = None class SingleFileWindowsRegistryFileReader( dfwinreg_interface.WinRegistryFileReader): """Single file Windows Registry file reader.""" def __init__(self, path): """Initializes a single file Windows Registry file reader. Args: path (str): path of the Windows Registry file. """ super().__init__() self._path = path def Open(self, path, ascii_codepage='cp1252'): """Opens the Windows Registry file specified by the path. Args: path (str): path of the Windows Registry file. The path is a Windows path relative to the root of the file system that contains the specific Windows Registry file. E.g. C:\\Windows\\System32\\config\\SYSTEM ascii_codepage (Optional[str]): ASCII string codepage. Returns: WinRegistryFile: Windows Registry file or None if the file cannot be opened. """ file_object = open(self._path, 'rb') # pylint: disable=consider-using-with if file_object is None: return None try: signature = file_object.read(4) if signature == b'regf': registry_file = windows_registry.REGFWindowsRegistryFile( ascii_codepage=ascii_codepage) else: registry_file = windows_registry.CREGWindowsRegistryFile( ascii_codepage=ascii_codepage) # Note that registry_file takes over management of file_object. registry_file.Open(file_object) except OSError: file_object.close() return None return registry_file class WindowsRegistryVolumeScanner(dfvfs_volume_scanner.WindowsVolumeScanner): """Windows Registry volume scanner. Attributes: registry (dfwinreg.WinRegistry): Windows Registry. """ def __init__(self, mediator=None): """Initializes a Windows Registry collector. Args: mediator (Optional[dfvfs.VolumeScannerMediator]): a volume scanner mediator. """ super().__init__(mediator=mediator) self._single_file = False self._users_path = False self.registry = None def _GetUsername(self, options): """Determines the username. Args: options (VolumeScannerOptions): volume scanner options. Returns: str: username or None if not available. Raises: ScannerError: if the scanner does not know how to proceed. UserAbort: if the user requested to abort. """ usernames = [] # TODO: handle alternative users path locations self._users_path = '\\Users' users_path_spec = self._path_resolver.ResolvePath(self._users_path) if not users_path_spec: self._users_path = '\\Documents and Settings' users_path_spec = self._path_resolver.ResolvePath(self._users_path) if users_path_spec: users_file_entry = dfvfs_resolver.Resolver.OpenFileEntry( users_path_spec) for sub_file_entry in users_file_entry.sub_file_entries: if sub_file_entry.IsDirectory(): usernames.append(sub_file_entry.name) if not usernames: return None # Handle options without an username. if hasattr(options, 'username'): if options.username == ['none']: return None if options.username: if options.username in usernames: return options.username elif len(usernames) == 1: return usernames[0] if not self._mediator: raise dfvfs_errors.ScannerError( 'Unable to proceed. Found user profile paths but no mediator to ' 'determine which user to select.') try: username = self._mediator.GetUsername(usernames) except KeyboardInterrupt: raise dfvfs_errors.UserAbort('Volume scan aborted.') return username def IsSingleFileRegistry(self): """Determines if the Registry consists of a single file. Returns: bool: True if the Registry consists of a single file. """ return self._single_file def ScanForWindowsVolume(self, source_path, options=None): """Scans for a Windows volume. Args: source_path (str): source path. options (Optional[VolumeScannerOptions]): volume scanner options. If None the default volume scanner options are used, which are defined in the VolumeScannerOptions class. Returns: bool: True if a Windows volume was found. Raises: ScannerError: if the source path does not exists, or if the source path is not a file or directory, or if the format of or within the source file is not supported. """ result = super().ScanForWindowsVolume( source_path, options=options) registry_file_reader = None if self._source_type == dfvfs_definitions.SOURCE_TYPE_FILE: self._single_file = True registry_file_reader = SingleFileWindowsRegistryFileReader(source_path) elif result: username = self._GetUsername(options) if username: self._path_resolver.SetEnvironmentVariable( 'UserProfile', f'{self._users_path:s}\\{username:s}') registry_file_reader = ( windows_registry.StorageMediaImageWindowsRegistryFileReader( self._file_system, self._path_resolver)) if registry_file_reader: self.registry = dfwinreg_registry.WinRegistry( registry_file_reader=registry_file_reader) return bool(registry_file_reader) class WindowsRegistryVolumeScannerMediator( dfvfs_command_line.CLIVolumeScannerMediator): """Windows Registry volume scanner mediator.""" _USER_PROMPT_USERNAMES = ( 'Please specify the username that should be processed. Note that you can ' 'abort with Ctrl^C.') def GetUsername(self, usernames): """Retrieves a username. This method can be used to prompt the user to provide a username. Args: usernames (list[str]): usernames. Returns: str: selected username or None. """ # TODO: use user artifact self._PrintUsernames(usernames) while True: self._output_writer.Write('\n') lines = self._textwrapper.wrap(self._USER_PROMPT_USERNAMES) self._output_writer.Write('\n'.join(lines)) self._output_writer.Write('\n\nUsername: ') try: selected_username = self._input_reader.Read() selected_username = selected_username.strip() if selected_username in usernames: break except ValueError: pass self._output_writer.Write('\n') lines = self._textwrapper.wrap( 'Unsupported username, please try again or abort with Ctrl^C.') self._output_writer.Write('\n'.join(lines)) self._output_writer.Write('\n\n') return selected_username def _PrintUsernames(self, usernames): """Prints an overview of usernames. Args: usernames (list[str]): usernames. Raises: ScannerError: if a username cannot be resolved. """ header = 'The following usernames were found:\n' self._output_writer.Write(header) column_names = ['Username', 'Profile path'] table_view = dfvfs_command_line.CLITabularTableView( column_names=column_names) for username in sorted(usernames, key=lambda username: username.lower()): # TODO: use user artifact table_view.AddRow([username, f'C:\\Users\\{username:s}']) self._output_writer.Write('\n') table_view.Write(self._output_writer)