Administrator用户直接获取SYSTEM权限

System Trustedlnstaller Administrator 文件权限给予 "IsolatedCommand"="cmd.exe /c takeown /f \"%1\" /r /d y /a && icacls \"%1\" /grant \"NT SERVICE\\TrustedInstaller\":F /t && whoami && echo 权限已授予TrustedInstaller(NT SERVICE\\TrustedInstaller)" 阅读详情
来源: http://www.nsfocus.com
作者:"scz" < scz@nsfocus.com>


标题: MSDN系列(3)--Administrator用户直接获取SYSTEM权限

日期: 2003-06-21 21:51
更新:

--------------------------------------------------------------------------

目录:

  ☆ 概述
  ☆ sysproc.c
  ☆ sysproc_now.c
  ☆ 参考资源

--------------------------------------------------------------------------

☆ 概述

翻看[5]的时候,其书中例8.1演示如何以SYSTEM身份启动cmd。以前我为了达到同样
目的,利用at命令,但平日里禁用Task Scheduler Service的,感觉操作很绕弯,不
爽得很。网上有现成的可执行程序直接获取SYSTEM权限,不喜欢没源码的此类型小工
具,从未试用过。

麻雀兄 <sparrow@smth>在水木清华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
  *   BOOL             bInheritHandles,     // inheritance option
  *   DWORD           dwCreationFlags,     // creation flags
  *   LPVOID           lpEnvironment,     // new environment block
  *   LPCTSTR           lpCurrentDirectory,   // current directory name
  *   LPSTARTUPINFO       lpStartupInfo,     // startup information
  *   LPPROCESS_INFORMATION lpProcessInformation // process information
  * );
  *
  * Typically, the process that calls the CreateProcessAsUser function
  * must have the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME
  * privileges.
  */
  if ( FALSE == CreateProcessAsUser
            (
              CreateSystemToken(),
              NULL,
              argv[1],
              NULL,
              NULL,
              FALSE,
              CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
              NULL,
              NULL,
              &si,
              &pi
            ) )
  {
    PrintWin32Error( "CreateProcessAsUser() failed", GetLastError() );
    return( EXIT_FAILURE );
  }
  /*
  * CreateProcessAsUser()无论是否成功,都返回。
  */
  DisableCurrentProcessSomePrivilege();
  /*
  * 主调进程马上要退出了,懒得显式关闭PROCESS_INFORMATION中的句柄,由操
  * 作系统隐式关闭去吧。事实上CreateSystemToken()中调用GetFromToken(),
  * 后者在堆区分配过内存,不过这次也不需要显式释放了。
  */
  return( EXIT_SUCCESS );
} /* end of main */

/************************************************************************/

--------------------------------------------------------------------------

如果第一次执行失败,注销/重登录再次执行即可成功。如果第一次执行成功,注销/
重登录再次执行将会失败。这只是演示如何编程实现"本地安全策略/用户权利指派"。

执行regedit,如果能看到下列内容,表示已经获取SYSTEM权限:

HKEY_LOCAL_MACHINE/SAM/SAM/Domains/Builtin

缺省情况下,管理员帐号只能看到:

HKEY_LOCAL_MACHINE/SAM/SAM

个人准备将sysproc.c扔进垃圾堆,离我所需相去甚远。

☆ sysproc_now.c

麻雀兄解释了Ashot Oganesyan K的中心思想,Win32 API/CreateProcess()最终会调
用Native API/ZwCreateProcess(),后者的第四形参是InheritFromProcessHandle,
子进程的主令牌(Primary Token)继承自这个进程句柄,一般情况下也就是父进程句
柄。将ZwCreateProcess()拦截(Hook),修改第四形参,使之对应一个拥有SYSTEM权
限的进程句柄,于是所创建的子进程将拥有SYSTEM权限。

我主要做了两处改进。一是利用ZwQuerySystemInformation()自己找出winlogon.exe
的PID,并获取进程句柄,从而不必在命令行上指定拥有SYSTEM权限的PID。二是增加
对XP、2003 Server的支持。

一开始我拦截ZwCreateProcess(),发现对于XP无效,怀疑CreateProcess()已经不调
用ZwCreateProcess()。增加了一点调试代码,确认流程并未经过ZwCreateProcess()。
然后我就到处乱找能跟踪系统调用的工具,最后用了BindView的strace工具([1])。
0.3版的strace为了在XP上使用,需要在注册表中做如下设置,重启后生效:

--------------------------------------------------------------------------
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Memory Management]
"EnforceWriteProtection"=dword:00000000
--------------------------------------------------------------------------

跟踪结果中只有NtCreateProcessEx(),而没有NtCreateProcess()。于是我换成拦截
ZwCreateProcessEx(),搞定。

不清楚ZwCreateProcessEx()的函数原型是什么,形参为九个,比ZwCreateProcess()
多一个。按照MS的一贯作风,应该不会动前八个形参,仅仅是扩展出第九个形参,因
此第四形参仍为InheritFromProcessHandle。ZwCreateProcess()的函数原型可参看
[5]。顺便说一句,编写、侦测rootkit时要留心XP/2003上的这种变化。

