mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-08-22 22:32:22 +02:00
Rework the way verinfo works.
This commit is contained in:
@@ -33,11 +33,11 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
requirements.SymbolRequirement(name = "nt_symbols", description = "Windows OS"), ]
|
||||
|
||||
@classmethod
|
||||
def get_version_entries(cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
pe_table_name: str,
|
||||
layer_name: str,
|
||||
base_address: int) -> typing.Dict[str, typing.Any]:
|
||||
def get_version_information(cls,
|
||||
context: interfaces.context.ContextInterface,
|
||||
pe_table_name: str,
|
||||
layer_name: str,
|
||||
base_address: int) -> typing.Optional[typing.Tuple[int]]:
|
||||
"""Get File and Product version information from PE files
|
||||
|
||||
Args:
|
||||
@@ -46,45 +46,30 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
base_address: base address of the PE (where MZ is found)
|
||||
"""
|
||||
|
||||
if layer_name is None:
|
||||
raise ValueError("Layer must be a string not None")
|
||||
|
||||
pe_data = io.BytesIO()
|
||||
entries = {} # type: typing.Dict[str, typing.Any]
|
||||
|
||||
dos_header = context.object(pe_table_name + constants.BANG +
|
||||
"_IMAGE_DOS_HEADER", offset = base_address,
|
||||
layer_name = layer_name)
|
||||
|
||||
try:
|
||||
for offset, data in dos_header.reconstruct():
|
||||
pe_data.seek(offset)
|
||||
pe_data.write(data)
|
||||
for offset, data in dos_header.reconstruct():
|
||||
pe_data.seek(offset)
|
||||
pe_data.write(data)
|
||||
|
||||
pe = pefile.PE(data = pe_data.getvalue(), fast_load = True)
|
||||
pe.parse_data_directories([pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_RESOURCE"]])
|
||||
pe = pefile.PE(data = pe_data.getvalue(), fast_load = True)
|
||||
pe.parse_data_directories([pefile.DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_RESOURCE"]])
|
||||
|
||||
entries = {}
|
||||
major = pe.VS_FIXEDFILEINFO.ProductVersionMS >> 16
|
||||
minor = pe.VS_FIXEDFILEINFO.ProductVersionMS & 0xFFFF
|
||||
product = pe.VS_FIXEDFILEINFO.ProductVersionLS >> 16
|
||||
build = pe.VS_FIXEDFILEINFO.ProductVersionLS & 0xFFFF
|
||||
|
||||
for finfo in pe.FileInfo:
|
||||
if finfo.name == "StringFileInfo":
|
||||
for table in finfo.StringTable:
|
||||
entries.update(table.entries)
|
||||
pe_data.close()
|
||||
|
||||
except ValueError:
|
||||
vollog.log(constants.LOGLEVEL_VVV,
|
||||
"Error parsing PE at {0:#x} in layer {1}".format(base_address, layer_name))
|
||||
|
||||
except AttributeError:
|
||||
vollog.log(constants.LOGLEVEL_VVV,
|
||||
"Error locating the string resources for PE at {0:#x} in layer {1}".format(base_address,
|
||||
layer_name))
|
||||
|
||||
except exceptions.InvalidAddressException as exp:
|
||||
vollog.log(constants.LOGLEVEL_VVV,
|
||||
"Required data at {0:#x} in layer {1} is unavailable".format(exp.invalid_address, layer_name))
|
||||
|
||||
finally:
|
||||
pe_data.close()
|
||||
|
||||
return entries
|
||||
return (major, minor, product, build)
|
||||
|
||||
def _generator(self,
|
||||
procs: typing.Generator[interfaces.objects.ObjectInterface, None, None],
|
||||
@@ -110,32 +95,24 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
BaseDllName = renderers.UnreadableValue()
|
||||
|
||||
session_layer_name = moddump.ModDump.find_session_layer(self.context, session_layers, mod.DllBase)
|
||||
if session_layer_name is None:
|
||||
file_version = renderers.UnreadableValue()
|
||||
product_version = renderers.UnreadableValue()
|
||||
else:
|
||||
entries = self.get_version_entries(self._context,
|
||||
pe_table_name,
|
||||
session_layer_name,
|
||||
mod.DllBase)
|
||||
|
||||
try:
|
||||
file_version = entries[b"FileVersion"].decode()
|
||||
except KeyError:
|
||||
file_version = renderers.UnreadableValue()
|
||||
|
||||
try:
|
||||
product_version = entries[b"ProductVersion"].decode()
|
||||
except KeyError:
|
||||
product_version = renderers.UnreadableValue()
|
||||
(major, minor, product, build) = [renderers.NotAvailableValue()] * 4
|
||||
try:
|
||||
(major, minor, product, build) = self.get_version_information(self._context,
|
||||
pe_table_name,
|
||||
session_layer_name,
|
||||
mod.DllBase)
|
||||
except (exceptions.InvalidAddressException, ValueError, AttributeError):
|
||||
(major, minor, product, build) = [renderers.UnreadableValue()] * 4
|
||||
|
||||
# the pid and process are not applicable for kernel modules
|
||||
yield (0, (renderers.NotApplicableValue(),
|
||||
renderers.NotApplicableValue(),
|
||||
format_hints.Hex(mod.DllBase),
|
||||
BaseDllName,
|
||||
file_version,
|
||||
product_version))
|
||||
major,
|
||||
minor,
|
||||
product,
|
||||
build))
|
||||
|
||||
# now go through the process and dll lists
|
||||
for proc in procs:
|
||||
@@ -147,20 +124,15 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
except exceptions.InvalidAddressException:
|
||||
BaseDllName = renderers.UnreadableValue()
|
||||
|
||||
entries = self.get_version_entries(self._context,
|
||||
pe_table_name,
|
||||
proc_layer_name,
|
||||
entry.DllBase)
|
||||
|
||||
session_layer_name = moddump.ModDump.find_session_layer(self.context, session_layers, mod.DllBase)
|
||||
(major, minor, product, build) = [renderers.NotAvailableValue()] * 4
|
||||
try:
|
||||
file_version = entries[b"FileVersion"].decode()
|
||||
except KeyError:
|
||||
file_version = renderers.UnreadableValue()
|
||||
|
||||
try:
|
||||
product_version = entries[b"ProductVersion"].decode()
|
||||
except KeyError:
|
||||
product_version = renderers.UnreadableValue()
|
||||
(major, minor, product, build) = self.get_version_information(self._context,
|
||||
pe_table_name,
|
||||
proc_layer_name,
|
||||
entry.DllBase)
|
||||
except (exceptions.InvalidAddressException, ValueError, AttributeError):
|
||||
(major, minor, product, build) = [renderers.UnreadableValue()] * 4
|
||||
|
||||
yield (0, (proc.UniqueProcessId,
|
||||
proc.ImageFileName.cast("string",
|
||||
@@ -168,8 +140,10 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
errors = "replace"),
|
||||
format_hints.Hex(entry.DllBase),
|
||||
BaseDllName,
|
||||
file_version,
|
||||
product_version))
|
||||
major,
|
||||
minor,
|
||||
product,
|
||||
build))
|
||||
|
||||
def run(self):
|
||||
procs = pslist.PsList.list_processes(self.context,
|
||||
@@ -189,6 +163,8 @@ class VerInfo(interfaces_plugins.PluginInterface):
|
||||
("Process", str),
|
||||
("Base", format_hints.Hex),
|
||||
("Name", str),
|
||||
("File", str),
|
||||
("Product", str)],
|
||||
("Major", int),
|
||||
("Minor", int),
|
||||
("Product", int),
|
||||
("Build", int)],
|
||||
self._generator(procs, mods, session_layers))
|
||||
|
||||
Reference in New Issue
Block a user