KB131065 montre comment activer SeDebugPrivilege pour ouvrir un handle à n'importe quel processus. Il a une fonction nommée SetPrivilege
qui appelle AdjustTokenPrivileges
, mais il existe deux implémentations et aucune mention pourquoi.Quelle utilisation de AdjustTokenPrivileges dans KB131065 est correcte?
La première appelle la mise en œuvre de l'ATP en deux passes:
//
// first pass. get current privilege setting
//
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious
);
if (GetLastError() != ERROR_SUCCESS) return FALSE;
//
// second pass. set privilege based on previous setting
//
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
if(bEnablePrivilege) {
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
}
else {
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);
}
AdjustTokenPrivileges(
hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL
);
Cela ressemble surpuissant. Je ne vois rien dans la documentation pour indiquer que les champs Attributes
du paramètre state-state reçoivent des indicateurs supplémentaires qui doivent être conservés. Il semble que ce code commence par en désactivant le privilège, puis il revient en arrière et le réactive ou le désactive à nouveau. Est-ce que je l'ai interprété correctement? Est-ce que d'autres recommandent cette technique?
La deuxième mise en œuvre de SetPrivilege
ressemble plus à ce que je pense:
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if(bEnablePrivilege) {
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
} else {
tp.Privileges[0].Attributes = 0;
}
AdjustTokenPrivileges(hToken, FALSE, &tp, cb, NULL, NULL);
est la deuxième version simplifiée à l'extrême? Je remarque que c'est essentiellement la même chose que ce qui est démontré dans Enabling and Disabling Privileges in C++, sauf que l'article de la base de connaissances ignore la valeur de retour de l'API et va directement à GetLastError
pour détecter le succès et l'échec.