为了区分2000/XP/2003,用GetVersionEx()做精确的OS版本判断。用IDA Pro 4.3.0
反汇编ntdll.dll即可找出下列信息:

--------------------------------------------------------------------------
XP

  ZwCreateProcess   2Fh
  ZwCreateProcessEx 30h

2003 Server

  ZwCreateProcess   31h
  ZwCreateProcessEx 32h
--------------------------------------------------------------------------

可能你看到的不是熟悉的int 2Eh,而类似如下代码:

--------------------------------------------------------------------------
ZwCreateProcessEx proc near
  mov   eax, 32h
  mov   edx, 7FFE0300h
  call   edx
  retn   24h
ZwCreateProcessEx endp
--------------------------------------------------------------------------

0x7FFE0300处是什么东西,用kd查看一下:

--------------------------------------------------------------------------
lkd> u 0x7ffe0300
SharedUserData!SystemCallStub:
7ffe0300 8bd4         mov   edx,esp
7ffe0302 0f34         sysenter
7ffe0304 c3           ret
--------------------------------------------------------------------------

这就是所谓"快速系统调用接口"。参看Intel卷II中对sysenter指令的解释。VC 7不
支持sysenter,我用_emit直接嵌入机器码。从Windows 2000/PII开始引入这个与传
统int 2Eh并存的快速系统调用接口,但你硬是要用int 2Eh仍然可以成功。ntoskrnl
中与这两种系统调用接口相对应的是KiFastCallEntry()、KiSystemService()。

--------------------------------------------------------------------------
lkd> u nt!KiFastCallEntry
nt!KiFastCallEntry:
8052d480 368b0d40f0dfff   mov   ecx,ss:[ffdff040]
8052d487 368b6104       mov   esp,ss:[ecx+0x4]
8052d48b b90403fe7f     mov   ecx,0x7ffe0304
8052d490 3b2504f0dfff   cmp   esp,[ffdff004]
8052d496 0f84ce030000   je     nt!KiServiceExit2+0x143 (8052d86a)
8052d49c 6a23         push   0x23
8052d49e 52           push   edx
8052d49f 83c208       add   edx,0x8
lkd> u nt!KiSystemService
nt!KiSystemService:
8052d4ad 6a00         push   0x0
8052d4af 55           push   ebp
8052d4b0 53           push   ebx
8052d4b1 56           push   esi
8052d4b2 57           push   edi
8052d4b3 0fa0         push   fs
8052d4b5 bb30000000     mov   ebx,0x30
8052d4ba 668ee3       mov   fs,bx
lkd>
--------------------------------------------------------------------------

要想拦截KiFastCallEntry(),可比拦截KiSystemService()复杂一些,关于这个就不
多解释了,反正这次的主要目的也不是拦截内核空间的什么东东。不过务必要记住这
件事,只拦截KiSystemService()很可能会得出错误结论。

[6]是一份不错的关于此方面内容的文档。

sysproc_now.c中演示了这两种系统调用接口,但是用条件编译注释掉了其中一种,
你可以根据自己的爱好选用任一种,均可成功达到目的。

--------------------------------------------------------------------------
/*
* For x86/EWindows XP SP1 & VC 7
* cl sysproc_now.c /Os /G6 /W3
*
* Support for Windows NT3.51 NT4.0 2000
* (c)1999 Ashot Oganesyan K, SmartLine, Inc
* Ashot Oganesyan K <ashot@aha.ru>
*
* Add support for Windows XP/2003 by scz <scz@nsfocus.com>
* 2003-06-21 21:22
*/

/************************************************************************
*                                               *
*                     Head File                     *
*                                               *
************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

/************************************************************************
*                                               *
*                     Macro                       *
*                                               *
************************************************************************/

#pragma comment( linker, "/subsystem:console" )
#pragma comment( lib,   "kernel32.lib"     )
#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_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)

/*
*************************************************************************
* ntddk.h
*/

typedef LONG KPRIORITY;

/*
* ntddk.h
*************************************************************************
*/

/*
*************************************************************************
* ntdef.h
*/

