CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - LoadUserProfile

LoadUserProfile

dział ogólny

LoadUserProfile

Nowy postprzez mckri » poniedziałek, 25 lutego 2013, 12:17

Witam.
Piszę program, którego jednym z zadań jest logowanie się na konto administracyjne. Wygląda to tak, że gdy zwykły użytkownik go uruchomi, program loguje się na podane (zapisane w konfiguracji) dane administratora komputera. Logowanie jako inny użytkownik wykonuję poprzez: CreateProcessWithLogonW. Gdy jest to Vista itd. z właczonym UAC, program dodatkowo podnosi sobie uprawnienia za pomocą funkcji ShellExecuteEx (z opcją lpVerb = "runas"). W ten sposób otrzymuję pełne prawa administratora programu na koncie użytkownika. Całą tą akcję nazwę "podniesieniem przywilejów" :). Oprócz tego chciałbym jeszcze załadować sobie profil użytkownika, tak aby program ostatecznie jako admin pracował na profilu użytkownika. Poprzez pracę na profilu użytkownika mam na myśli, że program będzie widział zmienne środowiskowe użytkownika (np. %TEMP%) oraz katalogi specjalne (identyfikowane przez CSIDL). Załadowanie profilu udaje się częsciowo na Windows 8 i 2008 R2, tzn. program po podniesieniu przywilejów widzi zmienne środowiskowe zwykłego użytkownika, ale nie ma dostępu do katalogów specjalnych. Obecnie ładowanie profilu realizuję w ten sposób:

Proces po podniesieniu przywilejów (w zdarzeniu OnCreate) ma poprawnie przyznane uprawnienia: SE_RESTORE_NAME i SE_BACKUP_NAME za pomocą LookupPrivilegeValue i AdjustTokenPrivileges

KOD cpp:     UKRYJ  
//Pobieranie tokena, ładowanie profilu i uruchamianie nowego procesu z profilem użytkownika
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);

  char szUserName[MAX_PATH]=""; //dla pobrania nazwy użytkownika
  char szUserProfile[MAX_PATH]=""; //dla pobrania katalogu użytkownika
  DWORD dwSize;
  TCHAR SpecDir[MAX_PATH], SpecDir2[MAX_PATH]; //dla katalogów specjalnych
  LPVOID    lpvEnv; //dla środowiska
  HANDLE    hToken; //dla Tokena
  DWORD dwPID = Edit4->Text.ToInt(); //PID procesu dawcy, który uuruchomiony jest na koncie zwykłego użytkownika

if ((hProcess = OpenProcess(MAXIMUM_ALLOWED /*PROCESS_QUERY_INFORMATION*/, FALSE, dwPID)) == 0) ShowMessage("OpenProcess " + (String)GetLastError()); //otwieram proces programu, który był uruchomiony przez użytkownika jako pierwszy - dawca organów

   if (!OpenProcessToken(hProcess,MAXIMUM_ALLOWED /*TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_READ|TOKEN_WRITE | TOKEN_IMPERSONATE*/, &hToken)) ShowMessage("OpenProcessToken "+ (String)GetLastError()); //otwieram token tegoż procesu

if(!ImpersonateLoggedOnUser(hToken))    ShowMessage("ImpersonateLoggedOnUser "+(String)GetLastError()); //wykonuje przypisanie tokenu konta dawcy dla bieżacego wątku

dwSize = sizeof(szUserName);
   GetUserName(szUserName,&dwSize);   //nazwa uzytkownika - z konta dawcy

dwSize = sizeof(szUserProfile);
   if(!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))     //pobieranie nazwy katalogu głównego uzytkownika, np. c:\users\Somebody - z konta dawcy
                ShowMessage("GetUserProfileDirectory "+(String)GetLastError());              

   SHGetFolderPath(NULL, CSIDL_DESKTOP,hToken,0,SpecDir);  //pobieram lokalizacje pulpitu uzytkownika - konta dawcy
   SHGetSpecialFolderPath( NULL, SpecDir2, CSIDL_PERSONAL , 0); //pobieram lokalizacje katalogu dokumentów uzytkownika - konta dawcy
   
   ShowMessage("GetUserProfileDirectory: "+(String)szUserProfile+
   "\n"+"GetUserName: "+(String)szUserName+
   "\n"+"SHGetFolderPath: "+(String)SpecDir+
   "\n"+"SHGetSpecialFolderPath: "+(String)SpecDir2+
   "\n"+"TEMP: "+getenv("TEMP"));  //kontrola pobranych informacji

   if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))  ShowMessage(L"CreateEnvironmentBlock " + (String)GetLastError()); //pobieram zmienne srodowiskowe uzytkownika - z konta dawcy

        PROFILEINFO profile;  //struktura profilu
        ZeroMemory(&profile,sizeof(profile));
        profile.dwSize=sizeof(profile);
        profile.lpDefaultPath=szUserProfile; //nazwa profilu
        profile.lpUserName = szUserName;  //nazwa usera
        //profile.dwFlags = PI_NOUI;

if(!RevertToSelf()) ShowMessage("RevertToSelf "+(String)GetLastError());

if(!LoadUserProfile(hToken,&profile))  ShowMessage("LoadUserProfile "+(String)GetLastError()); //ładuje profil uzytkownika

