提权之后,就可以切换桌面,切换会话,实现登录界面截图和模拟键盘了
以SharpDX截屏为例
1、切换桌面定义
C#
[Flags]
public enum ACCESS_MASK : uint
{
DELETE = 0x00010000,
READ_CONTROL = 0x00020000,
WRITE_DAC = 0x00040000,
WRITE_OWNER = 0x00080000,
SYNCHRONIZE = 0x00100000,
STANDARD_RIGHTS_REQUIRED = 0x000F0000,
STANDARD_RIGHTS_READ = 0x00020000,
STANDARD_RIGHTS_WRITE = 0x00020000,
STANDARD_RIGHTS_EXECUTE = 0x00020000,
STANDARD_RIGHTS_ALL = 0x001F0000,
SPECIFIC_RIGHTS_ALL = 0x0000FFFF,
ACCESS_SYSTEM_SECURITY = 0x01000000,
MAXIMUM_ALLOWED = 0x02000000,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000,
DESKTOP_READOBJECTS = 0x00000001,
DESKTOP_CREATEWINDOW = 0x00000002,
DESKTOP_CREATEMENU = 0x00000004,
DESKTOP_HOOKCONTROL = 0x00000008,
DESKTOP_JOURNALRECORD = 0x00000010,
DESKTOP_JOURNALPLAYBACK = 0x00000020,
DESKTOP_ENUMERATE = 0x00000040,
DESKTOP_WRITEOBJECTS = 0x00000080,
DESKTOP_SWITCHDESKTOP = 0x00000100,
WINSTA_ENUMDESKTOPS = 0x00000001,
WINSTA_READATTRIBUTES = 0x00000002,
WINSTA_ACCESSCLIPBOARD = 0x00000004,
WINSTA_CREATEDESKTOP = 0x00000008,
WINSTA_WRITEATTRIBUTES = 0x00000010,
WINSTA_ACCESSGLOBALATOMS = 0x00000020,
WINSTA_EXITWINDOWS = 0x00000040,
WINSTA_ENUMERATE = 0x00000100,
WINSTA_READSCREEN = 0x00000200,
WINSTA_ALL_ACCESS = 0x0000037F
}
[DllImport("user32.dll", SetLastError = true)]
public static extern nint OpenInputDesktop(uint dwFlags, bool fInherit, ACCESS_MASK dwDesiredAccess);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool CloseDesktop(nint hDesktop);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetThreadDesktop(nint hDesktop);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SwitchDesktop(nint hDesktop);
private static nint lastInputDesktop;
public static bool SwitchToInputDesktop()
{
try
{
CloseDesktop(lastInputDesktop);
nint inputDesktop = OpenInputDesktop();
if (inputDesktop == nint.Zero)
{
return false;
}
bool result = SetThreadDesktop(inputDesktop);
result &= SwitchDesktop(inputDesktop);
lastInputDesktop = inputDesktop;
return result;
}
catch (Exception ex)
{
return false;
}
}
2、截屏使用
在调用 TryAcquireNextFrame 获取一帧之前,调用 SwitchToInputDesktop
C#
SwitchToInputDesktop();
SharpDX.DXGI.Resource desktopResource = null;
OutputDuplicateFrameInformation frameInfo = new OutputDuplicateFrameInformation()
Result result = mDeskDupl.TryAcquireNextFrame(30, out frameInfo, out desktopResource);
3、模拟键盘使用
模拟键盘比较特殊,定时检测
C#
public const int KEYEVENTF_EXTENDEDKEY = 0x0000;
public const int KEYEVENTF_KEYUP = 0x0002;
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private readonly ConcurrentQueue<Action> inputActions = new();
private void CheckQueue()
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
Task.Factory.StartNew((a) =>
{
CancellationTokenSource tks = a as CancellationTokenSource;
while (tks.IsCancellationRequested == false)
{
if (inputActions.IsEmpty == false)
{
try
{
if (inputActions.TryDequeue(out var action))
{
if (Win32Interop.SwitchToInputDesktop()==false)
{
tks.Cancel();
CheckQueue();
}
action();
}
}
finally
{
}
}
else
{
Thread.Sleep(10);
}
}
}, cancellationTokenSource, TaskCreationOptions.LongRunning);
}
private void TryOnInputDesktop(Action inputAction)
{
inputActions.Enqueue(() =>
{
try
{
inputAction();
}
catch (Exception)
{
}
});
}
调用
C#
//先调用CheckQueue定时检测
CheckQueue();
//模拟键盘
TryOnInputDesktop(() =>
{
keybd_event(key, (byte)User32.MapVirtualKey(key, 0),type , 0);
});