typedef struct _UNICODE_STRING
{
  USHORT Length;
  USHORT MaximumLength;
  PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES
{
  ULONG       Length;
  HANDLE       RootDirectory;
  PUNICODE_STRING ObjectName;
  ULONG       Attributes;
  PVOID       SecurityDescriptor;
  PVOID       SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

/*
* ntdef.h
*************************************************************************
*/

/*
*************************************************************************
* <<Windows NT/2000 Native API Reference>> - Gary Nebbett
*/

typedef enum _SYSTEM_INFORMATION_CLASS
{
  SystemProcessesAndThreadsInformation = 5
} SYSTEM_INFORMATION_CLASS;

/*
* Information Class 5
*
* 为了便于编译,我将InheritedFromProcessId之后的成员扔掉了
*/
typedef struct _SYSTEM_PROCESSES
{
  ULONG       NextEntryDelta;
  ULONG       ThreadCount;
  ULONG       Reserved1[6];
  LARGE_INTEGER CreateTime;
  LARGE_INTEGER UserTime;
  LARGE_INTEGER KernelTime;
  UNICODE_STRING ProcessName;
  KPRIORITY     BasePriority;
  ULONG       ProcessId;
  ULONG       InheritedFromProcessId;
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;

/*
* <<Windows NT/2000 Native API Reference>> - Gary Nebbett
*************************************************************************
*/

/*
* 参看DDK文档以及<<Windows NT/2000 Native API Reference>> - Gary Nebbett
* 这些Native API由ntdll.dll输出
*/
typedef ULONG   ( __stdcall *RTLNTSTATUSTODOSERROR   ) ( IN NTSTATUS Status );
typedef NTSTATUS ( __stdcall *ZWCREATEPROCESS       ) ( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE InheritFromProcessHandle, IN BOOLEAN InheritHandles, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL );
typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION ) ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );

#pragma pack(push, 1)

typedef struct
{
  unsigned char     mov_eax;
  void           *address;
  unsigned short int jmp_eax;
} ASMJUMP, *PASMJUMP;

#pragma pack(pop)

/************************************************************************
*                                               *
*                   Function Prototype                 *
*                                               *
************************************************************************/

static BOOL DisableCurrentProcessDebugPrivilege
                    ( void );
static BOOL EnableCurrentProcessDebugPrivilege
                    ( void );
static DWORD GetPidFromProcessName
                    ( wchar_t *ProcessName );
static BOOL LocateNtdllEntry ( void );
static void PrintWin32Error ( char *message, DWORD dwMessageId );
static void PrintZwError   ( char *message, NTSTATUS status );
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 ZWCREATEPROCESS       ZwCreateProcess       = NULL;
static ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
/*
* 这是XP/2003新增的Native API,总共九个形参,比ZwCreateProcess()多一个
*/
static PVOID             ZwCreateProcessEx     = NULL;

/*
* winlogon.exe的进程句柄
*/
static HANDLE             winlogon           = NULL;
static DWORD             ZwCreateProcessNum     = 0;
static DWORD             ZwCreateProcessExNum   = 0;

/************************************************************************/

static BOOL DisableCurrentProcessDebugPrivilege ( void )
{
  return( SetCurrentProcessPrivilege( SE_DEBUG_NAME, FALSE ) );
} /* end of DisableCurrentProcessDebugPrivilege */

static BOOL EnableCurrentProcessDebugPrivilege ( void )
{
  return( SetCurrentProcessPrivilege( SE_DEBUG_NAME, TRUE ) );
} /* end of EnableCurrentProcessDebugPrivilege */

static DWORD GetPidFromProcessName ( wchar_t *ProcessName )
{
  NTSTATUS       status;
  PVOID         buf   = NULL;
  ULONG         size = 1;
  PSYSTEM_PROCESSES proc = NULL;
  ULONG         delta = 0;
  DWORD         pid   = 0;

  for ( size = 1; ; size *= 2 )
  {
    if ( NULL == ( buf = calloc( size, 1 ) ) )
    {
        fprintf( stderr, "calloc( %u, 1 ) failed/n", size );
        goto GetPidFromProcessName_exit;
    }
    status = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, buf, size, NULL );
    if ( !NT_SUCCESS( status ) )
    {
        if ( STATUS_INFO_LENGTH_MISMATCH == status )
        {
          free( buf );
          buf = NULL;
        }
        else
        {
          PrintZwError( "ZwQuerySystemInformation() failed", status );
          goto GetPidFromProcessName_exit;
        }
    }
    else
    {
        /*
        * printf( "size = %u/n", size );
        */
        break;
    }
  } /* end of for */
  proc = ( PSYSTEM_PROCESSES )buf;
  do
  {
    if ( NULL != proc->ProcessName.Buffer )
    {
        if ( 0 == _wcsicmp( ProcessName, proc->ProcessName.Buffer ) )
        {
          pid = proc->ProcessId;
          break;
        }
    }
    delta = proc->NextEntryDelta;
    proc = ( PSYSTEM_PROCESSES )( ( char * )proc + delta );
  }
  while ( 0 != delta );

GetPidFromProcessName_exit:

  if ( buf != NULL )
  {
    free( buf );
    buf = NULL;
  }
  return( pid );
} /* end of GetPidFromProcessName */

static void __declspec(naked) HackedZwCreateProcess ( void )
{
  /*
  *********************************************************************
  * 这两个__asm{}之间的代码只是调试代码,没有实际意义。
  */
  __asm
  {
    pushad
    pushfd
  }

  printf( "HackedZwCreateProcess()/n" );

  __asm
  {
    popfd
    popad
  }
  /*
  * 这两个__asm{}之间的代码只是调试代码,没有实际意义。
  *********************************************************************
  */

  /*
  * 第四形参是InheritFromProcessHandle
  * [esp]是返回地址
  */
  __asm
  {
    mov   eax,winlogon
    mov   dword ptr [esp+16],eax
    /*
      * EAX是调用号
      */
    mov   eax,ZwCreateProcessNum
    /*
      * EDX指向形参区域
      */
    lea   edx,dword ptr [esp+4]
    int   2Eh
    /*
      * __stdcall调用风格,由被调函数自己负责堆栈平衡。
      */
    retn   20h
  }
} /* end of HackedZwCreateProcess */

