.NET 8 + WPF 利用 DPAPI 和 RDP 实现本地映射远程程序

前言

在现代远程办公场景中,如何高效安全地访问远程计算机上的资源成为了一个重要问题。

本文将探讨如何结合 DPAPI(数据保护API)和 RDP(远程桌面协议)技术,实现在本地安全地映射并打开远程计算机上的程序。

通过详细的步骤和实际案例,将展示这一技术的应用价值,帮助大家提升远程工作的便利性和安全性,同时确保数据的加密传输与存储。

环境说明

开发工具:Visual Studio 2022

客户端技术:.NET 8 + WPF

其他技术:DPAPI

系统要求:Windows 7 及以上版本(64位)

正文

接下来是该工具的具体使用教程。

先对远程服务器上面的注册表进行设置。

路径如下:HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services

如下图所示,目前里面没啥东西。

可以通过当前工具进行设置,在服务器上面打开RemoteShadowApp程序,然后点击设置注册表,即可看到注册表被自动创建成功了。这样可以直接快速设置注册表。

当然,如果不想在服务器上面运行,也可以手动自己设置一下。自己创建一个注册表,创建DWORD键值对,名称是 fAllowUnlistedRemotePrograms 对应的值设为1。如果觉得麻烦,那就用我上面的工具直接设置,效果也是一样的。

在本机机器上面,就可以通过远程访问目标服务器的程序了。操作如下:

例如我要打开远程桌面上的Notepad++程序

我需要获取服务器的IP、登陆的用户名、密码、以及NotePad++的启动程序的绝对路径,例如如下图所示。

我没做记住信息功能,所以大家也可以自己创建一个记事本之类的,存储你的远程程序信息,方便粘贴进去填写。都输入完毕以后,点击 【打开远程程序】 按钮

注意事项:如果远程服务器有360等软件,可能会限制你的权限,例如一直卡在这个界面

此刻你需要点开 显示详细信息,可以看到有一个登陆按钮,点击登陆即可。

这个只有部分远程服务器会出现,如果本机没有一些限制设置或者安全软件,这一步不会出现。仅在有出现这个现象的时候才需要这样操作。

打开的远程的notepad++程序,效果如图所示。

接着我们打开远程服务器,看下现象。具体如图所示效果。

支持打开多个远程程序,例如,我现在打开一个以前自己写的控制台程序服务,地址如下

在刚才的程序里面,更改启动的路径为上面的控制台服务路径,然后启动。可以看到启动成功了。并且和上一个notepad程序可以共存。

同样,服务器上面也并不存在控制台程序的页面,但是存在进程。控制台程序也是占用服务器资源,而不会占用本地资源。

如果当前没啥需要,就可以退出启动器,退出启动器对已经打开的远程程序没有任何影响。启动器只是用来提供远程程序作用,没有其他功能。

启动器核心功能,主要是DPAPI加密功能。DPAPI(数据保护应用程序编程接口)是微软提供的一个用于帮助保护数据安全的API,它可以简化在Windows平台上的数据加密过程。DPAPI 提供了一个系统级别的加密服务,其特点是不需要应用程序自行处理加密密钥的存储和保护。DPAPI主要用于保护敏感信息,如密码、密钥和其他个人或系统数据。

如下所示代码,我在Wesky.Net.Opentools开源项目上也有集成该功能。此处我在本程序内直接使用来加密。必须加密以后的密码,才能被远程服务器识别。

下面是DPAPI具体的加密和解密过程:

c# 复制代码
 /// <summary>
 /// 加密数据
 /// </summary>
 /// <param name="dataToEncrypt"></param>
 /// <returns></returns>
 public static string EncryptData(string dataToEncrypt)
 {
     try
     {
         byte[] secret = Encoding.Unicode.GetBytes(dataToEncrypt);
         byte[] encryptedSecret = ProtectedData.Protect(secret, additionalEntropy, DataProtectionScope.LocalMachine);
         string res = string.Empty;
         foreach (byte b in encryptedSecret)
         {
             res += b.ToString("X2");
         }
         return res;

     }
     catch (Exception ex)
     {
         Console.WriteLine("加密过程中出现异常: " + ex.Message);
         return null;
     }
 }

 /// <summary>
 /// 解密数据
 /// </summary>
 /// <param name="dataToDecrypt"></param>
 /// <returns></returns>
 public static string DecryptData(string hexEncryptedData)
 {
     try
     {
         byte[] dataToDecrypt = ConvertHexStringToByteArray(hexEncryptedData);
         byte[] decryptedData = ProtectedData.Unprotect(dataToDecrypt, null, DataProtectionScope.LocalMachine);
         return Encoding.Default.GetString(decryptedData);
     }
     catch (Exception ex)
     {
         Console.WriteLine("解密过程中出现异常: " + ex.Message);
         return null;
     }
 }

设置注册表的地方,也是很简单的一个写死的代码,供参考

c# 复制代码
 // 指定注册表键的路径
 string registryPath = @"SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services"; // 根据需要修改路径
 string valueName = "fAllowUnlistedRemotePrograms"; // 注册表项名称

 try
 {
     // 创建或打开指定的注册表键
     using (RegistryKey key = Registry.LocalMachine.CreateSubKey(registryPath))
     {
         if (key != null)
         {
             // 设置值为 DWORD32 类型,并赋值为 1
             key.SetValue(valueName, 1, RegistryValueKind.DWord);
             MessageBox.Show("注册表键已创建并赋值成功。");
         }
         else
         {
             MessageBox.Show("无法创建注册表。");
         }
     }
 }
 catch (UnauthorizedAccessException)
 {
     MessageBox.Show("您没有权限设置注册表,请以管理员身份运行程序。");
 }
 catch (Exception ex)
 {
     MessageBox.Show($"设置注册表发生错误: {ex.Message}");
 }

总结

本工具打开的远程程序,支持局域网、外网,只要你可以通过远程桌面访问的服务器或者电脑,都可以通过该方式进行启动。

项目地址

如果需要本程序,可以通过下面地址获取。

pan.baidu.com/s/1QPstE5-1...

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:weskynet

出处:cnblogs.com/weskynet/p/18445584

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

相关推荐
向宇it5 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
九鼎科技-Leo6 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
qq_17448285756 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
锅包肉的九珍6 小时前
Scala的Array数组
开发语言·后端·scala
心仪悦悦6 小时前
Scala的Array(2)
开发语言·后端·scala
Heaphaestus,RC7 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
2401_882727577 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
baivfhpwxf20237 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
直裾7 小时前
Scala全文单词统计
开发语言·c#·scala
心仪悦悦7 小时前
Scala中的集合复习(1)
开发语言·后端·scala