@@ -4,6 +4,7 @@ use anyhow::Context as _;
44use win_api_wrappers:: identity:: account:: { enumerate_account_rights, get_username, lookup_account_by_name} ;
55use win_api_wrappers:: identity:: sid:: { Sid , SidAndAttributes } ;
66use win_api_wrappers:: process:: Process ;
7+ use win_api_wrappers:: raw:: core:: HRESULT ;
78use win_api_wrappers:: raw:: Win32 :: Foundation :: LUID ;
89use win_api_wrappers:: raw:: Win32 :: Security ;
910use win_api_wrappers:: raw:: Win32 :: System :: SystemServices ;
@@ -25,32 +26,56 @@ fn main() -> anyhow::Result<()> {
2526 . context ( "open current process token" ) ?;
2627
2728 // Verify that the current account is assigned with the SE_CREATE_TOKEN_NAME privilege.
28- let account_username = get_username ( Security :: Authentication :: Identity :: NameSamCompatible ) . unwrap ( ) ;
29+ println ! ( "Attempting to verify whether the current account is assigned with the SE_CREATE_TOKEN_NAME privilege" ) ;
30+ let account_username =
31+ get_username ( Security :: Authentication :: Identity :: NameSamCompatible ) . context ( "retrieve account username" ) ?;
2932 println ! ( "Account name: {account_username:?}" ) ;
30- let account = lookup_account_by_name ( & account_username) . unwrap ( ) ;
31- let rights = enumerate_account_rights ( & account. sid ) . unwrap ( ) ;
32- let has_create_token_right = rights. iter ( ) . any ( |right| right == u16cstr ! ( "SeCreateTokenPrivilege" ) ) ;
3333
34- if expect_elevation {
35- assert ! ( has_create_token_right) ;
36-
37- // SE_CREATE_TOKEN_NAME is required for performing the elevation.
38- let se_create_token_name_luid = privilege:: lookup_privilege_value ( None , privilege:: SE_CREATE_TOKEN_NAME )
39- . context ( "lookup SE_CREATE_TOKEN_NAME privilege" ) ?;
40- token
41- . adjust_privileges ( & TokenPrivilegesAdjustment :: Enable ( vec ! [ se_create_token_name_luid] ) )
42- . context ( "enable SE_CREATE_TOKEN_NAME privilege" ) ?;
43-
44- // Verify the SE_CREATE_TOKEN_NAME privilege is actually enabled.
45- let se_create_token_name_is_enabled = token
46- . privileges ( )
47- . context ( "list token privileges" ) ?
48- . as_slice ( )
49- . iter ( )
50- . find ( |privilege| privilege. Luid == se_create_token_name_luid)
51- . is_some ( ) ;
52-
53- assert ! ( se_create_token_name_is_enabled) ;
34+ match lookup_account_by_name ( & account_username) {
35+ Ok ( account) => {
36+ let rights = enumerate_account_rights ( & account. sid )
37+ . with_context ( || format ! ( "enumerate account rights for {account_username:?}" ) ) ?;
38+ let has_create_token_right = rights. iter ( ) . any ( |right| right == u16cstr ! ( "SeCreateTokenPrivilege" ) ) ;
39+
40+ if expect_elevation {
41+ assert ! ( has_create_token_right) ;
42+
43+ // SE_CREATE_TOKEN_NAME is required for performing the elevation.
44+ let se_create_token_name_luid =
45+ privilege:: lookup_privilege_value ( None , privilege:: SE_CREATE_TOKEN_NAME )
46+ . context ( "lookup SE_CREATE_TOKEN_NAME privilege" ) ?;
47+ token
48+ . adjust_privileges ( & TokenPrivilegesAdjustment :: Enable ( vec ! [ se_create_token_name_luid] ) )
49+ . context ( "enable SE_CREATE_TOKEN_NAME privilege" ) ?;
50+
51+ // Verify the SE_CREATE_TOKEN_NAME privilege is actually enabled.
52+ let se_create_token_name_is_enabled = token
53+ . privileges ( )
54+ . context ( "list token privileges" ) ?
55+ . as_slice ( )
56+ . iter ( )
57+ . find ( |privilege| privilege. Luid == se_create_token_name_luid)
58+ . is_some ( ) ;
59+
60+ assert ! ( se_create_token_name_is_enabled) ;
61+ }
62+ }
63+ Err ( e) => {
64+ println ! ( "Failed to look up account for {account_username:?}: {e}" ) ;
65+
66+ // Possible issue when running this program using psexec -s, under `NT AUTHORITY\SYSTEM` (LocalSystem):
67+ // - There is no direct domain credentials by default, unless the machine is domain joined and has a line-of-sight to the DC.
68+ // - This context may not be able to see the same network resources or DC that the interactive user.
69+ // Causing LookupAccountNameW to fail with a "no mapping" error.
70+ // Let’s just go ahead with the elevation in this case, assuming LocalSystem is enough for all intents and purposes at this point.
71+ if e. code ( ) == HRESULT ( 0x80070534u32 as i32 ) {
72+ println ! ( "Got the 'no mapping' error; continuing..." )
73+ } else {
74+ return Err ( anyhow:: Error :: new ( e) . context ( format ! (
75+ "unexpected error when looking up the account for {account_username:?}"
76+ ) ) ) ;
77+ }
78+ }
5479 }
5580
5681 let token_source = build_token_source ( LADM_SRC_NAME , LADM_SRC_LUID ) ;
@@ -122,7 +147,7 @@ fn main() -> anyhow::Result<()> {
122147 } else {
123148 match res {
124149 Ok ( _) => {
125- anyhow:: bail!( "admin token creation should have failed, because the current process is not elevated " )
150+ anyhow:: bail!( "admin token creation succeded, but this was not expected " )
126151 }
127152 Err ( e) => {
128153 assert_eq ! ( e. to_string( ) , "no token found for SE_CREATE_TOKEN_NAME privilege" ) ;
0 commit comments