Administrator使用者直接獲取SYSTEM許可權
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
來源: http://www.nsfocus.com作者:"scz" < [email protected]>
標題: MSDN系列(3)--Administrator使用者直接獲取SYSTEM許可權
日期: 2003-06-21 21:51
更新:
--------------------------------------------------------------------------
目錄:
☆ 概述
☆ sysproc.c
☆ sysproc_now.c
☆ 參考資源
--------------------------------------------------------------------------
☆ 概述
翻看[5]的時候,其書中例8.1演示如何以SYSTEM身份啟動cmd。以前我為了達到同樣
目的,利用at命令,但平日裡禁用Task Scheduler Service的,感覺操作很繞彎,不
爽得很。網上有現成的可執行程式直接獲取SYSTEM許可權,不喜歡沒原始碼的此型別小工
具,從未試用過。
麻雀兄 <[email protected]>在水木清華MSDN版上共享了一份Ashot Oganesyan K的原始碼,
也是直接獲取SYSTEM許可權。
一下子有了兩份現成的短小精悍型原始碼,心癢難耐,決定演練。最後發現還是麻雀
兄給的程式碼有實用價值。Gary Nebbett的程式碼對於2K/XP實際上失去了實用價值,這
要感謝rain的指點,具體技術討論見後。
本文提供了兩份完整原始碼,sysproc.c、sysproc_now.c,前者演示Gary Nebbett的
辦法,後者演示Ashot Oganesyan K的辦法。
Ashot Oganesyan K的原始碼只支援到2K,不清楚這位達人是否自己更新過,google
居然搜不到所提原始碼(再次感謝sparrow共享),沒辦法,我只好自己增加了對XP和
2003 Server的支援。此外為方便使用,sysproc_now.c自己找出winlogon.exe的PID,
不必在命令列上指定擁有SYSTEM許可權的PID了。
☆ sysproc.c
Gary Nebbett的中心思想就是利用ZwCreateToken()自己建立一個SYSTEM令牌(Token),
作為CreateProcessAsUser()第一形參使用。這個想法很好,我也費了好大勁去讀令
牌相關的各類技術文件,可是到2K/XP環境中實測時卻未達到預定效果。
開始完全按照Gary Nebbett所述編碼,2K中ZwCreateToken()失敗返回,說當前帳號
沒有足夠的許可權。XP中說當前帳號不能指派為所偽造的SYSTEM令牌的所有者(Owner)。
關於這點參sysproc.c/CreateSystemToken()函式中的註釋,從中也可看出XP比2K多
做了一些安全檢查。後來統一使用sysproc.c中演示的方式,這下都成了許可權不夠的
錯誤提示。
知道呼叫ZwCreateToken()需要SE_CREATE_TOKEN_NAME許可權,因此在程式中Enable了
該許可權,當時相關的程式碼路徑上並未提示Enable失敗。因此對"許可權不夠"感到非常困
惑。鑑於我對Privilege理解不足,乾脆不管三七二十一先將winnt.h中所列許可權全部
Enable了,還是同樣的下場。由此我才想到Administrator是否預設並未被Grant某些
許可權,AdjustTokenPrivileges()只能Enable/Disable那些已經Grant的許可權,比如前
面所提的SE_DEBUG_NAME許可權,並不能Grant許可權。正好rain來北京,我們聚了兩天,
順帶就此問題請教了rain和flier。rain為sysproc.c增加了一段程式碼,顯示當前帳號
所擁有的許可權,參CreateSystemToken()函式。從中發現Administrator果然沒有所需
的SE_CREATE_TOKEN_NAME許可權。rain告訴我,2K/XP中這種許可權需要顯式指派,也就
是"本地安全策略/使用者權利指派"所做的事,NT是否需要顯式指派我未證實過。預設
情況下,CreateProcessAsUser()所需SE_ASSIGNPRIMARYTOKEN_NAME許可權也未被指派
給管理員帳號。這兩種許可權在"本地安全策略/使用者權利指派"中對應:
SE_CREATE_TOKEN_NAME - Create a token object
SE_ASSIGNPRIMARYTOKEN_NAME - Replace a process level token
在此加深了對AdjustTokenPrivileges()的記憶。開始對MSDN中的描述並無感性認識,
只判斷返回值為FALSE,而未判斷GetLastError()為ERROR_NOT_ALL_ASSIGNED的情況,
導致當時相關的程式碼路徑上並未提示Enable失敗。
為管理員帳號手工增加這兩種許可權,登出並重新登入後,Gary Nebbett的目的達到了。
可以不利用"本地安全策略/使用者權利指派",而是自己程式設計實現這個步驟([2])。利用
LsaOpenPolicy()、LsaAddAccountRights()即可,AddPrivilege()演示了這個過程。
但問題是無論如何都必須登出/重登入才會生效。這對我來說,事實上已經失去了利
用價值,我需要的是立即(now)獲取SYSTEM許可權。
可能有人由ZwCreateToken()聯想到LogonUser(),關於後者可以參看[3]、[4],那不
是我需要的東西。
下面給出sysproc.c的完整原始碼,秉承一貫風格,以不建工程(Solution/Project)
直接命令列編譯為原則。註釋相當冗長,那是寫給我本人看的,對這些API特別不熟,
不寫個註釋在附近,下次看不懂是很正常的事,誰讓該死的Windows API這麼多形參。
--------------------------------------------------------------------------
/*
* For x86/EWindows XP SP1 & VC 7
* cl sysproc.c /Os /G6 /W3
*
* Gary Nebbett
* rain
*/
/************************************************************************
* *
* Head File *
* *
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <ntsecapi.h>
/************************************************************************
* *
* Macro *
* *
************************************************************************/
#pragma comment( linker, "/subsystem:console" )
#pragma comment( lib, "advapi32.lib" )
typedef LONG NTSTATUS;
/*
* you'll find a list of NTSTATUS status codes in the DDK header
* ntstatus.h (/WINDDK/2600.1106/inc/ddk/wxp/)
*/
#define NT_SUCCESS(status) ((NTSTATUS)(status)>=0)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
/*
*************************************************************************
* ntdef.h
*/
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
/*
* ntdef.h
*************************************************************************
*/
/*
* 參看DDK文件以及<<Windows NT/2000 Native API Reference>> - Gary Nebbett
* 這些Native API由ntdll.dll輸出
*/
typedef ULONG ( __stdcall *RTLNTSTATUSTODOSERROR ) ( IN NTSTATUS Status );
typedef NTSTATUS ( __stdcall *ZWCREATETOKEN ) ( OUT PHANDLE TokenHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN TOKEN_TYPE Type, IN PLUID AuthenticationId, IN PLARGE_INTEGER ExpirationTime, IN PTOKEN_USER User, IN PTOKEN_GROUPS Groups, IN PTOKEN_PRIVILEGES Privileges, IN PTOKEN_OWNER Owner, IN PTOKEN_PRIMARY_GROUP PrimaryGroup, IN PTOKEN_DEFAULT_DACL DefaultDacl, IN PTOKEN_SOURCE Source );
/************************************************************************
* *
* Function Prototype *
* *
************************************************************************/
static BOOL AddCurrentProcessPrivilege
( LPWSTR PrivilegeName );
static BOOL AddPrivilege ( LSA_HANDLE PolicyHandle,
PSID AccountSid, LPWSTR PrivilegeName );
static HANDLE CreateSystemToken ( void );
static BOOL DisableCurrentProcessSomePrivilege
( void );
static BOOL EnableCurrentProcessSomePrivilege
( void );
static PVOID GetFromToken ( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass );
static BOOL LocateNtdllEntry ( void );
static void PrintWin32Error ( char *message, DWORD dwMessageId );
static void PrintZwError ( char *message, NTSTATUS status );
static BOOL RemoveCurrentProcessPrivilege
( LPWSTR PrivilegeName );
static BOOL RemovePrivilege ( LSA_HANDLE PolicyHandle,
PSID AccountSid, LPWSTR PrivilegeName );
static BOOL SetCurrentProcessPrivilege
( LPCTSTR PrivilegeName, BOOL EnableFlag );
static BOOL SetPrivilege ( HANDLE TokenHandle, LPCTSTR PrivilegeName,
BOOL EnableFlag );
/************************************************************************
* *
* Static Global Var *
* *
************************************************************************/
/*
* 由ntdll.dll輸出的Native API函式指標
*/
static RTLNTSTATUSTODOSERROR RtlNtStatusToDosError = NULL;
static ZWCREATETOKEN ZwCreateToken = NULL;
/************************************************************************/
static BOOL AddCurrentProcessPrivilege ( LPWSTR PrivilegeName )
{
NTSTATUS status;
BOOL ret = FALSE;
LSA_HANDLE PolicyHandle = NULL;
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE CurrentProcessToken = NULL;
PTOKEN_USER token_user = NULL;
ZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
/*
* NTSTATUS LsaOpenPolicy
* (
* PLSA_UNICODE_STRING SystemName,
* PLSA_OBJECT_ATTRIBUTES ObjectAttributes,
* ACCESS_MASK DesiredAccess,
* PLSA_HANDLE PolicyHandle
* );
*/
status = LsaOpenPolicy( NULL, &ObjectAttributes, POLICY_ALL_ACCESS, &PolicyHandle );
if ( status != STATUS_SUCCESS )
{
PrintWin32Error( "LsaOpenPolicy() failed", LsaNtStatusToWinError( status ) );
goto AddCurrentProcessPrivilege_exit;
}
if ( FALSE == OpenProcessToken( GetCurrentProcess(),
TOKEN_QUERY,
&CurrentProcessToken ) )
{
PrintWin32Error( "OpenProcessToken() failed", GetLastError() );
goto AddCurrentProcessPrivilege_exit;
}
if ( NULL == ( token_user = ( PTOKEN_USER )GetFromToken( CurrentProcessToken, TokenUser ) ) )
{
goto AddCurrentProcessPrivilege_exit;
}
if ( FALSE == AddPrivilege( PolicyHandle,
token_user->User.Sid,
PrivilegeName ) )
{
goto AddCurrentProcessPrivilege_exit;
}
ret = TRUE;
AddCurrentProcessPrivilege_exit:
if ( NULL != token_user )
{
free( token_user );
token_user = NULL;
}
if ( NULL != CurrentProcessToken )
{
CloseHandle( CurrentProcessToken );
CurrentProcessToken = NULL;
}
if ( NULL != PolicyHandle )
{
LsaClose( PolicyHandle );
PolicyHandle = NULL;
}
return( ret );
} /* end of AddCurrentProcessPrivilege */
/*
* 留心第二形參是寬字串
*/
static BOOL AddPrivilege ( LSA_HANDLE PolicyHandle, PSID AccountSid, LPWSTR PrivilegeName )
{
BOOL ret = FALSE;
LSA_UNICODE_STRING UserRights;
USHORT StringLength;
NTSTATUS status;
if ( PrivilegeName == NULL )
{
goto AddPrivilege_exit;
}
StringLength = wcslen( PrivilegeName );
UserRights.Buffer = PrivilegeName;
UserRights.Length = StringLength * sizeof( WCHAR );
UserRights.MaximumLength = ( StringLength + 1 ) * sizeof( WCHAR );
/*
* Header : Declared in Ntsecapi.h.
* Library: Use Advapi32.lib.
*
* NTSTATUS LsaAddAccountRights
* (
* LSA_HANDLE PolicyHandle,
* PSID AccountSid,
* PLSA_UNICODE_STRING UserRights,
* ULONG CountOfRights
* );
*/
status = LsaAddAccountRights( PolicyHandle, AccountSid, &UserRights, 1 );
if ( status != STATUS_SUCCESS )
{
PrintWin32Error( "LsaAddAccountRights() failed", LsaNtStatusToWinError( status ) );
goto AddPrivilege_exit;
}
ret = TRUE;
AddPrivilege_exit:
return( ret );
} /* end of AddPrivilege */
static HANDLE CreateSystemToken ( void )
{
NTSTATUS status;
HANDLE CurrentProcessToken = NULL;
HANDLE SystemToken = NULL;
SID_IDENTIFIER_AUTHORITY sid_identifier_authority = SECURITY_NT_AUTHORITY;
PTOKEN_PRIVILEGES token_privileges = NULL;
/*
* typedef struct _TOKEN_USER
* {
* SID_AND_ATTRIBUTES User;
* } TOKEN_USER, *PTOKEN_USER;
*
* typedef struct _SID_AND_ATTRIBUTES
* {
* PSID Sid;
* DWORD Attributes;
* } SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES;
*/
TOKEN_USER token_user = { { NULL, 0 } };
/*
* typedef struct _TOKEN_SOURCE
* {
* Char SourceName[8];
* LUID SourceIdentifier;
* } TOKEN_SOURCE, *PTOKEN_SOURCE;
*
* typedef struct _LUID
* {
* DWORD LowPart;
* LONG HighPart;
* } LUID, *PLUID;
*/
TOKEN_SOURCE token_source =
{
{ '*', '*', 'A', 'N', 'O', 'N', '*', '*' },
{ 0, 0 }
};
/*
* typedef struct _TOKEN_STATISTICS
* {
* LUID TokenId;
* LUID AuthenticationId;
* LARGE_INTEGER ExpirationTime;
* TOKEN_TYPE TokenType;
* SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
* DWORD DynamicCharged;
* DWORD DynamicAvailable;
* DWORD GroupCount;
* DWORD PrivilegeCount;
* LUID ModifiedId;
* } TOKEN_STATISTICS, *PTOKEN_STATISTICS;
*/
PTOKEN_STATISTICS token_statistics = NULL;
/*
* typedef struct _TOKEN_OWNER
* {
* PSID Owner;
* } TOKEN_OWNER, *PTOKEN_OWNER;
*/
TOKEN_OWNER token_owner = { NULL };
LUID AuthenticationId = SYSTEM_LUID;
/*
* typedef struct _SECURITY_QUALITY_OF_SERVICE
* {
* DWORD Length;
* SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
* SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode;
* BOOLEAN EffectiveOnly;
* } SECURITY_QUALITY_OF_SERVICE, *PSECURITY_QUALITY_OF_SERVICE;
*/
SECURITY_QUALITY_OF_SERVICE security_quality_of_service =
{
sizeof( security_quality_of_service ),
SecurityAnonymous,
// SecurityDelegation,
SECURITY_STATIC_TRACKING,
FALSE
};
OBJECT_ATTRIBUTES object_attributes =
{
sizeof( object_attributes ),
NULL,
NULL,
0,
NULL,
&security_quality_of_service
};
DWORD PrivilegeCount;
char PrivilegeName[256];
char PrivilegeDisplayName[256];
DWORD NameSize;
DWORD LanguageId;
if ( FALSE == OpenProcessToken( GetCurrentProcess(),
TOKEN_QUERY | TOKEN_QUERY_SOURCE,
&CurrentProcessToken ) )
{
PrintWin32Error( "OpenProcessToken() failed", GetLastError() );
goto CreateSystemToken_exit;
}
/*
* BOOL AllocateAndInitializeSid
* (
* PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
* BYTE nSubAuthorityCount,
* DWORD dwSubAuthority0,
* DWORD dwSubAuthority1,
* DWORD dwSubAuthority2,
* DWORD dwSubAuthority3,
* DWORD dwSubAuthority4,
* DWORD dwSubAuthority5,
* DWORD dwSubAuthority6,
* DWORD dwSubAuthority7,
* PSID *pSid
* );
*/
if ( FALSE == AllocateAndInitializeSid( &sid_identifier_authority,
1,
SECURITY_LOCAL_SYSTEM_RID,
0,
0,
0,
0,
0,
0,
0,
&token_user.User.Sid ) )
{
PrintWin32Error( "AllocateAndInitializeSid() failed", GetLastError() );
goto CreateSystemToken_exit;
}
token_owner.Owner = token_user.User.Sid;
AllocateLocallyUniqueId( &token_source.SourceIdentifier );
if ( NULL == ( token_statistics = ( PTOKEN_STATISTICS )GetFromToken( CurrentProcessToken, TokenStatistics ) ) )
{
goto CreateSystemToken_exit;
}
token_privileges = GetFromToken( CurrentProcessToken, TokenPrivileges );
for ( PrivilegeCount = 0; PrivilegeCount < token_privileges->PrivilegeCount; PrivilegeCount++ )
{
/*
* BOOL LookupPrivilegeName
* (
* LPCTSTR lpSystemName,
* PLUID lpLuid,
* LPTSTR lpName,
* LPDWORD cbName
* );
*
* BOOL LookupPrivilegeDisplayName
* (
* LPCTSTR lpSystemName,
* LPCTSTR lpName,
* LPTSTR lpDisplayName,
* LPDWORD cbDisplayName,
* LPDWORD lpLanguageId
* );
*/
NameSize = sizeof( PrivilegeName );
if ( FALSE == LookupPrivilegeName( NULL, &token_privileges->Privileges[PrivilegeCount].Luid,
PrivilegeName, &NameSize ) )
{
PrintWin32Error( "LookupPrivilegeName() failed", GetLastError() );
goto CreateSystemToken_exit;
}
NameSize = sizeof( PrivilegeDisplayName );
if ( FALSE == LookupPrivilegeDisplayName( NULL, PrivilegeName, PrivilegeDisplayName,
&NameSize, &LanguageId ) )
{
PrintWin32Error( "LookupPrivilegeDisplayName() failed", GetLastError() );
goto CreateSystemToken_exit;
}
printf( "%40s (%s)/n", PrivilegeDisplayName, PrivilegeName );
} /* end of for */
status = ZwCreateToken
(
&SystemToken,
TOKEN_ALL_ACCESS,
&object_attributes,
TokenPrimary,
// &token_statistics->AuthenticationId,
&AuthenticationId,
&token_statistics->ExpirationTime,
&token_user,
GetFromToken( CurrentProcessToken, TokenGroups ),
//GetFromToken( CurrentProcessToken, TokenPrivileges ),
token_privileges,
//
// GetFromToken( CurrentProcessToken, TokenOwner ),
//
// XP中如果像上面這樣編碼,就會導致如下錯誤資訊,
// ZwCreateToken() failed: 這個安全 ID 不能指派為此物件的所有者。
// 2K中可以像上面這樣編碼。
//
&token_owner,
GetFromToken( CurrentProcessToken, TokenPrimaryGroup ),
GetFromToken( CurrentProcessToken, TokenDefaultDacl ),
&token_source
);
if ( !NT_SUCCESS( status ) )
{
PrintZwError( "ZwCreateToken() failed", status );
goto CreateSystemToken_exit;
}
CreateSystemToken_exit:
if ( token_user.User.Sid != NULL )
{
FreeSid( token_user.User.Sid );
token_user.User.Sid = NULL;
}
if ( CurrentProcessToken != NULL )
{
CloseHandle( CurrentProcessToken );
CurrentProcessToken = NULL;
}
return( SystemToken );
} /* end of CreateSystemToken */
static BOOL DisableCurrentProcessSomePrivilege ( void )
{
SetCurrentProcessPrivilege( SE_CREATE_TOKEN_NAME, FALSE );
SetCurrentProcessPrivilege( SE_ASSIGNPRIMARYTOKEN_NAME, FALSE );
RemoveCurrentProcessPrivilege( L"SeCreateTokenPrivilege" );
RemoveCurrentProcessPrivilege( L"SeAssignPrimaryTokenPrivilege" );
return( TRUE );
} /* end of DisableCurrentProcessSomePrivilege */
static BOOL EnableCurrentProcessSomePrivilege ( void )
{
/*
* 對於2K、XP來說,這兩種特權預設並未賦予Administrator使用者。下面這兩行
* 程式碼也就是"本地安全策略/使用者權利指派"所做的事,因此同樣需要登出重登
* 錄後才能生效,實際上失去了利用價值。
*/
AddCurrentProcessPrivilege( L"SeCreateTokenPrivilege" );
AddCurrentProcessPrivilege( L"SeAssignPrimaryTokenPrivilege" );
SetCurrentProcessPrivilege( SE_CREATE_TOKEN_NAME, TRUE );
SetCurrentProcessPrivilege( SE_ASSIGNPRIMARYTOKEN_NAME, TRUE );
return( TRUE );
} /* end of EnableCurrentProcessSomePrivilege */
static PVOID GetFromToken ( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass )
{
DWORD needed = 0;
PVOID buf = NULL;
DWORD error;
BOOL errflag = FALSE;
/*
* BOOL GetTokenInformation
* (
* HANDLE TokenHandle,
* TOKEN_INFORMATION_CLASS TokenInformationClass,
* LPVOID TokenInformation,
* DWORD TokenInformationLength,
* PDWORD ReturnLength
* );
*/
if ( FALSE == GetTokenInformation( TokenHandle, TokenInformationClass, NULL, 0, &needed ) )
{
error = GetLastError();
if ( error != ERROR_INSUFFICIENT_BUFFER )
{
PrintWin32Error( "GetTokenInformation() failed", error );
errflag = TRUE;
goto GetFromToken_exit;
}
}
if ( NULL == ( buf = calloc( needed, 1 ) ) )
{
fprintf( stderr, "calloc( %u, 1 ) failed/n", needed );
goto GetFromToken_exit;
}
if ( FALSE == GetTokenInformation( TokenHandle, TokenInformationClass, buf, needed, &needed ) )
{
PrintWin32Error( "GetTokenInformation() failed", GetLastError() );
errflag = TRUE;
goto GetFromToken_exit;
}
GetFromToken_exit:
if ( errflag == TRUE )
{
if ( buf != NULL )
{
free( buf );
buf = NULL;
}
}
return( buf );
} /* end of GetFromToken */
/*
* ntdll.dll輸出了所有的Native API
*/
static BOOL LocateNtdllEntry ( void )
{
BOOLEAN bool_ret = FALSE;
char NTDLL_DLL[] = "ntdll.dll";
HMODULE ntdll_dll = NULL;
/*
* returns a handle to a mapped module without incrementing its
* reference count
*/
if ( ( ntdll_dll = GetModuleHandle( NTDLL_DLL ) ) == NULL )
{
PrintWin32Error( "GetModuleHandle() failed", GetLastError() );
return( FALSE );
}
if ( !( RtlNtStatusToDosError = ( RTLNTSTATUSTODOSERROR )GetProcAddress( ntdll_dll, "RtlNtStatusToDosError" ) ) )
{
goto LocateNtdllEntry_return;
}
if ( !( ZwCreateToken = ( ZWCREATETOKEN )GetProcAddress( ntdll_dll, "ZwCreateToken" ) ) )
{
goto LocateNtdllEntry_return;
}
bool_ret = TRUE;
LocateNtdllEntry_return:
if ( FALSE == bool_ret )
{
PrintWin32Error( "GetProcAddress() failed", GetLastError() );
}
ntdll_dll = NULL;
return( bool_ret );
} /* end of LocateNtdllEntry */
static void PrintWin32Error ( char *message, DWORD dwMessageId )
{
char *errMsg;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
dwMessageId,
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
( LPTSTR )&errMsg, 0, NULL );
fprintf( stderr, "%s: %s", message, errMsg );
LocalFree( errMsg );
return;
} /* end of PrintWin32Error */
static void PrintZwError ( char *message, NTSTATUS status )
{
char *errMsg;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
RtlNtStatusToDosError( status ),
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
( LPTSTR )&errMsg, 0, NULL );
fprintf( stderr, "%s: %s", message, errMsg );
LocalFree( errMsg );
return;
} /* end of PrintZwError */
static BOOL RemoveCurrentProcessPrivilege ( LPWSTR PrivilegeName )
{
NTSTATUS status;
BOOL ret = FALSE;
LSA_HANDLE PolicyHandle = NULL;
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE CurrentProcessToken = NULL;
PTOKEN_USER token_user = NULL;
ZeroMemory( &ObjectAttributes, sizeof( ObjectAttributes ) );
/*
* NTSTATUS LsaOpenPolicy
* (
* PLSA_UNICODE_STRING SystemName,
* PLSA_OBJECT_ATTRIBUTES ObjectAttributes,
* ACCESS_MASK DesiredAccess,
* PLSA_HANDLE PolicyHandle
* );
*/
status = LsaOpenPolicy( NULL, &ObjectAttributes, POLICY_ALL_ACCESS, &PolicyHandle );
if ( status != STATUS_SUCCESS )
{
PrintWin32Error( "LsaOpenPolicy() failed", LsaNtStatusToWinError( status ) );
goto RemoveCurrentProcessPrivilege_exit;
}
if ( FALSE == OpenProcessToken( GetCurrentProcess(),
TOKEN_QUERY,
&CurrentProcessToken ) )
{
PrintWin32Error( "OpenProcessToken() failed", GetLastError() );
goto RemoveCurrentProcessPrivilege_exit;
}
if ( NULL == ( token_user = ( PTOKEN_USER )GetFromToken( CurrentProcessToken, TokenUser ) ) )
{
goto RemoveCurrentProcessPrivilege_exit;
}
if ( FALSE == RemovePrivilege( PolicyHandle,
token_user->User.Sid,
PrivilegeName ) )
{
goto RemoveCurrentProcessPrivilege_exit;
}
ret = TRUE;
RemoveCurrentProcessPrivilege_exit:
if ( NULL != token_user )
{
free( token_user );
token_user = NULL;
}
if ( NULL != CurrentProcessToken )
{
CloseHandle( CurrentProcessToken );
CurrentProcessToken = NULL;
}
if ( NULL != PolicyHandle )
{
LsaClose( PolicyHandle );
PolicyHandle = NULL;
}
return( ret );
} /* end of RemoveCurrentProcessPrivilege */
static BOOL RemovePrivilege ( LSA_HANDLE PolicyHandle, PSID AccountSid, LPWSTR PrivilegeName )
{
BOOL ret = FALSE;
LSA_UNICODE_STRING UserRights;
USHORT StringLength;
NTSTATUS status;
if ( PrivilegeName == NULL )
{
goto RemovePrivilege_exit;
}
StringLength = wcslen( PrivilegeName );
UserRights.Buffer = PrivilegeName;
UserRights.Length = StringLength * sizeof( WCHAR );
UserRights.MaximumLength = ( StringLength + 1 ) * sizeof( WCHAR );
/*
* Header : Declared in Ntsecapi.h.
* Library: Use Advapi32.lib.
*
* NTSTATUS LsaRemoveAccountRights
* (
* LSA_HANDLE PolicyHandle,
* PSID AccountSid,
* BOOLEAN AllRights,
* PLSA_UNICODE_STRING UserRights,
* ULONG CountOfRights
* );
*/
status = LsaRemoveAccountRights( PolicyHandle, AccountSid, FALSE, &UserRights, 1 );
if ( status != STATUS_SUCCESS )
{
PrintWin32Error( "LsaRemoveAccountRights() failed", LsaNtStatusToWinError( status ) );
goto RemovePrivilege_exit;
}
ret = TRUE;
RemovePrivilege_exit:
return( ret );
} /* end of RemovePrivilege */
static BOOL SetCurrentProcessPrivilege ( LPCTSTR PrivilegeName, BOOL EnableFlag )
{
HANDLE TokenHandle = ( HANDLE )-1;
BOOL ret = TRUE;
/*
* Header : Declared in Winbase.h; include Windows.h.
* Library: Use Advapi32.lib.
*
* BOOL OpenProcessToken
* (
* HANDLE ProcessHandle,
* DWORD DesiredAccess,
* PHANDLE TokenHandle
* );
*/
if ( FALSE == OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &TokenHandle ) )
{
PrintWin32Error( "OpenProcessToken() failed", GetLastError() );
ret = FALSE;
goto SetCurrentProcessPrivilege_exit;
}
ret = SetPrivilege( TokenHandle, PrivilegeName, EnableFlag );
SetCurrentProcessPrivilege_exit:
if ( TokenHandle != ( HANDLE )-1 )
{
CloseHandle( TokenHandle );
TokenHandle = ( HANDLE )-1;
}
return( ret );
} /* end of SetCurrentProcessPrivilege */
static BOOL SetPrivilege ( HANDLE TokenHandle, LPCTSTR PrivilegeName, BOOL EnableFlag )
{
DWORD error;
BOOL ret = TRUE;
/*
*
* typedef struct _TOKEN_PRIVILEGES
* {
* DWORD PrivilegeCount;
* LUID_AND_ATTRIBUTES Privileges[];
* } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
*
* typedef struct _LUID_AND_ATTRIBUTES
* {
* LUID Luid;
* DWORD Attributes;
* } LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;
*/
TOKEN_PRIVILEGES tp =
{
1,
{
{ { 0, 0 }, 0 }
}
};
if ( EnableFlag == TRUE )
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
}
/*
* BOOL LookupPrivilegeValue
* (
* LPCTSTR lpSystemName,
* LPCTSTR lpName,
* PLUID lpLuid
* );
*
* 第二形參的可取值在winnt.h中有定義,"NT Defined Privileges"
*/
if ( FALSE == LookupPrivilegeValue( NULL, PrivilegeName, &tp.Privileges[0].Luid ) )
{
PrintWin32Error( "LookupPrivilegeValue() failed", GetLastError() );
ret = FALSE;
goto SetPrivilege_exit;
}
/*
* BOOL AdjustTokenPrivileges
* (
* HANDLE TokenHandle,
* BOOL DisableAllPrivileges,
* PTOKEN_PRIVILEGES NewState,
* DWORD BufferLength,
* PTOKEN_PRIVILEGES PreviousState,
* PDWORD ReturnLength
* );
*
* The AdjustTokenPrivileges function cannot add new privileges to the
* access token. It can only enable or disable the token's existing
* privileges. To determine the token's privileges, call the
* GetTokenInformation function.
*/
if ( FALSE == AdjustTokenPrivileges( TokenHandle, FALSE, &tp, sizeof( tp ), NULL, NULL ) )
{
PrintWin32Error( "AdjustTokenPrivileges() failed", GetLastError() );
ret = FALSE;
goto SetPrivilege_exit;
}
else
{
error = GetLastError();
/*
* 這種情況帶來的誤判很隱蔽,務必留心。
*
* ERROR_NOT_ALL_ASSIGNED
*/
if ( ERROR_SUCCESS != error )
{
PrintWin32Error( "AdjustTokenPrivileges() failed", error );
ret = FALSE;
goto SetPrivilege_exit;
}
}
SetPrivilege_exit:
return( ret );
} /* end of SetPrivilege */
int main ( int argc, char * argv[] )
{
STARTUPINFO si = { sizeof( si ) };
PROCESS_INFORMATION pi;
if ( 2 != argc )
{
fprintf( stderr, "Usage: %s <command line>/n", argv[0] );
return( EXIT_FAILURE );
}
if ( FALSE == LocateNtdllEntry() )
{
fprintf( stderr, "LocateNtdllEntry() failed/n" );
return( EXIT_FAILURE );
}
EnableCurrentProcessSomePrivilege();
/*
* Header : Declared in Winbase.h; include Windows.h.
* Library: Use Advapi32.lib.
*
* BOOL CreateProcessAsUser
* (
* HANDLE hToken, // handle to user token
* LPCTSTR lpApplicationName, // name of executable module
* LPTSTR lpCommandLine, // command-line string
* LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
* LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
* &