if(CreateProcess(NULL,ParamStr(0).t_str(),NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, lpvEnv, NULL, &si, &pi)) //uruchamiam proces z profilem
   {
         CloseHandle(pi.hProcess);
         CloseHandle(pi.hThread);
   }
 

Po drodze nie ma błędów.

Efek całosci jest taki, że na programie z podniesionymi przywilejami na Windows XP 32b i Windows 7 64b - pokazują się poprawnie wartości zmiennych środowiskowych i lokalizacji katalogów specjalnych zwykłego uzytkownika (dawcy), natomiast na Windows 8 64b i Server 2008 R2 - pokazują się tylko zmienne środowiskowe. Dla katalogów specjalnych pokazują się "krzaki".

Pytanie, czy robię coś zle? Jak poprawnie ładować profil innego użytkownika w kontekście: admin pobiera profil użytkownika?
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows 7Opera

Re: LoadUserProfile

Nowy postprzez Cyfrowy Baron » poniedziałek, 25 lutego 2013, 18:52

Jak rozumiem masz problem tylko z Windows 8? Będzie trudno, bo to nowy system i mało kto z niego korzysta, a i środowisko włącznie z bibliotekami mogą nie być do tak całkiem kompatybilny z tym nowym systemem. Byś może XE3 jest już w pełni zgodny.

Nie pomogę, nie używam póki co Win8. :roll:
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: LoadUserProfile

Nowy postprzez mckri » wtorek, 26 lutego 2013, 23:04

Raczej podejrzewałbym tutaj jakieś nowe mechanizmy zabezpieczeń w Windows 8, które nie pozwalają z poziomu innego konta (admina) dostać się do lokalizacji (CSIDL) innego uzytkownika (usera) a nie samo środowisko programistyczne. Jak widać głównie wywołuje funkcje API. Byc może czegoś brakuje lub robię w nie własciwej kolejności.
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows 7Opera

Re: LoadUserProfile

Nowy postprzez Cyfrowy Baron » środa, 27 lutego 2013, 05:53

Administrator ma dostęp do absolutnie wszystkiego, więc w Windows 8 to się raczej nie zmieniło. Windows 8 ma chyba jakieś nowe API, więc środowisko programistyczne może nie posiadać niezbędnych bibliotek.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: LoadUserProfile

Nowy postprzez mckri » wtorek, 26 marca 2013, 00:27

Administrator niestety nie ma dostępu do wszystkiego! Istnieją pewne prawa, które trzeba sobie nadać.
Przykładowo będąc zalogowanym jako Administrator na Windows XP (SP2 / SP3) nie można pobrac Token procesu, który pracuje na koncie użytkownika.
Co ciekawe zauważyłem, że począwszy od Windows 6.0 (Vista i wyższe) prawa zostały nieco rozluźnione i jako Admin można pobrac Token procesu użytkownika. Jednak zależy mi również żeby to zrobić na Windows XP. Fragment kodu:

KOD cpp:     UKRYJ  
HANDLE hProcUser;
HANDLE hTokenProcUser;
HANDLE hProcUser = OpenProcess(PROCESS_QUERY_INFORMATION,  FALSE,  dwPIDuser);  //otwieram proces użytkownika - OK
OpenProcessToken(hProcUser, TOKEN_QUERY, &hTokenProcUser);  //próbuje pobrac uchwyt do Tokena procesu z konta użytkownika <-- tutaj otrzymuję GetLastError(): 5- Access Denied

//Wczesniej oczywiście nadaję sobie uprawnienia:
  SetPrivilege(hToken,SE_DEBUG_NAME,true);
  SetPrivilege(hToken,SE_RESTORE_NAME,true);
  SetPrivilege(hToken,SE_BACKUP_NAME,true);
  SetPrivilege(hToken,SE_IMPERSONATE_NAME,true);
  //SetPrivilege(hToken,SE_TCB_NAME,true);  <-- tego nadać sobie nie moge dla aplikacji desktop
  SetPrivilege(hToken,SE_TAKE_OWNERSHIP_NAME,true);
  SetPrivilege(hToken,SE_SECURITY_NAME,true);
  //SetPrivilege(hToken,SE_ASSIGNPRIMARYTOKEN_NAME,true);  <-- tego nadać sobie nie moge dla aplikacji desktop
  SetPrivilege(hToken,SE_INCREASE_QUOTA_NAME,true);
 

Próbowałem również z nadawaniem uprawnień typu "Access Security":
http://read.pudn.com/downloads70/sourcecode/game/253142/bwh-1.5/source/bwh_loader/openprocessu.cpp__.htm
http://vk.com/wall82890869_7

Jednak nadal otrzymuję Access Denied przy próbie pobrania Tokenu procesu z konta użytkownika.
Jeżeli ktoś coś wie w tym temacie, proszę o wskazówkę lub przykład.
Avatar użytkownika
mckri
Intelektryk
Intelektryk
 
Posty: 160
Dołączył(a): piątek, 15 sierpnia 2008, 13:48
Podziękował : 10
Otrzymał podziękowań: 2
System operacyjny: Windows Vista SP2
Kompilator: BCB 5/2007/2009
    Windows 7Opera


Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 4 gości