mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
158 lines
4.0 KiB
Perl
158 lines
4.0 KiB
Perl
package Parse::Win32Registry::WinNT::Security;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use base qw(Parse::Win32Registry::Entry);
|
|
|
|
use Carp;
|
|
use Parse::Win32Registry::Base qw(:all);
|
|
|
|
use constant SK_HEADER_LENGTH => 0x18;
|
|
use constant OFFSET_TO_FIRST_HBIN => 0x1000;
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
my $regfile = shift;
|
|
my $offset = shift; # offset to sk record relative to start of file
|
|
|
|
croak 'Missing registry file' if !defined $regfile;
|
|
croak 'Missing offset' if !defined $offset;
|
|
|
|
if (defined(my $cache = $regfile->{_security_cache})) {
|
|
if (exists $cache->{$offset}) {
|
|
return $cache->{$offset};
|
|
}
|
|
}
|
|
|
|
my $fh = $regfile->get_filehandle;
|
|
|
|
# 0x00 dword = security length (negative = allocated)
|
|
# 0x04 word = 'sk' signature
|
|
# 0x08 dword = offset to previous sk
|
|
# 0x0c dword = offset to next sk
|
|
# 0x10 dword = ref count
|
|
# 0x14 dword = length of security descriptor
|
|
# 0x18 = start of security descriptor
|
|
|
|
# Extracted offsets are always relative to first hbin
|
|
|
|
sysseek($fh, $offset, 0);
|
|
my $bytes_read = sysread($fh, my $sk_header, SK_HEADER_LENGTH);
|
|
if ($bytes_read != SK_HEADER_LENGTH) {
|
|
warnf('Could not read security at 0x%x', $offset);
|
|
return;
|
|
}
|
|
|
|
my ($length,
|
|
$sig,
|
|
$offset_to_previous,
|
|
$offset_to_next,
|
|
$ref_count,
|
|
$sd_length,
|
|
) = unpack('Va2x2VVVV', $sk_header);
|
|
|
|
$offset_to_previous += OFFSET_TO_FIRST_HBIN
|
|
if $offset_to_previous != 0xffffffff;
|
|
$offset_to_next += OFFSET_TO_FIRST_HBIN
|
|
if $offset_to_next != 0xffffffff;
|
|
|
|
my $allocated = 0;
|
|
if ($length > 0x7fffffff) {
|
|
$allocated = 1;
|
|
$length = (0xffffffff - $length) + 1;
|
|
}
|
|
# allocated should be true
|
|
|
|
if ($sig ne 'sk') {
|
|
warnf('Invalid signature for security at 0x%x', $offset);
|
|
return;
|
|
}
|
|
|
|
$bytes_read = sysread($fh, my $sd_data, $sd_length);
|
|
if ($bytes_read != $sd_length) {
|
|
warnf('Could not read security descriptor for security at 0x%x',
|
|
$offset);
|
|
return;
|
|
}
|
|
|
|
my $sd = unpack_security_descriptor($sd_data);
|
|
if (!defined $sd) {
|
|
warnf('Invalid security descriptor for security at 0x%x',
|
|
$offset);
|
|
# Abandon security object if security descriptor is invalid
|
|
return;
|
|
}
|
|
|
|
my $self = {};
|
|
$self->{_regfile} = $regfile;
|
|
$self->{_offset} = $offset;
|
|
$self->{_length} = $length;
|
|
$self->{_allocated} = $allocated;
|
|
$self->{_tag} = $sig;
|
|
$self->{_offset_to_previous} = $offset_to_previous;
|
|
$self->{_offset_to_next} = $offset_to_next;
|
|
$self->{_ref_count} = $ref_count;
|
|
$self->{_security_descriptor_length} = $sd_length;
|
|
$self->{_security_descriptor} = $sd;
|
|
bless $self, $class;
|
|
|
|
if (defined(my $cache = $regfile->{_security_cache})) {
|
|
$cache->{$offset} = $self;
|
|
}
|
|
|
|
return $self;
|
|
}
|
|
|
|
sub get_previous {
|
|
my $self = shift;
|
|
my $regfile = $self->{_regfile};
|
|
my $offset_to_previous = $self->{_offset_to_previous};
|
|
|
|
return Parse::Win32Registry::WinNT::Security->new($regfile,
|
|
$offset_to_previous);
|
|
}
|
|
|
|
sub get_next {
|
|
my $self = shift;
|
|
my $regfile = $self->{_regfile};
|
|
my $offset_to_next = $self->{_offset_to_next};
|
|
|
|
return Parse::Win32Registry::WinNT::Security->new($regfile,
|
|
$offset_to_next);
|
|
}
|
|
|
|
sub get_reference_count {
|
|
my $self = shift;
|
|
|
|
return $self->{_ref_count};
|
|
}
|
|
|
|
sub get_security_descriptor {
|
|
my $self = shift;
|
|
|
|
return $self->{_security_descriptor};
|
|
}
|
|
|
|
sub as_string {
|
|
my $self = shift;
|
|
|
|
return '(security entry)';
|
|
}
|
|
|
|
sub parse_info {
|
|
my $self = shift;
|
|
|
|
my $info = sprintf '0x%x sk len=0x%x alloc=%d prev=0x%x,next=0x%x refs=%d',
|
|
$self->{_offset},
|
|
$self->{_length},
|
|
$self->{_allocated},
|
|
$self->{_offset_to_previous},
|
|
$self->{_offset_to_next},
|
|
$self->{_ref_count};
|
|
|
|
return $info;
|
|
}
|
|
|
|
1;
|