summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/utils/probe.py65
-rw-r--r--src/utils/sw_inventory.py60
2 files changed, 47 insertions, 78 deletions
diff --git a/src/utils/probe.py b/src/utils/probe.py
index ee9a08e..c8218f2 100644
--- a/src/utils/probe.py
+++ b/src/utils/probe.py
@@ -12,6 +12,7 @@ import platform
import logging
import sys
+from src.utils.winreg import *
from enum import Enum
from subprocess import PIPE
@@ -45,35 +46,23 @@ def getlinuxversion(osrelease):
def getwindowsversion(winreghives):
"""
- Tries to obtain windows version information by
- querying the SOFTWARE registry hive. Registry
- hives path is a required parameter.
-
- Runs hivexget(1) to fetch ProductName and
- ReleaseId. If something fails (hivexget is
- not installed, or registry is not found) it
- returns a generic "Microsoft Windows" string.
+ Try to obtain windows version information by querying the SOFTWARE registry
+ hive to fetch ProductName and ReleaseId.
+ Return a generic "Microsoft Windows" string if something fails.
"""
- # XXX: 3.6 friendly
try:
- proc_prodname = subprocess.run(['hivexget',
- f'{winreghives}/SOFTWARE',
- 'microsoft\windows nt\currentversion',
- 'ProductName'], stdout=PIPE)
- proc_releaseid = subprocess.run(['hivexget',
- f'{winreghives}/SOFTWARE',
- 'microsoft\windows nt\currentversion',
- 'ReleaseId'], stdout=PIPE)
-
- prodname = proc_prodname.stdout.decode().replace('\n', '')
- releaseid = proc_releaseid.stdout.decode().replace('\n', '')
- bits = ' 64 bits' if windows_is64bit(winreghives) else ''
-
- if proc_prodname.returncode == 0 and proc_releaseid.returncode == 0:
- return f'{prodname} {releaseid}{bits}'
- except FileNotFoundError: # hivexget command not found
- pass
+ hivepath = f'{winreghives}/SOFTWARE'
+ hive = hive_handler_open(hivepath, write = False)
+ root_node = hive.root()
+ version_node = get_node_child_from_path(hive, root_node, 'Microsoft/Windows NT/CurrentVersion')
+
+ prodname = get_value_from_node(hive, version_node, 'ProductName')
+ releaseid = get_value_from_node(hive, version_node, 'ReleaseId')
+
+ return f'{prodname} {releaseid}'
+ except (RuntimeError, OgError) as e:
+ logging.error(f'Hivex was not able to operate over {hivepath}. Reported: {e}')
return 'Microsoft Windows'
@@ -81,28 +70,6 @@ def interpreter_is64bit():
return sys.maxsize > 2**32
-def windows_is64bit(winreghives):
- """
- Check for 64 bit Windows by means of retrieving the value of
- ProgramW6432Dir. This key is set if Windows is running 64 bit.
-
- If set returns True.
- If not set or hivexget exits with non-zero, returns False.
- """
- try:
- proc_hivexget = subprocess.run(['hivexget',
- f'{winreghives}/SOFTWARE',
- 'Microsoft\Windows\CurrentVersion',
- 'ProgramW6432Dir'], stdout=PIPE)
- stdout = proc_hivexget.stdout.decode().replace('\n', '')
-
- if proc_hivexget.returncode == 0 and stdout:
- return True
- except FileNotFoundError: # hivexget command not found
- pass
- return False
-
-
def linux_is64bit(mountpoint):
"""
If /sbin/init is detected, check if compiled for 64-bit machine.
@@ -174,7 +141,7 @@ def os_probe(mountpoint):
Returns a string depending on the OS it detects.
"""
- winreghives = f'{mountpoint}/Windows/System32/config'
+ winreghives = f'{mountpoint}{WINDOWS_HIVES_PATH}'
osrelease = f'{mountpoint}/etc/os-release'
if os.path.exists(osrelease):
diff --git a/src/utils/sw_inventory.py b/src/utils/sw_inventory.py
index bcf9f09..ccb70fe 100644
--- a/src/utils/sw_inventory.py
+++ b/src/utils/sw_inventory.py
@@ -16,33 +16,39 @@ from collections import namedtuple
import hivex
from src.utils.probe import os_probe
+from src.utils.winreg import *
Package = namedtuple('Package', ['name', 'version'])
Package.__str__ = lambda pkg: f'{pkg.name} {pkg.version}'
-WINDOWS_HIVES_PATH = '/Windows/System32/config'
-WINDOWS_HIVES_SOFTWARE = f'{WINDOWS_HIVES_PATH}/SOFTWARE'
DPKG_STATUS_PATH = '/var/lib/dpkg/status'
OSRELEASE_PATH = '/etc/os-release'
-def _fill_package_set(h, key, pkg_set):
+def _fill_package_set(hive, key, pkg_set):
"""
Fill the package set looking for entries at the current registry
node childs.
Any valid node child must have "DisplayVersion" or "DisplayName" keys.
"""
- childs = h.node_children(key)
- valid_childs = [h.node_get_child(key, h.node_name(child))
- for child in childs
- for value in h.node_values(child) if h.value_key(value) == 'DisplayVersion']
+ childs = hive.node_children(key)
+ valid_childs = []
+ for child in childs:
+ child_name = hive.node_name(child)
+ values = hive.node_values(child)
+
+ for value in values:
+ if hive.value_key(value) == 'DisplayVersion':
+ valid_child = hive.node_get_child(key, child_name)
+ valid_childs.append(valid_child)
+
for ch in valid_childs:
try:
- name = h.value_string(h.node_get_value(ch, 'DisplayName'))
- value = h.node_get_value(ch, 'DisplayVersion')
- version = h.value_string(value)
+ name = hive.value_string(hive.node_get_value(ch, 'DisplayName'))
+ value = hive.node_get_value(ch, 'DisplayVersion')
+ version = hive.value_string(value)
pkg = Package(name, version)
pkg_set.add(pkg)
except RuntimeError:
@@ -50,22 +56,19 @@ def _fill_package_set(h, key, pkg_set):
pass
-def _fill_package_set_1(h, pkg_set):
+def _fill_package_set_1(hive, pkg_set):
"""
Looks for entries in registry path
/Microsoft/Windows/CurrentVersion/Uninstall
Fills the given set with Package instances for each program found.
"""
- key = h.root()
- key = h.node_get_child(key, 'Microsoft')
- key = h.node_get_child(key, 'Windows')
- key = h.node_get_child(key, 'CurrentVersion')
- key = h.node_get_child(key, 'Uninstall')
- _fill_package_set(h, key, pkg_set)
+ root_node = hive.root()
+ key = get_node_child_from_path(hive, root_node, 'Microsoft/Windows/CurrentVersion/Uninstall')
+ _fill_package_set(hive, key, pkg_set)
-def _fill_package_set_2(h, pkg_set):
+def _fill_package_set_32_bit_compat(hive, pkg_set):
"""
Looks for entries in registry path
/Wow6432Node/Microsoft/Windows/CurrentVersion/Uninstall
@@ -73,23 +76,22 @@ def _fill_package_set_2(h, pkg_set):
Fills the given set with Package instances for each program found.
"""
- key = h.root()
- key = h.node_get_child(key, 'Wow6432Node')
- key = h.node_get_child(key, 'Microsoft')
- key = h.node_get_child(key, 'Windows')
- key = h.node_get_child(key, 'CurrentVersion')
- key = h.node_get_child(key, 'Uninstall')
- _fill_package_set(h, key, pkg_set)
+ root_node = hive.root()
+ key = get_node_child_from_path(hive, root_node, 'Wow6432Node/Windows/CurrentVersion/Uninstall')
+ _fill_package_set(hive, key, pkg_set)
def _get_package_set_windows(hivepath):
packages = set()
try:
- h = hivex.Hivex(hivepath)
+ h = hive_handler_open(hivepath, write = False)
_fill_package_set_1(h, packages)
- _fill_package_set_2(h, packages)
- except RuntimeError as e:
+ except (RuntimeError, OgError) as e:
logging.error(f'Hivex was not able to operate over {hivepath}. Reported: {e}')
+ try:
+ _fill_package_set_32_bit_compat(h, packages)
+ except (RuntimeError, OgError) as e:
+ pass
return packages
@@ -119,7 +121,7 @@ def _get_package_set_dpkg(dpkg_status_path):
def get_package_set(mountpoint):
dpkg_status_path = f'{mountpoint}{DPKG_STATUS_PATH}'
- softwarehive = f'{mountpoint}{WINDOWS_HIVES_SOFTWARE}'
+ softwarehive = f'{mountpoint}{WINDOWS_HIVE_SOFTWARE}'
if os.path.exists(softwarehive):
pkgset = _get_package_set_windows(softwarehive)
elif os.path.exists(dpkg_status_path):