Access System32\config\SYSTEM hive in C#

0

I'm writing a utility to try and retrieve the computer name of a device when booted in WinPE and can't seem to find a native way in C# to read an offline hive. I have the following code to retrieve it and I get an ERROR_BADDB error:

ERROR_BADDB 
1009 (0x3F1)
    The configuration registry database is corrupt.

OfflineReg class:

class OfflineReg {

    // import services
    // portions taken from https://www.experts-exchange.com/questions/27413505/Loading-modifying-value-in-registry-hive-from-NET-C.html
    // http://stackoverflow.com/questions/2917309/regloadappkey-working-fine-on-32-bit-os-failing-on-64-bit-os-even-if-both-proc
    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    private struct LUID {
        public uint LowPart;
        public int HighPart;
    }

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    private struct LUID_AND_ATTRIBUTES {
        public LUID pLuid;
        public System.UInt32 Attributes;
    }

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 1)]
    private struct TokPriv1Luid {
        public int Count;
        public LUID Luid;
        public System.UInt32 Attr;
    }

    private const System.Int32 ANYSIZE_ARRAY = 1;
    private const System.UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
    private const System.UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
    private const System.UInt32 TOKEN_QUERY = 0x0008;

    private const uint HKEY_LOCAL_MACHINE = 0x80000002;
    private const string SE_RESTORE_NAME = "SeRestorePrivilege";
    private const string SE_BACKUP_NAME = "SeBackupPrivilege";

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    static extern System.IntPtr GetCurrentProcess();

    [System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true)]
    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
    static extern bool OpenProcessToken(System.IntPtr ProcessHandle, System.UInt32 DesiredAccess, out System.IntPtr TokenHandle);

    [System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
    static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);

    [System.Runtime.InteropServices.DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    static extern bool AdjustTokenPrivileges(
        System.IntPtr htok,
        bool disableAllPrivileges,
        ref TokPriv1Luid newState,
        int len,
        System.IntPtr prev,
        System.IntPtr relen);

    [System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true)]
    static extern System.Int32 RegLoadKey(System.UInt32 hKey, System.String lpSubKey, System.String lpFile);

    [System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true)]
    static extern System.Int32 RegUnLoadKey(System.UInt32 hKey, string lpSubKey);

    private System.IntPtr _myToken;
    private TokPriv1Luid _tokenPrivileges = new TokPriv1Luid();
    private TokPriv1Luid _tokenPrivileges2 = new TokPriv1Luid();

    private LUID _restoreLuid;
    private LUID _backupLuid;

    /**
     * temp_key
     * Temporary key name to load in HKLM
     */
    private System.String temp_key = null;

    /*
     * OfflineReg
     * Initialize registry environment, capture privileges, load key into HKLM
     */
    public OfflineReg(System.String hivepath) {
        // get process token
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out _myToken)) {
            int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            throw new OfflineRegException("There was a problem invoking OpenProcessToken; error code: " + error);
        }

        // get privilege value for SE_RESTORE_NAME
        if (!LookupPrivilegeValue(null, SE_RESTORE_NAME, out _restoreLuid)) {
            int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            throw new OfflineRegException("There was a problem invoking LookupPrivilegeValue; error code: " + error);
        }

        // get privilege value for SE_BACKUP_NAME
        if (!LookupPrivilegeValue(null, SE_BACKUP_NAME, out _backupLuid)) {
            int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            throw new OfflineRegException("There was a problem invoking LookupPrivilegeValue; error code: " + error);
        }

        // set privileges to allow registry editing
        _tokenPrivileges.Attr = SE_PRIVILEGE_ENABLED;
        _tokenPrivileges.Luid = _restoreLuid;
        _tokenPrivileges.Count = 1;

        _tokenPrivileges2.Attr = SE_PRIVILEGE_ENABLED;
        _tokenPrivileges2.Luid = _backupLuid;
        _tokenPrivileges2.Count = 1;

        // adjust privileges
        if (!AdjustTokenPrivileges(_myToken, false, ref _tokenPrivileges, 0, System.IntPtr.Zero, System.IntPtr.Zero)) {
            int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            throw new OfflineRegException("There was a problem invoking AdjustTokenPrivileges; error code: " + error);
        }

        if (!AdjustTokenPrivileges(_myToken, false, ref _tokenPrivileges2, 0, System.IntPtr.Zero, System.IntPtr.Zero)) {
            int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            throw new OfflineRegException("There was a problem invoking AdjustTokenPrivileges; error code: " + error);
        }

        // attempt to load key
        System.Random rand = new System.Random();
        this.temp_key = "OfflineRegTmp" + rand.Next(0, 9) + rand.Next(0, 9) + rand.Next(0, 9);
        int result = RegLoadKey(HKEY_LOCAL_MACHINE, this.temp_key, hivepath);
        if (result != 0) {
            throw new OfflineRegException("There was a problem invoking RegLoadKey; error code: " + result);
        }
    }

Result returns 1009 when invoked with the path to my CONFIG file I copied from a test machine:

OfflineReg reg = new OfflineReg("path_to_my_vs_dir\CONFIG");
c#
registry
asked on Stack Overflow Feb 27, 2017 by sheppardzw

1 Answer

0

Found it - I need to access \Windows\System32\config\SYSTEM in that path, not by copying the file anywhere. It must depend on other registry hives in that directory.

Access the hive in its original path and you should be good.

answered on Stack Overflow Feb 28, 2017 by sheppardzw • edited Mar 8, 2017 by sheppardzw

User contributions licensed under CC BY-SA 3.0