#if 0
static void __declspec(naked) HackedZwCreateProcessEx ( void )
{
  /*
  *********************************************************************
  * 这两个__asm{}之间的代码只是调试代码,没有实际意义。
  */
  __asm
  {
    pushad
    pushfd
  }

  printf( "HackedZwCreateProcessEx()/n" );

  __asm
  {
    popfd
    popad
  }
  /*
  * 这两个__asm{}之间的代码只是调试代码,没有实际意义。
  *********************************************************************
  */

  /*
  * 第四形参是InheritFromProcessHandle
  * [esp]是返回地址
  */
  __asm
  {
    mov   eax,winlogon
    mov   dword ptr [esp+16],eax
    /*
      * EAX是调用号
      */
    mov   eax,ZwCreateProcessExNum
    /*
      * EDX指向形参区域
      */
    lea   edx,dword ptr [esp+4]
    int   2Eh
    /*
      * __stdcall调用风格,由被调函数自己负责堆栈平衡。注意这次有九个形
      * 参,平衡堆栈时要比前面多弹一个DWORD。
      */
    retn   24h
  }
} /* end of HackedZwCreateProcessEx */
#endif

#if 0
static void __declspec(naked) HackedZwCreateProcessEx ( void )
{
  /*
  *********************************************************************
  * 这两个__asm{}之间的代码只是调试代码,没有实际意义。
  */
  __asm
  {
    pushad
    pushfd
  }

  printf( "HackedZwCreateProcessEx()/n" );

  __asm
  {
    popfd
    popad
  }
  /*
  * 这两个__asm{}之间的代码只是调试代码,没有实际意义。
  *********************************************************************
  */

  /*
  * 第四形参是InheritFromProcessHandle
  * [esp]是返回地址
  */
  __asm
  {
    mov   eax,winlogon
    mov   dword ptr [esp+16],eax
    /*
      * EAX是调用号
      */
    mov   eax,ZwCreateProcessExNum
    /*
      * lkd> u 0x7ffe0300
      * SharedUserData!SystemCallStub:
      * 7ffe0300 8bd4         mov   edx,esp
      * 7ffe0302 0f34         sysenter
      * 7ffe0304 c3           ret
      */
    mov   edx,7FFE0300h
    call   edx
    /*
      * __stdcall调用风格,由被调函数自己负责堆栈平衡。注意这次有九个形
      * 参,平衡堆栈时要比前面多弹一个DWORD。
      */
    retn   24h
  }
} /* end of HackedZwCreateProcessEx */
#endif

/*
* 上面被条件编译注释掉的两段代码均可工作于XP/2003上。int 2Eh是传统系统调
* 用接口,sysenter是所谓"快速系统调用接口",参看Intel卷II中对该指令的解释。
* VC 7不支持sysenter,我用_emit直接嵌入机器码。
*/
static void __declspec(naked) HackedZwCreateProcessEx ( void )
{
  /*
  *********************************************************************
  * 这两个__asm{}之间的代码只是调试代码,没有实际意义。
  */
  __asm
  {
    pushad
    pushfd
  }

  printf( "HackedZwCreateProcessEx()/n" );

  __asm
  {
    popfd
    popad
  }
  /*
  * 这两个__asm{}之间的代码只是调试代码,没有实际意义。
  *********************************************************************
  */

  /*
  * 第四形参是InheritFromProcessHandle
  * [esp]是返回地址
  */
  __asm
  {
    mov   eax,winlogon
    mov   dword ptr [esp+16],eax
    /*
      * EAX是调用号
      */
    mov   eax,ZwCreateProcessExNum
    call   SystemCallStub
    retn   24h

SystemCallStub:

    mov   edx,esp
    /*
      * 0f34 sysenter
      */
    _emit   0x0f
    _emit   0x34
    ret
  }
} /* end of HackedZwCreateProcessEx */

/*
* ntdll.dll输出了所有的Native API
*/
static BOOL LocateNtdllEntry ( void )
{
  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_exit;
  }
  if ( !( ZwCreateProcess = ( ZWCREATEPROCESS )GetProcAddress( ntdll_dll, "ZwCreateProcess" ) ) )
  {
    goto LocateNtdllEntry_exit;
  }
  if ( !( ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( ntdll_dll, "ZwQuerySystemInformation" ) ) )
  {
    goto LocateNtdllEntry_exit;
  }
  if ( ZwCreateProcessExNum != 0 )
  {
    if ( !( ZwCreateProcessEx = ( PVOID )GetProcAddress( ntdll_dll, "ZwCreateProcessEx" ) ) )
    {
        goto LocateNtdllEntry_exit;
    }
  }
  ret = TRUE;

