创建高权限进程

Author:  sinister
Email:   sinister@whitecell.org
Homepage: http://www.whitecell.org
Date:    2006-02-12

/*****************************************************************
  文件名        : wssrun.c
  描述          : 创建高权限进程
  作者          : sinister
  最后修改日期  : 2006.2.09

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


//
// 写这个初衷是为了让 Windows 任务管理器可以结束掉一些服务
// 和僵死进程,用 pslist/pskill 之类工具无法获得象任务管理
// 器那样丰富的信息,还得来回切换,麻烦的很。最初想写个驱动
// 监视任务管理器运行,使用 SYSTEM 进程 TOKEN 替换来达到目的。
// 后来觉得通用性不好,就改用了这种方法。此方法还可使 regedit
// 查看、编辑 SAM 等注册表键,何乐而不为。
//
// wssrun taskmgr.exe
// wssrun regedit.exe
//


#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude

#pragma comment(lib,"Shlwapi.lib")


/
// 函数类型 :自定义工具函数
// 函数模块 :

// 功能 :提升当前进程权限
// 注意 :
/
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2006.2.09
/
// 重   大   修   改   历   史

// 修改者 :
// 修改日期 :
// 修改内容 :
/

BOOL
EnableDebugPriv( LPCTSTR szPrivilege )
{
  HANDLE hToken;
  LUID sedebugnameValue;
  TOKEN_PRIVILEGES tkp;

  if ( !OpenProcessToken( GetCurrentProcess(),
                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                          &hToken ) )
  {
    return FALSE;
  }
  if ( !LookupPrivilegeValue( NULL, szPrivilege, &sedebugnameValue ) )
  {
    CloseHandle( hToken );
    return FALSE;
  }

  tkp.PrivilegeCount = 1;
  tkp.Privileges[0].Luid = sedebugnameValue;
  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

  if ( !AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
  {
    CloseHandle( hToken );
    return FALSE;
  }

  return TRUE;
}

/
// 函数类型 :自定义工具函数
// 函数模块 :

// 功能 :通过指定进程名得到其进程 ID
// 注意 :
/
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2006.2.09
/
// 重   大   修   改   历   史

// 修改者 :
// 修改日期 :
// 修改内容 :
/

DWORD
GetProcessId( LPCTSTR szProcName )
{
  PROCESSENTRY32 pe;  
  DWORD dwPid;
  DWORD dwRet;
  BOOL bFound = FALSE;

  //
  // 通过 TOOHLP32 函数枚举进程
  //

  HANDLE hSP = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
  if ( hSP )
  {
    pe.dwSize = sizeof( pe );

    for ( dwRet = Process32First( hSP, &pe );
          dwRet;
          dwRet = Process32Next( hSP, &pe ) )
    {
      //
      // 使用 StrCmpNI 比较字符传,可忽略大小写
      //
      if ( StrCmpNI( szProcName, pe.szExeFile, strlen( szProcName ) ) == 0 )
      {
        dwPid = pe.th32ProcessID;
        bFound = TRUE;
        break;
      }
    }

    CloseHandle( hSP );

    if ( bFound == TRUE )
    {
      return dwPid;
    }
  }

  return NULL;
}

/
// 函数类型 :自定义工具函数
// 函数模块 :

// 功能 : 创建具有高权限的进程
// 注意 :
/
// 作者 : sinister
// 发布版本 : 1.00.00
// 发布日期 : 2006.2.09
/
// 重   大   修   改   历   史

// 修改者 :
// 修改日期 :
// 修改内容 :
/

BOOL
CreateSystemProcess( LPTSTR szProcessName )
{
  HANDLE hProcess;
  HANDLE hToken, hNewToken;
  DWORD dwPid;

  PACL pOldDAcl = NULL;
  PACL pNewDAcl = NULL;
  BOOL bDAcl;
  BOOL bDefDAcl;
  DWORD dwRet;

  PACL pSacl = NULL;
  PSID pSidOwner = NULL;
  PSID pSidPrimary = NULL;
  DWORD dwAclSize = 0;
  DWORD dwSaclSize = 0;
  DWORD dwSidOwnLen = 0;
  DWORD dwSidPrimLen = 0;

  DWORD dwSDLen;
  EXPLICIT_ACCESS ea;
  PSECURITY_DESCRIPTOR pOrigSd = NULL;
  PSECURITY_DESCRIPTOR pNewSd = NULL;

  STARTUPINFO si;
  PROCESS_INFORMATION pi;

  BOOL bError;

  if ( !EnableDebugPriv( "SeDebugPrivilege" ) )
  {
    printf( "EnableDebugPriv() to failed!/n" );

    bError = TRUE;
    goto Cleanup;
  }

  //
  // 选择 WINLOGON 进程
  //
  if ( ( dwPid = GetProcessId( "WINLOGON.EXE" ) ) == NULL )
  {
    printf( "GetProcessId() to failed!/n" );  

    bError = TRUE;
    goto Cleanup;
  }

  hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwPid );
  if ( hProcess == NULL )
  {
    printf( "OpenProcess() = %d/n", GetLastError() );  

    bError = TRUE;
    goto Cleanup;
  }

  if ( !OpenProcessToken( hProcess, READ_CONTROL | WRITE_DAC, &hToken ) )
  {
    printf( "OpenProcessToken() = %d/n", GetLastError() );

    bError = TRUE;
    goto Cleanup;
  }

  //
  // 设置 ACE 具有所有访问权限
  //
  ZeroMemory( &ea, sizeof( EXPLICIT_ACCESS ) );
  BuildExplicitAccessWithName( &ea,
                               "Everyone",
                               TOKEN_ALL_ACCESS,
                               GRANT_ACCESS,
                               0 );

  if ( !GetKernelObjectSecurity( hToken,
                                 DACL_SECURITY_INFORMATION,
                                 pOrigSd,
                                 0,
                                 &dwSDLen ) )
  {
    //
    // 第一次调用给出的参数肯定返回这个错误,这样做的目的是
    // 为了得到原安全描述符 pOrigSd 的长度
    //
    if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
    {
      pOrigSd = ( PSECURITY_DESCRIPTOR ) HeapAlloc( GetProcessHeap(),
                                                    HEAP_ZERO_MEMORY,
                                                    dwSDLen );
      if ( pOrigSd == NULL )
      {
        printf( "Allocate pSd memory to failed!/n" );

        bError = TRUE;
        goto Cleanup;
      }

      //
      // 再次调用才正确得到安全描述符 pOrigSd
      //
      if ( !GetKernelObjectSecurity( hToken,
                                     DACL_SECURITY_INFORMATION,
                                     pOrigSd,
                                     dwSDLen,
                                     &dwSDLen ) )
      {
        printf( "GetKernelObjectSecurity() = %d/n", GetLastError() );
        bError = TRUE;
        goto Cleanup;
      }
    }
    else
    {
      printf( "GetKernelObjectSecurity() = %d/n", GetLastError() );
      bError = TRUE;
      goto Cleanup;
    }
  }

  //
  // 得到原安全描述符的访问控制列表 ACL
  //
  if ( !GetSecurityDescriptorDacl( pOrigSd, &bDAcl, &pOldDAcl, &bDefDAcl ) )
  {
    printf( "GetSecurityDescriptorDacl() = %d/n", GetLastError() );

    bError = TRUE;
    goto Cleanup;
  }

  //
  // 生成新 ACE 权限的访问控制列表 ACL
  //
  dwRet = SetEntriesInAcl( 1, &ea, pOldDAcl, &pNewDAcl );
  if ( dwRet != ERROR_SUCCESS )
  {
    printf( "SetEntriesInAcl() = %d/n", GetLastError() );
    pNewDAcl = NULL;

    bError = TRUE;
    goto Cleanup;
  }

  if ( !MakeAbsoluteSD( pOrigSd,
                        pNewSd,
                        &dwSDLen,
                        pOldDAcl,
                        &dwAclSize,
                        pSacl,
                        &dwSaclSize,
                        pSidOwner,
                        &dwSidOwnLen,
                        pSidPrimary,
                        &dwSidPrimLen ) )
  {
    //
    // 第一次调用给出的参数肯定返回这个错误,这样做的目的是
    // 为了创建新的安全描述符 pNewSd 而得到各项的长度
    //
    if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
    {
      pOldDAcl = ( PACL ) HeapAlloc( GetProcessHeap(),
                                     HEAP_ZERO_MEMORY,
                                     dwAclSize );
      pSacl = ( PACL ) HeapAlloc( GetProcessHeap(),
                                  HEAP_ZERO_MEMORY,
                                  dwSaclSize );
      pSidOwner = ( PSID ) HeapAlloc( GetProcessHeap(),
                                      HEAP_ZERO_MEMORY,
                                      dwSidOwnLen );
      pSidPrimary = ( PSID ) HeapAlloc( GetProcessHeap(),
                                        HEAP_ZERO_MEMORY,
                                        dwSidPrimLen );
      pNewSd = ( PSECURITY_DESCRIPTOR ) HeapAlloc( GetProcessHeap(),
                                                   HEAP_ZERO_MEMORY,
                                                   dwSDLen );

      if ( pOldDAcl == NULL ||
           pSacl == NULL ||
           pSidOwner == NULL ||
           pSidPrimary == NULL ||
           pNewSd == NULL )
      {
        printf( "Allocate SID or ACL to failed!/n" );

        bError = TRUE;
        goto Cleanup;
      }

      //
      // 再次调用才可以成功创建新的安全描述符 pNewSd
      // 但新的安全描述符仍然是原访问控制列表 ACL
      //
      if ( !MakeAbsoluteSD( pOrigSd,
                            pNewSd,
                            &dwSDLen,
                            pOldDAcl,
                            &dwAclSize,
                            pSacl,
                            &dwSaclSize,
                            pSidOwner,
                            &dwSidOwnLen,
                            pSidPrimary,
                            &dwSidPrimLen ) )
      {
        printf( "MakeAbsoluteSD() = %d/n", GetLastError() );

        bError = TRUE;
        goto Cleanup;
      }
    }
    else
    {
      printf( "MakeAbsoluteSD() = %d/n", GetLastError() );

      bError = TRUE;
      goto Cleanup;
    }
  }

  //
  // 将具有所有访问权限的访问控制列表 pNewDAcl 加入到新的
  // 安全描述符 pNewSd 中
  //
  if ( !SetSecurityDescriptorDacl( pNewSd, bDAcl, pNewDAcl, bDefDAcl ) )
  {
    printf( "SetSecurityDescriptorDacl() = %d/n", GetLastError() );

    bError = TRUE;
    goto Cleanup;
  }

  //
  // 将新的安全描述符加到 TOKEN 中
  //
  if ( !SetKernelObjectSecurity( hToken, DACL_SECURITY_INFORMATION, pNewSd ) )
  {
    printf( "SetKernelObjectSecurity() = %d/n", GetLastError() );

    bError = TRUE;
    goto Cleanup;
  }

  //
  // 再次打开 WINLOGON 进程的 TOKEN,这时已经具有所有访问权限
  //
  if ( !OpenProcessToken( hProcess, TOKEN_ALL_ACCESS, &hToken ) )
  {
    printf( "OpenProcessToken() = %d/n", GetLastError() );  

    bError = TRUE;
    goto Cleanup;
  }

  //
  // 复制一份具有相同访问权限的 TOKEN
  //
  if ( !DuplicateTokenEx( hToken,
                          TOKEN_ALL_ACCESS,
                          NULL,
                          SecurityImpersonation,
                          TokenPrimary,
                          &hNewToken ) )
  {
    printf( "DuplicateTokenEx() = %d/n", GetLastError() );  

    bError = TRUE;
    goto Cleanup;
  }


  ZeroMemory( &si, sizeof( STARTUPINFO ) );
  si.cb = sizeof( STARTUPINFO );

  //
  // 不虚拟登陆用户的话,创建新进程会提示
  // 1314 客户没有所需的特权错误
  //
  ImpersonateLoggedOnUser( hNewToken );


  //
  // 我们仅仅是需要建立高权限进程,不用切换用户
  // 所以也无需设置相关桌面,有了新 TOKEN 足够
  //


  //
  // 利用具有所有权限的 TOKEN,创建高权限进程
  //
  if ( !CreateProcessAsUser( hNewToken,
                             NULL,
                             szProcessName,
                             NULL,
                             NULL,
                             FALSE,
                             NULL, //NORMAL_PRIORITY_CLASS | Create_NEW_CONSOLE,
                             NULL,
                             NULL,
                             &si,
                             &pi ) )
  {
    printf( "CreateProcessAsUser() = %d/n", GetLastError() );  

    bError = TRUE;
    goto Cleanup;
  }

  bError = FALSE;

  Cleanup:
  if ( pOrigSd )
  {
    HeapFree( GetProcessHeap(), 0, pOrigSd );
  }
  if ( pNewSd )
  {
    HeapFree( GetProcessHeap(), 0, pNewSd );
  }
  if ( pSidPrimary )
  {
    HeapFree( GetProcessHeap(), 0, pSidPrimary );
  }
  if ( pSidOwner )
  {
    HeapFree( GetProcessHeap(), 0, pSidOwner );
  }
  if ( pSacl )
  {
    HeapFree( GetProcessHeap(), 0, pSacl );
  }
  if ( pOldDAcl )
  {
    HeapFree( GetProcessHeap(), 0, pOldDAcl );
  }

  CloseHandle( pi.hProcess );
  CloseHandle( pi.hThread );
  CloseHandle( hToken );
  CloseHandle( hNewToken );
  CloseHandle( hProcess );

  if ( bError )
  {
    return FALSE;
  }

  return TRUE;
}


void
main( int argc, char** argv )
{
  if ( argc < 2 )
  {
    printf( "Usage: wssrun /n" );
    return ;
  }

  if ( CreateSystemProcess( argv[1] ) == FALSE )
  {
    printf( "wssrun: CreateSystemProcess() to failed!/n" );
    return ;
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值