1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
#
# Copyright (C) 2022 Soleta Networks <info@soleta.eu>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the
# Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
import os
import subprocess
import platform
from enum import Enum
from subprocess import PIPE
from src.utils.fs import find_mountpoint
OSFamily = Enum('OSFamily', ['LINUX', 'WINDOWS', 'UNKNOWN'])
def getlinuxversion(osrelease):
"""
Parses a os-release file to fetch 'PRETTY_NAME' key.
If file or key are not found, then returns generic
'Linux' string.
"""
mountpoint = find_mountpoint(osrelease)
with open(osrelease, 'r') as f:
for line in f:
if line.find('=') == -1:
continue
key, value = line.split('=')
if key == 'PRETTY_NAME':
value = value.replace('\n', '')
value = value.strip('"')
bits = ' 64 bits' if linux_is64bit(mountpoint) else ''
return f'{value}{bits}'
return 'Linux'
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.
"""
# 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
return 'Microsoft Windows'
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.
If init executable is not found, check for /lib64.
If /lib64 is found returns True, otherwise False.
"""
init_path = f'{mountpoint}/sbin/init'
lib64_path = f'{mountpoint}/lib64'
if os.path.exists(init_path):
bits, linkage = platform.architecture(executable=init_path)
return True if bits == '64bit' else False
return os.path.exists(lib64_path)
def cache_probe():
"""
Runs 'blkid -L CACHE' and returns stripped stdout
"""
proc_blkid = subprocess.run(['blkid', '-L', 'CACHE'],
stdout=subprocess.PIPE)
stdout = proc_blkid.stdout.decode().strip()
return stdout
def get_os_family(mountpoint):
winreghives = f'{mountpoint}/Windows/System32/'
osrelease = f'{mountpoint}/etc/os-release'
if os.path.exists(osrelease):
return OSFamily.LINUX
elif os.path.exists(winreghives):
return OSFamily.WINDOWS
else:
return OSFamily.UNKNOWN
def os_probe(mountpoint):
"""
Probes mountpoint for typical OS dependant files.
Windows: Tries finding and querying the software
registry hive.
Linux: Looks for /etc/os-release file.
Returns a string depending on the OS it detects.
"""
winreghives = f'{mountpoint}/Windows/System32/config'
osrelease = f'{mountpoint}/etc/os-release'
if os.path.exists(osrelease):
return getlinuxversion(osrelease)
elif os.path.exists(winreghives):
return getwindowsversion(winreghives)
else:
return ''
|