如何“忽视”流程

时间:2017-08-28 09:15:29

标签: c++ winapi

我在UAC对话框中回答“是”后启动了一个提升的进程。

这个过程很好,一切都按预期工作。

现在我需要在某个时候“忽视”这个过程,换句话说,过程应该不会像用户正常启动那样完全升级。

示例方案

  • 用户A已登录
  • 用户A启动将通过UAC提升的流程P1
  • 升级过程P1 lauchches过程P2和P2不应升高,应在用户A下再次运行。

有办法做到这一点吗?

1 个答案:

答案 0 :(得分:3)

提升的进程已链接令牌 - 它指的是非提升的用户会话。我们可以通过两种方式使用这个链接的令牌:

第一种方式

  1. 将其设为TokenPrimary(为此我们需要SE_TCB_PRIVILEGE 当我们查询此标记时)
  2. 使用此令牌调用CreateProcessAsUser。为此,我们也需要 SE_ASSIGNPRIMARYTOKEN_PRIVILEGESE_INCREASE_QUOTA_PRIVILEGE
  3. 获取所有这些权限 - 枚举进程,查询令牌, 如果进程令牌拥有所有这3个特权 - 冒充 它,在致电CreateProcessAsUser之前。因为提升的令牌有 SE_DEBUG_PRIVILEGE任务是可能的
  4. 第二种方式:

    1. 从链接令牌(AuthenticationId)查询登录会话ID 来自TOKEN_STATISTICS

    2. 在流程令牌中找到了具有相同AuthenticationId的流程。

    3. 通过帮助将此过程用作父进程 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS

    4. 实施方式1:

      static volatile UCHAR guz;
      
      ULONG RunNonElevated(HANDLE hToken, HANDLE hMyToken, PCWSTR lpApplicationName, PWSTR lpCommandLine)
      {
          ULONG err;
      
          PVOID stack = alloca(guz);
      
          ULONG cb = 0, rcb = FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges[SE_MAX_WELL_KNOWN_PRIVILEGE]);
      
          union {
              PVOID buf;
              PTOKEN_PRIVILEGES ptp;
          };
      
          do 
          {
              if (cb < rcb)
              {
                  cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
              }
      
              if (GetTokenInformation(hToken, TokenPrivileges, buf, cb, &rcb))
              {
                  if (ULONG PrivilegeCount = ptp->PrivilegeCount)
                  {
                      int n = 3;
                      BOOL fAdjust = FALSE;
      
                      PLUID_AND_ATTRIBUTES Privileges = ptp->Privileges;
                      do 
                      {
                          switch (Privileges->Luid.LowPart)
                          {
                          case SE_ASSIGNPRIMARYTOKEN_PRIVILEGE:
                          case SE_INCREASE_QUOTA_PRIVILEGE:
                          case SE_TCB_PRIVILEGE:
                              if (!(Privileges->Attributes & SE_PRIVILEGE_ENABLED))
                              {
                                  Privileges->Attributes |= SE_PRIVILEGE_ENABLED;
                                  fAdjust = TRUE;
                              }
      
                              if (!--n)
                              {
                                  err = NOERROR;
      
                                  if (DuplicateTokenEx(hToken, 
                                      TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE, 
                                      0, SecurityImpersonation, TokenImpersonation, 
                                      &hToken))
                                  {
                                      if (fAdjust)
                                      {
                                          AdjustTokenPrivileges(hToken, FALSE, ptp, rcb, NULL, NULL);
                                          err = GetLastError();
                                      }
      
                                      if (err == NOERROR)
                                      {
                                          if (SetThreadToken(0, hToken))
                                          {
                                              TOKEN_LINKED_TOKEN tlt;
                                              if (GetTokenInformation(hMyToken, TokenLinkedToken, &tlt, sizeof(tlt), &rcb))
                                              {
                                                  STARTUPINFO si = { sizeof (si) };
                                                  PROCESS_INFORMATION pi;
      
                                                  if (!CreateProcessAsUserW(tlt.LinkedToken, lpApplicationName, lpCommandLine, 
                                                      NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
                                                  {
                                                      err = GetLastError();
                                                  }
      
                                                  CloseHandle(tlt.LinkedToken);
      
                                                  if (err == NOERROR)
                                                  {
                                                      CloseHandle(pi.hThread);
                                                      CloseHandle(pi.hProcess);
                                                  }
                                              }
                                              else
                                              {
                                                  err = GetLastError();
                                              }
                                              SetThreadToken(0, 0);
                                          }
                                          else
                                          {
                                              err = GetLastError();
                                          }
                                      }
      
                                      CloseHandle(hToken);
                                  }
                                  else
                                  {
                                      err = GetLastError();
                                  }
      
                                  return err;
                              }
                          }
                      } while (Privileges++, --PrivilegeCount);
                  }
      
                  return ERROR_NOT_FOUND;
              }
      
          } while ((err = GetLastError()) == ERROR_INSUFFICIENT_BUFFER);
      
          return err;
      }
      
      ULONG RunNonElevated(HANDLE hMyToken, PCWSTR lpApplicationName, PWSTR lpCommandLine)
      {
          static TOKEN_PRIVILEGES tp = {
              1, { { { SE_DEBUG_PRIVILEGE } , SE_PRIVILEGE_ENABLED } }
          };
      
          AdjustTokenPrivileges(hMyToken, FALSE, &tp, sizeof(tp), NULL, NULL);
      
          ULONG err = NOERROR;
      
          // much more effective of course use NtQuerySystemInformation(SystemProcessesAndThreadsInformation) here
          HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0), hToken;
      
          if (hSnapshot != INVALID_HANDLE_VALUE)
          {
              PROCESSENTRY32W pe = { sizeof(pe) };
      
              if (Process32FirstW(hSnapshot, &pe))
              {
                  err = ERROR_NOT_FOUND;
      
                  do 
                  {
                      if (pe.th32ProcessID && pe.th32ParentProcessID)
                      {
                          if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID))
                          {
                              if (OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE, &hToken))
                              {
                                  err = RunNonElevated(hToken, hMyToken, lpApplicationName, lpCommandLine);
                                  CloseHandle(hToken);
                              }
                              else
                              {
                                  err = GetLastError();
                              }
                              CloseHandle(hProcess);
                          }
                          else
                          {
                              err = GetLastError();
                          }
                      }
                  } while (err && Process32NextW(hSnapshot, &pe));
              }
              else
              {
                  err = GetLastError();
              }
              CloseHandle(hSnapshot);
          }
      
          return err;
      }
      
      ULONG RunNonElevated(PCWSTR lpApplicationName, PWSTR lpCommandLine)
      {
          HANDLE hToken;
      
          ULONG err = NOERROR;
      
          if (OpenProcessToken(NtCurrentProcess(), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hToken))
          {
              TOKEN_ELEVATION_TYPE tet;
      
              ULONG rcb;
      
              if (GetTokenInformation(hToken, ::TokenElevationType, &tet, sizeof(tet), &rcb))
              {
                  if (tet == TokenElevationTypeFull)
                  {
                      RunNonElevated(hToken, lpApplicationName, lpCommandLine);
                  }
                  else
                  {
                      err = ERROR_ALREADY_ASSIGNED;
                  }
              }
              else
              {
                  err = GetLastError();
              }
      
              CloseHandle(hToken);
          }
          else
          {
              err = GetLastError();
          }
      
          return err;
      }
      

      实施方式2:

      ULONG CreateProcessEx(HANDLE hProcess,
                            PCWSTR lpApplicationName,
                            PWSTR lpCommandLine)
      {
      
          SIZE_T Size = 0;
      
          STARTUPINFOEX si = { sizeof(si) };
          PROCESS_INFORMATION pi;
      
          InitializeProcThreadAttributeList(0, 1, 0, &Size);
      
          ULONG err = GetLastError();
      
          if (err = ERROR_INSUFFICIENT_BUFFER)
          {
              si.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)alloca(Size);
      
              if (InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &Size))
              {
                  if (UpdateProcThreadAttribute(si.lpAttributeList, 0, 
                      PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hProcess, sizeof(hProcess), 0, 0) &&
                      CreateProcessW(lpApplicationName, lpCommandLine, 0, 0, 0, 
                      EXTENDED_STARTUPINFO_PRESENT, 0, 0, &si.StartupInfo, &pi))
                  {
                      CloseHandle(pi.hThread);
                      CloseHandle(pi.hProcess);
                  }
                  else
                  {
                      err = GetLastError();
                  }
      
                  DeleteProcThreadAttributeList(si.lpAttributeList);
              }
              else
              {
                  err = GetLastError();
              }
          }
          else
          {
              err = GetLastError();
          }
      
          return err;
      }
      
      ULONG CreateProcessEx(LUID AuthenticationId,
                            PCWSTR lpApplicationName,
                            PWSTR lpCommandLine)
      {
          ULONG err = ERROR_NOT_FOUND;
      
          HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      
          if (hSnapshot != INVALID_HANDLE_VALUE)
          {
              PROCESSENTRY32W pe = { sizeof(pe) };
      
              ULONG rcb;
      
              if (Process32First(hSnapshot, &pe))
              {
                  err = ERROR_NOT_FOUND;
                  BOOL found = FALSE;
      
                  do 
                  {
                      if (pe.th32ProcessID && pe.th32ParentProcessID)
                      {
                          if (HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION|PROCESS_CREATE_PROCESS, FALSE, pe.th32ProcessID))
                          {
                              HANDLE hToken;                  
      
                              if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
                              {
                                  TOKEN_STATISTICS ts;
      
                                  if (GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &rcb))
                                  {
                                      if (ts.AuthenticationId.LowPart == AuthenticationId.LowPart && 
                                          ts.AuthenticationId.HighPart == AuthenticationId.HighPart)
                                      {
                                          found = TRUE;
      
                                          err = CreateProcessEx(hProcess,
                                              lpApplicationName,
                                              lpCommandLine);
                                      }
                                  }
                                  CloseHandle(hToken);
                              }
      
                              CloseHandle(hProcess);
                          }
                      }
      
                  } while (!found && Process32Next(hSnapshot, &pe));
              }
              else
              {
                  err = GetLastError();
              }
      
              CloseHandle(hSnapshot);
          }
          else
          {
              err = GetLastError();
          }
      
          return err;
      }
      
      ULONG CreateProcessEx(PCWSTR lpApplicationName,
                            PWSTR lpCommandLine)
      {
          HANDLE hToken;
      
          ULONG err = NOERROR;
      
          if (OpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &hToken))
          {
              union {
                  TOKEN_ELEVATION_TYPE tet;
                  TOKEN_LINKED_TOKEN tlt;
              };
      
              ULONG rcb;
      
              if (GetTokenInformation(hToken, TokenElevationType, &tet, sizeof(tet), &rcb))
              {
                  if (tet == TokenElevationTypeFull)
                  {
                      if (GetTokenInformation(hToken, TokenLinkedToken, &tlt, sizeof(tlt), &rcb))
                      {
                          TOKEN_STATISTICS ts;
      
                          BOOL fOk = GetTokenInformation(tlt.LinkedToken, TokenStatistics, &ts, sizeof(ts), &rcb);
      
                          CloseHandle(tlt.LinkedToken);
      
                          if (fOk)
                          {
                              err = CreateProcessEx(ts.AuthenticationId,
                                  lpApplicationName,
                                  lpCommandLine);
                          }
                          else
                          {
                              err = GetLastError();
                          }
                      }
                      else
                      {
                          err = GetLastError();
                      }
                  }
                  else
                  {
                      err = ERROR_ALREADY_ASSIGNED;
                  }
              }
              else
              {
                  err = GetLastError();
              }
      
              CloseHandle(hToken);
          }
          else
          {
              err = GetLastError();
          }
      
          return err;
      }
      

      并测试:

      WCHAR ApplicationName[MAX_PATH];
      
      if (GetEnvironmentVariableW(L"ComSpec", ApplicationName, RTL_NUMBER_OF(ApplicationName)))
      {
          WCHAR cmdline[] = L"cmd.exe /k whoami /priv /groups\r\n";
          CreateProcessEx(ApplicationName, cmdline);
          RunNonElevated(ApplicationName, cmdline);
      }
      

      对于#2理论,我们找不到具有相同登录ID(AuthenticationId)的进程,就像在我们的链接令牌中一样。但方式#1总是必须工作。始终存在系统进程,其中SeTcbPrivilege(用于获取主要形式的链接令牌)+ SeAssignPrimaryTokenPrivilege(用于CreateProcessAsUser)(SeIncreaseQuotaPrivilege在msdn中监听{{1但是在我的测试中,即使没有启用此权限也能正常工作)。但是,所有系统进程(作为CreateProcessAsUser运行)在令牌中具有此3权限(从LocalSystem开始),并且某些系统进程始终在系统中运行。

      所以方式#1必须永远不会失败并且首选。我们也可以在这里使用来自我们进程的继承句柄,用于与子进程交互。这在#2中是不可能的。它显示的是图片的完整性

      一开始我们检查TOKEN_ELEVATION_TYPE并做好工作,只有smss.exe。如果TokenElevationTypeFull我们没有提升过程 - 所以没有任何东西。 case TokenElevationTypeLimited表示或UAC如果关闭(LUA禁用)或我们作为内置管理员运行,并且lua没有过滤此帐户的令牌(因此所有进程都是&#34;提升&#34;或更确切地说它是令牌没有通过TokenElevationTypeDefault过滤 - 在这种情况下也没有意义尝试运行&#34;没有提升&#34;此用户下的流程