mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-11 12:17:38 +02:00
Add elf parsing and symbol retrieval for linux kernel modules
This commit is contained in:
@@ -2,6 +2,23 @@
|
||||
"symbols": {
|
||||
},
|
||||
"user_types": {
|
||||
"Elf": {
|
||||
"fields": {
|
||||
"e_ident": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"count": 16,
|
||||
"kind": "array",
|
||||
"subtype": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 16
|
||||
},
|
||||
"Elf64_Ehdr": {
|
||||
"fields": {
|
||||
"e_ident": {
|
||||
@@ -18,8 +35,8 @@
|
||||
"e_type": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
"kind": "enum",
|
||||
"name": "EtypeEnum"
|
||||
}
|
||||
},
|
||||
"e_machine": {
|
||||
@@ -247,9 +264,635 @@
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 56
|
||||
},
|
||||
"Elf64_Dyn": {
|
||||
"fields": {
|
||||
"d_tag": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "long long"
|
||||
}
|
||||
},
|
||||
"d_ptr": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 16
|
||||
},
|
||||
"Elf64_Note": {
|
||||
"fields": {
|
||||
"n_namesz": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"n_descsz": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"n_type": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 12
|
||||
},
|
||||
"Elf64_Sym": {
|
||||
"fields": {
|
||||
"st_name": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"st_info": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
},
|
||||
"st_other": {
|
||||
"offset": 5,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
},
|
||||
"st_shndx": {
|
||||
"offset": 6,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
},
|
||||
"st_value": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"st_size": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 24
|
||||
},
|
||||
"Elf64_LinkMap": {
|
||||
"fields": {
|
||||
"l_addr": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"l_name": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"l_ld": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"l_next": {
|
||||
"offset": 24,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"l_prev": {
|
||||
"offset": 32,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 40
|
||||
},
|
||||
"Elf64_Rel": {
|
||||
"fields": {
|
||||
"r_offset": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"r_info": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 16
|
||||
},
|
||||
"Elf64_Rela": {
|
||||
"fields": {
|
||||
"r_offset": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"r_info": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"r_addend": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "long long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 24
|
||||
},
|
||||
"Elf32_Ehdr": {
|
||||
"fields": {
|
||||
"e_ident": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"count": 16,
|
||||
"kind": "array",
|
||||
"subtype": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
}
|
||||
},
|
||||
"e_type": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "enum",
|
||||
"name": "EtypeEnum"
|
||||
}
|
||||
},
|
||||
"e_machine": {
|
||||
"offset": 18,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
},
|
||||
"e_version": {
|
||||
"offset": 20,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"e_entry": {
|
||||
"offset": 24,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"e_phoff": {
|
||||
"offset": 28,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"e_shoff": {
|
||||
"offset": 32,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"e_flags": {
|
||||
"offset": 36,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"e_ehsize": {
|
||||
"offset": 40,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
},
|
||||
"e_phentsize": {
|
||||
"offset": 42,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
},
|
||||
"e_phnum": {
|
||||
"offset": 44,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
},
|
||||
"e_shentsize": {
|
||||
"offset": 46,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
},
|
||||
"e_shnum": {
|
||||
"offset": 48,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
},
|
||||
"e_shstrndx": {
|
||||
"offset": 50,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 52
|
||||
},
|
||||
"Elf32_Shdr": {
|
||||
"fields": {
|
||||
"sh_name": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_type": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_flags": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_addr": {
|
||||
"offset": 12,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_offset": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_size": {
|
||||
"offset": 20,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_link": {
|
||||
"offset": 24,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_info": {
|
||||
"offset": 28,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_addralign": {
|
||||
"offset": 32,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"sh_entsize": {
|
||||
"offset": 36,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 40
|
||||
},
|
||||
"Elf32_Phdr": {
|
||||
"fields": {
|
||||
"p_type": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "enum",
|
||||
"name": "PtypeEnum"
|
||||
}
|
||||
},
|
||||
"p_offset": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"p_vaddr": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"p_paddr": {
|
||||
"offset": 12,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"p_filesz": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"p_memsz": {
|
||||
"offset": 20,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"p_flags": {
|
||||
"offset": 24,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"p_align": {
|
||||
"offset": 28,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 32
|
||||
},
|
||||
"Elf32_Dyn": {
|
||||
"fields": {
|
||||
"d_tag": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "long"
|
||||
}
|
||||
},
|
||||
"d_ptr": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 8
|
||||
},
|
||||
"Elf32_Note": {
|
||||
"fields": {
|
||||
"n_namesz": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"n_descsz": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"n_type": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 12
|
||||
},
|
||||
"Elf32_Sym": {
|
||||
"fields": {
|
||||
"st_name": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"st_value": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"st_size": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long long"
|
||||
}
|
||||
},
|
||||
"st_info": {
|
||||
"offset": 12,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
},
|
||||
"st_other": {
|
||||
"offset": 13,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned char"
|
||||
}
|
||||
},
|
||||
"st_shndx": {
|
||||
"offset": 14,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned short"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 16
|
||||
},
|
||||
"Elf32_LinkMap": {
|
||||
"fields": {
|
||||
"l_addr": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"l_name": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"l_ld": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"l_next": {
|
||||
"offset": 12,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"l_prev": {
|
||||
"offset": 16,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 20
|
||||
},
|
||||
"Elf32_Rel": {
|
||||
"fields": {
|
||||
"r_offset": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"r_info": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 8
|
||||
},
|
||||
"Elf32_Rela": {
|
||||
"fields": {
|
||||
"r_offset": {
|
||||
"offset": 0,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"r_info": {
|
||||
"offset": 4,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "unsigned long"
|
||||
}
|
||||
},
|
||||
"r_addend": {
|
||||
"offset": 8,
|
||||
"type": {
|
||||
"kind": "base",
|
||||
"name": "long"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind": "struct",
|
||||
"size": 12
|
||||
}
|
||||
|
||||
},
|
||||
"enums": {
|
||||
"EtypeEnum": {
|
||||
"base": "unsigned short",
|
||||
"constants": {
|
||||
"ET_NONE": 0,
|
||||
"ET_REL": 1,
|
||||
"ET_EXEC": 2,
|
||||
"ET_DYN": 3,
|
||||
"ET_CORE": 4,
|
||||
"ET_LOPROC": 65280,
|
||||
"ET_HIPROC": 65535
|
||||
},
|
||||
"size": 2
|
||||
},
|
||||
"PtypeEnum": {
|
||||
"base": "unsigned long",
|
||||
"constants": {
|
||||
@@ -260,6 +903,7 @@
|
||||
"PT_NOTE": 4,
|
||||
"PT_SHLIB": 5,
|
||||
"PT_PHDR": 6,
|
||||
"PT_TLS": 7,
|
||||
"PT_LOOS": 1610612736,
|
||||
"PT_HIOS": 1879048191,
|
||||
"PT_LOWPROC": 1879048192,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
|
||||
from volatility.framework.symbols import intermed
|
||||
from volatility.framework.symbols.linux.extensions import elf
|
||||
|
||||
|
||||
class ElfIntermedSymbols(intermed.IntermediateSymbolTable):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.set_type_class('Elf', elf.elf)
|
||||
self.set_type_class('Elf64_Phdr', elf.elf_phdr)
|
||||
self.set_type_class('Elf32_Phdr', elf.elf_phdr)
|
||||
self.set_type_class('Elf32_Sym', elf.elf_sym)
|
||||
self.set_type_class('Elf64_Sym', elf.elf_sym)
|
||||
@@ -7,9 +7,11 @@ import logging
|
||||
from typing import Generator, Iterable, Iterator, Optional, Tuple
|
||||
|
||||
from volatility.framework import constants
|
||||
from volatility.framework import exceptions, objects, interfaces
|
||||
from volatility.framework import exceptions, objects, interfaces, symbols
|
||||
from volatility.framework.layers import linear
|
||||
from volatility.framework.symbols import generic, linux
|
||||
from volatility.framework.objects import utility
|
||||
from volatility.framework.symbols.linux.elf import ElfIntermedSymbols
|
||||
|
||||
vollog = logging.getLogger(__name__)
|
||||
|
||||
@@ -36,6 +38,113 @@ class module(generic.GenericIntelProcess):
|
||||
|
||||
raise AttributeError("module -> get_core_size: Unable to determine initial size of module")
|
||||
|
||||
def get_module_core(self):
|
||||
if self.has_member("core_layout"):
|
||||
return self.core_layout.base
|
||||
elif self.has_member("module_core"):
|
||||
return self.module_core
|
||||
|
||||
raise AttributeError("module -> get_module_core: Unable to get module core")
|
||||
|
||||
def get_module_init(self):
|
||||
if self.has_member("init_layout"):
|
||||
return self.init_layout.base
|
||||
elif self.has_member("module_init"):
|
||||
return self.module_init
|
||||
|
||||
raise AttributeError("module -> get_module_core: Unable to get module init")
|
||||
|
||||
def get_name(self):
|
||||
""" Get the name of the module as a string """
|
||||
return utility.array_to_string(self.name)
|
||||
|
||||
def _get_sect_count(self, grp):
|
||||
""" Try to determine the number of valid sections """
|
||||
arr = self._context.object(self.get_symbol_table().name + constants.BANG + "array",
|
||||
layer_name = self.vol.layer_name,
|
||||
offset = grp.attrs,
|
||||
subtype = self._context.symbol_space.get_type(self.get_symbol_table().name + constants.BANG + "pointer"),
|
||||
count = 25)
|
||||
|
||||
idx = 0
|
||||
while arr[idx]:
|
||||
idx = idx + 1
|
||||
|
||||
return idx
|
||||
|
||||
def get_sections(self):
|
||||
""" Get sections of the module """
|
||||
if self.sect_attrs.has_member("nsections"):
|
||||
num_sects = self.sect_attrs.nsections
|
||||
else:
|
||||
num_sects = self._get_sect_count(self.sect_attrs.grp)
|
||||
|
||||
arr = self._context.object(self.get_symbol_table().name + constants.BANG + "array",
|
||||
layer_name = self.vol.layer_name,
|
||||
offset = self.sect_attrs.attrs.vol.offset,
|
||||
subtype = self._context.symbol_space.get_type(self.get_symbol_table().name + constants.BANG + 'module_sect_attr'),
|
||||
count = num_sects)
|
||||
|
||||
for attr in arr:
|
||||
yield attr
|
||||
|
||||
def get_symbols(self):
|
||||
ret_syms = []
|
||||
|
||||
if symbols.symbol_table_is_64bit(self._context, self.get_symbol_table().name):
|
||||
prefix = "Elf64_"
|
||||
else:
|
||||
prefix = "Elf32_"
|
||||
|
||||
elf_table_name = ElfIntermedSymbols.create(self._context, "", "linux", "elf")
|
||||
|
||||
syms = self._context.object(self.get_symbol_table().name + constants.BANG + "array",
|
||||
layer_name = self.vol.layer_name,
|
||||
offset = self.section_symtab,
|
||||
subtype = self._context.symbol_space.get_type(elf_table_name + constants.BANG + prefix + "Sym"),
|
||||
count = self.num_symtab + 1)
|
||||
if self.section_strtab:
|
||||
for sym in syms:
|
||||
sym.set_cached_strtab(self.section_strtab)
|
||||
yield sym
|
||||
|
||||
def get_symbol(self, wanted_sym_name):
|
||||
""" Get value for a given symbol name """
|
||||
for sym in self.get_symbols():
|
||||
sym_name = sym.get_name()
|
||||
sym_addr = sym.st_value
|
||||
if wanted_sym_name == sym_name:
|
||||
return sym_addr
|
||||
|
||||
@property
|
||||
def section_symtab(self):
|
||||
if self.has_member("kallsyms"):
|
||||
return self.kallsyms.symtab
|
||||
elif self.has_member("symtab"):
|
||||
return self.symtab
|
||||
|
||||
raise AttributeError("module -> symtab: Unable to get symtab")
|
||||
|
||||
@property
|
||||
def num_symtab(self):
|
||||
if self.has_member("kallsyms"):
|
||||
return int(self.kallsyms.num_symtab)
|
||||
elif self.has_member("num_symtab"):
|
||||
return int(self.num_symtab)
|
||||
|
||||
raise AttributeError("module -> num_symtab: Unable to determine number of symbols")
|
||||
|
||||
@property
|
||||
def section_strtab(self):
|
||||
#Newer kernels
|
||||
if self.has_member("kallsyms"):
|
||||
return self.kallsyms.strtab
|
||||
#Older kernels
|
||||
elif self.has_member("strtab"):
|
||||
strtab = self.strtab
|
||||
|
||||
raise AttributeError("module -> strtab: Unable to get strtab")
|
||||
|
||||
|
||||
class task_struct(generic.GenericIntelProcess):
|
||||
|
||||
@@ -387,15 +496,3 @@ class vfsmount(objects.StructType):
|
||||
|
||||
def get_mnt_root(self):
|
||||
return self.mnt_root
|
||||
|
||||
|
||||
class kobject(objects.StructType):
|
||||
|
||||
def reference_count(self):
|
||||
refcnt = self.kref.refcount
|
||||
if self.has_member("counter"):
|
||||
ret = refcnt.counter
|
||||
else:
|
||||
ret = refcnt.refs.counter
|
||||
|
||||
return ret
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
# This file is Copyright 2019 Volatility Foundation and licensed under the Volatility Software License 1.0
|
||||
# which is available at https://www.volatilityfoundation.org/license/vsl-v1.0
|
||||
#
|
||||
|
||||
from volatility.framework import exceptions, constants
|
||||
from volatility.framework import objects, interfaces
|
||||
from volatility.framework.objects import utility
|
||||
from volatility.framework.renderers import conversion
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union, Type
|
||||
|
||||
|
||||
class elf(objects.StructType):
|
||||
'''
|
||||
Class used to create elf objects. It overrides the typename to Elf32_ or Elf64_,
|
||||
depending on the corresponding value on e_ident
|
||||
'''
|
||||
def __init__(self, context: interfaces.context.ContextInterface, type_name: str,
|
||||
object_info: interfaces.objects.ObjectInformation, size: int,
|
||||
members: Dict[str, Tuple[int, interfaces.objects.Template]]) -> None:
|
||||
|
||||
super().__init__(context = context,
|
||||
type_name = type_name,
|
||||
object_info = object_info,
|
||||
size = size,
|
||||
members = members)
|
||||
|
||||
|
||||
layer_name = self.vol.layer_name
|
||||
symbol_table_name = self.get_symbol_table().name
|
||||
# We read the MAGIC: (0x0 to 0x4) 0x7f 0x45 0x4c 0x46
|
||||
magic = self._context.object(symbol_table_name + constants.BANG + "unsigned long",
|
||||
layer_name = layer_name,
|
||||
offset = object_info.offset)
|
||||
|
||||
# Check validity
|
||||
if magic != 0x464c457f:
|
||||
return None
|
||||
|
||||
# We need to read the EI_CLASS (0x4 offset)
|
||||
ei_class = self._context.object(symbol_table_name + constants.BANG + "unsigned char",
|
||||
layer_name = layer_name,
|
||||
offset = object_info.offset + 0x4)
|
||||
|
||||
if ei_class == 1:
|
||||
self.__type_prefix = "Elf32_"
|
||||
elif ei_class == 2:
|
||||
self.__type_prefix = "Elf64_"
|
||||
else:
|
||||
self.__type_prefix = None
|
||||
|
||||
# Construct the full header
|
||||
self.__hdr = self._context.object(symbol_table_name + constants.BANG + self.__type_prefix + "Ehdr",
|
||||
layer_name = layer_name,
|
||||
offset = object_info.offset)
|
||||
self.__offset = object_info.offset
|
||||
|
||||
self.cached_symtab = None
|
||||
self.cached_strtab = None
|
||||
|
||||
def is_valid(self):
|
||||
'''
|
||||
Determine whether it is a valid object
|
||||
'''
|
||||
return self.__type_prefix is not None and self.__hdr is not None
|
||||
|
||||
def __getattr__(self, name):
|
||||
# Just redirect to the corresponding header
|
||||
if name[0:2] == "e_" and name in dir(self.__hdr):
|
||||
return self.__hdr.__getattr__(name)
|
||||
else:
|
||||
return self.__getattribute__(name)
|
||||
|
||||
def __dir__(self):
|
||||
return self.__hdr.__dir__() + ["get_program_headers", "is_valid", "get_section_headers", "get_symbols", "__dir__"]
|
||||
|
||||
def get_program_headers(self):
|
||||
program_headers = self._context.object(self.get_symbol_table().name + constants.BANG + "array",
|
||||
layer_name = self.vol.layer_name,
|
||||
offset = self.__offset + self.e_phoff,
|
||||
subtype = self._context.symbol_space.get_type(self.get_symbol_table().name + constants.BANG + self.__type_prefix + "Phdr"),
|
||||
count = self.e_phnum)
|
||||
|
||||
for prog_header in program_headers:
|
||||
prog_header.set_parent_e_type(self.e_type)
|
||||
prog_header.set_parent_offset(self.__offset)
|
||||
prog_header.set_type_prefix(self.__type_prefix)
|
||||
yield prog_header
|
||||
|
||||
def get_section_headers(self):
|
||||
section_headers = self._context.object(self.get_symbol_table().name + constants.BANG + "array",
|
||||
layer_name = self.vol.layer_name,
|
||||
offset = self.__offset + self.e_shoff,
|
||||
subtype =
|
||||
self._context.symbol_space.get_type(self.get_symbol_table().name + constants.BANG + self.__type_prefix + "Shdr"),
|
||||
count = self.e_shnum)
|
||||
return section_headers
|
||||
|
||||
def _find_symbols(self):
|
||||
dt_strtab = None
|
||||
dt_symtab = None
|
||||
dt_strent = None
|
||||
|
||||
for phdr in self.get_program_headers():
|
||||
try:
|
||||
# Find PT_DYNAMIC segment
|
||||
if str(phdr.p_type.description) != 'PT_DYNAMIC':
|
||||
continue
|
||||
except ValueError:
|
||||
# If the p_type value is outside the ones declared in the enumeration, an
|
||||
# exception is raised
|
||||
return None
|
||||
|
||||
# This section contains pointers to the strtab, symtab, and strent sections
|
||||
for dsec in phdr.dynamic_sections():
|
||||
if dsec.d_tag == 5:
|
||||
dt_strtab = dsec.d_ptr
|
||||
|
||||
elif dsec.d_tag == 6:
|
||||
dt_symtab = dsec.d_ptr
|
||||
|
||||
elif dsec.d_tag == 11:
|
||||
# Size of the symtab symbol entry
|
||||
dt_strent = dsec.d_ptr
|
||||
|
||||
break
|
||||
|
||||
if dt_strtab == None or dt_symtab == None or dt_strent == None:
|
||||
return None
|
||||
|
||||
self.cached_symtab = dt_symtab
|
||||
self.cached_strtab = dt_strtab
|
||||
|
||||
# Calculate number of symbol entries assuming that strtab follows symtab
|
||||
if dt_symtab < dt_strtab:
|
||||
self.cached_numsyms = int((int(dt_strtab) - int(dt_symtab)) / dt_strent)
|
||||
else:
|
||||
self.cached_numsyms = 1024
|
||||
|
||||
def get_symbols(self):
|
||||
if self.cached_symtab == None:
|
||||
self._find_symbols()
|
||||
|
||||
if self.cached_symtab == None:
|
||||
return
|
||||
|
||||
symtab_arr = self._context.object(self.get_symbol_table().name + constants.BANG + "array",
|
||||
layer_name = self.vol.layer_name,
|
||||
offset = self.cached_symtab,
|
||||
subtype = self._context.symbol_space.get_type(self.get_symbol_table().name + constants.BANG + self.__type_prefix + "Sym"),
|
||||
count = self.cached_numsyms)
|
||||
|
||||
for sym in symtab_arr:
|
||||
sym.set_cached_strtab(self.cached_strtab)
|
||||
yield sym
|
||||
|
||||
|
||||
class elf_sym(objects.StructType):
|
||||
""" An elf symbol entry"""
|
||||
|
||||
def set_cached_strtab(self, cached_strtab):
|
||||
self.cached_strtab = cached_strtab
|
||||
|
||||
def get_name(self):
|
||||
addr = self.cached_strtab + self.st_name
|
||||
|
||||
# Just get the first 255 characters, it should be enough for a symbol name
|
||||
name_bytes = self._context.layers[self.vol.layer_name].read(addr, 255, pad = True)
|
||||
|
||||
if name_bytes:
|
||||
idx = name_bytes.find(b"\x00")
|
||||
if idx != -1:
|
||||
name_bytes = name_bytes[:idx]
|
||||
else:
|
||||
return None
|
||||
|
||||
return name_bytes.decode('utf-8', errors='ignore')
|
||||
|
||||
|
||||
class elf_phdr(objects.StructType):
|
||||
""" An elf program header """
|
||||
|
||||
def __init__(self, context: interfaces.context.ContextInterface, type_name: str,
|
||||
object_info: interfaces.objects.ObjectInformation, size: int,
|
||||
members: Dict[str, Tuple[int, interfaces.objects.Template]]) -> None:
|
||||
|
||||
super().__init__(context = context,
|
||||
type_name = type_name,
|
||||
object_info = object_info,
|
||||
size = size,
|
||||
members = members)
|
||||
|
||||
self.__parent_e_type = None
|
||||
self.__parent_offset = None
|
||||
self.__type_prefix = None
|
||||
|
||||
def set_parent_e_type(self, e_type):
|
||||
self.__parent_e_type = e_type
|
||||
|
||||
def set_parent_offset(self, offset):
|
||||
self.__parent_offset = offset
|
||||
|
||||
def set_type_prefix(self, prefix):
|
||||
self.__type_prefix = prefix
|
||||
|
||||
def get_vaddr(self):
|
||||
offset = self.__getattr__("p_vaddr")
|
||||
|
||||
if self.__parent_e_type == 3: # ET_DYN
|
||||
offset = self.__parent_offset + offset
|
||||
|
||||
return offset
|
||||
|
||||
def dynamic_sections(self):
|
||||
# sanity check
|
||||
try:
|
||||
if str(self.p_type.description) != 'PT_DYNAMIC':
|
||||
return None
|
||||
except ValueError:
|
||||
# If the value is outside the ones declared in the enumeration, an
|
||||
# exception is raised
|
||||
return None
|
||||
|
||||
# the buffer of array starts at elf_base + our virtual address ( offset )
|
||||
arr_start = self.get_vaddr()
|
||||
|
||||
symbol_table_name = self.get_symbol_table().name
|
||||
|
||||
rtsize = self._context.symbol_space.get_type(symbol_table_name + \
|
||||
constants.BANG + \
|
||||
self.__type_prefix + "Dyn").size
|
||||
|
||||
for i in range(256):
|
||||
# use the real size
|
||||
idx = i * rtsize
|
||||
|
||||
dyn = self._context.object(symbol_table_name + constants.BANG + self.__type_prefix + "Dyn",
|
||||
layer_name = self.vol.layer_name,
|
||||
offset = arr_start + idx)
|
||||
|
||||
yield dyn
|
||||
|
||||
if dyn.d_tag == 0:
|
||||
break
|
||||
Reference in New Issue
Block a user