1. 程式人生 > >Administrator使用者直接獲取SYSTEM許可權

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
  * &

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述