je lui passe un PHANDLE ( qui est un HANDLE * )Edit: Minute: Il faut passer un pointeur vers le handle de token, on est bien d'accord...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 PHANDLE hToken=NULL; BOOL b1=OpenThreadToken(GetCurrentThread(),TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,FALSE, hToken);
Merci, j'ai compris ce que tu veux dire
Ici j'ai pas un thread, donc j'ai changé les fonctions à celles équivalentes pour un Process.
Quand je lance ce Process en compte SYSTEM, ça marche pas à cause de droit d'accès apparement, je reçois d1=5
pour le code suivant:l'interpretation de ce code d'erreur sur msdn me donne
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 PHANDLE hToken=new HANDLE; BOOL b1=OpenProcessToken(GetCurrentProcess(),FALSE, hToken); DWORD d1=GetLastError();ERROR_ACCESS_DENIED
5 (0x5) Access is denied.
Ben non, t'as pas compris. Relis l'article.Merci, j'ai compris ce que tu veux dire
Code : Sélectionner tout - Visualiser dans une fenêtre à part PHANDLE hToken=new HANDLE;
Code à l'arrache qui arrive à lire le nom d'un exécutable lancé par SYSTEM (mon PID =972), même à partir d'un compte simplement administrateur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 // testWin32.cpp : Defines the entry point for the console application. // #include "stdafx.h" BOOL SetPrivilege( HANDLE hToken, // access token handle LPCTSTR lpszPrivilege, // name of privilege to enable/disable BOOL bEnablePrivilege // to enable or disable privilege ) { TOKEN_PRIVILEGES tp; LUID luid; if ( !LookupPrivilegeValue( NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid ) ) // receives LUID of privilege { printf("LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (bEnablePrivilege) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if ( !AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { printf("The token does not have the specified privilege. \n"); return FALSE; } return TRUE; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hToken; // handle to process token HANDLE hCurrentThread = GetCurrentThread(); HANDLE hCurrentProcess = GetCurrentProcess(); BOOL b1=OpenThreadToken(hCurrentThread,TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,FALSE, &hToken); if(!b1) { b1=OpenProcessToken(hCurrentProcess,TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,&hToken); } if(b1) { b1 = SetPrivilege(hToken,SE_DEBUG_NAME,TRUE); assert(b1==TRUE); if(b1) { HANDLE hTokenSVCHOST = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,972); assert(hTokenSVCHOST!=INVALID_HANDLE_VALUE); wchar_t toto[256]; int len = GetModuleBaseName(hTokenSVCHOST,0,toto,256); assert(len>0); wprintf(L"GetModuleBaseName = %s",toto); } } else { assert(b1==TRUE); } system(""); return 0; }
Salut,
Waw! Il y en a eu des postes depuis midi.
Apparemment, le problème n'est pas réglé.
Je vois néanmoins que ça a évolué (dans tous les sens).
Aussi je vais m'en tenir à ta problématique du départ, c'est à dire ouvrir le jeton d'accès associé à un processus.
Ce n'est que la mise en oeuvre de ce que j'ai expliqué sommairement à midi.
Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 //debug sample token (mode console), by maxim_um #include <windows.h> #include <iostream> #include <string> using namespace std; #define SHOW(VALUE) cout<<#VALUE<<": "<<VALUE<<endl int main (){ HANDLE hToken = 0; HANDLE hImpersonateToken = 0; DWORD dwAccessDesired = TOKEN_DUPLICATE|TOKEN_QUERY; HANDLE hCProcess = GetCurrentProcess(); //facility for to get a pseudo handle process, //here for the current process; SHOW(hCProcess); SHOW(OpenProcessToken(hCProcess,dwAccessDesired , &hToken)); //see also OpenThreadToken(), it's recommended to use before OpenProcessToken() //for checking an existence of a token SHOW(GetLastError()); SHOW(hToken); //SecurityImpersonation for local SECURITY_IMPERSONATION_LEVEL; //for remote systems, use another value of security impersonation levels; SHOW(DuplicateToken (hToken, SecurityImpersonation, &hImpersonateToken)); SHOW(GetLastError()); SHOW(hImpersonateToken); //CloseHandle(), do not forget, à ne pas oublier!!! return 0; }
Cela dit, masterx_goldman, ce serait bien si tu exposes tes intentions, histoire d'avoir une vue globale (outre le fait d'accéder au token et obtenir éventuellement des infos sur l'utilisateur courant) et te proposer des pistes qui seraient peut être plus en adéquation avec tes objectifs.
enjoy;
Bon, pour expliquer ce que je veux faire:
Je veux lancer, à partir d'une application qui tourne en compte SYSTEM, une application dans le compte user actif
(celui qui a la session active qui peut être locale ou sur un domaine). Alors, pour ce faire, j'ai trouvé une discussion où on parle des étapes suivantes:
1) Le Processus P1 récupère d'un token sur le processus "explorer.exe" qui va donner une information "d'identité" pour la
session active.
2) lancement du processus en utilisant CreateProcessAsUser()
Après, moi je veux les faire communiquer( en utilisant des pipes, etc..) mais c'est pas encore le moment pour parler de ça
PS:
1)J'ai posé la question autrement , ici sur le forum http://www.developpez.net/forums/d80...-session-user/
2)Je peux pas utiliser la fonction CreateProcessWithLogonW ( ça sort des règles de fonctionnement permises chez les clients )
Alors ça vous dit quelque chose ?
Ça t'apprendra à ne pas donner de préfixe à tes pointeurs (appeler un HANDLE* hToken au lieu de phToken, quand les handles sont eux-mêmes des void*, c'est du suicide!)
Pour info, Toutes les erreurs que j'ai cité avant ont été résolues en suivant les conseils de Médinoc et Maxim_um
Maintenant, je suis à l'étape de lancement du processus, qui elle échoue en retourant un code d'erreur = 5Voici le code de mon Programme P1, j'espère que ça va vous permettre de bien voir l'erreur éventuelle et que ça aidera ceux qui chercheront à faire la même manip dans le futurERROR_ACCESS_DENIED
5 (0x5)
J'ai exécuté ça en deux modes différents:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 // test_pidProcess.cpp*: définit le point d'entrée pour l'application console. // #include "stdafx.h" #include <windows.h> #include <tlhelp32.h> //th32.lib ou libth32.a #include <stdio.h> #include<iostream> #include<fstream> using namespace std; DWORD GetPidByName(char *szProcName); #define SHOW(VALUE) cout<<#VALUE<<" :"<<VALUE<<endl int _tmain(int argc, _TCHAR* argv[]) { //Récupération du pid du processus explorer.exe DWORD processID=GetPidByName("explorer.exe"); printf("PID = %ld\n", processID); //Récupération d'un HANDLE sur le processus explorer.exe HANDLE hExplorerProcess = OpenProcess( PROCESS_QUERY_INFORMATION ,FALSE, processID ); DWORD d1=GetLastError(); //Obtention du token de uverture du token Récupération d'un HANDLE sur le processus explorer.exe HANDLE TokenHandle=NULL; BOOL b=OpenProcessToken(hExplorerProcess,TOKEN_DUPLICATE| TOKEN_QUERY, &TokenHandle); DWORD d2=GetLastError(); //Lancement d'un process dans la session active STARTUPINFO si; PROCESS_INFORMATION pi; memset(&si, 0, sizeof(si)); memset(&pi, 0, sizeof(pi)); CreateProcessAsUser(TokenHandle, "C:\\P2.exe", NULL, NULL, NULL, FALSE,//You cannot inherit handles across sessions CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi) ; DWORD d3=GetLastError(); ofstream fichier("C:\\log_P2.txt", ios::out | ios::trunc); if(fichier) { fichier << "retour de GetLastError(), d1 =" <<d1<< ", d2 = " <<d2<< ", d3 = " <<d3<<endl; fichier.close(); } else cerr << "Impossible d'ouvrir le fichier !" << endl; return 0; } //--------------------------------------------------- DWORD GetPidByName(char *szProcName) { DWORD dwPID = 0; PROCESSENTRY32 pe = {sizeof(PROCESSENTRY32)}; HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hSnap != INVALID_HANDLE_VALUE) { if(Process32First(hSnap, &pe)) { do { if(strcmpi(pe.szExeFile, szProcName) == 0) { dwPID = pe.th32ProcessID; break; } } while(Process32Next(hSnap, &pe)); } CloseHandle(hSnap); } return dwPID; }
1) dans le compte Administrateur (en l'exécutant à la main)
2) sous le compte SYSTEM en utilisant PsTools
Résultat :Pour 1) je suis pas sûr que ça devrait marcher, donc je m'attends pas beaucoup à ça sauf si vous me le confirmezretour de GetLastError(), d1 =0, d2 = 0, d3 = 5
Pour 2) Normalement, ça devrait marcher, mais y'a encore une petite erreur je pense, qui fait que ça marche pas
Seul un utilisateur disposant du privilège Assign Primary Token peut créer un processus avec un autre utilisateur en utilisant CreateProcessAsUser().
Par défaut, seul SYSTEM possède ce privilège, et il doit falloir l'activer avant usage.
Edit: Apparemment, la fonction CreateProcessWithTokenW(), elle, ne nécessite pas ce privilège, mais seulement le privilège Impersonate, que tous les administrateurs possèdent.
Héhé ça marche à 98 %
@Médinoc, oui tu avais raison, quand j'ai regardé la documentation sur msdnfallait juste ajouter TOKEN_ASSIGN_PRIMARY dans l'appel de la fonctionC++
BOOL WINAPI CreateProcessAsUser(
__in_opt HANDLE hToken,
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);
Parameters
hToken [in, optional]
A handle to the primary token that represents a user. The handle must have the TOKEN_QUERY, TOKEN_DUPLICATE, and TOKEN_ASSIGN_PRIMARY access rights. For more information, see Access Rights for Access-Token Objects. The user represented by the token must have read and execute access to the application specified by the lpApplicationName or the lpCommandLine parameter.Si on désigne par :
Code : Sélectionner tout - Visualiser dans une fenêtre à part BOOL b=OpenProcessToken(hExplorerProcess,TOKEN_DUPLICATE| TOKEN_QUERY|TOKEN_ASSIGN_PRIMARY, &TokenHandle);
P1: le processus qui va se lancer en compte SYSTEM
P2: le processus qui va se lancer en compte user
Résultat:
Quand je lance P1 en compte SYSTEM en utilisant:
1) PSTools ==> P2 se lance (aucune erreur de GetLastError())
2) Service Windows qui lui même tourne en compte SYSTEM( bien entendu ) ==> P2 se lance sans problème, tourne correctement
mais le GetLastError() retourne une valeur non nulle >_<
code d'erreur 1307, et son interprétation sur msdn donne :
Je pense que c'est à cause du NULL que je passe en paramètre lpProcessAttributes pour la fonction CreateProcessAsUserERROR_INVALID_OWNER
1307 (0x51B) This security ID may not be assigned as the owner of this object.
et que ça devrait pas être NULL pour des raisons d'héritage du HANDLE par les processus fils éventuels de P2 ...
J'aime pas voir ce message d'erreur même si le programme se lance et tourne normalement.
Merci pour votre patience à suivre toute cette longue discussion
Cette erreur est le résultat d'un conflit, en fait, tu as attribué à ton application les droits de la session locale (à confirmer avec TaskManager ou Sysinternals Process Explorer par exemple.) mais elle a conservé l'id de session system, ce qui provoque l'erreur. Dans une moindre mesure, elle a également hérité, si je ne m'abuse, de l'environnement system. Je pense que tu devrais pouvoir trouver les fonctions adéquates (comme ProcessIdToSessionId) dans la section Terminal Services de l'aide SDK.
Aussi, sans aborder la qualité ou le style du code, je n'y vois pas de fonction importante comme DuplicateTokenEx, en fait, ton code me semble incomplet pour donner un résultat satisfaisant, d'ailleurs je suis étonné que tu arrives jusqu'à cette fameuse erreur 1307.
Je viens de remarquer que j'ai fait aussi une erreur dans mon exemple avec DuplicateToken (au lieu de DuplicateTokenEx) et la non-réutilisation du token dupliqué.
Qu'est ce qu'elle a hérité ?
Les fonctions adéquates pour faire quoi ?Je pense que tu devrais pouvoir trouver les fonctions adéquates (comme ProcessIdToSessionId) dans la section Terminal Services de l'aide SDK.
Pourquoi je dois dupliquer le Token , le Primary Token que j'ai obtenu ne me permet pas de le manipuler ? Enfin je comprends pas trop ces notions de token..Aussi, sans aborder la qualité ou le style du code, je n'y vois pas de fonction importante comme DuplicateTokenEx, en fait, ton code me semble incomplet pour donner un résultat satisfaisant, d'ailleurs je suis étonné que tu arrives jusqu'à cette fameuse erreur 1307.
ça j'ai pas bien compris , merci de m'expliquer encore plusJe viens de remarquer que j'ai fait aussi une erreur dans mon exemple avec DuplicateToken (au lieu de DuplicateTokenEx) et la non-réutilisation du token dupliqué.
Enfin ce qui m'étonne vraiment c'est que malgrès cette erreur le programme tourne ! ( ou alors il tourne mais dans un mode surlequel il aura des problèmes d'identité ou d'accès ... ?)
Hériter dans le sens que ton application utilisateur évolue dans l'environnement «System». Une manière simple de mettre en évidence la chose, donc à tester, c'est de consulter par exemple les variables d'environnement avec une macro du genre «system("set userprofile");» ce qui en cas d'héritage donnerait par exemple "NetworkService" en lieu et place du nom de l'utilisateur. Pareil pour l'identificateur de session, qui génère l'erreur.
Alors le Token.
Dans le contexte de la discussion, il s'agit plus précisément d'un Access Token (Jeton d'accès). Il est généré par le système d'authentification LSA lors de la connexion (Logon). Il contient entre autres le SID unique de l'utilisateur courant, la liste des SID de groupes locaux et distants auxquels appartient l'utilisateur courant et enfin la liste des privilèges dont dispose ce même utilisateur durant la session en cours.
En fait, pour que tu puisses visualiser la chose, disons que dans un cadre idéal il faut récupérer les propriétés d'un Token par duplication (DuplicateTokenEx()). Cela permet une manipulation aisée du Token dupliqué (modifications des privilèges par exemple) sans compromettre le cadre de sécurité lié au Token dont il dérive et même du système dans sa globalité. Concrètement ou plutôt visuellement, il s'agit là d'une technique d'usurpation, mais pour qu’elle soit complète, il faut non seulement utiliser de mêmes vêtements (environnement obtenu avec CreateEnvironmentBlock() et qui sera utilisé dans CreateProcessAsUser()) mais aussi une même pièce d'identité (Session ID: [ProcessIdToSessionId() ou WTSGetActiveConsoleSessionId()] et WTSQueryUserToken()).
Voilà, je pense ne rien avoir oublié et que l'essentiel y est. En tout cas, j'espère qu'avec ces quelques notions supplémentaires, tu pourras aller de l'avant.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager