Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Perl code to read and print the folder permissions on regkeys

Posted on 2014-08-29
4
Medium Priority
?
378 Views
Last Modified: 2014-09-03
Hi,

Can someone please help to write Perl code that fetches values from registry keys and also prints what permissions different users of system have on those keys?

 Cheers,

 Dev
0
Comment
Question by:searchsanjaysharma
  • 4
4 Comments
 
LVL 25

Expert Comment

by:clockwatcher
ID: 40296159
See the python docs on  _winreg  (https://docs.python.org/2/library/_winreg.html) for accessing the registry.

I couldn't find any examples of reading the security settings so went ahead and wrote one up.  Basically, boils down to using the win32api module to make a windows api call to RegGetKeySecurity, using the winsecurity module to get the DACL, and finally enumerating over the access control entries.  Both win32api and win32security are part of the pywin32  extensions (http://sourceforge.net/projects/pywin32/).

Anyway... here's an example of both reading from the registry and listing the permissions on a key:

import win32api
import win32security
import _winreg

class Ace(object):
    ace_flags = {win32security.CONTAINER_INHERIT_ACE: 'Container Inherit',
                 win32security.FAILED_ACCESS_ACE_FLAG: 'Failed Access',
                 win32security.INHERIT_ONLY_ACE: 'Inherit only',
                 win32security.INHERITED_ACE: 'Inherited ACE',
                 win32security.NO_PROPAGATE_INHERIT_ACE: 'No propagate',
                 win32security.OBJECT_INHERIT_ACE: 'Object inherit',
                 win32security.SUCCESSFUL_ACCESS_ACE_FLAG: 'Successful access'}
                     
    def __init__(self, ace):
        self.ace = ace
        ( (self.access_type, self.flags), self.mask, self.pysid) = ace

    def getType(self):
        if self.access_type == win32security.ACCESS_ALLOWED_ACE_TYPE:
            return "Allow"
        if self.access_type == win32security.ACCESS_DENIED_ACE_TYPE:
            return "Deny"

    def getFlags(self):
        readable_flags = list()
        for (f, v) in self.ace_flags.items():
            if f & self.flags == f:
                readable_flags.append(v)
        return readable_flags
    
class RegKey(object):

    registry_rights = {_winreg.KEY_ALL_ACCESS: 'All Access',
                      _winreg.KEY_WRITE: 'Write',
                      _winreg.KEY_READ: 'Read',
                      _winreg.KEY_EXECUTE: 'Read',
                      _winreg.KEY_QUERY_VALUE: 'Query value',
                      _winreg.KEY_SET_VALUE: 'Set value',
                      _winreg.KEY_CREATE_SUB_KEY: 'Create subkey',
                      _winreg.KEY_ENUMERATE_SUB_KEYS: 'Enum subkeys',
                      _winreg.KEY_NOTIFY: 'Request notification',
                      _winreg.KEY_CREATE_LINK: 'Link (reserved)' }
    
    def __init__(self, key_path, machine=None, root=winreg.HKEY_LOCAL_MACHINE):
        self.registry = _winreg.ConnectRegistry(None, root)
        self.key_path = key_path
        self.key = _winreg.OpenKey(self.registry, key_path)
        self.security = win32api.RegGetKeySecurity(self.key.handle, win32security.DACL_SECURITY_INFORMATION)
        self.dacl = self.security.GetSecurityDescriptorDacl()
        self.aces = list()
        for i in range(self.dacl.GetAceCount()):
            self.aces.append(Ace(self.dacl.GetAce(i)))

    def dump_values(self):
        (subkey_count, value_count, last_modified) = _winreg.QueryInfoKey(self.key)
        print "Values:"
        for i in range(value_count):
            (name, data, value_type) = _winreg.EnumValue(self.key, i)
            print "\t{0}: {1}".format(name, data)

    def dump_subkeys(self):
        (subkey_count, value_count, last_modified) = _winreg.QueryInfoKey(self.key)
        print "Subkeys:"
        for i in range(subkey_count):
           print "\t{0}".format(_winreg.EnumKey(self.key, i))

    def dump_ace(self, ace):
        print "Ace: {0}".format(ace.ace)
        print " Type: {0}".format(ace.getType())
        print " Flags: {0}".format(", ".join(ace.getFlags()))  
        account = win32security.LookupAccountSid(None, ace.pysid);
        print " Account: {0}\{1}".format(account[1], account[0])
        print " Access:"
        if ace.mask & _winreg.KEY_ALL_ACCESS == _winreg.KEY_ALL_ACCESS:
            print "\t{0}".format(self.registry_rights[_winreg.KEY_ALL_ACCESS])
        else:
            for (p, v) in self.registry_rights.items():
                if p & ace.mask == p:
                   print "\t{0}".format(v)
        
    def dump_dacl(self):
        for ace in self.aces:
            self.dump_ace(ace)
            print
            
    
if __name__ == '__main__':
    r = RegKey(r"Software\Microsoft\Windows\CurrentVersion\Internet Settings",
               root=_winreg.HKEY_CURRENT_USER)
    r.dump_subkeys()
    r.dump_values()
    r.dump_dacl()

Open in new window

0
 
LVL 25

Expert Comment

by:clockwatcher
ID: 40296192
Crap.  Sorry about that.  I could've sworn this was in the python section.  But just noticed you wanted perl.  Obviously not getting enough sleep.  I'll see about throwing together a perl version.
0
 
LVL 25

Expert Comment

by:clockwatcher
ID: 40296195
I knew I wasn't completely crazy.  You did ask about it in python:  http://www.experts-exchange.com/Programming/Languages/Scripting/Python/Q_28508002.html

Anyway... bored and there's nothing much on TV so I'll throw together a perl version too.
0
 
LVL 25

Accepted Solution

by:
clockwatcher earned 2000 total points
ID: 40296817
Here's a perl version.
use Win32::TieRegistry (Delimiter=>"/",
          qw(KEY_ALL_ACCESS KEY_WRITE KEY_READ KEY_EXECUTE
             KEY_QUERY_VALUE KEY_SET_VALUE KEY_CREATE_SUB_KEY
             KEY_ENUMERATE_SUB_KEYS KEY_NOTIFY KEY_CREATE_LINK));

use Win32 qw (DACL_SECURITY_INFORMATION);
use Win32::API;

Win32::API::Struct->typedef('ACL_SIZE_INFORMATION', qw (
	DWORD AceCount;
	DWORD AclBytesInUse;
	DWORD AclBytesFree;
));
Win32::API::Struct->typedef('ACE', qw (
	BYTE AceType;
	BYTE AceFlags;
	WORD AceSize;
	DWORD AccessMask;
	LPDWORD pAccessMask;
	DWORD SidStart;
)); 

Win32::API::More->Import("advapi32", "BOOL GetSecurityDescriptorDacl(LPVOID pSecurityDescriptor, LPBOOL lpbDaclPresent, LPVOID pDacl, LPBOOL lpbDaclDefaulted)");
Win32::API::More->Import("advapi32", "BOOL GetAclInformation(DWORD pAcl, LPACL_SIZE_INFORMATION pAclInfo, DWORD nAclInfoLen, DWORD dwAclInfoClass)");
Win32::API::More->Import("advapi32", "BOOL GetAce(DWORD pAcl, DWORD dwAceIndex, LPVOID ppAce)");
Win32::API::More->Import("advapi32", "BOOL LookupAccountSid(DWORD lpSystemName, DWORD lpSid, LPTSTR lpName, LPDWORD cchName, LPTSTR lpReferencedDomainName, LPDWORD cchReferencedDomainName, LPDWORD peUse)");
Win32::API::More->Import("advapi32", "BOOL ConvertSidToStringSid(DWORD Sid, LPVOID ppStringSid)");


sub DumpSubKeys {
   my $key = shift;
   print "Subkeys:\n";
   for (keys(%{$key})) {
      print "\t$_\n" unless m#^/#;
   }
}

sub DumpValues {
   my $key = shift;
   print "Values:\n";
   for (keys(%{$key})) {
       $value = $key->{$_};
       print "\t$_ => $value\n" if m#^/#;
   }
}


	
sub DumpACL {

   my %access_map = (
	KEY_ALL_ACCESS, "All access",
	KEY_WRITE, "Write",
	KEY_READ, "Read",
	KEY_EXECUTE, "Execute",
	KEY_QUERY_VALUE, "Query",
	KEY_SET_VALUE, "Set value",
	KEY_CREATE_SUB_KEY, "Create subkey",
	KEY_ENUMERATE_SUB_KEYS, "Enum subkeys",
	KEY_NOTIFY, "Notify",
	KEY_CREATE_LINK, "Create link" );
	
   my $key = shift;
   my $pSecurityDescriptor = 0;
   $key->RegGetKeySecurity(DACL_SECURITY_INFORMATION, $pSecurityDescriptor);

   my $pPresent = 0;
   my $pDACL = pack "L", 0;
   my $pDefaulted = 0;
   if (GetSecurityDescriptorDacl($pSecurityDescriptor, $pPresent, $pDACL, $pDefaulted)) {
      $pDACL = unpack "L", $pDACL;

      my $pInfo = Win32::API::Struct->new('ACL_SIZE_INFORMATION');
      $pInfo->{'AceCount'} = 0;
      $pInfo->{'AclBytesInUse'} = 0;
      $pInfo->{'AclBytesFree'} = 0;

      if (GetAclInformation($pDACL, $pInfo, $pInfo->sizeof, 2)) {
         for (my $i=0; $i < $pInfo->{AceCount}; $i++) {
             my $pAce = Win32::API::Struct->new('ACE');
             $pAce->{AceType} = 0;
             $pAce->{AceFlags} = 0;
             $pAce->{AceSize} = 0;
             $pAce->{AccessMask} = 0;
             $pAce->{pAccessMask} = 0;
             $pAce->{SidStart} = 0;

             my $ppAce = pack "L", 0;
             if (GetAce($pDACL, $i, $ppAce)) {
                 $ppAce = unpack "L", $ppAce;
                 $pAce->FromMemory($ppAce);

                 print " Type: $pAce->{'AceType'}\n";
                 print " Flags: $pAce->{'AceFlags'}\n";
                 print " Mask: $pAce->{'AccessMask'}\n";

                 my $name = " " x 260; 
		 my $lName = length($name);
                 my $domainName = " " x 260;
                 my $ldomainName = length($domainName);
                 my $peUse = 0;
                 if (LookupAccountSid(0, $ppAce + 8, $name, $lName, $domainName, $ldomainName, $peUse)) {
                    $domainName =~ s/\x00.*//;
                    $name =~ s/\x00.*//;
                    print " Account: $domainName\\$name\n";
                 }
                 else {
                    print "LookupAccountSid Error = $^E\n";
                 }

                 print " Access:\n";
                 for my $k (keys(%access_map)) {
                     print "\t$access_map{$k}\n" if ($k & $pAce->{'AccessMask'}) == $k;
                 }

             }
             else {
                 print $^E;
             }
         }  
      }
   }
}

my $key = $Registry->{"CUser/Software/Microsoft/Windows/CurrentVersion/Internet Settings"};
DumpSubKeys($key);
DumpValues($key);
DumpACL($key);

Open in new window

0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
Measuring Server's processing rate with a simple powershell command. The differences in processing rate also was recorded in different use-cases, when a server in free and busy states.
Learn the basics of while and for loops in Python.  while loops are used for testing while, or until, a condition is met: The structure of a while loop is as follows:     while <condition>:         do something         repeate: The break statement m…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
Suggested Courses

580 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question