LocateNtdllEntry_exit:

  if ( FALSE == ret )
  {
    PrintWin32Error( "GetProcAddress() failed", GetLastError() );
  }
  ntdll_dll = NULL;
  return( 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 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[] )
{
#if 0
  DisableCurrentProcessDebugPrivilege();
  return( EXIT_SUCCESS );
#endif

  OSVERSIONINFO         osversioninfo;
  DWORD             winlogonPid = 0;
  STARTUPINFO         si       = { sizeof( si ) };
  PROCESS_INFORMATION     pi;
  /*
  * typedef struct _MEMORY_BASIC_INFORMATION
  * {
  *   PVOID BaseAddress;
  *   PVOID AllocationBase;
  *   DWORD AllocationProtect;
  *   SIZE_T RegionSize;
  *   DWORD State;
  *   DWORD Protect;
  *   DWORD Type;
  * } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
  */
  MEMORY_BASIC_INFORMATION mbi;
  DWORD             OldProtect;

  ZeroMemory( &pi, sizeof( pi ) );
  if ( 2 != argc )
  {
    fprintf( stderr, "Usage: %s <command line>/n", argv[0] );
    goto main_exit;
  }
  /*
  * typedef struct _OSVERSIONINFO
  * {
  *   DWORD dwOSVersionInfoSize;
  *   DWORD dwMajorVersion;
  *   DWORD dwMinorVersion;
  *   DWORD dwBuildNumber;
  *   DWORD dwPlatformId;
  *   TCHAR szCSDVersion[128];
  * } OSVERSIONINFO;
  *
  * BOOL GetVersionEx ( LPOSVERSIONINFO lpVersionInfo );
  */
  ZeroMemory( &osversioninfo, sizeof( osversioninfo ) );
  osversioninfo.dwOSVersionInfoSize = sizeof( osversioninfo );
  if ( FALSE == GetVersionEx( &osversioninfo ) )
  {
    PrintWin32Error( "GetVersionEx() failed", GetLastError() );
    goto main_exit;
  }
  printf( "Version %u.%u/n", osversioninfo.dwMajorVersion, osversioninfo.dwMinorVersion );
  if ( osversioninfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
  {
    if ( osversioninfo.dwMajorVersion == 3 && osversioninfo.dwMinorVersion == 51 )
    {
        /*
        * NT 3.51
        */
        ZwCreateProcessNum = 0x1E;
    }
    else if ( osversioninfo.dwMajorVersion == 4 && osversioninfo.dwMinorVersion == 0 )
    {
        /*
        * NT 4.0
        */
        ZwCreateProcessNum = 0x1F;
    }
    else if ( osversioninfo.dwMajorVersion == 5 && osversioninfo.dwMinorVersion == 0 )
    {
        /*
        * 2000
        */
        ZwCreateProcessNum = 0x29;
    }
    else if ( osversioninfo.dwMajorVersion == 5 && osversioninfo.dwMinorVersion == 1 )
    {
        /*
        * XP
        *
        * 与以前所有版本不同的是,Win32 API/CreateProcess()最终调用了
        * Native API/ZwCreateProcessEx(),因此Hook 0x2F无用。
        */
        ZwCreateProcessExNum = 0x30;
    }
    else if ( osversioninfo.dwMajorVersion == 5 && osversioninfo.dwMinorVersion == 2 )
    {
        /*
        * 2003
        */
        ZwCreateProcessExNum = 0x32;
    }
  }
  if ( ZwCreateProcessNum == 0 && ZwCreateProcessExNum == 0 )
  {
    fprintf( stderr, "Checking your Platform/n" );
    goto main_exit;
  }
  if ( FALSE == LocateNtdllEntry() )
  {
    fprintf( stderr, "LocateNtdllEntry() failed/n" );
    goto main_exit;
  }
  /*
  * 为了方便使用者,我们固定获取winlogon.exe进程句柄。
  */
  if ( 0 == ( winlogonPid = GetPidFromProcessName( L"winlogon.exe" ) ) )
  {
    fprintf( stderr, "GetPidFromProcessName() failed/n" );
    goto main_exit;
  }
  EnableCurrentProcessDebugPrivilege();
  /*
  * Header : Declared in Winbase.h; include Windows.h.
  * Library: Use Kernel32.lib.
  *
  * HANDLE OpenProcess
  * (
  *   DWORD dwDesiredAccess, // access flag
  *   BOOL bInheritHandle,   // handle inheritance option
  *   DWORD dwProcessId     // process identifier
  * );
  */
  if ( NULL == ( winlogon = OpenProcess( PROCESS_CREATE_PROCESS, TRUE, winlogonPid ) ) )
  {
    PrintWin32Error( "OpenProcess() failed", GetLastError() );
    goto main_exit;
  }
  /*
  * DWORD VirtualQuery
  * (
  *   LPCVOID             lpAddress, // address of region
  *   PMEMORY_BASIC_INFORMATION lpBuffer,   // information buffer
  *   SIZE_T             dwLength   // size of buffer
  * );
  */
  ZeroMemory( &mbi, sizeof( mbi ) );
  if ( 0 != ZwCreateProcessNum )
  {
    VirtualQuery( ZwCreateProcess, &mbi, sizeof( mbi ) );
  }
  else
  {
    VirtualQuery( ZwCreateProcessEx, &mbi, sizeof( mbi ) );
  }
  /*
  * BOOL VirtualProtect
  * (
  *   LPVOID lpAddress,     // region of committed pages
  *   SIZE_T dwSize,       // size of the region
  *   DWORD flNewProtect,   // desired access protection
  *   PDWORD lpflOldProtect // old protection
  * );
  */
  if ( FALSE == VirtualProtect( mbi.AllocationBase, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect ) )
  {
    PrintWin32Error( "VirtualProtect() failed", GetLastError() );
    goto main_exit;
  }
  if ( 0 != ZwCreateProcessNum )
  {
    /*
      * mov eax, HackedZwCreateProcess
      * jmp eax
      */
    ( ( PASMJUMP )ZwCreateProcess )->mov_eax = 0xB8;
    ( ( PASMJUMP )ZwCreateProcess )->address = HackedZwCreateProcess;
    ( ( PASMJUMP )ZwCreateProcess )->jmp_eax = 0xE0FF;
  }
  else
  {
    /*
      * mov eax, HackedZwCreateProcessEx
      * jmp eax
      */
    ( ( PASMJUMP )ZwCreateProcessEx )->mov_eax = 0xB8;
    ( ( PASMJUMP )ZwCreateProcessEx )->address = HackedZwCreateProcessEx;
    ( ( PASMJUMP )ZwCreateProcessEx )->jmp_eax = 0xE0FF;
  }
  /*
  * BOOL CreateProcess
  * (
  *   LPCTSTR           lpApplicationName,   // name of executable module
  *   LPTSTR           lpCommandLine,     // command line string
  *   LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
  *   LPSECURITY_ATTRIBUTES lpThreadAttributes,   // SD
  *   BOOL             bInheritHandles,     // handle inheritance option
  *   DWORD           dwCreationFlags,     // creation flags
  *   LPVOID           lpEnvironment,     // new environment block
  *   LPCTSTR           lpCurrentDirectory,   // current directory name
  *   LPSTARTUPINFO       lpStartupInfo,     // startup information
  *   LPPROCESS_INFORMATION lpProcessInformation // process information
  * );
  */
  if ( FALSE == CreateProcess
            (
              NULL,
              argv[1],
              NULL,
              NULL,
              TRUE,
              CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
              NULL,
              NULL,
              &si,
              &pi
            ) )
  {
    PrintWin32Error( "CreateProcess() failed", GetLastError() );
    goto main_exit;
  }
  /*
  * CreateProcess()无论是否成功,都返回。与Unix下的exec*()不同。
  */

main_exit:

  if ( NULL != pi.hThread )
  {
    CloseHandle( pi.hThread );
    pi.hThread = NULL;
  }
  if ( NULL != pi.hProcess )
  {
    CloseHandle( pi.hProcess );
    pi.hProcess = NULL;
  }
  if ( NULL != winlogon )
  {
    CloseHandle( winlogon );
    winlogon = NULL;
  }
  DisableCurrentProcessDebugPrivilege();
  return( EXIT_FAILURE );
} /* end of main */

/************************************************************************/

--------------------------------------------------------------------------

至于CreateRemoteThread(),想在这上面发彪的兄弟别搭理我,我不熟它,这次不尝
试。目的就是练手,以此慢慢熟悉某些咱感兴趣的Windows角落,功利主义者是也。

再谢rain、flier的指点以及sparrow的共享代码。

☆ 参考资源

[ 1] Strace for NT
  http://razor.bindview.com/tools/desc/strace_readme.html
  http://razor.bindview.com/tools/files/strace-0.3.zip

[ 2] LsaAddAccountRights
  http://www.mvps.org/win32/lsa/laar.html
  http://www.mvps.org/win32/lsa/lsa_laar.cpp

[ 3] GUI-Based RunAs
  http://www.codeguru.com/misc/RunUser.html

[ 4] Start a Command As Any User
  http://www.codeguru.com/misc/CmdAsUser.html

[ 5] <<Windows NT/2000 Native API Reference>> - Gary Nebbett

 
Win11获取最高权限,和几种强制删除文件方法[--拒绝访问、需要Administrator权限..] 在Windows 11中,获取高于标准管理员权限的权限(如SYSTEM权限)通常需要使用特定工具或方法。以下是一些常见的方式,附几种强制删除文件方法,当前账户设置为管理员这里就不赘述了,这个权限范围不大,当时删除一个顽固软件,任务管理器无法删除,赋值文件所属权限,更名,使用Administrator管理员均不能删除,后面不断尝试,最终成功解决!本文。 阅读详情

相关推荐

在SYSTEM权限下以当前用户权限运行程序

在SYSTEM权限下以登陆用户运行程序。 ap.exe yourprogram.exe 请勿用于非法用途,即使要用一定要自己编译去掉banner!

从 Admin 权限切换到 System 权限

渗透技巧——从 Admin 权限切换到 System 权限 0x00 前言 在渗透测试中,某些情况下需要用到 system 权限,例如操作注册表 HKEY_LOCAL_MACHINESAMSAM 恰巧最近看到了一篇文章介绍了几种获得 system 权限的方法,于是决定结合自己的经验对这方面的技巧做系统整理 当然,前提是已经获得系统的管理员权限 学习链接: https://blog.xpnsec.c...

qq_35129925的博客 5168

汽车电子电气架构

控制器:从多独立 ECU → 域控制器(DCU) → 中央计算平台 + 区域控制器,硬件集成度持续提升,冗余减少;算力:从分散无集中算力 → 按域分配算力 → 全域算力集中,算力量级从 MIPS 跃升至 TOPS,支撑高阶智驾;网络:从低速 CAN/LIN 独占 → 以太网为主、总线为辅 → 高速以太网主干,数据传输速率提升千倍;软硬件:从软硬件深度绑定 → 初步解耦 → 完全解耦(SOA),实现 “硬件预埋、软件解锁”;线束。

LXY_LXY_的博客 1439

没有权限访问,windows更改文件权限,获取SYSTEM 或者 Administrator 、TrustedInstaller权限,解决删除文件需要来自SYSTEM的权限

windows更改文件权限,获取SYSTEM 或者 Administrator权限,解决删除文件需要来自SYSTEM的权限。 4.如下图,此时添加按钮已经可以点击。按下图顺序操作,点击add——select a principal——按照上面说过的过程-选择Everyone并确定,最后选择完全控制,确定即可,此时文件权限修改成功,可以执行删除等操作。

Heyuanfly的博客 4575

如何降低 Claude Code 封号风险:实用指南

本文针对 Claude Code 用户频繁遭遇账号封禁的问题,提供了一套经过实战验证的解决方案。通过分析封号的根本原因——共享VPN导致的IP异常标记,文章详细介绍了如何通过"独立服务器+中转服务+环境配置"三步走策略,显著降低封号风险。

goodparty的专栏 2146

光纤布拉格光栅(FBG)笔记【1】:波导结构和布拉格波长推导

引言 本文是光纤布拉格光栅(FBG)的笔记【1】,主要介绍了光纤布拉格光栅的波导结构,并且利用动量和能量守恒推导了光纤布拉格波长的表达式 普通光纤中让折射率发生周期性变化就是结构最简单的均匀光纤布拉格光栅(FBG),其波导结构如下图所示。 其传感原理描述可以分为以下的三点: ①光纤纤芯传播的光会在每个光栅面进行反射和透射; ②如果不满足布拉格条件,依次排列的光栅平面反射的光会逐渐变得不同直到最后相互抵消;同时由于系数不匹配,与布拉格波长不相符的光在每个光栅平面的反射也很微弱,这些光大部分在光纤中发生透.

subtitle_的博客 2万+

从administrator到system权限的几种方式

文章目录前言1. 通过sc命令(只适用于win xp)2. 通过计划任务命令(win7-win10)2.1 通过at命令实现(只适用于win7)2.2 通过schtasks实现(win7-win10)3. 通过psexec4. Meterpreter参考文章 前言 对windows中从admin到system权限到方法做一个小的记录。主要参考了三好学生的博客,三好学生博客地址。 以下利用方式的前提是已经获取了计算机的administrator权限。 1. 通过sc命令(只适用于win xp) 以syste

Shanfenglan's blog 4万+

【参数配置】OpenClaw 的破解之道(Doom Loop)

本文深入解析了OpenClaw中的Doom Loop(死循环)问题及其应对策略。主要内容包括: Agent Loop的核心概念:基于ReAct范式,OpenClaw通过"思考-行动-观察"循环执行任务,但可能陷入无进展的死循环。 Doom Loop现象:Agent持续执行但任务进度为零,常见于四种工具调用场景:相同调用重复执行、调用不存在工具、轮询工具卡死、操作交替振荡。 OpenClaw的防御机制: 第一道防线:重试端断路器,通过上下文压缩熔断(最多3次)和总重试次数熔断(32-160次)防止无限重试。

海兰 4042

转贴 Administrator用户直接获取SYSTEM权限

转贴 Administrator用户直接获取SYSTEM权限

qq_43678568的博客 430

2024年数字IC秋招-格科微-数字电路设计工程师-笔试题

笔试题型:简答题(9个)笔试平台:牛客(电脑监控)笔试时间:2h。

qq_42135020的博客 1605

095、PCIE物理层测试模式:从信号眼图到误码率实战

本文介绍了PCIe物理层测试模式的调试方法和实战经验。重点解析了环回测试、合规性测试和静默模式的应用场景及配置要点,分享了信号眼图分析、误码率测试和接收端验证的实用技巧。作者结合自身调试经历,强调物理层测试对排查信号完整性问题的重要性,建议在量产前进行基础测试,并提醒注意芯片勘误和测试模式切换等易错点。通过合理使用测试模式,可显著提高PCIe链路调试效率,确保物理层稳定可靠。

z534437748的博客 60

[转贴]Administrator用户直接获取SYSTEM权限

 Administrator用户直接获取SYSTEM权限来源:http://www.nsfocus.com作者:"scz" scz@nsfocus.com>标题: MSDN系列(3)--Administrator用户直接获取SYSTEM权限日期: 2003-06-21 21:51更新:-------------------------------------------------

享受开发,颠倒银河 7581

RKNN 端侧部署必看:YOLOv11 Pose 姿态估计模型转换与性能优化实战

随着人工智能技术在边缘计算领域的快速发展,姿态估计作为计算机视觉的重要分支,在智能监控、人机交互、体感游戏等场景中展现出巨大的应用潜力。本文深入研究了YOLOv11 Pose模型在Rockchip RKNN平台上的部署方案,从理论基础、模型转换、平台优化到实际部署进行了全面阐述。通过详细的技术分析和实验验证,证明了RKNN平台能够有效提升YOLOv11 Pose的推理性能,在RK3588硬件平台上实现了高达100 FPS的实时姿态检测,为边缘计算场景下的姿态估计应用提供了高效的解决方案。

m0_71589036的博客 184

XP如何获得系统SYSTEM权限

如果你以为xp中最高权限的是Administrator的话,那么你就错了。实际上xp最高的权限是SYSTEM权限,它能对系统进行任何的操作!那么我们该如何才能获得system权限呢?请看下面: 首先,下载PStools,它是windows下的一个强大的工具包,其中的工具包含各种不同的功能。我们今天的主角psexec.exe就是其中重要的一员。psexec.e...

weixin_34407348的博客 657

深度学习实战87-高中数学自适应测试系统研究与应用研发,前后台页面设计

大家好,我是微学AI ,今天给大家介绍一下深度学习实战87-高中数学自适应测试系统研究与应用研发,前后台页面设计。高中数学自适应测试系统旨在通过精准评估学生能力,用最少的题目发现其薄弱环节,并提供定制化的学习计划,帮助学生快速提升成绩。同时,系统结合了AI大模型实现自动判卷、生成报告,减轻教师负担,并支持个性化作业布置,使教学更加高效。学生可以清晰了解自身学习状态,教师也能获得精准的学生画像,实现差异化教学。

微学AI的博客 446

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Windows 7 普通管理员获取system所有权限

将下列代码保存成reg文件,双击运行就可以注入注册表。 此时,在想要获取权限的文件点击右键 管理员获取权限即可~ Windows Registry Editor Version 5.00 "NoWorkingDirectory"="" [HKEY_CLASSES_ROOT\*\shell\runas\command] @="cmd.exe /c takeown /f \"%1\" && ica

整理中 1303

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

获取比Administrator还高的权限——SYSTEM权限

获取比Administrator还高的权限——SYSTEM权限设置PsTool环境常用命令以系统权限打开cmd以系统权限打开explorer(其实也是桌面) 首先,我们会用到PsTool中的PsExec.exe,这个工具可以帮助我们以系统权限运行程序,甚至可以在非管理员权限的情况下操作! 设置PsTool环境 先下一个PsTool,解压,接着是设置PsTool环境。具体操作如下 第一步->打...

qq_39721774的博客 4630

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Windows权限体系深度解析:User、Administrator与System的权能疆界

Windows权限体系的核心在于User、Administrator和System三种权限主体的权能划分。标准用户仅能操作用户配置文件,适合日常使用以降低风险;管理员拥有系统级权限,通过UAC实现最小权限原则;System代表操作系统内核,具备最高权限,可访问所有资源。实际应用中应遵循最小权限原则,日常使用标准账户,谨慎提权,避免滥用System权限以防系统崩溃。理解这些权限等级有助于安全管理和故障排查。

Bruce_xiaowei的博客 2122

让你搞懂 administrator最高权限

前言 今天我才发现我一直犯了个致命的错误。 我一直以为刚买来电脑的时候,注册的账户显示的是管理员,就以为该账户就是最高权限了。 后来发现当我在执行一些命令的时候一直显示 下图的错误: 思考 我不禁陷入了思考,系统错误5 是指我的权限不够高的意思。 我用的账户是管理员啊,cmd也是用管理员状态运行的。 为啥还是不行呢? 经过我的不断查询才知道最高权限是administrator administrator账户默认是关闭的,默认没有密码 启动adminrator账户 net user administrat

辉小歌的博客 3791

从Administrator到SYSTEM:Windows权限提升的核心原理与四种实战方法

在Windows系统管理与安全领域,权限是访问控制的核心概念,它决定了用户或进程能执行的操作范围。其基本原理基于安全令牌机制,每个进程都关联一个包含用户身份和特权信息的令牌。权限提升的技术价值在于突破默认权限边界,以执行系统级维护、故障排查或安全评估等关键任务。典型的应用场景包括修改受保护的系统文件、操作其他用户进程、进行深度安全渗透测试等。本文聚焦于Windows环境中从Administrator权限提升至最高SYSTEM权限的实战路径,深入剖析了计划任务滥用、服务控制管理器操作、进程令牌复制等核心方法,

weixin_30920597的博客 318

System和Administrator两个账户哪个权限更高,为什么有人说同权呢

权限常识

XXokok的博客 1342
上一篇: 了解 Windows Vista 内核
下一篇: 改好DEBUG七处缺点的comexe实现报告
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值