查询回收站,同时冒充用户

时间:2016-05-31 12:52:34

标签: c# winapi impersonation

长话短说,我正在尝试以另一个用户的身份查询回收站。这是一个带有服务的WPF应用程序,我需要在服务中查询回收站... 我知道 ...我们需要使用NetNamedPipeBinding,并且不能使用OperationBehavior属性。

到目前为止,我使用以下方法在Windows 10 VM中取得了成功:

然后我在Windows XP VM中尝试了相同的代码,但我无法使用它。一旦SHQueryRecycleBin被调用,我就会看到一个消息框显示:

  

C:\上的回收站已损坏。是否要清空此驱动器的回收站?

我知道这不是真的,因为如果我作为测试人员运行,我可以查询回收站,并通过Windows资源管理器查看它。

这看起来像是一个常见问题,我找到了Microsoft KB article。这列在原因中:

  

当引用的逻辑驱动器是NTFS驱动器且权限比较操作中出错时,可能会发生此问题。

我相信我的所有问题都与权限有关。但这就是我被困住的地方。我不知道为什么我没有必要的权限,也不知道如何解决这个问题。有没有人有任何想法?

我尝试使用ProcessAccessFlags.AllTOKEN_ALL_ACCESSAdjustTokenPrivileges作为远景,但没有帮助。

我一直在使用LINQPad对此进行测试,并使用此SO answer在系统帐户下运行LINQPad。为了完整性,这里有一个片段,应该可以轻松复制/粘贴,输出在测试仪和系统下运行。

作为测试人员运行:

OpenProcessToken returned 1
AdjustTokenPrivileges = True
Got user's token as 2264
Process running as XPTESTER\tester
Impersonating XPTESTER\tester
hresult=0, cbSize=20, i64Size=160420, i64NumItems=8

以系统身份运行:

OpenProcessToken returned 1
AdjustTokenPrivileges = True
Got user's token as 2128
Process running as NT AUTHORITY\SYSTEM
Impersonating XPTESTER\tester
hresult=0, cbSize=20, i64Size=0, i64NumItems=0

原油测试代码:

void Main()
{
    string drive = "C:";
    uint pid = 1676;
    IntPtr userToken = DuplicateProcessToken(pid);

    LUID tLuid = new LUID();
    TOKEN_PRIVILEGES NewState = new TOKEN_PRIVILEGES();
    NewState.PrivilegeCount = 1;
    NewState.Privileges.pLuid = tLuid;
    NewState.Privileges.Attributes = SE_PRIVILEGE_ENABLED;
    var adjustResult = AdjustTokenPrivileges(userToken, false, ref NewState, (uint)Marshal.SizeOf(NewState), IntPtr.Zero, IntPtr.Zero);
    Console.WriteLine("AdjustTokenPrivileges = {0}", adjustResult);

    Console.WriteLine("Got user's token as {0}", userToken);
    Console.WriteLine("Process running as {0}", WindowsIdentity.GetCurrent().Name);
    using(var impersonatedUser = WindowsIdentity.Impersonate(userToken))
    {
        var winIdentity = WindowsIdentity.GetCurrent();
        Console.WriteLine("Impersonating {0}", winIdentity.Name);   

        var result = new SHQUERYRBINFO();
        result.cbSize = Marshal.SizeOf(typeof(SHQUERYRBINFO));
        int hresult = SHQueryRecycleBin(drive, ref result);

        Console.WriteLine(
            "hresult={0}, cbSize={1}, i64Size={2}, i64NumItems={3}",
            hresult,
            result.cbSize,
            result.i64Size,
            result.i64NumItems);
    }
}

public const Int32 SE_PRIVILEGE_ENABLED = 0x00000002;

public static IntPtr DuplicateProcessToken(uint pid)
{
    IntPtr hProcess = OpenProcess(ProcessAccessFlags.All, 0, pid);  
    uint uPriv = TOKEN_ALL_ACCESS;  
    IntPtr token = IntPtr.Zero;
    int result = OpenProcessToken(hProcess, uPriv, ref token);
    Console.WriteLine("OpenProcessToken returned {0}", result);
    return token;
}

public const uint STANDARD_RIGHTS_REQUIRED = 0x00F0000;
public const uint STANDARD_RIGHTS_READ = 0x002000;
public const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
public const uint TOKEN_DUPLICATE = 0x0002;
public const uint TOKEN_IMPERSONATE = 0x004;
public const uint TOKEN_QUERY = 0x0008;
public const uint TOKEN_QUERY_SOURCE = 0x0010;
public const uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
public const uint TOKEN_ADJUST_GROUPS = 0x0040;
public const uint TOKEN_ADJUST_DEFAULT = 0x0080;
public const uint TOKEN_ADJUST_SESSIONID = 0x0100;
public const uint TOKEN_READ = (STANDARD_RIGHTS_REQUIRED | TOKEN_QUERY);
public const uint TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED
    | TOKEN_ASSIGN_PRIMARY
    | TOKEN_DUPLICATE
    | TOKEN_IMPERSONATE
    | TOKEN_QUERY
    | TOKEN_QUERY_SOURCE
    | TOKEN_ADJUST_PRIVILEGES
    | TOKEN_ADJUST_GROUPS
    | TOKEN_ADJUST_DEFAULT
    | TOKEN_ADJUST_SESSIONID);

// Pack = 8 for x64
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct SHQUERYRBINFO
{
    public int cbSize;
    public long i64Size;
    public long i64NumItems;        
}

[DllImport("shell32.dll", SetLastError = true)]
private static extern int SHQueryRecycleBin(string pszRootPath, ref SHQUERYRBINFO pSHQueryRBInfo);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, int blnheritHanfle, uint dwAppProcessId);

[DllImport("advapi32.dll", SetLastError = true)]
public static extern int OpenProcessToken(IntPtr processHandle, uint desiredAccess, ref IntPtr tokenHandle);

[Flags]
public enum ProcessAccessFlags : uint
{
    All = 0x001F0FFF,
    Terminate = 0x00000001,
    CreateThread = 0x00000002,
    VMOperation = 0x00000008,
    VMRead = 0x00000010,
    VMWrite = 0x00000020,
    DupHandle = 0x00000040,
    SetInformation = 0x00000200,
    QueryInformation = 0x00000400,
    Synchronize = 0x00100000
}

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AdjustTokenPrivileges(
    IntPtr TokenHandle,
    [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
    ref TOKEN_PRIVILEGES NewState,
    UInt32 BufferLength,
    IntPtr PreviousState,
    IntPtr ReturnLength);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct LUID
{
  public Int32 LowPart;
  public Int32 HighPart;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct LUID_AND_ATTRIBUTES
{
  public LUID pLuid;
  public Int32 Attributes;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TOKEN_PRIVILEGES
{
  public Int32 PrivilegeCount;
  public LUID_AND_ATTRIBUTES Privileges;
}

0 个答案:

没有答案