c - Vend tilbage til normal bruger i Windows-program med requiredAdministrator in manifest?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at indkapslere en række gentagne installationsopgaver i et privat opsætningsprogram. Programmet er beregnet til intern brug, der konfigurerer brugerdefinerede enkeltanlægssystemer til industrielle brugere. Jeg har brug for administratorrettigheder til at finjustere en række Windows-indstillinger til vores miljø og så skal jeg indstille nogle aktuelle brugerindstillinger for applikationssoftwarepakkerne til brug.


Er det muligt for et Windows-program (i almindelig C, oprettet med Visual Studio 2017), der bruger requireAdministrator i manifestet til at tilbageføre til den bruger, der startede programmet, når administrativ privilegium ikke længere er nødvendig? Jeg har set dette gjort i linux, men har ikke været i stand til at finde nogen eksempler (eller endda nævnt) om dette i Windows. Hjælp? Vær venlig?

Bedste reference


Det gør du ikke.


En måde, der gives et stykke tid tilbage, er at spore den kørende forekomst af explorer og kaste en fjern tråd i den (med CreateRemoteThread), der gør hvad du vil. Men CreateRemoteTherad er omhyggelig og hvad hvis explorer ikke kører?


Hvis du kender brugernavnet, kan du bruge CreateService () til at oprette en tjeneste, der kører som den bruger og ServiceStart () for at starte det, men det er sin egen smerte, og nu skal koden håndtere ikke adgang til skrivebordet. kører som brugeren på skrivebordet indebærer at grave ind i den undokumenterede.


Det korrekte design er at bruge to eksekverbare filer, den første med asInvoker, der starter det andet med requireAdministrator ved hjælp af API-opkaldet ShellExecuteEx, venter på at det er færdigt, kontrollerer exitkoden, og efter succes går den enkelte bruger trinvis.

Andre referencer 1


Der er ingen måde at de-løfte en løbeproces. Du kan muligvis sænke dine rettigheder lidt, men ikke hele vejen. Selvom det var muligt, skulle du hardkodes listen over grupper og privilegier til at fjerne/deaktivere i dit token, fordi jeg ikke tror, ​​at der er en API til at begrænse et token ligesom UAC gør.


Der er mange halv-assed løsninger derude for at starte en uopløftet børneproces:



  • Brug af opgaveplanlæggeren

  • IShellDispatch2::ShellExecute i 'main' Explorer.exe-forekomsten

  • CreateProcessAsUser med token fra 'main' Explorer.exe-forekomsten

  • Bootstrapper-forekomst løfter en anden forekomst og kommunikerer tilbage til forælder, når den skal udføre uoplyste handlinger

  • Udnyt Explorer-fejl og udfør blot "\%windirExplorer.exe" "c:path omyapp.exe"



Alle disse løsninger har problemer relateret til: [5] [6] [7]



  • Explorer kører muligvis ikke (brugerdefineret shell eller Explorer crash)

  • Explorer kører forhøjet

  • Ikke-administrative brugere hæver med en anden administratorkonto med et andet SID

  • RunAs.exe er blevet brugt, og din overordnede proces er ikke den samme som 'main' logon session eller Explorer.exe


Andre referencer 2


Endelig svar
Da jeg endelig kunne installere en ren Windows 10 på et ekstra system til test og oprette en ren ikke-adminkonto, der skulle testes med, fungerede det nye forbedrede svar ikke. Jeg tilføjede et GetUserName () -opkald efter at efterligne og skrev det til fejlsøgningsloggen for at høre, at brugernavnet var det samme før og efter udgivelsen, selv om alle funktionerne returnerede succes. Jeg kan kun antage, at GetShellWindow () [[Jeg prøvede også GetDesktopWindow (), bare i tilfælde]] returnerede et håndtag til en explorer/shell under admin konteksten. Så nu bruger jeg en ryddet op (for at gøre den almindelig C) version af funktionen GetConsoleUserToken (), jeg fandt her: https://social.msdn.microsoft.com/Forums/windowsdesktop/da-US/17db92be- 0ebd-4b54-9e88-a122c7bc351d/mærkeligt-problem-med-wtsqueryusertoken-and-impersonateloggedonuser? Forum=windowsgeneraldevelopmentissues Dette arbejder på både mit udviklingssystem OG på den rene Windows 10 non-admin-bruger. funktionen søger faktisk alle igangværende processer til explorer.exe, der hører til (er vedhæftet?) til konsolssessionen, og mens jeg fejler den, så jeg, at den finder mere end en explorer.exe-proces, men kun ONE er den rigtige. [8]


Tak for alle forslag og kommentarer! De gav mig gode ideer og satte mig på en sti, der tillod mig at bruge bedre søgeord for at finde det, jeg havde brug for.


Til Microsoft: Det virker ret unødvendigt kompliceret at gøre noget, der ikke bør være svært for en administrator-niveau proces at gøre.


Nyt, forbedret svar:
Efter forslaget fra eryksun oprettede jeg følgende eksempelfunktion, der viser alle de trin, mit program havde brug for for at få den aktuelle brugernøgle åbnet. Mit program har krævetAdministrator i manifestet, hvis din ikke gør det, skal du muligvis foretage ændringer eller tilføjelser til min prøve. Her arbejder det perfekt for mig (men tilsyneladende ikke på en ren maskine under en ikke-administratorkonto):


BOOL ChangeHkcuSettings( void )
{
   BOOL     bResult = FALSE;  // HKCU was not accessed
   HWND     hwndShell;
   DWORD    dwThreadId;
   DWORD    dwProcessId;
   HKEY     hKeyUserHive;
   HANDLE   hToken;
   HANDLE   hProcess;

   hwndShell  = GetShellWindow();
   dwThreadId = GetWindowThreadProcessId( hwndShell, &dwProcessId );
   hProcess   = OpenProcess( PROCESS\_QUERY\_INFORMATION, FALSE, dwProcessId );
   if( NULL != hProcess )
   {
      if( OpenProcessToken( hProcess,
                            TOKEN\_QUERY
                          | TOKEN\_DUPLICATE
                          | TOKEN\_IMPERSONATE,
                            &hToken ) )
      {
         if( ImpersonateLoggedOnUser( hToken ) )
         {
            if( ERROR\_SUCCESS == RegOpenCurrentUser( KEY\_ALL\_ACCESS, &hKeyUserHive ) )
            {
               // ... use the user hive key to access necessary HKCU items ...
               RegCloseKey( hKeyUserHive );
               bResult = TRUE;   // HKCU was accessed
            }
            RevertToSelf();
         }
         CloseHandle( hToken );
      }
      CloseHandle( hProcess );
   }
   return bResult;
}


Tak igen til eryksun for forslaget!


ORIGINAL ANSWER: Jeg tror, ​​jeg fandt en anden måde, der vil fungere for mig ... I stedet for at bruge HKEY\_CURRENT\_USER (som vil være administrator) kan administratorkontoen åbne den specifikke brugers registreringsdatabasenøgle under HKEY\_USERS i stedet. Jeg skal finde den rigtige bruger SID, men mit opsætning kender brugerens navn (og adgangskode til indstilling af automatisk logon), så jeg tror det er muligt. For mig er dette meget lettere, da al koden allerede eksisterer i et enkelt program, der tidligere skrev ALT til HKEY\_LOCAL\_MACHINE, som var let og fungerede godt. Forsøg at være 'korrekt' er meget mere arbejde, måske mere end det burde være!