-
Notifications
You must be signed in to change notification settings - Fork 394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new resident data displaying plugin. Scan in correct layer. Condense code and remove duplication. Fix bugs #1169
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, generally looks good. A couple of minor house keeping things just to keep the coding style in check but otherwise looks good thanks!
def _generator(self): | ||
layer = self.context.layers[self.config["primary"]] | ||
def enumerate_mft_records(self, attr_callback): | ||
phys_layer = self.context.layers[self.config["primary"]].config["memory_layer"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nicer to handle KeyErrors
here (or use get
so tht failures result in phys_layer being None
which can be easily checked).. The requirements should ensure everything works but, give it's two dictionary lookups that could fail, it just feels a little fragile.
attribute_object = symbol_table + constants.BANG + "ATTRIBUTE" | ||
si_object = symbol_table + constants.BANG + "STANDARD_INFORMATION_ENTRY" | ||
fn_object = symbol_table + constants.BANG + "FILE_NAME_ENTRY" | ||
self.mft_object = symbol_table + constants.BANG + "MFT_ENTRY" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As part of the coding style, these should be defined as part of __init__
(initialized to None
) so that accidental accesses don't throw up an AttributeError
.
# which DATA attribute should be displayed | ||
self._display_first_data = False | ||
|
||
def _parse_data_record(self, mft_record, attr): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add typing information to this just to make it easier to spot things going wrong please? This will return a Generator
type so the return at the start wouldn't require Optional
in the type. Makes it easier to figure out if code using it will throw errors...
content, | ||
) | ||
|
||
def parse_data_records(self, mft_record, attr): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also be a generator, even though you can't tell until the very end of the function.
This MR performs a number of tasks related to the mftscan file and MFT-related functionatlity:
Fixes bugs, such as incorrect instantiation of absent values
Creates a unified and inheritable code flow for plugins that want to parse MFT records and their attributes.
Previously, ADSscan and MFTScan scanned in the kernel virtual address space, which is incorrect and caused in many samples over half the entries to be missed. These scans should occur in the physical address space.
Stops printing a disassembly of ADS data, which makes no sense anyway and made the output strange.
Adds a new plugin, ResidentData, in the file that hexdumps all of the resident data of a file (the first $DATA attribute). This inherits and uses a combined implementation of $DATA attribute access from the ADS plugin, which displays the second (and third and fourth ..., if present) $DATA attribute. Volatility 2 displayed resident data inline with the regular MFTscan type output, but this was confusing and would break grep results.