Automatically set security attributes when moving files with Win32 API ? (C#) - c#

I'm currently developing an app that have to move a file to another application folder. But the other application must have a specific permissions on files that are copied.
When I use the Win32 API to MoveFileFromApp (it's uwp app), it doesn't update the security attributes to inherit the folder.
here is the code of MoveFile (C#)
[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern bool MoveFileFromApp(
string lpExistingFileName, string lpNewFileName);
Does anyone know how to set these security permissions for the folder automatically during the moving process ?
Thank you very much !

I tried to use SetNamedSecurityInfo method by P/Invoke in UWP app with the following code. The error ERROR_ACCESS_DENIED(error code is 5) always exists in UWP app. But in Win32, the usage of SetNamedSecurityInfo method with the value UNPROTECTED_DACL_SECURITY_INFORMATION to inherit the security attributes is successful.
In UWP, there are some limitations on file system access permission. Though the SetNamedSecurityInfo method can be called successfully, it does not work as expected.
The code to use SetNamedSecurityInfo method in UWP:
public uint DACL_SECURITY_INFORMATION = 0x00000004;
public uint UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000;
public uint ACL_REVISION = 0x2;
[StructLayout(LayoutKind.Sequential)]
public struct ACL
{
public byte AclRevision;
public byte Sbz1;
public ushort AclSize;
public ushort AceCount;
public ushort Sbz2;
}
public enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY,
SE_REGISTRY_WOW64_64KEY,
}
[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool MoveFileFromAppW(
string lpExistingFileName,
string lpNewFileName);
[DllImport("advapi32.DLL", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern uint SetNamedSecurityInfo(
string lpFileName,
SE_OBJECT_TYPE ObjectType,
uint SecurityInfo,
IntPtr psidOwner,
IntPtr psidGroup,
ref ACL pDacl,
IntPtr pSacl);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool InitializeAcl(ref ACL pAcl, int nAclLength, uint dwAclRevision);
[DllImport("api-ms-win-core-file-fromapp-l1-1-0.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall,
SetLastError = true)]
internal static extern bool MoveFileFromApp(
string lpExistingFileName,
string lpNewFileName
);
public void SetFilePermission(string FileName)
{//Use the method to let the file inherit the security attributes from parent object
bool ret = false;
ACL pDacl = new ACL();
ret = InitializeAcl(ref pDacl, Marshal.SizeOf<ACL>(), ACL_REVISION);
uint SecurityInfo = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
uint err = SetNamedSecurityInfo(FileName, SE_OBJECT_TYPE.SE_FILE_OBJECT, SecurityInfo, IntPtr.Zero, IntPtr.Zero, ref pDacl, IntPtr.Zero);
}

Related

Why FindNextFile is not working in my C# code?

The code is not working for me. I am using Visual Studio 2008 and .NET 3.5. I am not getting file name. The return value from FindNextFile is null. The reason not to use Directory.GetFiles() is that i want to traverse file one by one. For Directory.GetFiles(), i am gettign all the files in array at a time
struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
class Program
{
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern bool FindClose(IntPtr hFindFile);
static void Main(string[] args)
{
StreamWriter sw = new StreamWriter("dir.txt", false);
string dir = Path.GetFullPath(System.IO.Directory.GetCurrentDirectory());
WIN32_FIND_DATA wfd = new WIN32_FIND_DATA();
IntPtr h = FindFirstFile((dir + #"\*.*"), out wfd);
while (FindNextFile(h, out wfd))
sw.WriteLine(wfd.cFileName);
FindClose(h);
sw.Flush();
sw.Close();
}
}
Many Windows APIs support two string types: ANSI (8-bit characters) and Wide (16-bit characters). The problem here seems to be that you are calling the wide version of the APIs but interpreting the results as ANSI.
You can fix this by marking the WIN32_FIND_DATA struct as unicode (or auto). CharSet.Auto and CharSet.Unicode seem to do the same thing here.
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct WIN32_FIND_DATA {
UPDATE
Try adding an [Out] attribute to the imports as suggested by Hans Passant.
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern IntPtr FindFirstFile(string lpFileName, [Out] out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern bool FindNextFile(IntPtr hFindFile, [Out] out WIN32_FIND_DATA lpFindFileData);

How to load registry hive for a newly created windows user who have never login?

I created a new windows user using C# and I would like to restrict list of apps to run through setting registry using C#. But the user profile and its registry is not initialized yet, since the user has never login, it will not have registry hive loaded and I cannot make changes.
I have tried Process.start() and set LoadUserProfile=true. I can see that the folder for the user is created under C:\Users\
However, if I get the user's sid and check HKEY_USERS\ , there is no such entry. I learned that when a user login, windows will load the registry hive, and unload when log out. Therefore I need to load the registry hive without user login.
Reference:
Editing registry value for newly created user
Load registry hive from C# fails
Get sid
NTAccount user = new NTAccount(username);
SecurityIdentifier s = (SecurityIdentifier)user.Translate(typeof(SecurityIdentifier));
string sidString = s.ToString();
Load Registry
public class RegistryTest
{
[StructLayout(LayoutKind.Sequential)]
private struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
private struct LUID_AND_ATTRIBUTES
{
public LUID pLuid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct TokPriv1Luid
{
public int Count;
public LUID Luid;
public UInt32 Attr;
}
private const Int32 ANYSIZE_ARRAY = 1;
private const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
private const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
private const UInt32 TOKEN_QUERY = 0x0008;
private const uint HKEY_USERS = 0x80000003;
private const string SE_RESTORE_NAME = "SeRestorePrivilege";
private const string SE_BACKUP_NAME = "SeBackupPrivilege";
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
static extern bool AdjustTokenPrivileges(
IntPtr htok,
bool disableAllPrivileges,
ref TokPriv1Luid newState,
int len,
IntPtr prev,
IntPtr relen);
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegLoadKey(UInt32 hKey, String lpSubKey, String lpFile);
[DllImport("advapi32.dll", SetLastError = true)]
static extern int RegUnLoadKey(UInt32 hKey, string lpSubKey);
private IntPtr _myToken;
private TokPriv1Luid _tokenPrivileges = new TokPriv1Luid();
private TokPriv1Luid _tokenPrivileges2 = new TokPriv1Luid();
private LUID _restoreLuid;
private LUID _backupLuid;
public RegistryTest(string sid)
{
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out _myToken))
Console.WriteLine("OpenProcess Error");
if (!LookupPrivilegeValue(null, SE_RESTORE_NAME, out _restoreLuid))
Console.WriteLine("LookupPrivilegeValue Error");
if (!LookupPrivilegeValue(null, SE_BACKUP_NAME, out _backupLuid))
Console.WriteLine("LookupPrivilegeValue Error");
_tokenPrivileges.Attr = SE_PRIVILEGE_ENABLED;
_tokenPrivileges.Luid = _restoreLuid;
_tokenPrivileges.Count = 1;
_tokenPrivileges2.Attr = SE_PRIVILEGE_ENABLED;
_tokenPrivileges2.Luid = _backupLuid;
_tokenPrivileges2.Count = 1;
if (!AdjustTokenPrivileges(_myToken, false, ref _tokenPrivileges, 0, IntPtr.Zero, IntPtr.Zero))
Console.WriteLine("AdjustTokenPrivileges Error: " + Marshal.GetLastWin32Error());
if (!AdjustTokenPrivileges(_myToken, false, ref _tokenPrivileges2, 0, IntPtr.Zero, IntPtr.Zero))
Console.WriteLine("AdjustTokenPrivileges Error: " + Marshal.GetLastWin32Error());
// --> RegLoadKey fails with return value 32<--
int retVal = RegLoadKey(HKEY_USERS, sid, #"C:\Users\Default\NTUSER.DAT");
if (retVal != 0)
Console.WriteLine("RegLoadKey Error:" + retVal);
}
}
The RegLoadKey API should return 0 but I got 32
I have find a way to do it, I load default registry hive in C:\Users\Default. After I change it to C:\Users\[username]\NTUSER.DAT and then the registry hive is loaded.

Getting Symbols from debugged process MainModule

I started writing a debugger in C#, to debug any process on my operating system. For now, it only can handle breakpoints (HW, SW, and Memory), but now I wanted to show the opcode of the process.
My first attempt was with nidsasm (NASM), but this is not suitable, because after startup a.Net Application assembler instructions are different from ndisasm (tested with CheatEngine).
So I searched a while and found some methods from the dbghelp.dll which can be called to list all loaded modules and symbols (plus the base address). Ok, my attempt is, to disassemble all modules separately with SharpDisasm.
I use ProcessModuleCollection modules = ProcessData.Instance.MPMR.ReadProcess.Modules; to get all loaded modules of the process. This works perfectly.
Now I tried to load the symbols of the MainModule, but at this point, I stuck with the implementation. I implemented the SymEnumSymbols Function with p/Invoke and other necessary functions like SymInitialize.
When I call it with a BaseAddress of for example the "User32.dll", all symbols are printed perfectly, but for the MainModule, I didn't get any symbols.
This is a screenshot from CheatEngine:
Symbols gained from Cheat Engine
As you can see, there are symbols like "Form1_Load", which I don't get with my implementation.
This is the necessary code sample:
if (!DebugApi.SymInitialize(ProcessData.Instance.MPMR.M_hProcess, null, false))
{
var err = Marshal.GetLastWin32Error();
//throw new Exception("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
Console.WriteLine("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
return;
}
if (!DebugApi.SymEnumSymbols(ProcessData.Instance.MPMR.M_hProcess, (ulong)ProcessData.Instance.MPMR.ReadProcess.MainModule.BaseAddress, "!", DebugApi.EnumSyms, IntPtr.Zero))
{
var err = Marshal.GetLastWin32Error();
//throw new Exception("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
Console.WriteLine("GetMemoryInfo failed : GetLastError() : " + new Win32Exception(err).Message);
return;
}
DebugApi.SymCleanup(ProcessData.Instance.MPMR.M_hProcess);
And my DebugApi, with all necessary p/Invoke functions.
public class DebugApi
{
[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, [MarshalAs(UnmanagedType.Bool)]bool fInvadeProcess);
[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymCleanup(IntPtr hProcess);
[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern ulong SymLoadModuleEx(IntPtr hProcess, IntPtr hFile, string ImageName, string ModuleName, long BaseOfDll, int DllSize, IntPtr Data, int Flags);
[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymEnumSymbols(IntPtr hProcess, ulong BaseOfDll, string Mask, PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, IntPtr UserContext);
public delegate bool PSYM_ENUMERATESYMBOLS_CALLBACK(ref SYMBOL_INFO pSymInfo, uint SymbolSize, IntPtr UserContext);
public static bool EnumSyms(ref SYMBOL_INFO pSymInfo, uint SymbolSize, IntPtr UserContext)
{
Console.Out.WriteLine("Name: " + pSymInfo.Name);
return true;
}
[Flags]
public enum SymFlag : uint
{
VALUEPRESENT = 0x00000001,
REGISTER = 0x00000008,
REGREL = 0x00000010,
FRAMEREL = 0x00000020,
PARAMETER = 0x00000040,
LOCAL = 0x00000080,
CONSTANT = 0x00000100,
EXPORT = 0x00000200,
FORWARDER = 0x00000400,
FUNCTION = 0x00000800,
VIRTUAL = 0x00001000,
THUNK = 0x00002000,
TLSREL = 0x00004000,
}
[Flags]
public enum SymTagEnum : uint
{
Null,
Exe,
Compiland,
CompilandDetails,
CompilandEnv,
Function,
Block,
Data,
Annotation,
Label,
PublicSymbol,
UDT,
Enum,
FunctionType,
PointerType,
ArrayType,
BaseType,
Typedef,
BaseClass,
Friend,
FunctionArgType,
FuncDebugStart,
FuncDebugEnd,
UsingNamespace,
VTableShape,
VTable,
Custom,
Thunk,
CustomType,
ManagedType,
Dimension
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SYMBOL_INFO
{
public uint SizeOfStruct;
public uint TypeIndex;
public ulong Reserved1;
public ulong Reserved2;
public uint Reserved3;
public uint Size;
public ulong ModBase;
public SymFlag Flags;
public ulong Value;
public ulong Address;
public uint Register;
public uint Scope;
public SymTagEnum Tag;
public int NameLen;
public int MaxNameLen;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
public string Name;
}
}
My Functions should be ok, because it works with other Modules (loaded dll's for example). Maybe I don't understand the concept of symbols of a .Net Executable or missing something.
can it be that you are looking for System.Diagnostics.SymbolStore.ISymbolScope.
Have a look at the class SymbolAccess, you can use it to gain access to ISymbolScope.GetLocals() that returns ISymbolVariable[] and GetChildren() again returning in this time an array called ISymbolVariable[]
Now another interesting set of reference code samples is the Debugger extension lets you "snif" the values as shown here

FindNextFile ERROR_INVALID_NAME

I'm trying to use the WINAPI functions FindFirstFile and FindNextFile.
However, I'm experiencing some issues.
When I first call the function FindFirstFile it works fine. I've got a valid handler and the first folder/file name is properly populated inside the WIN32_FIND_DATA structure. No error is found with GetLastError.
Then, I call FindNextFile which returns true as there are more folders in the directory I'm scanning. But I can't retrieve the next folder/file name and GetLastError returns 123 (0x7B) ERROR_INVALID_NAME.
I'm a little confused as it says in the official documentation that if an error occurs it should return 0.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa364428(v=vs.85).aspx
Return value
If the function succeeds, the return value is nonzero and the lpFindFileData parameter contains information about the next file or directory found.
If the function fails, the return value is zero and the contents of lpFindFileData are indeterminate. To get extended error information, call the GetLastError function.
If the function fails because no more matching files can be found, the GetLastError function returns ERROR_NO_MORE_FILES.
I'm using .NET 4.5.1 and Visual Studio 2013 on Windows 7 x64.
Here is a sample code.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
...
[DllImport("Kernel32.dll", EntryPoint = "FindFirstFile", SetLastError = true)]
public static extern IntPtr FindFirstFile(string lpFileName, ref WIN32_FIND_DATA lpFindFileData);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("Kernel32.dll", EntryPoint = "FindFirstFile", SetLastError = true)]
public static extern bool FindNextFile(IntPtr hFindFile, ref WIN32_FIND_DATA lpFindFileData);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("Kernel32.dll", EntryPoint = "FindClose", SetLastError = true)]
public static extern bool FindClose(IntPtr hFindFile);
...
public static void Test()
{
WIN32_FIND_DATA metaDataFile = new WIN32_FIND_DATA();
IntPtr nextHandle = FileScanner.FindFirstFile("C:\\*", ref metaDataFile);
Console.WriteLine(Marshal.GetLastWin32Error()); // This equals 0x0 ERROR_SUCCESS
Console.WriteLine(metaDataFile.cFileName); // This equals $Recycle.Bin
/* Check invalid handler */
if (nextHandle != new IntPtr(-1L))
{
bool moreFiles = true;
while (moreFiles)
{
moreFiles = FileScanner.FindNextFile(nextHandle, ref metaDataFile);
Console.WriteLine(Marshal.GetLastWin32Error()); // This equals 0x7B ERROR_INVALID_NAME
Console.WriteLine(metaDataFile.cFileName); // This equals $Recycle.Bin and this value never change.
}
FindClose(nextHandle);
}
}
For some reason, moreFiles is always true and GetLastError returns ERROR_INVALID_NAME ...
If you need any details please ask me.
Any help would really be appreciated !
Only call Marshal.GetLastWin32Error is the API call reports failure. In the case of FindNextFile it does so by returning false. You are checking the value returned by Marshal.GetLastWin32Error indiscriminately.
The documentation makes this clear when it tells you how the functions indicate failure. You even linked the text. But you said:
I'm a little confused as it says in the official documentation that if an error occurs it should return 0.
That's right. So check the return value against 0. In the case of a BOOL marshalled as C# bool, that means that the function returns false if it fails. But you simply ignored the return value and tested the value returned by Marshal.GetLastWin32Error(), something altogether different.
The code should be more like this:
public static void Test()
{
WIN32_FIND_DATA fd = new WIN32_FIND_DATA();
IntPtr findHandle = FileScanner.FindFirstFile("C:\\*", ref fd);
if (findHandle == INVALID_HANDLE_VALUE)
throw new Win32Exception();
do
{
Console.WriteLine(fd.cFileName);
} while (FileScanner.FindNextFile(findHandle, ref fd));
// you might check that Marshal.GetLastWin32Error() returns ERROR_NO_MORE_FILES
// at this point, otherwise the enumeration failed abnormally
if (!FindClose(findHandle))
throw new Win32Exception();
}
Your other problem, and it's what hurting you most, is your p/invoke declarations. Look closely at this one:
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("Kernel32.dll", EntryPoint = "FindFirstFile", SetLastError = true)]
public static extern bool FindNextFile(IntPtr hFindFile,
ref WIN32_FIND_DATA lpFindFileData);
The EntryPoint is not correct. So you are actually calling FindFirstFile instead of FindNextFile and it's hardly surprising that fails.
Specifying the EntryPoint when you don't need to is simply asking for trouble. And you've fallen right into the trap. I'd declare these imports like so:
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindFirstFile(string lpFileName,
ref WIN32_FIND_DATA lpFindFileData);
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool FindNextFile(IntPtr hFindFile,
ref WIN32_FIND_DATA lpFindFileData);
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool FindClose(IntPtr hFindFile);
Note that there's no need for the return attribute since UnmanagedType.Bool is the default.
And then you'd need to change the CharSet on the struct to be CharSet.Unicode to match. There's no point at all in opting for ANSI here.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WIN32_FIND_DATA
{
....
}
Finally, all of this code seems to me to be pointless. What's wrong with Directory.EnumerateFiles and Directory.EnumerateDirectories?

Mount other users hive with C# .net

I'm writing an application that will write some registry key for every selected user.
I was wondering if there was a proper way to mount another user's hive to write in it.
At the moment, I'm using "REG LOAD" to mount every hive. It's functional, but messy.
Any Idea ?
Thanks in advance for your answers.
Cheers.
--- EDIT 19.06.2013 ---
Okay, thanks for the help, I was able to call the function, but was unauthorized to mount the registry.
I tought it was a missing privilege, and force it to run in admin.
I still recieve a 0x522 error, which mean, according to MSDN, that I don't have the right to mount the hive.
I searched the web and found different explanation and possibilities, but I still can't manage to mount the hive.
I'm pretty new in C# developpement and Windows API...
Here's the code I tried to understand and used in my tests.
Am I missing something ?
Thanks in advance for your answer.
namespace mountregistry2
{
public partial class Form1 : Form
{
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public int LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
public LUID Luid;
public int Attributes;
public int PrivilegeCount;
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int OpenProcessToken(int ProcessHandle, int DesiredAccess,
ref int tokenhandle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetCurrentProcess();
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int LookupPrivilegeValue(string lpsystemname, string lpname,
[MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int AdjustTokenPrivileges(int tokenhandle, int disableprivs,
[MarshalAs(UnmanagedType.Struct)]ref TOKEN_PRIVILEGES Newstate, int bufferlength,
int PreivousState, int Returnlength);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int RegLoadKey(uint hKey, string lpSubKey, string lpFile);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int RegUnLoadKey(uint hKey, string lpSubKey);
public const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public const int TOKEN_QUERY = 0x00000008;
public const int SE_PRIVILEGE_ENABLED = 0x00000002;
public const string SE_RESTORE_NAME = "SeRestorePrivilege";
public const string SE_BACKUP_NAME = "SeBackupPrivilege";
public const uint HKEY_USERS = 0x80000003;
public string shortname;
bool unloaded = false;
private void testmountregistry()
{
int token = 0;
int retval = 0;
TOKEN_PRIVILEGES TokenPrivileges1 = new TOKEN_PRIVILEGES();
TOKEN_PRIVILEGES TokenPrivileges2 = new TOKEN_PRIVILEGES();
LUID RestoreLuid = new LUID();
LUID BackupLuid = new LUID();
retval = GetCurrentProcess();
MessageBox.Show(retval.ToString("X")); //returns FFFFFFFF, which should work
retval = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref token);
MessageBox.Show(retval.ToString("X"));//RETURNS 1
retval = LookupPrivilegeValue(null, SE_RESTORE_NAME, ref RestoreLuid);
MessageBox.Show(retval.ToString("X"));//Returns 1
retval = LookupPrivilegeValue(null, SE_BACKUP_NAME, ref BackupLuid);
MessageBox.Show(retval.ToString("X"));//Returns 1
TokenPrivileges1.PrivilegeCount = 1;
TokenPrivileges1.Attributes = SE_PRIVILEGE_ENABLED;
TokenPrivileges1.Luid = RestoreLuid;
TokenPrivileges2.PrivilegeCount = 1;
TokenPrivileges2.Attributes = SE_PRIVILEGE_ENABLED;
TokenPrivileges2.Luid = BackupLuid;
retval = AdjustTokenPrivileges(token, 0, ref TokenPrivileges1, 1024, 0, 0);
MessageBox.Show(retval.ToString("X"));//Returns 1
retval = AdjustTokenPrivileges(token, 0, ref TokenPrivileges2, 1024, 0, 0);
MessageBox.Show(retval.ToString("X"));//Returns 1
uint hkey_users = 0x80000003;
int interror = RegLoadKey(hkey_users, "test", #"C:\Users\Public\NTUSER.DAT");
MessageBox.Show(interror.ToString("X"));//Return 0x522
return;
}
}
}
You can call the RegLoadKey API method using platform invoke.
[DllImport("advapi32.dll", SetLastError = true)]
static extern Int32 RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile);

Categories

Resources