如何启动 Windows 服务网络进程以侦听 UAC 下普通用户可见的 localhost 套接字上的端口?

Posted

技术标签:

【中文标题】如何启动 Windows 服务网络进程以侦听 UAC 下普通用户可见的 localhost 套接字上的端口?【英文标题】:How to launch a Windows service network process to listen to a port on a localhost socket that is visible to a normal user under UAC? 【发布时间】:2010-04-02 11:14:32 【问题描述】:

这是代码(在 Delphi 的标准 TService 中):

const
  ProcessExe = 'MyNetApp.exe';

function RunService: Boolean;
var
  StartInfo : TStartupInfo;
  ProcInfo : TProcessInformation;
  CreateOK : Boolean;
begin 
  CreateOK := false;
  FillChar(StartInfo,SizeOf(TStartupInfo),#0);
  FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
  StartInfo.cb := SizeOf(TStartupInfo);
  CreateOK := CreateProcess(nil, PChar(ProcessEXE),nil,nil,False,
                    CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS,
                    nil, PChar(InstallDir), StartInfo, ProcInfo);
  CloseHandle(ProcInfo.hProcess);
  CloseHandle(ProcInfo.hThread);
  Result := CreateOK;
end;

procedure TServicel.ServiceExecute(Sender: TService);
const
  IntervalsBetweenRuns = 4; //no of IntTimes between checks
  IntTime = 250; //ms
var
  Count: SmallInt;
begin
  Count := IntervalsBetweenRuns;  //first time run immediately
  while not Terminated do
  begin
    Inc(Count);
    if Count >= IntervalsBetweenRuns then
    begin
      Count := 0;
      //We check to see if the process is running,
      //if not we run it. That's all there is to it.
      //if ProcessEXE crashes, this service host will just rerun it
      if processExists(ProcessEXE)=0 then
        RunService;
    end;
    Sleep(IntTime);
    ServiceThread.ProcessRequests(False);
  end;
end;

MyNetApp.exe 是侦听端口 9870 的 SOCKS5 代理。用户将浏览器配置为该代理,充当安全隧道/匿名器。

在 2000/XP/2003 上一切正常,但在带有 UAC 的 Vista/Win7 上,服务在 LocalSystem 下的 Session0 中运行,并且端口 9870 未显示在 netstat 中以进行登录用户管理员。

似乎 UAC 妨碍了我。

我可以用 SECURITY_ATTRIBUTES 或 CreateProcess 做什么,或者我可以用 CreateProcessAsUser 或模拟做什么来确保系统上的登录用户可以使用服务上的网络套接字(注意,这个应用用于大规模部署,我无权访问用户凭据,并要求用户提升权限才能在 Vista/Win7 上安装服务)

【问题讨论】:

【参考方案1】:

服务应该能够读取 HKLM 配置单元。 创建注册表句柄时,请确保将访问设置设置为 KEY_READ (ARegHandle.Access := KEY_READ;),并且在打开密钥时,使用 Create as false 或 OpenReadOnly 在其中打开。

【讨论】:

这是问题所在,谢谢。我没有对我的 NetApp 中的 Reg 权限给予足够的关注,并且在调试时发现错误的树为什么它在工作,但在以 NT AUTHORITY\SYSTEM 运行时却没有【参考方案2】:

原来问题与在 netstat 下不可见端口无关。我在 Win7 机器上使用之前构建的版本进行了另一项测试,即使 netstat 没有显示以管理员或普通用户身份侦听的端口,浏览器仍然可以绑定到该端口(为什么会这样?)

实际发生的情况是 MyNetApp.exe 无法正确运行(仅在 Win7 上),因为在 NT AUTHORITY\SYSTEM 帐户下运行时,它无法读取 C:\ProgramData\ (%ALLUSERPROFILE%) 中的文件-- 它需要我的客户放在那里的子文件夹中的文件。

当我检查 SYSTEM 用户对这些文件的“有效权限”时,我获得了完全控制权。

发生了什么事?

更新: 不,那也不是。 MyNetApp.exe 通过读取我在安装期间设置的 HKEY_LOCAL_MACHINE\SOFTWARE\MyCompany\MyApp\ 中的字符串(到 %ALLUSERPROFILE%\MyCompany\MyApp。似乎它得到的是一个空字符串,即打破它。为什么 NT AUTHORITY\SYSTEM 不会得到与我在安装程序中设置的字符串相同的字符串(以提升的权限运行,以便它可以安装服务)

【讨论】:

以上是关于如何启动 Windows 服务网络进程以侦听 UAC 下普通用户可见的 localhost 套接字上的端口?的主要内容,如果未能解决你的问题,请参考以下文章

如何启动一个进程以从 Windows 服务运行 bat 文件

如何找出哪个进程正在侦听 Windows 上的 TCP 或 UDP 端口?

如何找出哪个进程正在侦听 Windows 上的 TCP 或 UDP 端口?

如何测试网络管道服务是不是正在侦听

如何在启动时启动 Docker 守护进程(Windows 服务)而无需登录?

如何以编程方式获取正在侦听某个端口的进程的 pid?